Skip to content
Open
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
23 changes: 17 additions & 6 deletions src/components/dashboard/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Image from 'next/image';

import { Card } from '@/src/types/card';
import formatDateTime from '@/src/util/formatDateTime';

import ColorTagChip from '../ui/Chips/ColorTagChip';
import DefaultProfileImage from '../ui/DefaultProfileImage';
Expand Down Expand Up @@ -48,14 +49,24 @@ export default function Card({ cardData }: CardDataProps) {
className='sm:size-[14px] lg:size-[18px] '
/>
<div className='text-[12px] font-medium text-gray5 sm:text-[10px]'>
{dueDate}
{formatDateTime(dueDate)}
</div>
</div>

<DefaultProfileImage
classNames='size-6 rounded-full bg-green px-[8px] text-[12px]'
nickname={assignee.nickname}
/>
{assignee.profileImageUrl ? (
<div className='relative size-6'>
<Image
src={assignee.profileImageUrl}
fill={true}
className='rounded-full'
alt={assignee.nickname}
/>
</div>
) : (
<DefaultProfileImage
classNames='size-6 rounded-full bg-green text-[12px]'
nickname={assignee.nickname}
/>
)}
</div>
</div>
</div>
Expand Down
20 changes: 18 additions & 2 deletions src/components/dashboard/CardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useModal } from '@/src/contexts/ModalProvider';
import { Card as CardType } from '@/src/types/card';
import { Column } from '@/src/types/dashboard';

import CardDetailModal from '../ui/Modal/CardDetailModal';
import TodoModal from '../ui/Modal/TodoModal';
import Card from './Card';
interface CardListProps {
Expand Down Expand Up @@ -91,6 +92,17 @@ export default function CardList({
);
};

const handleCardDetailModal = (cardId: number) => {
openModal(
<CardDetailModal
boardid={boardid}
cardId={cardId}
onClose={() => closeModal(modalId)}
/>,
modalId,
);
};

useEffect(() => {
void fetchData();
}, []);
Expand Down Expand Up @@ -143,8 +155,12 @@ export default function CardList({
className='w-full py-2'
onClick={handleCreateCard}
/>
{data.cards.map((cardData, index) => (
<button type='button' key={index}>
{data.cards.map((cardData) => (
<button
type='button'
key={cardData.id}
onClick={() => handleCardDetailModal(cardData.id)}
>
<Card cardData={cardData} />
</button>
))}
Expand Down
6 changes: 4 additions & 2 deletions src/components/ui/Chips/DotNameTagChip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ export default function DotNameTagChip({
alt='보라색 점 아이콘'
width={2}
height={2}
className='size-1.5'
className='size-1.5 sm:hidden'
/>
<div className='text-xs text-violet2 sm:text-[10px]'>{children}</div>
<div className='whitespace-nowrap text-xs text-violet2 sm:text-[10px]'>
{children}
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Image from 'next/image';
import React, { useEffect, useState } from 'react';

import { useGetCommentList } from '@/src/apis/card/useGetCommentList';
import { useModal } from '@/src/contexts/ModalProvider';
import { useGetCardDetail } from '@/src/hooks/Card/useGetCardDetail';
import { useGetColumnList } from '@/src/hooks/dashboard/useGetColumnList';
import { Card } from '@/src/types/card';
Expand All @@ -11,27 +12,37 @@ import ColorTagChip from '../Chips/ColorTagChip';
import DotNameTagChip from '../Chips/DotNameTagChip';
import DefaultProfileImage from '../DefaultProfileImage';
import ModalTextarea from '../ModalInput/ModalTextarea';
import TodoModal from './TodoModal';

interface CardDetailsProps {
boardid: string | string[] | undefined;
cardId: number;
onClose: () => void;
}

const CardDetails: React.FC<CardDetailsProps> = ({ cardId }) => {
const CardDetailModal: React.FC<CardDetailsProps> = ({
boardid,
cardId,
onClose,
}) => {
const [cardData, setCardData] = useState<Card | null>(null);
const [comment, setComment] = useState('');
const [isMenuOpen, setIsMenuOpen] = useState<boolean>(false);

const { openModal, closeModal } = useModal();
const modalId = crypto.randomUUID();

// const { commentListInfo, execute: executeGetComment } = useGetCommentList(
// 99,
// cardId,
// );
const { commentListInfo } = useGetCommentList(99, cardId);
const { data } = useGetColumnList();
const currentColumnTitle = data?.find(
const { data: columnData } = useGetColumnList();
const currentColumnTitle = columnData?.find(
(item) => item.id === cardData?.columnId,
)?.title;
// const { execute: executePostComment } = usePostComment();

// const { execute: executePostComment } = usePostComment();
useEffect(() => {
const fetchData = async () => {
try {
Expand All @@ -52,18 +63,47 @@ const CardDetails: React.FC<CardDetailsProps> = ({ cardId }) => {
setIsMenuOpen(!isMenuOpen);
};

const handleClose = () => {};
const handleEditCard = () => {
openModal(
<TodoModal
onClose={() => closeModal(modalId)}
mode='수정'
postData={{
assigneeUserId: 0,
dashboardId: Number(boardid),
columnId: cardData.columnId,
title: '',
description: '',
dueDate: '',
tags: [],
imageUrl: '',
}}
getData={{
assigneeUserId: cardData.assignee.id,
dashboardId: Number(boardid),
columnId: cardData.columnId,
title: cardData.title,
description: cardData.description,
dueDate: cardData.dueDate,
tags: cardData.tags,
imageUrl: cardData.imageUrl,
}}
/>,
modalId,
);
};

const handlePostComment = () => {
if (comment) {
// executePostComment(comment, cardId, cardData?.columnId);
// console.log('!', comment, cardId, cardData?.columnId);
}
alert(comment);
};

return (
<div className='relative flex max-w-[730px] shrink-0 flex-col gap-6 rounded-lg bg-white px-7 py-8 text-black4 sm:w-[327px] sm:gap-4 sm:px-5 sm:py-3 md:w-[680px]'>
<div className='flex flex-row sm:flex-col-reverse'>
<div className='relative flex max-w-[730px] shrink-0 flex-col gap-6 rounded-lg bg-white px-7 py-8 text-black4 scrollbar-hide sm:w-[327px] sm:gap-4 sm:px-5 sm:py-3 md:w-[680px] md:px-6 md:py-7'>
<div className='flex flex-row scrollbar-hide sm:flex-col-reverse'>
<h1 className='grow justify-start text-2xl font-bold sm:text-xl'>
{cardData.title}
</h1>
Expand All @@ -76,12 +116,15 @@ const CardDetails: React.FC<CardDetailsProps> = ({ cardId }) => {
src='/icons/close.svg'
fill={true}
alt='menu'
onClick={handleClose}
onClick={onClose}
/>
</button>
{isMenuOpen && (
<div className='absolute right-10 top-8 z-10 flex h-[82px] w-[93px] flex-col gap-1.5 rounded-md border border-gray3 bg-white p-1.5 text-center text-sm font-normal leading-6 shadow-[0_4px_20px_0_rgba(0_0_0_0.08)] sm:right-10 sm:top-6 sm:text-xs sm:leading-normal'>
<button className='h-8 w-full shrink-0 rounded hover:bg-violet1 hover:text-violet2 sm:h-[30px]'>
<button
onClick={handleEditCard}
className='h-8 w-full shrink-0 rounded hover:bg-violet1 hover:text-violet2 sm:h-[30px]'
>
수정하기
</button>
<button className='h-8 w-full shrink-0 rounded hover:bg-violet1 hover:text-violet2 sm:h-[30px]'>
Expand All @@ -91,13 +134,13 @@ const CardDetails: React.FC<CardDetailsProps> = ({ cardId }) => {
)}
</div>
</div>
<div className='flex flex-row gap-6 sm:flex-col-reverse'>
<div className='flex flex-row gap-6 scrollbar-hide sm:flex-col-reverse'>
<div className='relative flex w-[450px] flex-col gap-6 sm:max-w-[287px] md:w-[420px]'>
<div className='relative flex flex-col gap-4'>
<div className='flex flex-row items-center gap-5'>
<div className='flex flex-row items-center gap-5 sm:gap-3'>
<DotNameTagChip>{currentColumnTitle}</DotNameTagChip>
<hr className='h-5 border-l border-gray3' />
<div className='flex flex-row gap-1.5'>
<div className='flex flex-row gap-1.5 overflow-x-auto scrollbar-hide'>
{cardData.tags.map((tag, index) => (
<ColorTagChip key={index}>{tag}</ColorTagChip>
))}
Expand All @@ -106,14 +149,16 @@ const CardDetails: React.FC<CardDetailsProps> = ({ cardId }) => {
<div className='text-sm font-normal text-[#000] sm:text-xs'>
{cardData.description}
</div>
<div className='relative h-[260px] w-full rounded-md sm:h-[168px] sm:max-w-[287px]'>
<Image
src={cardData.imageUrl}
fill={true}
alt={cardData.title}
style={{ objectFit: 'cover' }}
/>
</div>
{cardData.imageUrl && (
<div className='relative h-[260px] w-full rounded-md sm:h-[168px] sm:max-w-[287px]'>
<Image
src={cardData.imageUrl}
fill={true}
alt={cardData.title}
style={{ objectFit: 'cover' }}
/>
</div>
)}
</div>
{commentListInfo && (
<div className='flex flex-col gap-5'>
Expand Down Expand Up @@ -204,4 +249,4 @@ const CardDetails: React.FC<CardDetailsProps> = ({ cardId }) => {
);
};

export default CardDetails;
export default CardDetailModal;
101 changes: 68 additions & 33 deletions src/components/ui/Modal/TodoModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ interface TodoModalProps {
onClose: () => void;
mode: string;
postData: PostData;
onCreated: (message: string) => void;
getData?: GetData;
onCreated?: (message: string) => void;
}

interface PostData {
Expand All @@ -27,10 +28,22 @@ interface PostData {
imageUrl: string | File;
}

interface GetData {
assigneeUserId: number;
dashboardId: number;
columnId: number;
title: string;
description: string;
dueDate: string;
tags: string[];
imageUrl: string | File;
}

const TodoModal: React.FC<TodoModalProps> = ({
onClose,
mode,
postData,
getData,
onCreated,
}) => {
const [formData, setFormData] = useState<PostData>({
Expand Down Expand Up @@ -123,45 +136,67 @@ const TodoModal: React.FC<TodoModalProps> = ({

<div className='flex flex-col gap-8'>
{mode === '생성' && (
<ModalDropdown
label='담당자'
data={memberOptions}
onDropdownSelect={handleChangeAssignee}
/>
)}

{/* mode가 '수정'일 때도 보이도록 */}
{mode === '수정' && (
<div className='flex flex-row items-center gap-2.5'>
<ModalDropdown
label='상태'
data={columnsOptions}
onDropdownSelect={handleChangeColumn}
/>
<>
<ModalDropdown
label='담당자'
data={memberOptions}
onDropdownSelect={handleChangeAssignee}
/>
</div>

<ModalInput
label='제목'
required={true}
onValueChange={handleChangeTitle}
/>

<ModalTextarea
label='설명'
required={true}
isButton={false}
onTextChange={handleChangeDescription}
/>

<ModalInput label='마감일' onValueChange={handleChangeDueDate} />
<ModalInput label='태그' onValueChange={handleChangeTags} />
<ModalImage label='이미지' onImageSelect={handleChangeImageUrl} />
</>
)}

<ModalInput
label='제목'
required={true}
onValueChange={handleChangeTitle}
/>

<ModalTextarea
label='설명'
required={true}
isButton={false}
onTextChange={handleChangeDescription}
/>

<ModalInput label='마감일' onValueChange={handleChangeDueDate} />
<ModalInput label='태그' onValueChange={handleChangeTags} />
<ModalImage label='이미지' onImageSelect={handleChangeImageUrl} />
{/* mode가 '수정'일 때도 보이도록 */}
{mode === '수정' && (
<>
<div className='flex flex-row items-center gap-2.5'>
<ModalDropdown
label='상태'
data={columnsOptions}
currentId={getData?.columnId}
onDropdownSelect={handleChangeColumn}
/>
<ModalDropdown
label='담당자'
data={memberOptions}
currentId={getData?.assigneeUserId}
onDropdownSelect={handleChangeAssignee}
/>
</div>
<ModalInput
label='제목'
required={true}
onValueChange={handleChangeTitle}
/>

<ModalTextarea
label='설명'
required={true}
isButton={false}
onTextChange={handleChangeDescription}
/>

<ModalInput label='마감일' onValueChange={handleChangeDueDate} />
<ModalInput label='태그' onValueChange={handleChangeTags} />
<ModalImage label='이미지' onImageSelect={handleChangeImageUrl} />
</>
)}
</div>

<div className='mt-7 flex justify-end gap-3 sm:mt-6 sm:justify-center'>
Expand Down
Loading