Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 1x 1x 4x 4x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x | 'use client';
import { Button } from '@/components/ui';
import { cn } from '@/lib/utils';
import { CardInfoRow } from './card-info-row';
import { CardParticipationRow } from './card-participation-row';
import { CardProfile } from './card-profile';
import { type CardTag, CardTags } from './card-tags';
import { CardThumbnail } from './card-thumbnail';
type CardProps = {
title: string;
images?: string[];
tags: string[];
location: string;
dateTime: string;
nickName: string;
participantCount: number;
maxParticipants: number;
profileImage?: string | null;
onClick?: () => void;
leaveAndChatActions?: {
onLeave: () => void;
onChat: () => void;
};
tabType?: 'current' | 'myPost' | 'past';
};
const calculateProgress = (count: number, max: number): number => {
const safeMax = max > 0 ? max : 1;
const rawProgress = (count / safeMax) * 100;
return Math.min(100, Math.max(0, rawProgress));
};
const convertToCardTags = (tags: string[]): CardTag[] => {
return tags.map((tag, index) => ({ id: index, label: tag }));
};
const Card = ({
title,
images,
tags,
location,
dateTime,
nickName,
participantCount,
maxParticipants,
profileImage,
onClick,
leaveAndChatActions,
tabType,
}: CardProps) => {
const thumbnail = images?.[0];
const cardTags = convertToCardTags(tags);
const progress = calculateProgress(participantCount, maxParticipants);
const shouldShowButtons = leaveAndChatActions && tabType !== 'past';
const leaveButtonText = tabType === 'myPost' ? '모임 취소' : '모임 탈퇴';
return (
<div
className={cn(
'bg-mono-white flex w-full rounded-3xl p-4 shadow-sm',
onClick && 'cursor-pointer',
)}
onClick={onClick}
>
<div className='flex min-w-0 gap-4'>
<div className='flex flex-col justify-between'>
<CardThumbnail thumbnail={thumbnail} title={title} />
<div className='flex flex-1 items-center'>
<CardProfile nickName={nickName} profileImage={profileImage} />
</div>
{shouldShowButtons && (
<Button
className='mt-3'
size='sm'
variant='tertiary'
onClick={(e) => {
e.stopPropagation();
leaveAndChatActions.onLeave();
}}
>
{leaveButtonText}
</Button>
)}
</div>
<div className='flex min-w-0 flex-1 flex-col justify-between'>
<div>
<h3 className='text-text-md-semibold w-full truncate text-gray-900'>{title}</h3>
<CardTags tags={cardTags} />
<div className='mt-3.25 flex flex-col gap-1'>
<CardInfoRow iconId='map-pin-1' label={location} />
<CardInfoRow iconId='calendar-1' label={dateTime} />
</div>
<CardParticipationRow
maxParticipants={maxParticipants}
participantCount={participantCount}
progress={progress}
/>
</div>
{shouldShowButtons && (
<Button
className='mt-3'
size='sm'
variant='primary'
onClick={(e) => {
e.stopPropagation();
leaveAndChatActions.onChat();
}}
>
채팅 입장
</Button>
)}
</div>
</div>
</div>
);
};
export default Card;
|