Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions src/pages/all-contribution-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,40 @@ import { useEffect, useRef } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import { getAllContributions } from '../apis/contribution';
import logo from '../assets/icons/logo.svg';
import benchIcon from '../assets/icons/bench.svg';
import bottleIcon from '../assets/icons/bottle.svg';
import clothesIcon from '../assets/icons/clothes.svg';
import countIcon from '../assets/icons/count.svg';
import flowerpotIcon from '../assets/icons/flowerpot.svg';
import noteIcon from '../assets/icons/note.svg';
import sneakersIcon from '../assets/icons/sneakers.svg';
import toiletPaperIcon from '../assets/icons/toilet-paper.svg';
import LoadingSpinner from '../components/common/LoadingSpinner';
import type { ContributionFeed } from '../types/contribution';

const FEED_PAGE_SIZE = 10;

const contributionTargetIcons = [
{ keywords: ['휴지', '화장지', '두루마리'], icon: toiletPaperIcon },
{ keywords: ['노트', '공책'], icon: noteIcon },
{ keywords: ['유리병', '병'], icon: bottleIcon },
{ keywords: ['종량제', '쓰레기봉투', '쓰레기 봉투'], icon: countIcon },
{ keywords: ['화분'], icon: flowerpotIcon },
{ keywords: ['티셔츠', '티 셔츠', '의류', '옷'], icon: clothesIcon },
{ keywords: ['신발', '운동화'], icon: sneakersIcon },
{ keywords: ['벤치'], icon: benchIcon },
];

const getContributionIcon = (feed: ContributionFeed) => {
if (feed.eventType !== 'REWARD_PROGRESS') {
return countIcon;
}

return contributionTargetIcons.find(({ keywords }) =>
keywords.some((keyword) => feed.targetName.includes(keyword)),
)?.icon ?? countIcon;
};

interface UserCountBannerProps {
userCount: number;
summaryMessage: string;
Expand Down Expand Up @@ -61,13 +90,16 @@ function UserCountBanner({
}

function ContributionFeedCard({ feed }: { feed: ContributionFeed }) {
const contributionIcon = getContributionIcon(feed);

return (
<article className='flex min-h-24 items-center gap-5 rounded-[20px] bg-white px-4 py-4 shadow-lg shadow-black/5'>
<div className='flex h-14 w-14 shrink-0 items-center justify-center overflow-hidden rounded-full bg-bg-green3'>
<img
src={feed.profileImageUrl || logo}
alt={`${feed.nickname}님의 프로필`}
className='h-full w-full object-cover'
src={contributionIcon}
alt=''
aria-hidden='true'
className='h-full w-full object-contain'
/>
</div>
<div className='min-w-0 flex-1 break-words text-base font-medium leading-[1.5] text-text [overflow-wrap:anywhere]'>
Expand Down
54 changes: 31 additions & 23 deletions src/pages/home-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import Modal from '../components/common/Modal';
import { logout } from '../apis/auth';
import { clearAuthData } from '../apis/token';
import { getCommunityList } from '../apis/community';
import HeartIcon from '../assets/icons/heart.svg';
import CommentIcon from '../assets/icons/comment.svg';

const formatCategory = (categoryValue: string | number) => {
const value = String(categoryValue);
Expand Down Expand Up @@ -157,31 +159,37 @@ export default function HomePage() {
오늘의 커뮤니티 <span className='ml-1 text-2xl leading-none'>›</span>
</button>

<button type='button' onClick={() => navigate(`/community/${communityPreview.id}`)} aria-label={`${communityPreview.title} 게시글 보기`} className='mt-3 flex w-full items-center gap-3 rounded-2xl bg-white p-3 text-left shadow-[0_7px_16px_rgba(0,0,0,0.07)]'>
<div className='min-w-0 flex-1'>
<div className='flex items-center justify-between gap-3'>
<span className='rounded-full bg-skyblue-bg px-2 py-1 text-[10px] font-semibold text-skyblue-text'>{formatCategory(communityPreview.category)}</span>
<span className='text-[12px] font-medium text-gray-400'>{formatTimeAgo(communityPreview.createdAt)}</span>
</div>
<h3 className='mt-3 truncate text-[15px] font-bold leading-none'>{communityPreview.title}</h3>
<div className='mt-4 flex items-center gap-5 text-[12px] font-semibold text-gray-500'>
<span className='flex items-center gap-2'>
<span className='h-5 w-5 rounded-full bg-[linear-gradient(135deg,#06C65F,#66E1FF)]' />
{communityPreview.writer}
</span>
<span className='flex items-center gap-1'>
<span className='h-3 w-3 rounded-[2px] border border-gray-400' />
{communityPreview.numComments}
</span>
<button type='button' onClick={() => navigate(`/community/${communityPreview.id}`)} aria-label={`${communityPreview.title} 게시글 보기`} className='mt-3 w-full rounded-2xl bg-white p-4 text-left shadow-[0_7px_16px_rgba(0,0,0,0.07)]'>
<div className='flex items-center gap-3'>
<div className='min-w-0 flex-1'>
<span className='inline-flex rounded-full bg-skyblue-bg px-2 py-1 text-[10px] font-semibold text-skyblue-text'>{formatCategory(communityPreview.category)}</span>
<h3 className='mt-3 truncate text-[15px] font-bold leading-none'>{communityPreview.title}</h3>
{communityPreview.preview && <p className='mt-2 truncate text-[13px] font-medium text-gray-600'>{communityPreview.preview}</p>}
</div>
{communityPreview.imageUrl && (
<img
src={communityPreview.imageUrl}
alt=''
className='h-[58px] w-[58px] shrink-0 rounded-xl object-cover'
/>
)}
</div>

<div className='mt-3 flex items-center text-[12px] font-semibold leading-none text-gray-500'>
<span className='flex min-w-0 items-center gap-2'>
<span className='h-5 w-5 shrink-0 rounded-full bg-[linear-gradient(135deg,#06C65F,#66E1FF)]' />
<span className='truncate'>{communityPreview.writer}</span>
</span>
<span className='ml-3 flex shrink-0 items-center gap-1'>
<img src={HeartIcon} alt='' className='h-3 w-[13px]' />
{communityPreview.numLikes}
</span>
<span className='ml-2 flex shrink-0 items-center gap-1'>
<img src={CommentIcon} alt='' className='h-3 w-[13px]' />
{communityPreview.numComments}
</span>
<span className='ml-auto shrink-0 pl-3 text-gray-400'>{formatTimeAgo(communityPreview.createdAt)}</span>
</div>
{communityPreview.imageUrl && (
<img
src={communityPreview.imageUrl}
alt=''
className='h-[58px] w-[58px] shrink-0 rounded-xl object-cover'
/>
)}
</button>
</section>
)}
Expand Down
Loading