From 8f5ff651edb60fe8c6df50da2a079659f96d8c9e Mon Sep 17 00:00:00 2001 From: Lectom C Han Date: Tue, 5 Aug 2025 14:44:41 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EA=B8=80=EC=93=B0=EA=B8=B0/=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=95=9C=EA=B8=80=20=EC=88=98=EC=A0=95=20=EA=B0=84?= =?UTF-8?q?=EB=8B=A8=20=EA=B6=8C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- viewer/biome.json | 2 +- viewer/src/components/DynamicForm.tsx | 20 +- viewer/src/components/DynamicTable.tsx | 27 ++- viewer/src/components/FeedbackFormCard.tsx | 18 +- viewer/src/components/Header.tsx | 5 +- viewer/src/components/MainLayout.tsx | 10 +- viewer/src/components/PageLayout.tsx | 17 +- viewer/src/components/UserProfileBox.tsx | 4 +- .../components/providers/ThemeProvider.d.ts | 2 +- viewer/src/components/ui/avatar.tsx | 76 +++---- viewer/src/components/ui/dialog.tsx | 190 +++++++++--------- viewer/src/index.css | 124 +----------- viewer/src/pages/FeedbackCreatePage.tsx | 105 ++++++---- viewer/src/pages/FeedbackDetailPage.tsx | 158 ++++++++++++--- viewer/src/pages/FeedbackListPage.tsx | 8 +- viewer/src/pages/IssueListPage.tsx | 5 +- viewer/src/pages/ProfilePage.tsx | 5 +- viewer/src/services/issue.ts | 2 +- 18 files changed, 407 insertions(+), 371 deletions(-) diff --git a/viewer/biome.json b/viewer/biome.json index 13289e7..d6a7be6 100644 --- a/viewer/biome.json +++ b/viewer/biome.json @@ -15,4 +15,4 @@ "quoteStyle": "double" } } -} \ No newline at end of file +} diff --git a/viewer/src/components/DynamicForm.tsx b/viewer/src/components/DynamicForm.tsx index 3aacffc..5b54248 100644 --- a/viewer/src/components/DynamicForm.tsx +++ b/viewer/src/components/DynamicForm.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState } from "react"; import type { FeedbackField } from "@/services/feedback"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -11,13 +11,11 @@ import { } from "@/components/ui/select"; import { Textarea } from "@/components/ui/textarea"; -// 컴포넌트 외부에 안정적인 참조를 가진 빈 객체 상수 선언 -const EMPTY_INITIAL_DATA = {}; - interface DynamicFormProps { fields: FeedbackField[]; + formData: Record; + setFormData: (formData: Record) => void; onSubmit: (formData: Record) => Promise; - initialData?: Record; submitButtonText?: string; onCancel?: () => void; cancelButtonText?: string; @@ -26,24 +24,18 @@ interface DynamicFormProps { export function DynamicForm({ fields, + formData, + setFormData, onSubmit, - initialData = EMPTY_INITIAL_DATA, // 기본값으로 상수 사용 submitButtonText = "제출", onCancel, cancelButtonText = "취소", hideButtons = false, }: DynamicFormProps) { - const [formData, setFormData] = - useState>(initialData); const [isSubmitting, setIsSubmitting] = useState(false); - useEffect(() => { - // initialData prop이 변경될 때만 폼 데이터를 동기화 - setFormData(initialData); - }, [initialData]); - const handleFormChange = (fieldId: string, value: unknown) => { - setFormData((prev) => ({ ...prev, [fieldId]: value })); + setFormData({ ...formData, [fieldId]: value }); }; const handleSubmit = async (e: React.FormEvent) => { diff --git a/viewer/src/components/DynamicTable.tsx b/viewer/src/components/DynamicTable.tsx index 2a64921..4873684 100644 --- a/viewer/src/components/DynamicTable.tsx +++ b/viewer/src/components/DynamicTable.tsx @@ -90,12 +90,19 @@ export function DynamicTable({ }: DynamicTableProps) { const [sorting, setSorting] = useState([]); const [columnFilters, setColumnFilters] = useState([]); - const [columnVisibility, setColumnVisibility] = useState({}); + const [columnVisibility, setColumnVisibility] = useState({ + screenshot: false, + createdAt: false, + }); const [columnSizing, setColumnSizing] = useState({}); const [expanded, setExpanded] = useState({}); const [globalFilter, setGlobalFilter] = useState(""); const [date, setDate] = useState(); + const columnNameMap = useMemo(() => { + return new Map(rawColumns.map((col) => [col.id, col.name])); + }, [rawColumns]); + const columns = useMemo[]>(() => { // 컬럼 순서 고정: 'id', 'title'/'name'을 항상 앞으로 const fixedOrder = ["id", "title", "name"]; @@ -124,7 +131,9 @@ export function DynamicTable({ return ( } + + + + + + ); + }; + + if (loading) { + return
페이지 로딩 중...
; + } + + if (error) { + return ; + } + return ( - setIsEditing(true)} - /> + {isEditing ? ( + + ) : ( + + )} ); } diff --git a/viewer/src/pages/FeedbackListPage.tsx b/viewer/src/pages/FeedbackListPage.tsx index 300c80d..9af40ec 100644 --- a/viewer/src/pages/FeedbackListPage.tsx +++ b/viewer/src/pages/FeedbackListPage.tsx @@ -59,8 +59,12 @@ export function FeedbackListPage() { const renderExpandedRow = (row: Row) => (
-

{String(row.original.title ?? '')}

-

{String(row.original.contents ?? '')}

+

+ {String(row.original.title ?? "")} +

+

+ {String(row.original.contents ?? "")} +

); diff --git a/viewer/src/pages/IssueListPage.tsx b/viewer/src/pages/IssueListPage.tsx index f239b2d..eabb45b 100644 --- a/viewer/src/pages/IssueListPage.tsx +++ b/viewer/src/pages/IssueListPage.tsx @@ -62,10 +62,7 @@ export function IssueListPage() { } return ( - + {error && } {schema && ( +
{ { id: "createdAt", name: "생성일", type: "date" }, { id: "updatedAt", name: "수정일", type: "date" }, ]; -} \ No newline at end of file +}