From eab4830d9430c2f7e6d3d81343a3e80518352809 Mon Sep 17 00:00:00 2001 From: sun Date: Thu, 18 Sep 2025 13:21:57 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=EC=9E=84=EC=8B=9C=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/(protected)/dashboard/[id]/page.tsx | 30 +- src/components/card/Card.tsx | 9 + src/components/column/Column.tsx | 33 +- src/components/modal/cardModal/Comment.tsx | 15 +- .../modal/cardModal/CreateCardModal.tsx | 32 +- .../modal/cardModal/DetailCardModal.tsx | 34 ++- .../modal/cardModal/ModifyCardModal.tsx | 283 ++++++++++-------- .../modal/columnModal/CreateColumnModal.tsx | 3 - .../modal/columnModal/DeleteColumnModal.tsx | 2 - src/components/modal/refactor | 20 -- 10 files changed, 243 insertions(+), 218 deletions(-) delete mode 100644 src/components/modal/refactor diff --git a/src/app/(protected)/dashboard/[id]/page.tsx b/src/app/(protected)/dashboard/[id]/page.tsx index ac542c9..3f1ef65 100644 --- a/src/app/(protected)/dashboard/[id]/page.tsx +++ b/src/app/(protected)/dashboard/[id]/page.tsx @@ -6,21 +6,17 @@ import Chip from "@/components/common/chip/Chip"; import Column from "@/components/column/Column"; import MyButton from "@/components/common/Button"; import { getColumns } from "@/features/columns/api"; -import { useColumnId } from "@/features/columns/store"; import { ColumnData } from "@/features/dashboard/types"; -import CreateCardModal from "@/components/modal/cardModal/CreateCardModal"; import CreateColumnModal from "@/components/modal/columnModal/CreateColumnModal"; export default function DashboardId() { const { id } = useParams(); const dashboardId = Number(id); - const [modal, setModal] = useState(null); + const [modal, setModal] = useState(null); const [isKebabOpen, setIsKebabOpen] = useState(null); const [columns, setColumns] = useState([]); const [isLoading, setIsLoading] = useState(true); - // Zustand 스토어에서 함수 가져오기 - const { setColumnIdData, setStatus } = useColumnId(); useEffect(() => { if (!dashboardId) return; @@ -30,13 +26,9 @@ export default function DashboardId() { setIsLoading(true); const response = await getColumns(dashboardId); const columnsData = Array.isArray(response) ? response : response?.data || []; - setColumns(columnsData); - - const statusMap = Object.fromEntries(columnsData.map((c) => [c.title, c.id])); - setStatus(statusMap); } catch (error) { - console.error("컬럼 목록 조회 실패:", error); + console.error("컬럼 목록 조회 실패", error); setColumns([]); } finally { setIsLoading(false); @@ -44,17 +36,6 @@ export default function DashboardId() { })(); }, [dashboardId]); - // 카드 추가 버튼 클릭 시 - zustand에 정보 저장하고 모달 열기 - const handleAddCard = (columnId: number, columnTitle: string) => { - console.log("카드 추가 클릭 - 컬럼 ID:", columnId, "대시보드 ID:", dashboardId); - - // Zustand에 현재 선택된 컬럼과 대시보드 정보 저장 - setColumnIdData(dashboardId, columnId, columnTitle); - - // 카드 생성 모달 열기 - setModal("card"); - }; - const handleAddColumn = () => { setModal("column"); }; @@ -74,7 +55,6 @@ export default function DashboardId() { key={item.id} status={item.title} cards={item.cards ?? []} - onAddCard={() => handleAddCard(item.id, item.title)} kebabIndex={isKebabOpen === i} isKebabOpen={() => setIsKebabOpen((prev) => (prev === i ? null : i))} dashboardId={dashboardId} @@ -93,12 +73,6 @@ export default function DashboardId() { - - {/* 모달들 */} - {modal === "card" && ( - - )} - {modal === "column" && ( )} diff --git a/src/components/card/Card.tsx b/src/components/card/Card.tsx index b42b835..e26875c 100644 --- a/src/components/card/Card.tsx +++ b/src/components/card/Card.tsx @@ -19,7 +19,10 @@ type CardWithAssignee = Omit & { profileImageUrl?: string; }; setColumns?: React.Dispatch>; + dashboardId?: number; columnId?: number; + cardId?: number; + status: string; }; export default function Card({ @@ -29,7 +32,10 @@ export default function Card({ imageUrl, assignee, setColumns, + dashboardId, columnId, + cardId, + status, }: CardWithAssignee) { const [isOpen, setIsOpen] = useState(false); @@ -130,7 +136,10 @@ export default function Card({ isOpen setIsOpen={setIsOpen} setColumns={setColumns} + dashboardId={dashboardId} columnId={columnId} + cardId={cardId} + status={status} /> )} diff --git a/src/components/column/Column.tsx b/src/components/column/Column.tsx index 3ea415e..cefd656 100644 --- a/src/components/column/Column.tsx +++ b/src/components/column/Column.tsx @@ -4,13 +4,14 @@ import { useState, useEffect, useRef } from "react"; import DeleteColumnModal from "@/components/modal/columnModal/DeleteColumnModal"; import ManageColumnModal from "@/components/modal/columnModal/ManageColumnModal"; +// import CreateCardModal from "@/components/modal/cardModal/CreateCardModal"; +import CreateCardModal from "@/components/modal/cardModal/ModifyCardModal"; import Card from "@/components/card/Card"; import Chip from "@/components/common/chip/Chip"; import KebabModal from "@/components/modal/KebabModal"; import MyButton from "@/components/common/Button"; import Button from "@/components/common/Button"; import { ColumnProps } from "@/features/dashboard/types"; -import { useColumnId } from "@/features/columns/store"; import { getCards } from "@/features/cards/api"; import type { CardData } from "@/features/dashboard/types"; @@ -24,8 +25,7 @@ export default function Column({ dashboardId, setColumns, }: ColumnProps) { - const [modal, setModal] = useState(null); - const { setColumnIdData } = useColumnId(); + const [modal, setModal] = useState(null); const loader = useRef(null); const [loading, setLoading] = useState(false); @@ -87,7 +87,6 @@ export default function Column({ const handleClickCard = (cardId: number) => { if (dashboardId == null || columnId == null) return; - setColumnIdData(dashboardId, columnId, status, cardId); }; return ( @@ -134,7 +133,12 @@ export default function Column({ {/* 카드 추가 버튼 */}
{})} + onClick={ + onAddCard ?? + (() => { + setModal("card"); + }) + } color="buttonBasic" className="flex h-10 w-full items-center justify-center" > @@ -146,7 +150,14 @@ export default function Column({
{cards?.map((card) => (
card.id && handleClickCard(card.id)}> - +
))} {hasMore &&
} @@ -154,6 +165,16 @@ export default function Column({
{/* 수정하기, 삭제하기 모달 관리 */} + {modal === "card" && ( + setModal(null)} + setColumns={setColumns} + dashboardId={dashboardId} + columnId={columnId} + mode="create" + /> + )} {modal === "manage" && columnId !== null && ( ([]); const [editingId, setEditingId] = useState(null); @@ -19,12 +22,6 @@ export default function CommentList() { const [isLoading, setIsLoading] = useState(false); const [hasMore, setHasMore] = useState(true); const [cursorId, setCursorId] = useState(null); - - const { columnIdData } = useColumnId(); - const cardId = columnIdData?.cardId ?? 0; - const dashboardId = columnIdData?.dashboardId ?? 0; - const columnId = columnIdData?.columnId ?? 0; - // 댓글 목록 불러오기 const fetchComments = useCallback( async (reset = false) => { diff --git a/src/components/modal/cardModal/CreateCardModal.tsx b/src/components/modal/cardModal/CreateCardModal.tsx index 27aa878..765acd4 100644 --- a/src/components/modal/cardModal/CreateCardModal.tsx +++ b/src/components/modal/cardModal/CreateCardModal.tsx @@ -13,7 +13,6 @@ import Button from "@/components/common/Button"; import { Modal, ModalHeader, ModalContext, ModalFooter } from "@/components/modal/Modal"; import { createCard } from "@/features/cards/api"; import { uploadCardImage } from "@/features/columns/api"; -import { useColumnId } from "@/features/columns/store"; import type { Card } from "@/features/cards/types"; import { ColumnData } from "@/features/dashboard/types"; import { getMembers } from "@/features/members/api"; @@ -27,6 +26,8 @@ type ModalType = { setIsOpen: () => void; setColumns: React.Dispatch>; onCardCreated?: () => void; + dashboardId: number; + columnId: number; }; export default function CreateCardModal({ @@ -34,10 +35,9 @@ export default function CreateCardModal({ setIsOpen, setColumns, onCardCreated, + dashboardId, + columnId, }: ModalType) { - // Zustand에서 컬럼 정보 가져오기 - const { columnIdData, setCardId, setUserId, setMembersId } = useColumnId(); - // input 값들 const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); @@ -46,17 +46,12 @@ export default function CreateCardModal({ const [imageFile, setImageFile] = useState(null); const [imageUrl, setImageUrl] = useState(""); const [isLoading, setIsLoading] = useState(false); - const [members, setMembers] = useState([]); const [assigneeId, setAssigneeId] = useState(null); // 필수 값 체크 const isDisabled = title.trim() === "" || description.trim() === ""; - // Zustand에서 값 가져오기 - const dashboardId = columnIdData?.dashboardId ?? 0; - const columnId = columnIdData?.columnId ?? 0; - useEffect(() => { if (!isOpen || !dashboardId) return; @@ -88,14 +83,11 @@ export default function CreateCardModal({ const handleAssigneeSelect = (opt: Option) => { const selectedId = Number(opt.value); setAssigneeId(selectedId); - - // 선택된 담당자만 Zustand에 저장 - setMembersId([opt]); }; const handleCreate = async () => { if (isDisabled || isLoading) return; - if (!columnIdData) { + if (!columnId) { alert("컬럼 정보가 없습니다."); return; } @@ -151,17 +143,17 @@ export default function CreateCardModal({ // API 응답 구조에 따른 처리 const createdCard: Card = "data" in (createResult as any) ? (createResult as any).data : createResult; - - const createdCardId = createdCard as Card & { id: number }; - if (createdCardId.id) { - setCardId(createdCardId.id); - setUserId(assigneeId); - } + const createColumnId = createdCard.columnId; + // const createdCardId = createdCard as Card & { id: number }; + // if (createdCardId.id) { + // setCardId(createdCardId.id); + // setUserId(assigneeId); + // } // 컬럼 상태 업데이트 setColumns((prevColumns) => prevColumns.map((col) => - col.id === columnId + col.id === createColumnId ? { ...col, cards: [{ ...createdCard, tags } as CardWithTags, ...(col.cards ?? [])], diff --git a/src/components/modal/cardModal/DetailCardModal.tsx b/src/components/modal/cardModal/DetailCardModal.tsx index f18593e..527e442 100644 --- a/src/components/modal/cardModal/DetailCardModal.tsx +++ b/src/components/modal/cardModal/DetailCardModal.tsx @@ -7,7 +7,6 @@ import KebabModal from "@/components/modal/KebabModal"; import Button from "@/components/common/Button"; import { Modal, ModalHeader, ModalContext } from "@/components/modal/Modal"; import { getCard, deleteCard } from "@/features/cards/api"; -import { useColumnId } from "@/features/columns/store"; import { cn } from "@/lib/utils/cn"; import Comment from "./Comment"; @@ -20,19 +19,28 @@ type ModalType = { isOpen: boolean; setIsOpen: React.Dispatch>; setColumns?: React.Dispatch>; + dashboardId?: number; columnId?: number; + cardId?: number; + status: string; }; -export default function DetailCardModal({ isOpen, setIsOpen, setColumns }: ModalType) { +export default function DetailCardModal({ + isOpen, + setIsOpen, + setColumns, + dashboardId, + columnId, + cardId, + status, +}: ModalType) { const [card, setCard] = useState(null); const [isKebabOpen, setIsKebabOpen] = useState(false); const [isModifyModal, setIsModifyModal] = useState(false); const [isLoading, setIsLoading] = useState(false); - const { columnIdData, setMembersId } = useColumnId(); - const cardId = columnIdData?.cardId; - const columnId = columnIdData?.columnId; - const columnTitle = columnIdData?.columnTitle; + console.log("맴버", card?.assignee); + console.log(status); // 카드 데이터 다시 불러오기 함수 const fetchCardData = async () => { @@ -56,7 +64,7 @@ export default function DetailCardModal({ isOpen, setIsOpen, setColumns }: Modal /> ), }; - setMembersId([assigneeOption]); + // setMembersId([assigneeOption]); } } catch (e) { console.error("카드 로딩 오류:", e); @@ -201,7 +209,7 @@ export default function DetailCardModal({ isOpen, setIsOpen, setColumns }: Modal
- +
{card?.tags?.map((tag: any, index: number) => { @@ -231,7 +239,7 @@ export default function DetailCardModal({ isOpen, setIsOpen, setColumns }: Modal /> ) : null}
- +
@@ -266,8 +274,12 @@ export default function DetailCardModal({ isOpen, setIsOpen, setColumns }: Modal setIsOpen={setIsModifyModal} cardData={card} setColumns={setColumns} - onModifyComplete={handleModifyComplete} - columnTitle={columnIdData?.columnTitle ?? ""} + dashboardId={dashboardId} + columnId={columnId} + mode="edit" + cardId={cardId} + status={statusOptions} + members={card?.assignee} /> )}
diff --git a/src/components/modal/cardModal/ModifyCardModal.tsx b/src/components/modal/cardModal/ModifyCardModal.tsx index 13d3a7e..f7d09af 100644 --- a/src/components/modal/cardModal/ModifyCardModal.tsx +++ b/src/components/modal/cardModal/ModifyCardModal.tsx @@ -1,8 +1,7 @@ "use client"; import dayjs from "dayjs"; -import { useState, useEffect } from "react"; +import { useEffect, useState } from "react"; -import Chip from "@/components/common/chip/Chip"; import DatePicker from "@/components/form/DatePicker"; import Field from "@/components/form/Field"; import ImgUpload from "@/components/form/ImgUpload"; @@ -12,33 +11,43 @@ import TagInput, { Tag } from "@/components/form/TagInput"; import Textarea from "@/components/form/Textarea"; import Button from "@/components/common/Button"; import { Modal, ModalHeader, ModalContext, ModalFooter } from "@/components/modal/Modal"; -import { updateCard } from "@/features/cards/api"; +import { createCard, updateCard } from "@/features/cards/api"; import { uploadCardImage } from "@/features/columns/api"; -import { useColumnId } from "@/features/columns/store"; +import type { Card } from "@/features/cards/types"; import { ColumnData } from "@/features/dashboard/types"; +import { Member } from "@/features/members/types"; import { getMembers } from "@/features/members/api"; -import { Card } from "@/features/cards/types"; + import { getColorForTag } from "@/lib/utils/tagColor"; -const now = dayjs(); +type CardWithTags = Card & { tags: Tag[] }; -type ModalType = { +type CardModalProps = { isOpen: boolean; - setIsOpen: React.Dispatch>; + setIsOpen: () => void | React.Dispatch>; + setColumns: React.Dispatch>; + dashboardId: number; + columnId: number; + mode?: "create" | "edit"; cardData?: Card | null; - setColumns?: React.Dispatch>; - onModifyComplete?: () => void; - columnTitle: string; + cardId?: number; + status?: string | Option[]; // 상태 옵션들 + members?: Member | Option[]; // 멤버 옵션들 }; -export default function ModifyCardModal({ +export default function CardModal({ isOpen, setIsOpen, - cardData, setColumns, - onModifyComplete, - columnTitle, -}: ModalType) { + dashboardId, + columnId, + mode = "create", + cardData = null, + cardId, + status, + members: propMembers, +}: CardModalProps) { + // 폼 상태 const [title, setTitle] = useState(""); const [description, setDescription] = useState(""); const [dueDate, setDueDate] = useState(null); @@ -46,38 +55,23 @@ export default function ModifyCardModal({ const [imageFile, setImageFile] = useState(null); const [imageUrl, setImageUrl] = useState(""); const [isLoading, setIsLoading] = useState(false); - const [selectedColumnId, setSelectedColumnId] = useState(null); // 추가: 선택된 컬럼 ID - - // 멤버 관련 const [members, setMembers] = useState([]); - const [selectedMember, setSelectedMember] = useState