From a53340e3c198be14e707ce439b7d04ef767ba7ab Mon Sep 17 00:00:00 2001 From: Lectom C Han Date: Sun, 3 Aug 2025 00:40:25 +0900 Subject: [PATCH] =?UTF-8?q?js=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{src => }/components/LanguageSelectBox.js | 0 .../src/components/DynamicForm.js | 0 .../src/components/DynamicTable.js | 0 .../src/components/ErrorDisplay.js | 0 .../{ => effort_js}/src/components/Header.js | 0 .../src/components/MainLayout.js | 0 .../src/components/ProjectSelectBox.js | 0 .../src/components/ThemeSelectBox.js | 0 .../src/components/UserProfileBox.js | 0 .../src/components/providers/ThemeProvider.js | 0 .../src/components/ui/button.js | 0 .../src/components/ui/calendar.js | 0 .../{ => effort_js}/src/components/ui/card.js | 0 .../src/components/ui/dropdown-menu.js | 0 .../src/components/ui/input.js | 0 .../src/components/ui/label.js | 0 .../src/components/ui/popover.js | 0 .../src/components/ui/select.js | 0 .../src/components/ui/separator.js | 0 .../src/components/ui/table.js | 0 .../src/components/ui/textarea.js | 0 viewer/{ => effort_js}/src/lib/utils.js | 0 .../src/pages/FeedbackCreatePage.js | 0 .../src/pages/FeedbackDetailPage.js | 0 .../src/pages/FeedbackListPage.js | 0 .../src/pages/IssueViewerPage.js | 0 viewer/{ => effort_js}/src/services/error.js | 0 .../{ => effort_js}/src/services/feedback.js | 2 +- viewer/{ => effort_js}/src/services/issue.js | 2 +- .../{ => effort_js}/src/services/project.js | 0 viewer/{ => effort_js/src}/vite.config.js | 0 viewer/src/components/Header.tsx | 14 ++++- viewer/src/components/MainLayout.tsx | 4 +- viewer/src/pages/FeedbackCreatePage.tsx | 17 ++++-- viewer/src/pages/FeedbackDetailPage.tsx | 58 +++++++++++-------- viewer/src/pages/FeedbackListPage.tsx | 20 ++++--- viewer/src/services/feedback.ts | 6 ++ viewer/src/store/useSettingsStore.ts | 17 +++++- viewer/tsconfig.json | 3 +- viewer/vite.config.ts | 1 + 40 files changed, 96 insertions(+), 48 deletions(-) rename viewer/{src => }/components/LanguageSelectBox.js (100%) rename viewer/{ => effort_js}/src/components/DynamicForm.js (100%) rename viewer/{ => effort_js}/src/components/DynamicTable.js (100%) rename viewer/{ => effort_js}/src/components/ErrorDisplay.js (100%) rename viewer/{ => effort_js}/src/components/Header.js (100%) rename viewer/{ => effort_js}/src/components/MainLayout.js (100%) rename viewer/{ => effort_js}/src/components/ProjectSelectBox.js (100%) rename viewer/{ => effort_js}/src/components/ThemeSelectBox.js (100%) rename viewer/{ => effort_js}/src/components/UserProfileBox.js (100%) rename viewer/{ => effort_js}/src/components/providers/ThemeProvider.js (100%) rename viewer/{ => effort_js}/src/components/ui/button.js (100%) rename viewer/{ => effort_js}/src/components/ui/calendar.js (100%) rename viewer/{ => effort_js}/src/components/ui/card.js (100%) rename viewer/{ => effort_js}/src/components/ui/dropdown-menu.js (100%) rename viewer/{ => effort_js}/src/components/ui/input.js (100%) rename viewer/{ => effort_js}/src/components/ui/label.js (100%) rename viewer/{ => effort_js}/src/components/ui/popover.js (100%) rename viewer/{ => effort_js}/src/components/ui/select.js (100%) rename viewer/{ => effort_js}/src/components/ui/separator.js (100%) rename viewer/{ => effort_js}/src/components/ui/table.js (100%) rename viewer/{ => effort_js}/src/components/ui/textarea.js (100%) rename viewer/{ => effort_js}/src/lib/utils.js (100%) rename viewer/{ => effort_js}/src/pages/FeedbackCreatePage.js (100%) rename viewer/{ => effort_js}/src/pages/FeedbackDetailPage.js (100%) rename viewer/{ => effort_js}/src/pages/FeedbackListPage.js (100%) rename viewer/{ => effort_js}/src/pages/IssueViewerPage.js (100%) rename viewer/{ => effort_js}/src/services/error.js (100%) rename viewer/{ => effort_js}/src/services/feedback.js (98%) rename viewer/{ => effort_js}/src/services/issue.js (92%) rename viewer/{ => effort_js}/src/services/project.js (100%) rename viewer/{ => effort_js/src}/vite.config.js (100%) diff --git a/viewer/src/components/LanguageSelectBox.js b/viewer/components/LanguageSelectBox.js similarity index 100% rename from viewer/src/components/LanguageSelectBox.js rename to viewer/components/LanguageSelectBox.js diff --git a/viewer/src/components/DynamicForm.js b/viewer/effort_js/src/components/DynamicForm.js similarity index 100% rename from viewer/src/components/DynamicForm.js rename to viewer/effort_js/src/components/DynamicForm.js diff --git a/viewer/src/components/DynamicTable.js b/viewer/effort_js/src/components/DynamicTable.js similarity index 100% rename from viewer/src/components/DynamicTable.js rename to viewer/effort_js/src/components/DynamicTable.js diff --git a/viewer/src/components/ErrorDisplay.js b/viewer/effort_js/src/components/ErrorDisplay.js similarity index 100% rename from viewer/src/components/ErrorDisplay.js rename to viewer/effort_js/src/components/ErrorDisplay.js diff --git a/viewer/src/components/Header.js b/viewer/effort_js/src/components/Header.js similarity index 100% rename from viewer/src/components/Header.js rename to viewer/effort_js/src/components/Header.js diff --git a/viewer/src/components/MainLayout.js b/viewer/effort_js/src/components/MainLayout.js similarity index 100% rename from viewer/src/components/MainLayout.js rename to viewer/effort_js/src/components/MainLayout.js diff --git a/viewer/src/components/ProjectSelectBox.js b/viewer/effort_js/src/components/ProjectSelectBox.js similarity index 100% rename from viewer/src/components/ProjectSelectBox.js rename to viewer/effort_js/src/components/ProjectSelectBox.js diff --git a/viewer/src/components/ThemeSelectBox.js b/viewer/effort_js/src/components/ThemeSelectBox.js similarity index 100% rename from viewer/src/components/ThemeSelectBox.js rename to viewer/effort_js/src/components/ThemeSelectBox.js diff --git a/viewer/src/components/UserProfileBox.js b/viewer/effort_js/src/components/UserProfileBox.js similarity index 100% rename from viewer/src/components/UserProfileBox.js rename to viewer/effort_js/src/components/UserProfileBox.js diff --git a/viewer/src/components/providers/ThemeProvider.js b/viewer/effort_js/src/components/providers/ThemeProvider.js similarity index 100% rename from viewer/src/components/providers/ThemeProvider.js rename to viewer/effort_js/src/components/providers/ThemeProvider.js diff --git a/viewer/src/components/ui/button.js b/viewer/effort_js/src/components/ui/button.js similarity index 100% rename from viewer/src/components/ui/button.js rename to viewer/effort_js/src/components/ui/button.js diff --git a/viewer/src/components/ui/calendar.js b/viewer/effort_js/src/components/ui/calendar.js similarity index 100% rename from viewer/src/components/ui/calendar.js rename to viewer/effort_js/src/components/ui/calendar.js diff --git a/viewer/src/components/ui/card.js b/viewer/effort_js/src/components/ui/card.js similarity index 100% rename from viewer/src/components/ui/card.js rename to viewer/effort_js/src/components/ui/card.js diff --git a/viewer/src/components/ui/dropdown-menu.js b/viewer/effort_js/src/components/ui/dropdown-menu.js similarity index 100% rename from viewer/src/components/ui/dropdown-menu.js rename to viewer/effort_js/src/components/ui/dropdown-menu.js diff --git a/viewer/src/components/ui/input.js b/viewer/effort_js/src/components/ui/input.js similarity index 100% rename from viewer/src/components/ui/input.js rename to viewer/effort_js/src/components/ui/input.js diff --git a/viewer/src/components/ui/label.js b/viewer/effort_js/src/components/ui/label.js similarity index 100% rename from viewer/src/components/ui/label.js rename to viewer/effort_js/src/components/ui/label.js diff --git a/viewer/src/components/ui/popover.js b/viewer/effort_js/src/components/ui/popover.js similarity index 100% rename from viewer/src/components/ui/popover.js rename to viewer/effort_js/src/components/ui/popover.js diff --git a/viewer/src/components/ui/select.js b/viewer/effort_js/src/components/ui/select.js similarity index 100% rename from viewer/src/components/ui/select.js rename to viewer/effort_js/src/components/ui/select.js diff --git a/viewer/src/components/ui/separator.js b/viewer/effort_js/src/components/ui/separator.js similarity index 100% rename from viewer/src/components/ui/separator.js rename to viewer/effort_js/src/components/ui/separator.js diff --git a/viewer/src/components/ui/table.js b/viewer/effort_js/src/components/ui/table.js similarity index 100% rename from viewer/src/components/ui/table.js rename to viewer/effort_js/src/components/ui/table.js diff --git a/viewer/src/components/ui/textarea.js b/viewer/effort_js/src/components/ui/textarea.js similarity index 100% rename from viewer/src/components/ui/textarea.js rename to viewer/effort_js/src/components/ui/textarea.js diff --git a/viewer/src/lib/utils.js b/viewer/effort_js/src/lib/utils.js similarity index 100% rename from viewer/src/lib/utils.js rename to viewer/effort_js/src/lib/utils.js diff --git a/viewer/src/pages/FeedbackCreatePage.js b/viewer/effort_js/src/pages/FeedbackCreatePage.js similarity index 100% rename from viewer/src/pages/FeedbackCreatePage.js rename to viewer/effort_js/src/pages/FeedbackCreatePage.js diff --git a/viewer/src/pages/FeedbackDetailPage.js b/viewer/effort_js/src/pages/FeedbackDetailPage.js similarity index 100% rename from viewer/src/pages/FeedbackDetailPage.js rename to viewer/effort_js/src/pages/FeedbackDetailPage.js diff --git a/viewer/src/pages/FeedbackListPage.js b/viewer/effort_js/src/pages/FeedbackListPage.js similarity index 100% rename from viewer/src/pages/FeedbackListPage.js rename to viewer/effort_js/src/pages/FeedbackListPage.js diff --git a/viewer/src/pages/IssueViewerPage.js b/viewer/effort_js/src/pages/IssueViewerPage.js similarity index 100% rename from viewer/src/pages/IssueViewerPage.js rename to viewer/effort_js/src/pages/IssueViewerPage.js diff --git a/viewer/src/services/error.js b/viewer/effort_js/src/services/error.js similarity index 100% rename from viewer/src/services/error.js rename to viewer/effort_js/src/services/error.js diff --git a/viewer/src/services/feedback.js b/viewer/effort_js/src/services/feedback.js similarity index 98% rename from viewer/src/services/feedback.js rename to viewer/effort_js/src/services/feedback.js index 5996da9..0c52058 100644 --- a/viewer/src/services/feedback.js +++ b/viewer/effort_js/src/services/feedback.js @@ -1,5 +1,5 @@ // src/services/feedback.ts -import { handleApiError } from "./error"; +import { handleApiError } from "../../../src/services/error"; // --- API 함수 --- const getFeedbacksSearchApiUrl = (projectId, channelId) => `/api/v2/projects/${projectId}/channels/${channelId}/feedbacks/search`; diff --git a/viewer/src/services/issue.js b/viewer/effort_js/src/services/issue.js similarity index 92% rename from viewer/src/services/issue.js rename to viewer/effort_js/src/services/issue.js index eaa253b..0ac14e7 100644 --- a/viewer/src/services/issue.js +++ b/viewer/effort_js/src/services/issue.js @@ -1,5 +1,5 @@ // src/services/issue.ts -import { handleApiError } from "./error"; +import { handleApiError } from "../../../src/services/error"; /** * 특정 프로젝트의 모든 이슈를 검색합니다. * @param projectId 프로젝트 ID diff --git a/viewer/src/services/project.js b/viewer/effort_js/src/services/project.js similarity index 100% rename from viewer/src/services/project.js rename to viewer/effort_js/src/services/project.js diff --git a/viewer/vite.config.js b/viewer/effort_js/src/vite.config.js similarity index 100% rename from viewer/vite.config.js rename to viewer/effort_js/src/vite.config.js diff --git a/viewer/src/components/Header.tsx b/viewer/src/components/Header.tsx index 21ac292..0124925 100644 --- a/viewer/src/components/Header.tsx +++ b/viewer/src/components/Header.tsx @@ -1,3 +1,4 @@ +import { cn } from "@/lib/utils"; import { NavLink } from "react-router-dom"; import { ProjectSelectBox } from "./ProjectSelectBox"; import { ThemeSelectBox } from "./ThemeSelectBox"; @@ -10,7 +11,11 @@ const menuItems = [ { name: "Issue", path: "/issues", type: "issue" }, ]; -export function Header() { +interface HeaderProps { + className?: string; +} + +export function Header({ className }: HeaderProps) { const { projectId, channelId } = useSettingsStore(); const getPath = (type: string, basePath: string) => { @@ -23,7 +28,12 @@ export function Header() { const homePath = `/projects/${projectId}`; return ( -
+
-
-
+
+
diff --git a/viewer/src/pages/FeedbackCreatePage.tsx b/viewer/src/pages/FeedbackCreatePage.tsx index 7104562..88b4acd 100644 --- a/viewer/src/pages/FeedbackCreatePage.tsx +++ b/viewer/src/pages/FeedbackCreatePage.tsx @@ -4,9 +4,9 @@ import { useSettingsStore } from "@/store/useSettingsStore"; import { useSyncChannelId } from "@/hooks/useSyncChannelId"; import { DynamicForm } from "@/components/DynamicForm"; import { - getFeedbackSchema, + getFeedbackFields, createFeedback, - type FeedbackSchema, + type FeedbackField, type CreateFeedbackRequest, } from "@/services/feedback"; import { ErrorDisplay } from "@/components/ErrorDisplay"; @@ -17,7 +17,7 @@ export function FeedbackCreatePage() { const navigate = useNavigate(); const { projectId, channelId } = useSettingsStore(); - const [schema, setSchema] = useState(null); + const [schema, setSchema] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [submitMessage, setSubmitMessage] = useState(null); @@ -28,8 +28,13 @@ export function FeedbackCreatePage() { const fetchSchema = async () => { try { setLoading(true); - const schemaData = await getFeedbackSchema(projectId, channelId); - setSchema(schemaData); + const schemaData = await getFeedbackFields(projectId, channelId); + // ID, Created, Updated, Issue 필드 제외 + const filteredSchema = schemaData.filter( + (field) => + !["id", "createdAt", "updatedAt", "issues"].includes(field.id), + ); + setSchema(filteredSchema); } catch (err) { setError( err instanceof Error ? err.message : "폼을 불러오는 데 실패했습니다.", @@ -91,7 +96,7 @@ export function FeedbackCreatePage() { {schema && ( diff --git a/viewer/src/pages/FeedbackDetailPage.tsx b/viewer/src/pages/FeedbackDetailPage.tsx index 17c8cdb..3e00cf9 100644 --- a/viewer/src/pages/FeedbackDetailPage.tsx +++ b/viewer/src/pages/FeedbackDetailPage.tsx @@ -7,6 +7,12 @@ import { updateFeedback, } from "@/services/feedback"; import { ErrorDisplay } from "@/components/ErrorDisplay"; +import { + Card, + CardContent, + CardHeader, + CardTitle, +} from "@/components/ui/card"; import { Separator } from "@/components/ui/separator"; export function FeedbackDetailPage() { @@ -128,31 +134,35 @@ export function FeedbackDetailPage() {

-
-
- - ID: {feedback?.id} - - - 생성일:{" "} - {feedback?.createdAt - ? new Date(feedback.createdAt).toLocaleString("ko-KR") - : "N/A"} - -
- - - {successMessage && ( -
- {successMessage} + + +
+ 피드백 정보 +
+ ID: {feedback?.id} + + 생성일:{" "} + {feedback?.createdAt + ? new Date(feedback.createdAt).toLocaleString("ko-KR") + : "N/A"} + +
- )} -
+ + + + {successMessage && ( +
+ {successMessage} +
+ )} +
+
); } diff --git a/viewer/src/pages/FeedbackListPage.tsx b/viewer/src/pages/FeedbackListPage.tsx index 78d19d8..b53239a 100644 --- a/viewer/src/pages/FeedbackListPage.tsx +++ b/viewer/src/pages/FeedbackListPage.tsx @@ -5,9 +5,9 @@ import { useSyncChannelId } from "@/hooks/useSyncChannelId"; import { DynamicTable } from "@/components/DynamicTable"; import { getFeedbacks, - getFeedbackSchema, + getFeedbackFields, type Feedback, - type FeedbackSchema, + type FeedbackField, } from "@/services/feedback"; import { ErrorDisplay } from "@/components/ErrorDisplay"; import { Button } from "@/components/ui/button"; @@ -17,7 +17,7 @@ export function FeedbackListPage() { const { projectId, channelId } = useSettingsStore(); const navigate = useNavigate(); - const [schema, setSchema] = useState(null); + const [schema, setSchema] = useState(null); const [feedbacks, setFeedbacks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -30,7 +30,7 @@ export function FeedbackListPage() { setLoading(true); setError(null); - const schemaData = await getFeedbackSchema(projectId, channelId); + const schemaData = await getFeedbackFields(projectId, channelId); setSchema(schemaData); const feedbacksData = await getFeedbacks(projectId, channelId); @@ -67,11 +67,13 @@ export function FeedbackListPage() { {error && } {schema && ( - +
+ +
)} ); diff --git a/viewer/src/services/feedback.ts b/viewer/src/services/feedback.ts index e480b39..400676b 100644 --- a/viewer/src/services/feedback.ts +++ b/viewer/src/services/feedback.ts @@ -188,5 +188,11 @@ export const updateFeedback = async ( if (!response.ok) { await handleApiError("피드백 수정에 실패했습니다.", response); } + + const contentLength = response.headers.get("Content-Length"); + if (contentLength === "0" || !contentLength) { + return {} as Feedback; // 혹은 적절한 기본 객체 + } + return response.json(); }; diff --git a/viewer/src/store/useSettingsStore.ts b/viewer/src/store/useSettingsStore.ts index 81dc0db..b09bf16 100644 --- a/viewer/src/store/useSettingsStore.ts +++ b/viewer/src/store/useSettingsStore.ts @@ -1,11 +1,23 @@ import { create } from "zustand"; import { persist } from "zustand/middleware"; -export const useSettingsStore = create()( + +interface SettingsState { + projectId: string; + channelId: string; + theme: "light" | "dark" | "system"; + setProjectId: (projectId: string) => void; + setChannelId: (channelId: string) => void; + setTheme: (theme: "light" | "dark" | "system") => void; +} + +export const useSettingsStore = create()( persist( (set) => ({ - projectId: "1", // 기본 프로젝트 ID를 1로 설정 + projectId: "1", // 기본 프로젝트 ID + channelId: "4", // 기본 채널 ID theme: "system", setProjectId: (projectId) => set({ projectId }), + setChannelId: (channelId) => set({ channelId }), setTheme: (theme) => set({ theme }), }), { @@ -13,3 +25,4 @@ export const useSettingsStore = create()( }, ), ); + diff --git a/viewer/tsconfig.json b/viewer/tsconfig.json index c955ba6..bf9832c 100644 --- a/viewer/tsconfig.json +++ b/viewer/tsconfig.json @@ -8,6 +8,7 @@ /* Bundler mode */ "moduleResolution": "bundler", + "allowJs": false, "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, @@ -25,5 +26,5 @@ "@/*": ["./src/*"] } }, - "include": ["src"] + "include": ["src", "effort_js/src/services/error.js", "effort_js/src/services/feedback.js", "effort_js/src/services/issue.js", "effort_js/src/services/project.js"] } diff --git a/viewer/vite.config.ts b/viewer/vite.config.ts index 10a133b..8efd243 100644 --- a/viewer/vite.config.ts +++ b/viewer/vite.config.ts @@ -18,6 +18,7 @@ export default defineConfig(({ mode }) => { alias: { "@": path.resolve(__dirname, "./src"), }, + extensions: [".ts", ".tsx", ".mjs", ".mts", ".json"], }, server: { proxy: {