From 9277c93ddc2cd0533a629d1bcf0dcfd9ab586b00 Mon Sep 17 00:00:00 2001 From: DDD1542 Date: Sun, 29 Mar 2026 16:57:32 +0900 Subject: [PATCH] [agent-pipeline] pipe-20260329072859-n5mz round-1 --- .../app/(main)/admin/approvalBox/page.tsx | 8 +- .../(main)/admin/approvalTemplate/page.tsx | 8 +- frontend/app/(main)/admin/audit-log/page.tsx | 2 +- .../tabs/HierarchyTab.tsx | 62 +++---- frontend/app/(main)/admin/debug/page.tsx | 10 +- frontend/app/(main)/admin/menu/page.tsx | 2 +- .../screenMng/dashboardList/[id]/page.tsx | 14 +- .../(main)/admin/systemMng/i18nList/page.tsx | 166 +++++++++--------- .../admin/systemMng/tableMngList/page.tsx | 2 +- .../admin/userMng/rolesList/[id]/page.tsx | 26 +-- .../(main)/admin/userMng/rolesList/page.tsx | 20 +-- .../admin/userMng/userAuthList/page.tsx | 2 +- frontend/app/(main)/main/page.tsx | 2 +- frontend/app/(main)/multilang/page.tsx | 80 ++++----- frontend/app/(main)/page.tsx | 2 +- .../app/(main)/screen/[screenCode]/page.tsx | 4 +- .../app/(main)/screens/[screenId]/page.tsx | 2 +- .../app/(pop)/pop/screens/[screenId]/page.tsx | 4 +- frontend/components/admin/CompanySwitcher.tsx | 22 +-- frontend/components/admin/LangKeyModal.tsx | 6 +- frontend/components/admin/RoleDeleteModal.tsx | 14 +- frontend/components/admin/RoleFormModal.tsx | 24 +-- .../components/admin/UserAuthEditModal.tsx | 22 +-- frontend/components/admin/UserAuthTable.tsx | 26 +-- .../components/admin/UserHistoryModal.tsx | 18 +- frontend/components/admin/UserTable.tsx | 20 +-- .../admin/department/DepartmentMembers.tsx | 6 +- .../admin/multilang/KeyGenerateModal.tsx | 23 ++- .../approval/ApprovalRequestModal.tsx | 44 +++-- frontend/components/auth/LoginForm.tsx | 8 +- frontend/components/common/ScreenModal.tsx | 4 +- .../dashboard/widgets/MapTestWidgetV2.tsx | 6 +- .../widgets/VehicleMapOnlyWidget.tsx | 4 +- .../components/dataflow/DataFlowDesigner.tsx | 8 +- frontend/components/layout/AdminButton.tsx | 14 +- frontend/components/layout/AppLayout.tsx | 56 +++--- frontend/components/layout/ProfileModal.tsx | 2 +- frontend/components/layout/UserDropdown.tsx | 16 +- .../components/multilang/LangKeyModal.tsx | 104 +++++------ .../pop/management/PopDeployModal.tsx | 22 +-- .../pop/management/PopScreenPreview.tsx | 6 +- .../pop/management/PopScreenSettingModal.tsx | 14 +- .../components/screen/CreateScreenModal.tsx | 2 +- .../screen/InteractiveScreenViewer.tsx | 16 +- .../screen/InteractiveScreenViewerDynamic.tsx | 10 +- .../screen/OptimizedButtonComponent.tsx | 4 +- .../components/screen/ScreenDesigner_old.tsx | 30 ++-- .../components/screen/ScreenGroupModal.tsx | 2 +- .../components/screen/ScreenGroupTreeView.tsx | 82 ++++----- .../components/screen/ScreenRelationFlow.tsx | 100 +++++------ .../components/screen/TableSettingModal.tsx | 8 +- .../config-panels/ButtonConfigPanel-fixed.tsx | 4 +- .../config-panels/button-config/ActionTab.tsx | 80 ++++----- .../v2/config-panels/V2ButtonConfigPanel.tsx | 12 +- .../V2ItemRoutingConfigPanel.tsx | 12 +- frontend/components/vehicle/VehicleReport.tsx | 4 +- frontend/contexts/MenuContext.tsx | 6 +- frontend/hooks/useAuth.ts | 42 ++--- frontend/hooks/useLogin.ts | 6 +- frontend/hooks/useMenu.ts | 2 +- frontend/hooks/useProfile.ts | 6 +- frontend/hooks/useScreenDataTransfer.ts | 6 +- frontend/lib/api/auditLog.ts | 8 +- frontend/lib/api/file.ts | 4 +- frontend/lib/api/globalFile.ts | 4 +- frontend/lib/api/multiTableExcel.ts | 2 +- frontend/lib/api/multilang.ts | 4 +- frontend/lib/api/screen.ts | 4 +- frontend/lib/api/vehicleTrip.ts | 4 +- frontend/lib/authLogger.ts | 2 +- .../ConditionalSectionViewer.tsx | 4 +- .../MailRecipientSelectorComponent.tsx | 18 +- .../mail-recipient-selector/types.ts | 6 +- .../RelatedDataButtonsConfigPanel.tsx | 12 +- .../ScreenSplitPanelConfigPanel.tsx | 24 +-- .../SplitPanelLayoutConfigPanel.tsx | 14 +- .../ActionButtonConfigModal.tsx | 6 +- .../SplitPanelLayout2ConfigPanel.tsx | 31 ++-- .../v2-file-upload/FileUploadComponent.tsx | 2 +- .../ItemRoutingConfigPanel.tsx | 90 +++++----- .../PopWorkDetailComponent.tsx | 6 +- frontend/lib/services/enhancedFormService.ts | 4 +- frontend/lib/utils/buttonActions.ts | 2 +- frontend/types/auth.ts | 2 +- frontend/types/userHistory.ts | 22 +-- frontend/types/v2-form.ts | 6 +- 86 files changed, 805 insertions(+), 815 deletions(-) diff --git a/frontend/app/(main)/admin/approvalBox/page.tsx b/frontend/app/(main)/admin/approvalBox/page.tsx index 33834a96..163d6ba3 100644 --- a/frontend/app/(main)/admin/approvalBox/page.tsx +++ b/frontend/app/(main)/admin/approvalBox/page.tsx @@ -722,10 +722,10 @@ function ProxyTab() { const data = res?.data || res || []; const rawUsers: any[] = Array.isArray(data) ? data : []; const users: UserSearchResult[] = rawUsers.map((u: any) => ({ - userId: u.userId || u.user_id || "", - userName: u.userName || u.user_name || "", - positionName: u.positionName || u.position_name || "", - deptName: u.deptName || u.dept_name || "", + userId: u.user_id || "", + userName: u.user_name || "", + positionName: u.position_name || "", + deptName: u.dept_name || "", })); setResults(users); } catch { diff --git a/frontend/app/(main)/admin/approvalTemplate/page.tsx b/frontend/app/(main)/admin/approvalTemplate/page.tsx index a69d198e..43d38629 100644 --- a/frontend/app/(main)/admin/approvalTemplate/page.tsx +++ b/frontend/app/(main)/admin/approvalTemplate/page.tsx @@ -163,8 +163,8 @@ function UserSearchInput({ ); const selectUser = (user: any) => { - const userId = user.user_id || user.userId || ""; - const userName = user.user_name || user.userName || userId; + const userId = user.user_id || ""; + const userName = user.user_name || userId; onSelect(userId, userName); setSearchText(""); setShowResults(false); @@ -196,8 +196,8 @@ function UserSearchInput({ className="flex w-full items-center gap-2 px-3 py-1.5 text-left text-xs hover:bg-accent" onClick={() => selectUser(user)} > - {user.user_name || user.userName} - ({user.user_id || user.userId}) + {user.user_name} + ({user.user_id}) ))} diff --git a/frontend/app/(main)/admin/audit-log/page.tsx b/frontend/app/(main)/admin/audit-log/page.tsx index 747d4640..9805c0cf 100644 --- a/frontend/app/(main)/admin/audit-log/page.tsx +++ b/frontend/app/(main)/admin/audit-log/page.tsx @@ -291,7 +291,7 @@ function groupByDate(entries: AuditLogEntry[]): Map { export default function AuditLogPage() { const { user } = useAuth(); - const isSuperAdmin = user?.companyCode === "*" || user?.company_code === "*"; + const isSuperAdmin = user?.company_code === "*"; const [entries, setEntries] = useState([]); const [total, setTotal] = useState(0); diff --git a/frontend/app/(main)/admin/cascading-management/tabs/HierarchyTab.tsx b/frontend/app/(main)/admin/cascading-management/tabs/HierarchyTab.tsx index ebc0342b..2f7cca19 100644 --- a/frontend/app/(main)/admin/cascading-management/tabs/HierarchyTab.tsx +++ b/frontend/app/(main)/admin/cascading-management/tabs/HierarchyTab.tsx @@ -102,38 +102,38 @@ export default function HierarchyTab() { // snake_case를 camelCase로 변환하는 함수 const transformGroup = (g: any): HierarchyGroup => ({ - groupId: g.group_id || g.groupId, - groupCode: g.group_code || g.groupCode, - groupName: g.group_name || g.groupName, + groupId: g.group_id, + groupCode: g.group_code, + groupName: g.group_name, description: g.description, - hierarchyType: g.hierarchy_type || g.hierarchyType, - maxLevels: g.max_levels || g.maxLevels, - isFixedLevels: g.is_fixed_levels || g.isFixedLevels, - selfRefTable: g.self_ref_table || g.selfRefTable, - selfRefIdColumn: g.self_ref_id_column || g.selfRefIdColumn, - selfRefParentColumn: g.self_ref_parent_column || g.selfRefParentColumn, - selfRefValueColumn: g.self_ref_value_column || g.selfRefValueColumn, - selfRefLabelColumn: g.self_ref_label_column || g.selfRefLabelColumn, - selfRefLevelColumn: g.self_ref_level_column || g.selfRefLevelColumn, - selfRefOrderColumn: g.self_ref_order_column || g.selfRefOrderColumn, - bomTable: g.bom_table || g.bomTable, - bomParentColumn: g.bom_parent_column || g.bomParentColumn, - bomChildColumn: g.bom_child_column || g.bomChildColumn, - bomItemTable: g.bom_item_table || g.bomItemTable, - bomItemIdColumn: g.bom_item_id_column || g.bomItemIdColumn, - bomItemLabelColumn: g.bom_item_label_column || g.bomItemLabelColumn, - bomQtyColumn: g.bom_qty_column || g.bomQtyColumn, - bomLevelColumn: g.bom_level_column || g.bomLevelColumn, - emptyMessage: g.empty_message || g.emptyMessage, - noOptionsMessage: g.no_options_message || g.noOptionsMessage, - loadingMessage: g.loading_message || g.loadingMessage, - companyCode: g.company_code || g.companyCode, - isActive: g.is_active || g.isActive, - createdBy: g.created_by || g.createdBy, - createdDate: g.created_date || g.createdDate, - updatedBy: g.updated_by || g.updatedBy, - updatedDate: g.updated_date || g.updatedDate, - levelCount: g.level_count || g.levelCount || 0, + hierarchyType: g.hierarchy_type, + maxLevels: g.max_levels, + isFixedLevels: g.is_fixed_levels, + selfRefTable: g.self_ref_table, + selfRefIdColumn: g.self_ref_id_column, + selfRefParentColumn: g.self_ref_parent_column, + selfRefValueColumn: g.self_ref_value_column, + selfRefLabelColumn: g.self_ref_label_column, + selfRefLevelColumn: g.self_ref_level_column, + selfRefOrderColumn: g.self_ref_order_column, + bomTable: g.bom_table, + bomParentColumn: g.bom_parent_column, + bomChildColumn: g.bom_child_column, + bomItemTable: g.bom_item_table, + bomItemIdColumn: g.bom_item_id_column, + bomItemLabelColumn: g.bom_item_label_column, + bomQtyColumn: g.bom_qty_column, + bomLevelColumn: g.bom_level_column, + emptyMessage: g.empty_message, + noOptionsMessage: g.no_options_message, + loadingMessage: g.loading_message, + companyCode: g.company_code, + isActive: g.is_active, + createdBy: g.created_by, + createdDate: g.created_date, + updatedBy: g.updated_by, + updatedDate: g.updated_date, + levelCount: g.level_count || 0, levels: g.levels, }); diff --git a/frontend/app/(main)/admin/debug/page.tsx b/frontend/app/(main)/admin/debug/page.tsx index 4e3646b4..e4b5b77a 100644 --- a/frontend/app/(main)/admin/debug/page.tsx +++ b/frontend/app/(main)/admin/debug/page.tsx @@ -26,11 +26,11 @@ export default function AdminDebugPage() { {user && (

사용자 정보

-

ID: {user.userId}

-

이름: {user.userName}

-

타입: {user.userType}

-

부서: {user.deptName}

-

회사: {user.companyCode}

+

ID: {user.user_id}

+

이름: {user.user_name}

+

타입: {user.user_type}

+

부서: {user.dept_name}

+

회사: {user.company_code}

)} diff --git a/frontend/app/(main)/admin/menu/page.tsx b/frontend/app/(main)/admin/menu/page.tsx index acc1a287..ce333133 100644 --- a/frontend/app/(main)/admin/menu/page.tsx +++ b/frontend/app/(main)/admin/menu/page.tsx @@ -53,7 +53,7 @@ export default function MenuPage() { const { userLang } = useMultiLang({ companyCode: "*" }); // SUPER_ADMIN 여부 확인 - const isSuperAdmin = user?.userType === "SUPER_ADMIN"; + const isSuperAdmin = user?.user_type === "SUPER_ADMIN"; // 다국어 텍스트 상태 const [uiTexts, setUiTexts] = useState>({}); diff --git a/frontend/app/(main)/admin/screenMng/dashboardList/[id]/page.tsx b/frontend/app/(main)/admin/screenMng/dashboardList/[id]/page.tsx index aa6edc2c..d87786b4 100644 --- a/frontend/app/(main)/admin/screenMng/dashboardList/[id]/page.tsx +++ b/frontend/app/(main)/admin/screenMng/dashboardList/[id]/page.tsx @@ -525,15 +525,15 @@ export default function DashboardDesignerPage({ params }: { params: Promise<{ id const menu = menuResponse.data; const updateData = { - menuUrl: dashboardUrl, - parentObjId: menu.parent_obj_id ?? menu.PARENT_OBJ_ID ?? "0", - menuNameKor: menu.menu_name_kor ?? menu.MENU_NAME_KOR ?? "", - menuDesc: menu.menu_desc ?? menu.MENU_DESC ?? "", + menu_url: dashboardUrl, + parent_obj_id: menu.parent_obj_id ?? menu.PARENT_OBJ_ID ?? "0", + menu_name_kor: menu.menu_name_kor ?? menu.MENU_NAME_KOR ?? "", + menu_desc: menu.menu_desc ?? menu.MENU_DESC ?? "", seq: menu.seq ?? menu.SEQ ?? 1, - menuType: menu.menu_type ?? menu.MENU_TYPE ?? "1", + menu_type: menu.menu_type ?? menu.MENU_TYPE ?? "1", status: menu.status ?? menu.STATUS ?? "active", - companyCode: menu.company_code ?? menu.COMPANY_CODE ?? "", - langKey: menu.lang_key ?? menu.LANG_KEY ?? "", + company_code: menu.company_code ?? menu.COMPANY_CODE ?? "", + lang_key: menu.lang_key ?? menu.LANG_KEY ?? "", }; // 메뉴 URL 업데이트 diff --git a/frontend/app/(main)/admin/systemMng/i18nList/page.tsx b/frontend/app/(main)/admin/systemMng/i18nList/page.tsx index 0ce088fb..1fcc0957 100644 --- a/frontend/app/(main)/admin/systemMng/i18nList/page.tsx +++ b/frontend/app/(main)/admin/systemMng/i18nList/page.tsx @@ -22,28 +22,28 @@ import { apiClient } from "@/lib/api/client"; import { LangCategory } from "@/lib/api/multilang"; interface Language { - langCode: string; - langName: string; - langNative: string; - isActive: string; + lang_code: string; + lang_name: string; + lang_native: string; + is_active: string; } interface LangKey { - keyId: number; - companyCode: string; - menuName: string; - langKey: string; + key_id: number; + company_code: string; + menu_name: string; + lang_key: string; description: string; - isActive: string; - categoryId?: number; + is_active: string; + category_id?: number; } interface LangText { - textId: number; - keyId: number; - langCode: string; - langText: string; - isActive: string; + text_id: number; + key_id: number; + lang_code: string; + lang_text: string; + is_active: string; } export default function I18nPage() { @@ -126,17 +126,17 @@ export default function I18nPage() { // 회사 필터링 if (selectedCompany && selectedCompany !== "all") { - filteredKeys = filteredKeys.filter((key) => key.companyCode === selectedCompany); + filteredKeys = filteredKeys.filter((key) => key.company_code === selectedCompany); } // 텍스트 검색 필터링 if (searchText.trim()) { const searchLower = searchText.toLowerCase(); filteredKeys = filteredKeys.filter((key) => { - const langKey = (key.langKey || "").toLowerCase(); + const langKey = (key.lang_key || "").toLowerCase(); const description = (key.description || "").toLowerCase(); - const menuName = (key.menuName || "").toLowerCase(); - const companyName = companies.find((c) => c.code === key.companyCode)?.name?.toLowerCase() || ""; + const menuName = (key.menu_name || "").toLowerCase(); + const companyName = companies.find((c) => c.code === key.company_code)?.name?.toLowerCase() || ""; return ( langKey.includes(searchLower) || @@ -168,23 +168,23 @@ export default function I18nPage() { // 언어 키 선택 처리 const handleKeySelect = (key: LangKey) => { setSelectedKey(key); - fetchLangTexts(key.keyId); + fetchLangTexts(key.key_id); }; // 텍스트 변경 처리 const handleTextChange = (langCode: string, value: string) => { const newEditingTexts = [...editingTexts]; - const existingIndex = newEditingTexts.findIndex((t) => t.langCode === langCode); + const existingIndex = newEditingTexts.findIndex((t) => t.lang_code === langCode); if (existingIndex >= 0) { - newEditingTexts[existingIndex].langText = value; + newEditingTexts[existingIndex].lang_text = value; } else { newEditingTexts.push({ - textId: 0, - keyId: selectedKey!.keyId, - langCode: langCode, - langText: value, - isActive: "Y", + text_id: 0, + key_id: selectedKey!.key_id, + lang_code: langCode, + lang_text: value, + is_active: "Y", }); } @@ -198,19 +198,19 @@ export default function I18nPage() { try { const requestData = { texts: editingTexts.map((text) => ({ - langCode: text.langCode, - langText: text.langText, - isActive: text.isActive || "Y", - createdBy: user?.userId || "system", - updatedBy: user?.userId || "system", + lang_code: text.lang_code, + lang_text: text.lang_text, + is_active: text.is_active || "Y", + createdBy: user?.user_id || "system", + updatedBy: user?.user_id || "system", })), }; - const response = await apiClient.post(`/multilang/keys/${selectedKey.keyId}/texts`, requestData); + const response = await apiClient.post(`/multilang/keys/${selectedKey.key_id}/texts`, requestData); const data = response.data; if (data.success) { alert("저장되었습니다."); - fetchLangTexts(selectedKey.keyId); + fetchLangTexts(selectedKey.key_id); } } catch (error) { alert("저장에 실패했습니다."); @@ -240,13 +240,13 @@ export default function I18nPage() { try { const requestData = { ...languageData, - createdBy: user?.userId || "admin", - updatedBy: user?.userId || "admin", + createdBy: user?.user_id || "admin", + updatedBy: user?.user_id || "admin", }; let response; if (editingLanguage) { - response = await apiClient.put(`/multilang/languages/${editingLanguage.langCode}`, requestData); + response = await apiClient.put(`/multilang/languages/${editingLanguage.lang_code}`, requestData); } else { response = await apiClient.post("/multilang/languages", requestData); } @@ -314,7 +314,7 @@ export default function I18nPage() { // 언어 전체 선택/해제 const handleSelectAllLanguages = (checked: boolean) => { if (checked) { - setSelectedLanguages(new Set(languages.map((lang) => lang.langCode))); + setSelectedLanguages(new Set(languages.map((lang) => lang.lang_code))); } else { setSelectedLanguages(new Set()); } @@ -331,13 +331,13 @@ export default function I18nPage() { try { const requestData = { ...keyData, - createdBy: user?.userId || "admin", - updatedBy: user?.userId || "admin", + createdBy: user?.user_id || "admin", + updatedBy: user?.user_id || "admin", }; let response; if (editingKey) { - response = await apiClient.put(`/multilang/keys/${editingKey.keyId}`, requestData); + response = await apiClient.put(`/multilang/keys/${editingKey.key_id}`, requestData); } else { response = await apiClient.post("/multilang/keys", requestData); } @@ -406,7 +406,7 @@ export default function I18nPage() { // 전체 선택/해제 const handleSelectAll = (checked: boolean) => { if (checked) { - const allKeyIds = getFilteredLangKeys().map((key) => key.keyId); + const allKeyIds = getFilteredLangKeys().map((key) => key.key_id); setSelectedKeys(new Set(allKeyIds)); } else { setSelectedKeys(new Set()); @@ -439,7 +439,7 @@ export default function I18nPage() { setSelectedKeys(new Set()); fetchLangKeys(); - if (selectedKey && selectedKeys.has(selectedKey.keyId)) { + if (selectedKey && selectedKeys.has(selectedKey.key_id)) { handleCancel(); } } else { @@ -462,7 +462,7 @@ export default function I18nPage() { if (data.success) { alert("언어 키가 영구적으로 삭제되었습니다."); fetchLangKeys(); - if (selectedKey && selectedKey.keyId === keyId) { + if (selectedKey && selectedKey.key_id === keyId) { handleCancel(); } } @@ -511,44 +511,44 @@ export default function I18nPage() { cell: ({ row }: any) => ( handleCheckboxChange(row.original.keyId, e.target.checked)} + checked={selectedKeys.has(row.original.key_id)} + onChange={(e) => handleCheckboxChange(row.original.key_id, e.target.checked)} onClick={(e) => e.stopPropagation()} className="h-4 w-4" - disabled={row.original.isActive === "N"} + disabled={row.original.is_active === "N"} /> ), }, { - accessorKey: "companyCode", + accessorKey: "company_code", header: "회사", cell: ({ row }: any) => { const companyName = - row.original.companyCode === "*" + row.original.company_code === "*" ? "공통" - : companies.find((c) => c.code === row.original.companyCode)?.name || row.original.companyCode; + : companies.find((c) => c.code === row.original.company_code)?.name || row.original.company_code; - return {companyName}; + return {companyName}; }, }, { - accessorKey: "menuName", + accessorKey: "menu_name", header: "메뉴명", cell: ({ row }: any) => ( - {row.original.menuName} + {row.original.menu_name} ), }, { - accessorKey: "langKey", + accessorKey: "lang_key", header: "언어 키", cell: ({ row }: any) => (
handleEditKey(row.original)} > - {row.original.langKey} + {row.original.lang_key}
), }, @@ -556,22 +556,22 @@ export default function I18nPage() { accessorKey: "description", header: "설명", cell: ({ row }: any) => ( - {row.original.description} + {row.original.description} ), }, { - accessorKey: "isActive", + accessorKey: "is_active", header: "상태", cell: ({ row }: any) => ( ), }, @@ -592,55 +592,55 @@ export default function I18nPage() { cell: ({ row }: any) => ( handleLanguageCheckboxChange(row.original.langCode, e.target.checked)} + checked={selectedLanguages.has(row.original.lang_code)} + onChange={(e) => handleLanguageCheckboxChange(row.original.lang_code, e.target.checked)} onClick={(e) => e.stopPropagation()} className="h-4 w-4" - disabled={row.original.isActive === "N"} + disabled={row.original.is_active === "N"} /> ), }, { - accessorKey: "langCode", + accessorKey: "lang_code", header: "언어 코드", cell: ({ row }: any) => (
handleEditLanguage(row.original)} > - {row.original.langCode} + {row.original.lang_code}
), }, { - accessorKey: "langName", + accessorKey: "lang_name", header: "언어명 (영문)", cell: ({ row }: any) => ( - {row.original.langName} + {row.original.lang_name} ), }, { - accessorKey: "langNative", + accessorKey: "lang_native", header: "언어명 (원어)", cell: ({ row }: any) => ( - {row.original.langNative} + {row.original.lang_native} ), }, { - accessorKey: "isActive", + accessorKey: "is_active", header: "상태", cell: ({ row }: any) => ( ), }, @@ -813,7 +813,7 @@ export default function I18nPage() { <> 선택된 키:{" "} - {selectedKey.companyCode}.{selectedKey.menuName}.{selectedKey.langKey} + {selectedKey.company_code}.{selectedKey.menu_name}.{selectedKey.lang_key} ) : ( @@ -827,18 +827,18 @@ export default function I18nPage() { {/* 스크롤 가능한 텍스트 영역 */}
{languages - .filter((lang) => lang.isActive === "Y") + .filter((lang) => lang.is_active === "Y") .map((lang) => { - const text = editingTexts.find((t) => t.langCode === lang.langCode); + const text = editingTexts.find((t) => t.lang_code === lang.lang_code); return ( -
+
- {lang.langName} + {lang.lang_name} handleTextChange(lang.langCode, e.target.value)} + placeholder={`${lang.lang_name} 텍스트 입력`} + value={text?.lang_text || ""} + onChange={(e) => handleTextChange(lang.lang_code, e.target.value)} className="flex-1" />
diff --git a/frontend/app/(main)/admin/systemMng/tableMngList/page.tsx b/frontend/app/(main)/admin/systemMng/tableMngList/page.tsx index 8803504a..71423ffb 100644 --- a/frontend/app/(main)/admin/systemMng/tableMngList/page.tsx +++ b/frontend/app/(main)/admin/systemMng/tableMngList/page.tsx @@ -132,7 +132,7 @@ export default function TableManagementPage() { const [typeFilter, setTypeFilter] = useState(null); // 최고 관리자 여부 확인 (회사코드가 "*" AND userType이 "SUPER_ADMIN") - const isSuperAdmin = user?.companyCode === "*" && user?.userType === "SUPER_ADMIN"; + const isSuperAdmin = user?.company_code === "*" && user?.user_type === "SUPER_ADMIN"; // 다국어 텍스트 로드 useEffect(() => { diff --git a/frontend/app/(main)/admin/userMng/rolesList/[id]/page.tsx b/frontend/app/(main)/admin/userMng/rolesList/[id]/page.tsx index 4609312c..586707c6 100644 --- a/frontend/app/(main)/admin/userMng/rolesList/[id]/page.tsx +++ b/frontend/app/(main)/admin/userMng/rolesList/[id]/page.tsx @@ -27,7 +27,7 @@ export default function RoleDetailPage({ params }: { params: Promise<{ id: strin const router = useRouter(); const { refreshMenus } = useMenu(); - const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN"; + const isSuperAdmin = currentUser?.company_code === "*" && currentUser?.user_type === "SUPER_ADMIN"; // 상태 관리 const [roleGroup, setRoleGroup] = useState(null); @@ -77,9 +77,9 @@ export default function RoleDetailPage({ params }: { params: Promise<{ id: strin if (membersResponse.success && membersResponse.data) { setSelectedUsers( membersResponse.data.map((member: any) => ({ - id: member.userId, - label: member.userName || member.userId, - description: member.deptName, + id: member.user_id, + label: member.user_name || member.user_id, + description: member.dept_name, })), ); } @@ -88,12 +88,12 @@ export default function RoleDetailPage({ params }: { params: Promise<{ id: strin const userAPI = await import("@/lib/api/user"); console.log("🔍 사용자 목록 조회 요청:", { - companyCode: roleGroup.companyCode, + companyCode: roleGroup.company_code, size: 1000, }); const usersResponse = await userAPI.userAPI.getList({ - companyCode: roleGroup.companyCode, + companyCode: roleGroup.company_code, size: 1000, // 대량 조회 }); @@ -106,9 +106,9 @@ export default function RoleDetailPage({ params }: { params: Promise<{ id: strin if (usersResponse.success && usersResponse.data) { setAvailableUsers( usersResponse.data.map((user: any) => ({ - id: user.userId, - label: user.userName || user.userId, - description: user.deptName, + id: user.user_id, + label: user.user_name || user.user_id, + description: user.dept_name, })), ); console.log("📋 설정된 전체 사용자 수:", usersResponse.data.length); @@ -124,8 +124,8 @@ export default function RoleDetailPage({ params }: { params: Promise<{ id: strin console.log("🔍 [loadMenuPermissions] 메뉴 권한 로드 시작", { roleGroupId: roleGroup.objid, - roleGroupName: roleGroup.authName, - companyCode: roleGroup.companyCode, + roleGroupName: roleGroup.auth_name, + companyCode: roleGroup.company_code, }); try { @@ -252,9 +252,9 @@ export default function RoleDetailPage({ params }: { params: Promise<{ id: strin
-

{roleGroup.authName}

+

{roleGroup.auth_name}

- {roleGroup.authCode} • {roleGroup.companyCode} + {roleGroup.auth_code} • {roleGroup.company_code}

([]); @@ -81,7 +81,7 @@ export default function RolesPage() { ? selectedCompany : isSuperAdmin ? undefined - : currentUser?.companyCode; + : currentUser?.company_code; console.log("권한 그룹 목록 조회:", { isSuperAdmin, selectedCompany, companyFilter }); @@ -101,7 +101,7 @@ export default function RolesPage() { } finally { setIsLoading(false); } - }, [isSuperAdmin, selectedCompany, currentUser?.companyCode]); + }, [isSuperAdmin, selectedCompany, currentUser?.company_code]); useEffect(() => { if (isAdmin) { @@ -268,8 +268,8 @@ export default function RolesPage() { >
-

{role.authName}

-

{role.authCode}

+

{role.auth_name}

+

{role.auth_code}

회사 - {companies.find((c) => c.company_code === role.companyCode)?.company_name || role.companyCode} + {companies.find((c) => c.company_code === role.company_code)?.company_name || role.company_code}
)} @@ -296,14 +296,14 @@ export default function RolesPage() { 멤버 수
- {role.memberCount || 0}명 + {role.member_count || 0}명
메뉴 권한 - {role.menuCount || 0}개 + {role.menu_count || 0}개
diff --git a/frontend/app/(main)/admin/userMng/userAuthList/page.tsx b/frontend/app/(main)/admin/userMng/userAuthList/page.tsx index 4ad69183..cee2ca53 100644 --- a/frontend/app/(main)/admin/userMng/userAuthList/page.tsx +++ b/frontend/app/(main)/admin/userMng/userAuthList/page.tsx @@ -20,7 +20,7 @@ export default function UserAuthPage() { const { user: currentUser } = useAuth(); // 최고 관리자 여부 - const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN"; + const isSuperAdmin = currentUser?.company_code === "*" && currentUser?.user_type === "SUPER_ADMIN"; // 상태 관리 const [users, setUsers] = useState([]); diff --git a/frontend/app/(main)/main/page.tsx b/frontend/app/(main)/main/page.tsx index 615aaf70..c1290093 100644 --- a/frontend/app/(main)/main/page.tsx +++ b/frontend/app/(main)/main/page.tsx @@ -17,7 +17,7 @@ export default function MainPage() { const router = useRouter(); const { user } = useAuth(); - const userName = user?.userName || "사용자"; + const userName = user?.user_name || "사용자"; const today = new Date(); const dateStr = today.toLocaleDateString("ko-KR", { year: "numeric", month: "long", day: "numeric", weekday: "long" }); diff --git a/frontend/app/(main)/multilang/page.tsx b/frontend/app/(main)/multilang/page.tsx index 93fbc1b0..244d79fb 100644 --- a/frontend/app/(main)/multilang/page.tsx +++ b/frontend/app/(main)/multilang/page.tsx @@ -14,28 +14,28 @@ import { useAuth } from "@/hooks/useAuth"; import { apiClient } from "@/lib/api/client"; interface Language { - langCode: string; - langName: string; - langNative: string; - isActive: string; + lang_code: string; + lang_name: string; + lang_native: string; + is_active: string; } interface LangKey { - keyId: number; - companyCode: string; - menuCode: string; - langKey: string; - keyType: string; + key_id: number; + company_code: string; + menu_code: string; + lang_key: string; + key_type: string; description: string; - isActive: string; + is_active: string; } interface LangText { - textId: number; - keyId: number; - langCode: string; - langText: string; - isActive: string; + text_id: number; + key_id: number; + lang_code: string; + lang_text: string; + is_active: string; } export default function MultiLangPage() { @@ -132,28 +132,28 @@ export default function MultiLangPage() { // 회사 필터링 if (selectedCompany) { - filteredKeys = filteredKeys.filter((key) => key.companyCode === selectedCompany); + filteredKeys = filteredKeys.filter((key) => key.company_code === selectedCompany); } // 메뉴 필터링 if (selectedMenu) { - filteredKeys = filteredKeys.filter((key) => key.menuCode === selectedMenu); + filteredKeys = filteredKeys.filter((key) => key.menu_code === selectedMenu); } // 키 타입 필터링 if (selectedKeyType) { - filteredKeys = filteredKeys.filter((key) => key.keyType === selectedKeyType); + filteredKeys = filteredKeys.filter((key) => key.key_type === selectedKeyType); } // 텍스트 검색 필터링 if (searchText.trim()) { const searchLower = searchText.toLowerCase(); filteredKeys = filteredKeys.filter((key) => { - const langKey = (key.langKey || "").toLowerCase(); + const langKey = (key.lang_key || "").toLowerCase(); const description = (key.description || "").toLowerCase(); - const companyName = companies.find((c) => c.code === key.companyCode)?.name?.toLowerCase() || ""; - const menuName = menus.find((m) => m.code === key.menuCode)?.name?.toLowerCase() || ""; - const keyTypeName = keyTypes.find((t) => t.code === key.keyType)?.name?.toLowerCase() || ""; + const companyName = companies.find((c) => c.code === key.company_code)?.name?.toLowerCase() || ""; + const menuName = menus.find((m) => m.code === key.menu_code)?.name?.toLowerCase() || ""; + const keyTypeName = keyTypes.find((t) => t.code === key.key_type)?.name?.toLowerCase() || ""; return ( langKey.includes(searchLower) || @@ -170,31 +170,31 @@ export default function MultiLangPage() { const columns = [ { - accessorKey: "companyCode", + accessorKey: "company_code", header: "회사", cell: ({ row }: any) => { - const company = companies.find((c) => c.code === row.original.companyCode); - return company ? company.name : row.original.companyCode; + const company = companies.find((c) => c.code === row.original.company_code); + return company ? company.name : row.original.company_code; }, }, { - accessorKey: "menuCode", + accessorKey: "menu_code", header: "메뉴", cell: ({ row }: any) => { - const menu = menus.find((m) => m.code === row.original.menuCode); - return menu ? menu.name : row.original.menuCode; + const menu = menus.find((m) => m.code === row.original.menu_code); + return menu ? menu.name : row.original.menu_code; }, }, { - accessorKey: "langKey", + accessorKey: "lang_key", header: "언어 키", }, { - accessorKey: "keyType", + accessorKey: "key_type", header: "타입", cell: ({ row }: any) => { - const type = keyTypes.find((t) => t.code === row.original.keyType); - return type ? type.name : row.original.keyType; + const type = keyTypes.find((t) => t.code === row.original.key_type); + return type ? type.name : row.original.key_type; }, }, { @@ -202,11 +202,11 @@ export default function MultiLangPage() { header: "설명", }, { - accessorKey: "isActive", + accessorKey: "is_active", header: "상태", cell: ({ row }: any) => ( - - {row.original.isActive === "Y" ? "활성" : "비활성"} + + {row.original.is_active === "Y" ? "활성" : "비활성"} ), }, @@ -415,11 +415,11 @@ export default function MultiLangPage() {
{languages.map((lang) => ( -
-
{lang.langName}
-
{lang.langNative}
- - {lang.isActive === "Y" ? "활성" : "비활성"} +
+
{lang.lang_name}
+
{lang.lang_native}
+ + {lang.is_active === "Y" ? "활성" : "비활성"}
))} diff --git a/frontend/app/(main)/page.tsx b/frontend/app/(main)/page.tsx index 292e4bbd..b7befe6a 100644 --- a/frontend/app/(main)/page.tsx +++ b/frontend/app/(main)/page.tsx @@ -17,7 +17,7 @@ export default function MainHomePage() { const router = useRouter(); const { user } = useAuth(); - const userName = user?.userName || "사용자"; + const userName = user?.user_name || "사용자"; const today = new Date(); const dateStr = today.toLocaleDateString("ko-KR", { year: "numeric", month: "long", day: "numeric", weekday: "long" }); diff --git a/frontend/app/(main)/screen/[screenCode]/page.tsx b/frontend/app/(main)/screen/[screenCode]/page.tsx index 64c1bb34..6739eb6e 100644 --- a/frontend/app/(main)/screen/[screenCode]/page.tsx +++ b/frontend/app/(main)/screen/[screenCode]/page.tsx @@ -30,10 +30,10 @@ export default function ScreenCodeRedirectPage() { }); const items = res.data?.data?.data || res.data?.data || []; const arr = Array.isArray(items) ? items : []; - const exact = arr.find((s: any) => s.screenCode === screenCode); + const exact = arr.find((s: any) => s.screen_code === screenCode); const target = exact || arr[0]; if (target) { - router.replace(`/screens/${target.screenId || target.screen_id}`); + router.replace(`/screens/${target.screen_id}`); } else { router.replace("/"); } diff --git a/frontend/app/(main)/screens/[screenId]/page.tsx b/frontend/app/(main)/screens/[screenId]/page.tsx index efcef2a4..01995692 100644 --- a/frontend/app/(main)/screens/[screenId]/page.tsx +++ b/frontend/app/(main)/screens/[screenId]/page.tsx @@ -582,7 +582,7 @@ function ScreenViewPage({ screenIdProp, menuObjidProp }: ScreenViewPageProps = { menuObjid, screenId, tableName: screen?.tableName, - userId: user?.userId, + userId: user?.user_id, userName, companyCode, selectedRowsData, diff --git a/frontend/app/(pop)/pop/screens/[screenId]/page.tsx b/frontend/app/(pop)/pop/screens/[screenId]/page.tsx index c7933033..5a0efa6d 100644 --- a/frontend/app/(pop)/pop/screens/[screenId]/page.tsx +++ b/frontend/app/(pop)/pop/screens/[screenId]/page.tsx @@ -218,7 +218,7 @@ function PopScreenViewPage() { 닫기 - {screen.screenName} + {screen.screen_name} ({currentModeKey.replace("_", " ")}) @@ -295,7 +295,7 @@ function PopScreenViewPage() { POP 대시보드 - {screen.screenName} + {screen.screen_name}
diff --git a/frontend/components/admin/LangKeyModal.tsx b/frontend/components/admin/LangKeyModal.tsx index 6801e873..46bbfbce 100644 --- a/frontend/components/admin/LangKeyModal.tsx +++ b/frontend/components/admin/LangKeyModal.tsx @@ -34,9 +34,9 @@ export default function LangKeyModal({ isOpen, onClose, onSave, keyData, compani if (keyData) { // 수정 모드 setFormData({ - companyCode: keyData.companyCode || "", - menuName: keyData.menuName || "", - langKey: keyData.langKey || "", + companyCode: keyData.company_code || "", + menuName: keyData.menu_name || "", + langKey: keyData.lang_key || "", description: keyData.description || "", }); } else { diff --git a/frontend/components/admin/RoleDeleteModal.tsx b/frontend/components/admin/RoleDeleteModal.tsx index 8f7c6d3b..b174c9af 100644 --- a/frontend/components/admin/RoleDeleteModal.tsx +++ b/frontend/components/admin/RoleDeleteModal.tsx @@ -88,8 +88,8 @@ export function RoleDeleteModal({ isOpen, onClose, onSuccess, role }: RoleDelete 이 작업은 되돌릴 수 없습니다. 권한 그룹을 삭제하면 다음 데이터도 함께 삭제됩니다:

    -
  • 연결된 모든 멤버 ({role.memberCount || 0}명)
  • -
  • 설정된 모든 메뉴 권한 ({role.menuCount || 0}개)
  • +
  • 연결된 모든 멤버 ({role.member_count || 0}명)
  • +
  • 설정된 모든 메뉴 권한 ({role.menu_count || 0}개)
@@ -100,20 +100,20 @@ export function RoleDeleteModal({ isOpen, onClose, onSuccess, role }: RoleDelete
권한 그룹명 - {role.authName} + {role.auth_name}
권한 코드 - {role.authCode} + {role.auth_code}
회사 - {role.companyCode} + {role.company_code}
- {role.memberNames && ( + {role.member_names && (
멤버: -

{role.memberNames}

+

{role.member_names}

)}
diff --git a/frontend/components/admin/RoleFormModal.tsx b/frontend/components/admin/RoleFormModal.tsx index b6e0fd0b..b92f84f6 100644 --- a/frontend/components/admin/RoleFormModal.tsx +++ b/frontend/components/admin/RoleFormModal.tsx @@ -43,13 +43,13 @@ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleF const isEditMode = !!editingRole; // 최고 관리자 여부 - const isSuperAdmin = currentUser?.companyCode === "*" && currentUser?.userType === "SUPER_ADMIN"; + const isSuperAdmin = currentUser?.company_code === "*" && currentUser?.user_type === "SUPER_ADMIN"; // 폼 데이터 const [formData, setFormData] = useState({ authName: "", authCode: "", - companyCode: currentUser?.companyCode || "", + companyCode: currentUser?.company_code || "", status: "active", }); @@ -106,9 +106,9 @@ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleF if (isEditMode && editingRole) { // 수정 모드: 기존 데이터 로드 setFormData({ - authName: editingRole.authName || "", - authCode: editingRole.authCode || "", - companyCode: editingRole.companyCode || "", + authName: editingRole.auth_name || "", + authCode: editingRole.auth_code || "", + companyCode: editingRole.company_code || "", status: editingRole.status || "active", }); } else { @@ -116,13 +116,13 @@ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleF setFormData({ authName: "", authCode: "", - companyCode: currentUser?.companyCode || "", + companyCode: currentUser?.company_code || "", status: "active", }); } setShowAlert(false); } - }, [isOpen, isEditMode, editingRole, currentUser?.companyCode, isSuperAdmin, loadCompanies]); + }, [isOpen, isEditMode, editingRole, currentUser?.company_code, isSuperAdmin, loadCompanies]); // 입력 핸들러 const handleInputChange = useCallback((field: string, value: string) => { @@ -143,16 +143,16 @@ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleF if (isEditMode && editingRole) { // 수정 response = await roleAPI.update(editingRole.objid, { - authName: formData.authName, - authCode: formData.authCode, + auth_name: formData.authName, + auth_code: formData.authCode, status: formData.status, }); } else { // 생성 response = await roleAPI.create({ - authName: formData.authName, - authCode: formData.authCode, - companyCode: formData.companyCode, + auth_name: formData.authName, + auth_code: formData.authCode, + company_code: formData.companyCode, }); } diff --git a/frontend/components/admin/UserAuthEditModal.tsx b/frontend/components/admin/UserAuthEditModal.tsx index 7ce04f4c..6cbbd836 100644 --- a/frontend/components/admin/UserAuthEditModal.tsx +++ b/frontend/components/admin/UserAuthEditModal.tsx @@ -35,7 +35,7 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth // 모달 열릴 때 현재 권한 설정 useEffect(() => { if (isOpen && user) { - setSelectedUserType(user.userType || "USER"); + setSelectedUserType(user.user_type || "USER"); setShowConfirmation(false); } }, [isOpen, user]); @@ -82,7 +82,7 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth const selectedOption = userTypeOptions.find((opt) => opt.value === selectedUserType); // 권한 변경 여부 확인 - const isUserTypeChanged = user && selectedUserType !== user.userType; + const isUserTypeChanged = user && selectedUserType !== user.user_type; // 권한 변경 처리 const handleSave = async () => { @@ -101,11 +101,11 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth try { const response = await userAPI.update({ - userId: user.userId, - userName: user.userName, - companyCode: user.companyCode, - deptCode: user.deptCode, - userType: selectedUserType, + user_id: user.user_id, + user_name: user.user_name, + company_code: user.company_code, + dept_code: user.dept_code, + user_type: selectedUserType, }); if (response.success) { @@ -136,20 +136,20 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth
사용자 ID - {user.userId} + {user.user_id}
사용자명 - {user.userName} + {user.user_name}
회사 - {user.companyName || user.companyCode} + {user.company_name || user.company_code}
현재 권한 - {userTypeOptions.find((opt) => opt.value === user.userType)?.label || user.userType} + {userTypeOptions.find((opt) => opt.value === user.user_type)?.label || user.user_type}
diff --git a/frontend/components/admin/UserAuthTable.tsx b/frontend/components/admin/UserAuthTable.tsx index 50e7d889..48d82536 100644 --- a/frontend/components/admin/UserAuthTable.tsx +++ b/frontend/components/admin/UserAuthTable.tsx @@ -82,32 +82,32 @@ export function UserAuthTable({ users, isLoading, paginationInfo, onEditAuth, on render: (_value, _row, index) => {getRowNumber(index)}, }, { - key: "userId", + key: "user_id", label: "사용자 ID", render: (value) => {value}, }, { - key: "userName", + key: "user_name", label: "사용자명", }, { - key: "companyName", + key: "company_name", label: "회사", hideOnMobile: true, - render: (_value, row) => {row.companyName || row.companyCode}, + render: (_value, row) => {row.company_name || row.company_code}, }, { - key: "deptName", + key: "dept_name", label: "부서", hideOnMobile: true, render: (value) => {value || "-"}, }, { - key: "userType", + key: "user_type", label: "현재 권한", className: "text-center", render: (_value, row) => { - const typeInfo = getUserTypeInfo(row.userType); + const typeInfo = getUserTypeInfo(row.user_type); return ( {typeInfo.icon} @@ -122,11 +122,11 @@ export function UserAuthTable({ users, isLoading, paginationInfo, onEditAuth, on const cardFields: RDVCardField[] = [ { label: "회사", - render: (user) => {user.companyName || user.companyCode}, + render: (user) => {user.company_name || user.company_code}, }, { label: "부서", - render: (user) => {user.deptName || "-"}, + render: (user) => {user.dept_name || "-"}, }, ]; @@ -135,14 +135,14 @@ export function UserAuthTable({ users, isLoading, paginationInfo, onEditAuth, on data={users} columns={columns} - keyExtractor={(u) => u.userId} + keyExtractor={(u) => u.user_id} isLoading={isLoading} emptyMessage="등록된 사용자가 없습니다." skeletonCount={10} - cardTitle={(u) => u.userName} - cardSubtitle={(u) => {u.userId}} + cardTitle={(u) => u.user_name} + cardSubtitle={(u) => {u.user_id}} cardHeaderRight={(u) => { - const typeInfo = getUserTypeInfo(u.userType); + const typeInfo = getUserTypeInfo(u.user_type); return ( {typeInfo.icon} diff --git a/frontend/components/admin/UserHistoryModal.tsx b/frontend/components/admin/UserHistoryModal.tsx index b6c3d804..d7686213 100644 --- a/frontend/components/admin/UserHistoryModal.tsx +++ b/frontend/components/admin/UserHistoryModal.tsx @@ -70,10 +70,10 @@ export function UserHistoryModal({ isOpen, onClose, userId, userName }: UserHist if (response && response.success && Array.isArray(response.data)) { const responseTotal = response.total || 0; - // No 컬럼을 rowNum 값으로 설정 (페이징 고려) + // No 컬럼을 row_num 값으로 설정 (페이징 고려) const mappedHistoryList = response.data.map((item, index) => ({ ...item, - no: item.rowNum || responseTotal - (pageToLoad - 1) * pageSize - index, // rowNum 우선, 없으면 계산 + no: item.row_num || responseTotal - (pageToLoad - 1) * pageSize - index, // row_num 우선, 없으면 계산 })); setHistoryList(mappedHistoryList); @@ -211,22 +211,22 @@ export function UserHistoryModal({ isOpen, onClose, userId, userName }: UserHist {history.no} {history.sabun || "-"} - {history.userId || "-"} - {history.userName || "-"} - {history.deptName || "-"} + {history.user_id || "-"} + {history.user_name || "-"} + {history.dept_name || "-"} {getStatusText(history.status || "")} - - {history.historyType || "-"} + + {history.history_type || "-"} - {history.writerName || "-"} + {history.writer_name || "-"} - {history.regDateTitle || formatDate(history.regDate || "")} + {history.reg_date_title || formatDate(history.reg_date || "")} )) diff --git a/frontend/components/admin/UserTable.tsx b/frontend/components/admin/UserTable.tsx index bfa8b176..6a663232 100644 --- a/frontend/components/admin/UserTable.tsx +++ b/frontend/components/admin/UserTable.tsx @@ -42,12 +42,12 @@ export function UserTable({ // 히스토리 모달 상태 관리 const [historyModal, setHistoryModal] = useState<{ isOpen: boolean; - userId: string; - userName: string; + user_id: string; + user_name: string; }>({ isOpen: false, - userId: "", - userName: "", + user_id: "", + user_name: "", }); // NO 컬럼 계산 함수 (페이지네이션 고려) @@ -88,8 +88,8 @@ export function UserTable({ const handleOpenHistoryModal = (user: User) => { setHistoryModal({ isOpen: true, - userId: user.user_id, - userName: user.user_name || user.user_id, + user_id: user.user_id, + user_name: user.user_name || user.user_id, }); }; @@ -97,8 +97,8 @@ export function UserTable({ const handleCloseHistoryModal = () => { setHistoryModal({ isOpen: false, - userId: "", - userName: "", + user_id: "", + user_name: "", }); }; @@ -300,8 +300,8 @@ export function UserTable({ ); diff --git a/frontend/components/admin/department/DepartmentMembers.tsx b/frontend/components/admin/department/DepartmentMembers.tsx index 5b164890..677fb010 100644 --- a/frontend/components/admin/department/DepartmentMembers.tsx +++ b/frontend/components/admin/department/DepartmentMembers.tsx @@ -43,7 +43,7 @@ export function DepartmentMembers({ // 부서원 삭제 확인 모달 const [removeConfirmOpen, setRemoveConfirmOpen] = useState(false); - const [memberToRemove, setMemberToRemove] = useState<{ userId: string; name: string } | null>(null); + const [memberToRemove, setMemberToRemove] = useState<{ user_id: string; name: string } | null>(null); // 부서원 목록 로드 useEffect(() => { @@ -144,7 +144,7 @@ export function DepartmentMembers({ // 부서원 제거 확인 요청 const handleRemoveMemberRequest = (userId: string, userName: string) => { - setMemberToRemove({ userId, name: userName }); + setMemberToRemove({ user_id: userId, name: userName }); setRemoveConfirmOpen(true); }; @@ -155,7 +155,7 @@ export function DepartmentMembers({ try { const response = await departmentAPI.removeDepartmentMember( selectedDepartment.dept_code, - memberToRemove.userId + memberToRemove.user_id ); if (response.success) { diff --git a/frontend/components/admin/multilang/KeyGenerateModal.tsx b/frontend/components/admin/multilang/KeyGenerateModal.tsx index 536915ef..5ca3f675 100644 --- a/frontend/components/admin/multilang/KeyGenerateModal.tsx +++ b/frontend/components/admin/multilang/KeyGenerateModal.tsx @@ -43,8 +43,8 @@ import { import { apiClient } from "@/lib/api/client"; interface Company { - companyCode: string; - companyName: string; + company_code: string; + company_name: string; } interface KeyGenerateModalProps { @@ -104,12 +104,11 @@ export function KeyGenerateModal({ try { const response = await apiClient.get("/admin/companies"); if (response.data.success && response.data.data) { - // snake_case를 camelCase로 변환하고 공통(*)은 제외 const companyList = response.data.data .filter((c: any) => c.company_code !== "*") .map((c: any) => ({ - companyCode: c.company_code, - companyName: c.company_name, + company_code: c.company_code, + company_name: c.company_name, })); setCompanies(companyList); } @@ -354,8 +353,8 @@ export function KeyGenerateModal({ > {targetCompanyCode === "*" ? "공통 (*) - 모든 회사 적용" - : companies.find((c) => c.companyCode === targetCompanyCode) - ? `${companies.find((c) => c.companyCode === targetCompanyCode)?.companyName} (${targetCompanyCode})` + : companies.find((c) => c.company_code === targetCompanyCode) + ? `${companies.find((c) => c.company_code === targetCompanyCode)?.company_name} (${targetCompanyCode})` : "대상 선택"} @@ -390,10 +389,10 @@ export function KeyGenerateModal({ {companies.map((company) => ( { - setTargetCompanyCode(company.companyCode); + setTargetCompanyCode(company.company_code); setCompanySearchOpen(false); }} className="text-xs sm:text-sm" @@ -401,10 +400,10 @@ export function KeyGenerateModal({ - {company.companyName} ({company.companyCode}) + {company.company_name} ({company.company_code}) ))} diff --git a/frontend/components/approval/ApprovalRequestModal.tsx b/frontend/components/approval/ApprovalRequestModal.tsx index 45c7ef86..878a2513 100644 --- a/frontend/components/approval/ApprovalRequestModal.tsx +++ b/frontend/components/approval/ApprovalRequestModal.tsx @@ -63,16 +63,12 @@ interface ApprovalRequestModalProps { } interface UserSearchResult { - userId: string; - userName: string; - positionName?: string; - deptName?: string; - deptCode?: string; - email?: string; - user_id?: string; - user_name?: string; + user_id: string; + user_name: string; position_name?: string; dept_name?: string; + dept_code?: string; + email?: string; } function genId(): string { @@ -136,14 +132,14 @@ export const ApprovalRequestModal: React.FC = ({ const data = res?.data || res || []; const rawUsers: any[] = Array.isArray(data) ? data : []; const users: UserSearchResult[] = rawUsers.map((u: any) => ({ - userId: u.userId || u.user_id || "", - userName: u.userName || u.user_name || "", - positionName: u.positionName || u.position_name || "", - deptName: u.deptName || u.dept_name || "", - deptCode: u.deptCode || u.dept_code || "", + user_id: u.user_id || "", + user_name: u.user_name || "", + position_name: u.position_name || "", + dept_name: u.dept_name || "", + dept_code: u.dept_code || "", email: u.email || "", })); - setAllUsers(users.filter((u) => u.userId)); + setAllUsers(users.filter((u) => u.user_id)); } catch { setAllUsers([]); } finally { @@ -203,7 +199,7 @@ export const ApprovalRequestModal: React.FC = ({ // Combobox에서 이미 선택된 사용자 제외한 목록 const availableUsers = allUsers.filter( - (u) => !approvers.some((a) => a.user_id === u.userId) + (u) => !approvers.some((a) => a.user_id === u.user_id) ); const addApprover = (user: UserSearchResult) => { @@ -211,10 +207,10 @@ export const ApprovalRequestModal: React.FC = ({ ...prev, { id: genId(), - user_id: user.userId, - user_name: user.userName, - position_name: user.positionName || "", - dept_name: user.deptName || "", + user_id: user.user_id, + user_name: user.user_name, + position_name: user.position_name || "", + dept_name: user.dept_name || "", }, ]); setComboboxOpen(false); @@ -511,8 +507,8 @@ export const ApprovalRequestModal: React.FC = ({ {availableUsers.map((user) => ( addApprover(user)} className="flex cursor-pointer items-center gap-3 px-3 py-2 text-xs sm:text-sm" > @@ -521,13 +517,13 @@ export const ApprovalRequestModal: React.FC = ({

- {user.userName} + {user.user_name} - ({user.userId}) + ({user.user_id})

- {[user.deptName, user.positionName].filter(Boolean).join(" / ") || "-"} + {[user.dept_name, user.position_name].filter(Boolean).join(" / ") || "-"}

diff --git a/frontend/components/auth/LoginForm.tsx b/frontend/components/auth/LoginForm.tsx index bf40542f..0fda8a6c 100644 --- a/frontend/components/auth/LoginForm.tsx +++ b/frontend/components/auth/LoginForm.tsx @@ -47,13 +47,13 @@ export function LoginForm({ {/* 사용자 ID */}
- + = ({ className }) => { groupedData={selectedData} userId={userId} userName={userName} - companyCode={user?.companyCode} + companyCode={user?.company_code || user?.companyCode} isInModal={true} /> ); @@ -1301,7 +1301,7 @@ export const ScreenModal: React.FC = ({ className }) => { }} userId={userId} userName={userName} - companyCode={user?.companyCode} + companyCode={user?.company_code || user?.companyCode} isInModal={true} /> ); diff --git a/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx b/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx index 22240195..f5277204 100644 --- a/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx +++ b/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx @@ -553,7 +553,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { const parsed = JSON.parse(marker.description); // 다양한 필드명 지원 (plate_no 우선 - 차량 번호판으로 경로 구분) userId = parsed.plate_no || parsed.plateNo || parsed.car_number || parsed.carNumber || - parsed.user_id || parsed.userId || parsed.driver_id || parsed.driverId || + parsed.user_id || parsed.driver_id || parsed.car_no || parsed.carNo || parsed.vehicle_no || parsed.vehicleNo || parsed.id || parsed.code || ""; vehicleId = parsed.vehicle_id || parsed.vehicleId || parsed.car_id || parsed.carId; @@ -1916,7 +1916,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { const parsed = JSON.parse(marker.description || "{}"); // 식별자 찾기 (user_id 또는 vehicle_number) - const identifier = parsed.user_id || parsed.userId || parsed.vehicle_number || + const identifier = parsed.user_id || parsed.vehicle_number || parsed.vehicleNumber || parsed.plate_no || parsed.plateNo || parsed.car_number || parsed.carNumber || marker.name; @@ -2076,7 +2076,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { const parsed = JSON.parse(marker.description || "{}"); // 다양한 필드명 지원 (plate_no 우선) const visibleUserId = parsed.plate_no || parsed.plateNo || parsed.car_number || parsed.carNumber || - parsed.user_id || parsed.userId || parsed.driver_id || parsed.driverId || + parsed.user_id || parsed.driver_id || parsed.car_no || parsed.carNo || parsed.vehicle_no || parsed.vehicleNo || parsed.id || parsed.code || marker.name; if (visibleUserId) { diff --git a/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx b/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx index dd73e6dd..7b6dd1ae 100644 --- a/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx +++ b/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx @@ -137,8 +137,8 @@ export default function VehicleMapOnlyWidget({ element, refreshInterval = 30000 : "inactive", speed: parseFloat(row.speed) || 0, destination: row.destination || "대기 중", - userId: row.user_id || row.userId || undefined, - tripId: row.trip_id || row.tripId || undefined, + userId: row.user_id || undefined, + tripId: row.trip_id || undefined, }; }) // 유효한 위도/경도가 있는 차량만 필터링 diff --git a/frontend/components/dataflow/DataFlowDesigner.tsx b/frontend/components/dataflow/DataFlowDesigner.tsx index 64c7576a..111ac773 100644 --- a/frontend/components/dataflow/DataFlowDesigner.tsx +++ b/frontend/components/dataflow/DataFlowDesigner.tsx @@ -39,7 +39,7 @@ export const DataFlowDesigner: React.FC = ({ const { user: authUser } = useAuth(); // 실제 사용자 회사 코드 사용 (prop보다 사용자 정보 우선) - const companyCode = authUser?.company_code || authUser?.companyCode || propCompanyCode; + const companyCode = authUser?.company_code || propCompanyCode; // 커스텀 훅 사용 const { @@ -690,14 +690,14 @@ export const DataFlowDesigner: React.FC = ({ targetDiagramId!, saveRequest, companyCode, - authUser?.userId || "SYSTEM", + authUser?.user_id || "SYSTEM", ); } else { // 새로운 관계도 생성 const newDiagram = await DataFlowAPI.createJsonDataFlowDiagram( saveRequest, companyCode, - authUser?.userId || "SYSTEM", + authUser?.user_id || "SYSTEM", ); // 새로 생성된 다이어그램 ID를 내부 상태에 저장 (다음 저장부터는 업데이트 모드) @@ -758,7 +758,7 @@ export const DataFlowDesigner: React.FC = ({ diagramId, currentDiagramId, companyCode, - authUser?.userId, + authUser?.user_id, setIsSaving, setHasUnsavedChanges, setShowSaveModal, diff --git a/frontend/components/layout/AdminButton.tsx b/frontend/components/layout/AdminButton.tsx index 7ade682e..b1f668e3 100644 --- a/frontend/components/layout/AdminButton.tsx +++ b/frontend/components/layout/AdminButton.tsx @@ -11,18 +11,18 @@ export function AdminButton({ user }: AdminButtonProps) { // 디버깅용 로그 console.log("=== AdminButton 디버깅 ==="); console.log("user:", user); - console.log("user?.userType:", user?.userType); + console.log("user?.user_type:", user?.user_type); console.log("user?.isAdmin:", user?.isAdmin); - console.log("user?.userId:", user?.userId); + console.log("user?.user_id:", user?.user_id); // 관리자 권한 확인 로직 (3단계 권한 체계) const isAdmin = user?.isAdmin || - user?.userType === "SUPER_ADMIN" || - user?.userType === "COMPANY_ADMIN" || - user?.userType === "ADMIN" || - user?.userType === "admin" || - user?.userId === "plm_admin"; + user?.user_type === "SUPER_ADMIN" || + user?.user_type === "COMPANY_ADMIN" || + user?.user_type === "ADMIN" || + user?.user_type === "admin" || + user?.user_id === "plm_admin"; console.log("최종 관리자 권한 확인:", isAdmin); diff --git a/frontend/components/layout/AppLayout.tsx b/frontend/components/layout/AppLayout.tsx index 04d649d6..ace9aac3 100644 --- a/frontend/components/layout/AppLayout.tsx +++ b/frontend/components/layout/AppLayout.tsx @@ -54,25 +54,25 @@ import { CompanySwitcher } from "@/components/admin/CompanySwitcher"; import { getIconComponent } from "@/components/admin/MenuIconPicker"; interface ExtendedUserInfo { - userId: string; - userName: string; + user_id: string; + user_name: string; userNameEng?: string; userNameCn?: string; deptCode?: string; - deptName?: string; + dept_name?: string; positionCode?: string; - positionName?: string; + position_name?: string; email?: string; tel?: string; cellPhone?: string; - userType?: string; + user_type?: string; userTypeName?: string; authName?: string; partnerCd?: string; isAdmin: boolean; sabun?: string; photo?: string | null; - companyCode?: string; + company_code?: string; locale?: string; } @@ -263,8 +263,8 @@ function AppLayoutInner({ children }: AppLayoutProps) { // 현재 회사명 조회 (SUPER_ADMIN 전용) useEffect(() => { const fetchCurrentCompanyName = async () => { - if ((user as ExtendedUserInfo)?.userType === "SUPER_ADMIN") { - const companyCode = (user as ExtendedUserInfo)?.companyCode; + if ((user as ExtendedUserInfo)?.user_type === "SUPER_ADMIN") { + const companyCode = (user as ExtendedUserInfo)?.company_code; if (companyCode === "*") { setCurrentCompanyName("WACE (최고 관리자)"); @@ -283,7 +283,7 @@ function AppLayoutInner({ children }: AppLayoutProps) { }; fetchCurrentCompanyName(); - }, [(user as ExtendedUserInfo)?.companyCode, (user as ExtendedUserInfo)?.userType]); + }, [(user as ExtendedUserInfo)?.company_code, (user as ExtendedUserInfo)?.user_type]); // 화면 크기 감지 및 사이드바 초기 상태 설정 useEffect(() => { @@ -627,12 +627,12 @@ function AppLayoutInner({ children }: AppLayoutProps) { {user.photo && user.photo.trim() !== "" && user.photo !== "null" ? ( {user.userName ) : (
- {user.userName?.substring(0, 1)?.toUpperCase() || "U"} + {user.user_name?.substring(0, 1)?.toUpperCase() || "U"}
)}
@@ -641,9 +641,9 @@ function AppLayoutInner({ children }: AppLayoutProps) {
-

{user.userName || "사용자"}

+

{user.user_name || "사용자"}

- {user.deptName || user.email || user.userId} + {user.dept_name || user.email || user.user_id}

@@ -697,7 +697,7 @@ function AppLayoutInner({ children }: AppLayoutProps) { )} - {(user as ExtendedUserInfo)?.userType === "SUPER_ADMIN" && ( + {(user as ExtendedUserInfo)?.user_type === "SUPER_ADMIN" && (
@@ -711,9 +711,9 @@ function AppLayoutInner({ children }: AppLayoutProps) {
)} - {((user as ExtendedUserInfo)?.userType === "SUPER_ADMIN" || - (user as ExtendedUserInfo)?.userType === "COMPANY_ADMIN" || - (user as ExtendedUserInfo)?.userType === "admin") && ( + {((user as ExtendedUserInfo)?.user_type === "SUPER_ADMIN" || + (user as ExtendedUserInfo)?.user_type === "COMPANY_ADMIN" || + (user as ExtendedUserInfo)?.user_type === "admin") && (
-

{user.userName || "사용자"}

+

{user.user_name || "사용자"}

- {user.deptName || user.email || user.userId} + {user.dept_name || user.email || user.user_id}

@@ -801,24 +801,24 @@ function AppLayoutInner({ children }: AppLayoutProps) { {user.photo && user.photo.trim() !== "" && user.photo !== "null" ? ( {user.userName ) : (
- {user.userName?.substring(0, 1)?.toUpperCase() || "U"} + {user.user_name?.substring(0, 1)?.toUpperCase() || "U"}
)}

- {user.userName || "사용자"} ({user.userId || ""}) + {user.user_name || "사용자"} ({user.user_id || ""})

{user.email || ""}

- {user.deptName && user.positionName - ? `${user.deptName}, ${user.positionName}` - : user.deptName || user.positionName || "부서 정보 없음"} + {user.dept_name && user.position_name + ? `${user.dept_name}, ${user.position_name}` + : user.dept_name || user.position_name || "부서 정보 없음"}

diff --git a/frontend/components/layout/ProfileModal.tsx b/frontend/components/layout/ProfileModal.tsx index d3e5535b..e8bfd89b 100644 --- a/frontend/components/layout/ProfileModal.tsx +++ b/frontend/components/layout/ProfileModal.tsx @@ -278,7 +278,7 @@ export function ProfileModal({
- +
diff --git a/frontend/components/layout/UserDropdown.tsx b/frontend/components/layout/UserDropdown.tsx index 7f769289..234a4240 100644 --- a/frontend/components/layout/UserDropdown.tsx +++ b/frontend/components/layout/UserDropdown.tsx @@ -34,12 +34,12 @@ export function UserDropdown({ user, onProfileClick, onPopModeClick, onLogout }: {user.photo && user.photo.trim() !== "" && user.photo !== "null" ? ( {user.userName ) : (
- {user.userName?.substring(0, 1)?.toUpperCase() || "U"} + {user.user_name?.substring(0, 1)?.toUpperCase() || "U"}
)}
@@ -53,12 +53,12 @@ export function UserDropdown({ user, onProfileClick, onPopModeClick, onLogout }: {user.photo && user.photo.trim() !== "" && user.photo !== "null" ? ( {user.userName ) : (
- {user.userName?.substring(0, 1)?.toUpperCase() || "U"} + {user.user_name?.substring(0, 1)?.toUpperCase() || "U"}
)}
@@ -66,13 +66,13 @@ export function UserDropdown({ user, onProfileClick, onPopModeClick, onLogout }: {/* 사용자 정보 */}

- {user.userName || "사용자"} ({user.userId || ""}) + {user.user_name || "사용자"} ({user.user_id || ""})

{user.email || ""}

- {user.deptName && user.positionName - ? `${user.deptName}, ${user.positionName}` - : user.deptName || user.positionName || "부서 정보 없음"} + {user.dept_name && user.position_name + ? `${user.dept_name}, ${user.position_name}` + : user.dept_name || user.position_name || "부서 정보 없음"}

diff --git a/frontend/components/multilang/LangKeyModal.tsx b/frontend/components/multilang/LangKeyModal.tsx index 06189c58..ecb4c119 100644 --- a/frontend/components/multilang/LangKeyModal.tsx +++ b/frontend/components/multilang/LangKeyModal.tsx @@ -12,27 +12,27 @@ import { Badge } from "@/components/ui/badge"; import { apiClient } from "@/lib/api/client"; interface Language { - langCode: string; - langName: string; - langNative: string; + lang_code: string; + lang_name: string; + lang_native: string; } interface LangKey { - keyId?: number; - companyCode: string; - menuCode: string; - langKey: string; - keyType: string; + key_id?: number; + company_code: string; + menu_code: string; + lang_key: string; + key_type: string; description: string; - isActive: string; + is_active: string; } interface LangText { - textId?: number; - keyId?: number; - langCode: string; - langText: string; - isActive: string; + text_id?: number; + key_id?: number; + lang_code: string; + lang_text: string; + is_active: string; } interface LangKeyModalProps { @@ -57,12 +57,12 @@ export function LangKeyModal({ onSave, }: LangKeyModalProps) { const [keyData, setKeyData] = useState({ - companyCode: "", - menuCode: "", - langKey: "", - keyType: "TEXT", + company_code: "", + menu_code: "", + lang_key: "", + key_type: "TEXT", description: "", - isActive: "Y", + is_active: "Y", }); const [textData, setTextData] = useState([]); const [loading, setLoading] = useState(false); @@ -70,15 +70,15 @@ export function LangKeyModal({ useEffect(() => { if (langKey) { setKeyData(langKey); - fetchLangTexts(langKey.keyId!); + fetchLangTexts(langKey.key_id!); } else { setKeyData({ - companyCode: "", - menuCode: "", - langKey: "", - keyType: "TEXT", + company_code: "", + menu_code: "", + lang_key: "", + key_type: "TEXT", description: "", - isActive: "Y", + is_active: "Y", }); initializeTextData(); } @@ -86,9 +86,9 @@ export function LangKeyModal({ const initializeTextData = () => { const initialTexts = languages.map((lang) => ({ - langCode: lang.langCode, - langText: "", - isActive: "Y", + lang_code: lang.lang_code, + lang_text: "", + is_active: "Y", })); setTextData(initialTexts); }; @@ -100,12 +100,12 @@ export function LangKeyModal({ if (data.success) { const texts = data.data; const allTexts = languages.map((lang) => { - const existingText = texts.find((t: LangText) => t.langCode === lang.langCode); + const existingText = texts.find((t: LangText) => t.lang_code === lang.lang_code); return ( existingText || { - langCode: lang.langCode, - langText: "", - isActive: "Y", + lang_code: lang.lang_code, + lang_text: "", + is_active: "Y", } ); }); @@ -118,7 +118,7 @@ export function LangKeyModal({ }; const handleSave = async () => { - if (!keyData.companyCode || !keyData.menuCode || !keyData.langKey) { + if (!keyData.company_code || !keyData.menu_code || !keyData.lang_key) { alert("필수 항목을 입력해주세요."); return; } @@ -136,7 +136,7 @@ export function LangKeyModal({ }; const updateTextData = (langCode: string, value: string) => { - setTextData((prev) => prev.map((text) => (text.langCode === langCode ? { ...text, langText: value } : text))); + setTextData((prev) => prev.map((text) => (text.lang_code === langCode ? { ...text, lang_text: value } : text))); }; return ( @@ -155,10 +155,10 @@ export function LangKeyModal({
- +
- + setKeyData((prev) => ({ ...prev, langKey: e.target.value }))} + id="lang_key" + value={keyData.lang_key} + onChange={(e) => setKeyData((prev) => ({ ...prev, lang_key: e.target.value }))} placeholder="예: menu.dashboard, button.save" />
- + updateTextData(text.langCode, e.target.value)} - placeholder={`${languages.find((l) => l.langCode === text.langCode)?.langName} 텍스트 입력`} + value={text.lang_text} + onChange={(e) => updateTextData(text.lang_code, e.target.value)} + placeholder={`${languages.find((l) => l.lang_code === text.lang_code)?.lang_name} 텍스트 입력`} />
diff --git a/frontend/components/pop/management/PopDeployModal.tsx b/frontend/components/pop/management/PopDeployModal.tsx index eac12074..edfd3044 100644 --- a/frontend/components/pop/management/PopDeployModal.tsx +++ b/frontend/components/pop/management/PopDeployModal.tsx @@ -107,9 +107,9 @@ export function PopDeployModal({ if (isGroupMode && groupScreens) { setGroupEntries( groupScreens.map((s) => ({ - screenId: s.screenId, - screenName: s.screenName, - newScreenName: s.screenName, + screenId: s.screen_id ?? s.screenId, + screenName: s.screen_name ?? s.screenName, + newScreenName: s.screen_name ?? s.screenName, newScreenCode: "", included: true, })), @@ -117,10 +117,10 @@ export function PopDeployModal({ setScreenName(""); setScreenCode(""); } else if (screen) { - setScreenName(screen.screenName); + setScreenName(screen.screen_name ?? screen.screenName); setScreenCode(""); setGroupEntries([]); - analyzeLinks(screen.screenId); + analyzeLinks(screen.screen_id ?? screen.screenId); } }, [open, screen, groupScreens, isGroupMode]); @@ -169,21 +169,21 @@ export function PopDeployModal({ const linked: LinkedScreenInfo[] = result.linkedScreenIds.map( (linkedId) => { const linkedScreen = allScreens.find( - (s) => s.screenId === linkedId, + (s) => (s.screen_id ?? s.screenId) === linkedId, ); const refs = result.references.filter( (r) => r.targetScreenId === linkedId, ); return { screenId: linkedId, - screenName: linkedScreen?.screenName || `화면 ${linkedId}`, - screenCode: linkedScreen?.screenCode || "", + screenName: (linkedScreen?.screen_name ?? linkedScreen?.screenName) || `화면 ${linkedId}`, + screenCode: (linkedScreen?.screen_code ?? linkedScreen?.screenCode) || "", references: refs.map((r) => ({ componentId: r.componentId, referenceType: r.referenceType, })), deploy: true, - newScreenName: linkedScreen?.screenName || `화면 ${linkedId}`, + newScreenName: (linkedScreen?.screen_name ?? linkedScreen?.screenName) || `화면 ${linkedId}`, newScreenCode: "", }; }, @@ -219,7 +219,7 @@ export function PopDeployModal({ if (!screen || !screenName || !screenCode) return; screensToSend = [ { - sourceScreenId: screen.screenId, + sourceScreenId: screen.screen_id ?? screen.screenId, screenName, screenCode, }, @@ -283,7 +283,7 @@ export function PopDeployModal({ {isGroupMode ? `"${groupName}" 카테고리의 화면 ${groupScreens!.length}개를 다른 회사로 복사합니다.` : screen - ? `"${screen.screenName}" (ID: ${screen.screenId}) 화면을 다른 회사로 복사합니다.` + ? `"${screen.screen_name ?? screen.screenName}" (ID: ${screen.screen_id ?? screen.screenId}) 화면을 다른 회사로 복사합니다.` : "화면을 선택해주세요."} diff --git a/frontend/components/pop/management/PopScreenPreview.tsx b/frontend/components/pop/management/PopScreenPreview.tsx index a56188db..8a3b4302 100644 --- a/frontend/components/pop/management/PopScreenPreview.tsx +++ b/frontend/components/pop/management/PopScreenPreview.tsx @@ -46,7 +46,7 @@ export function PopScreenPreview({ screen, className }: PopScreenPreviewProps) { const checkLayout = async () => { try { setLoading(true); - const layout = await screenApi.getLayoutPop(screen.screenId); + const layout = await screenApi.getLayoutPop(screen.screen_id ?? screen.screenId); // v2 레이아웃: sections는 객체 (Record) // v1 레이아웃: sections는 배열 @@ -71,7 +71,7 @@ export function PopScreenPreview({ screen, className }: PopScreenPreviewProps) { }, [screen]); // 미리보기 URL - const previewUrl = screen ? `/pop/screens/${screen.screenId}?preview=true&device=${deviceType}` : null; + const previewUrl = screen ? `/pop/screens/${screen.screen_id ?? screen.screenId}?preview=true&device=${deviceType}` : null; // 새 탭에서 열기 const openInNewTab = () => { @@ -98,7 +98,7 @@ export function PopScreenPreview({ screen, className }: PopScreenPreviewProps) {

미리보기

{screen && ( - {screen.screenName} + {screen.screen_name ?? screen.screenName} )} diff --git a/frontend/components/pop/management/PopScreenSettingModal.tsx b/frontend/components/pop/management/PopScreenSettingModal.tsx index 3e07526b..ada3b14e 100644 --- a/frontend/components/pop/management/PopScreenSettingModal.tsx +++ b/frontend/components/pop/management/PopScreenSettingModal.tsx @@ -88,7 +88,7 @@ export function PopScreenSettingModal({ if (!open || !screen) return; // 화면 정보 설정 - setScreenName(screen.screenName || ""); + setScreenName((screen.screen_name ?? screen.screenName) || ""); setScreenDescription(screen.description || ""); setScreenIcon(""); setSelectedCategoryId(""); @@ -114,7 +114,7 @@ export function PopScreenSettingModal({ try { setLoading(true); - const layout = await screenApi.getLayoutPop(screen.screenId); + const layout = await screenApi.getLayoutPop(screen.screen_id ?? screen.screenId); if (layout && layout.subScreens) { setSubScreens( @@ -172,8 +172,8 @@ export function PopScreenSettingModal({ }; // screen_definitions 테이블에 화면명/설명 업데이트 - if (screenName !== screen.screenName || screenDescription !== (screen.description || "")) { - await screenApi.updateScreenInfo(screen.screenId, { + if (screenName !== (screen.screen_name ?? screen.screenName) || screenDescription !== (screen.description || "")) { + await screenApi.updateScreenInfo(screen.screen_id ?? screen.screenId, { screenName, description: screenDescription, isActive: "Y", @@ -181,7 +181,7 @@ export function PopScreenSettingModal({ } // 레이아웃에 하위 화면 정보 저장 - const currentLayout = await screenApi.getLayoutPop(screen.screenId); + const currentLayout = await screenApi.getLayoutPop(screen.screen_id ?? screen.screenId); const updatedLayout = { ...currentLayout, version: "pop-1.0", @@ -192,7 +192,7 @@ export function PopScreenSettingModal({ })), }; - await screenApi.saveLayoutPop(screen.screenId, updatedLayout); + await screenApi.saveLayoutPop(screen.screen_id ?? screen.screenId, updatedLayout); toast.success("화면 설정이 저장되었습니다."); onSave?.(screenUpdate); @@ -213,7 +213,7 @@ export function PopScreenSettingModal({ POP 화면 설정 - {screen.screenName} [{screen.screenCode}] + {screen.screen_name ?? screen.screenName} [{screen.screen_code ?? screen.screenCode}] diff --git a/frontend/components/screen/CreateScreenModal.tsx b/frontend/components/screen/CreateScreenModal.tsx index dd3b7216..fc463273 100644 --- a/frontend/components/screen/CreateScreenModal.tsx +++ b/frontend/components/screen/CreateScreenModal.tsx @@ -228,7 +228,7 @@ export default function CreateScreenModal({ open, onOpenChange, onCreated, isPop screenCode: screenCode.trim(), companyCode, description: description.trim() || undefined, - createdBy: (user as any)?.userId, + createdBy: (user as any)?.user_id, dataSourceType: dataSourceType, }; diff --git a/frontend/components/screen/InteractiveScreenViewer.tsx b/frontend/components/screen/InteractiveScreenViewer.tsx index fbde032d..5735eb3c 100644 --- a/frontend/components/screen/InteractiveScreenViewer.tsx +++ b/frontend/components/screen/InteractiveScreenViewer.tsx @@ -1599,7 +1599,7 @@ export const InteractiveScreenViewer: React.FC = ( // console.log("💾 저장 시작"); // ✅ 사용자 정보가 로드되지 않았으면 저장 불가 - if (!user?.userId) { + if (!user?.user_id) { alert("사용자 정보를 불러오는 중입니다. 잠시 후 다시 시도해주세요."); return; } @@ -1743,14 +1743,14 @@ export const InteractiveScreenViewer: React.FC = ( (allComponents.find(c => (c as any).columnName) as any)?.tableName || "dynamic_form_data"; // 기본값 - // 🆕 자동으로 작성자 정보 추가 (user.userId가 확실히 있음) - const writerValue = user.userId; - const companyCodeValue = user.companyCode || ""; - + // 🆕 자동으로 작성자 정보 추가 (user.user_id가 확실히 있음) + const writerValue = user.user_id; + const companyCodeValue = user.company_code || ""; + console.log("👤 현재 사용자 정보:", { - userId: user.userId, + userId: user.user_id, userName: userName, - companyCode: user.companyCode, // ✅ 회사 코드 + companyCode: user.company_code, // ✅ 회사 코드 formDataWriter: mappedData.writer, // ✅ 폼에서 입력한 writer 값 formDataCompanyCode: mappedData.company_code, // ✅ 폼에서 입력한 company_code 값 defaultWriterValue: writerValue, @@ -2093,7 +2093,7 @@ export const InteractiveScreenViewer: React.FC = ( componentId: fileComponent.id, currentUploadedFiles: fileComponent.uploadedFiles?.length || 0, hasOnFormDataChange: !!onFormDataChange, - userInfo: user ? { userId: user.userId, companyCode: user.companyCode } : "no user" + userInfo: user ? { userId: user.user_id, companyCode: user.company_code } : "no user" }); const handleFileUpdate = useCallback(async (updates: Partial) => { diff --git a/frontend/components/screen/InteractiveScreenViewerDynamic.tsx b/frontend/components/screen/InteractiveScreenViewerDynamic.tsx index 58f8f85b..db75b754 100644 --- a/frontend/components/screen/InteractiveScreenViewerDynamic.tsx +++ b/frontend/components/screen/InteractiveScreenViewerDynamic.tsx @@ -423,9 +423,9 @@ export const InteractiveScreenViewerDynamic: React.FC = ({ config.dataflowConfig.flowConfig, { buttonId: component.id, - screenId: component.screenId, + screenId: component.screen_id, companyCode, - userId: formData.userId ?? formData.user_id, + userId: formData.user_id, formData, selectedRows: selectedRows || [], selectedRowsData: selectedRowsData || [], diff --git a/frontend/components/screen/ScreenDesigner_old.tsx b/frontend/components/screen/ScreenDesigner_old.tsx index 18c627d7..ec33ea83 100644 --- a/frontend/components/screen/ScreenDesigner_old.tsx +++ b/frontend/components/screen/ScreenDesigner_old.tsx @@ -405,17 +405,17 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD // 선택된 화면의 테이블만 로드 (최적화된 API 사용) useEffect(() => { const fetchScreenTable = async () => { - if (!selectedScreen?.tableName) { + if (!selectedScreen?.table_name) { setTables([]); return; } try { - // console.log(`=== 테이블 정보 조회 시작: ${selectedScreen.tableName} ===`); + // console.log(`=== 테이블 정보 조회 시작: ${selectedScreen.table_name} ===`); const startTime = performance.now(); // 최적화된 단일 테이블 조회 API 사용 - const response = await apiClient.get(`/screen-management/tables/${selectedScreen.tableName}`); + const response = await apiClient.get(`/screen-management/tables/${selectedScreen.table_name}`); const endTime = performance.now(); // console.log(`테이블 조회 완료: ${(endTime - startTime).toFixed(2)}ms`); @@ -423,20 +423,20 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD const data = response.data; if (data.success && data.data) { setTables([data.data]); - // console.log(`테이블 ${selectedScreen.tableName} 로드 완료, 컬럼 ${data.data.columns.length}개`); + // console.log(`테이블 ${selectedScreen.table_name} 로드 완료, 컬럼 ${data.data.columns.length}개`); } else { // console.error("테이블 조회 실패:", data.message); - setTables([createMockTableForScreen(selectedScreen.tableName)]); + setTables([createMockTableForScreen(selectedScreen.table_name)]); } } catch (error) { // console.error("테이블 조회 중 오류:", error); // 선택된 화면의 테이블에 대한 임시 데이터 생성 - setTables([createMockTableForScreen(selectedScreen.tableName)]); + setTables([createMockTableForScreen(selectedScreen.table_name)]); } }; fetchScreenTable(); - }, [selectedScreen?.tableName]); + }, [selectedScreen?.table_name]); // 검색된 테이블 필터링 const filteredTables = useMemo(() => { @@ -968,7 +968,7 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD try { setIsSaving(true); - await screenApi.saveLayout(selectedScreen.screenId, layout); + await screenApi.saveLayout(selectedScreen.screen_id, layout); setHasUnsavedChanges(false); // 저장 완료 시 변경사항 플래그 해제 toast.success("레이아웃이 성공적으로 저장되었습니다."); } catch (error) { @@ -985,7 +985,7 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD try { setIsLoading(true); - const savedLayout = await screenApi.getLayout(selectedScreen.screenId); + const savedLayout = await screenApi.getLayout(selectedScreen.screen_id); if (savedLayout && savedLayout.components) { // 격자 설정이 없는 경우 기본값 추가 @@ -1386,8 +1386,8 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
{/* 상단 툴바 */} - {selectedScreen.tableName} + {selectedScreen.table_name} {clipboard && clipboard.data.length > 0 && ( @@ -1578,10 +1578,10 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD {selectedScreen && (
선택된 화면
-
{selectedScreen.screenName}
+
{selectedScreen.screen_name}
- {selectedScreen.tableName} + {selectedScreen.table_name}
)} @@ -1618,7 +1618,7 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD

{selectedScreen - ? `${selectedScreen.tableName} 테이블의 컬럼 정보를 조회하고 있습니다.` + ? `${selectedScreen.table_name} 테이블의 컬럼 정보를 조회하고 있습니다.` : "화면을 선택하면 해당 테이블의 컬럼 정보가 표시됩니다."}

diff --git a/frontend/components/screen/ScreenGroupModal.tsx b/frontend/components/screen/ScreenGroupModal.tsx index 2726ce04..eda48eea 100644 --- a/frontend/components/screen/ScreenGroupModal.tsx +++ b/frontend/components/screen/ScreenGroupModal.tsx @@ -116,7 +116,7 @@ export function ScreenGroupModal({ const response = await apiClient.get("/auth/me"); const result = response.data; if (result.success && result.data) { - const companyCode = result.data.companyCode || result.data.company_code || ""; + const companyCode = result.data.company_code || ""; setCurrentCompanyCode(companyCode); setIsSuperAdmin(companyCode === "*"); } diff --git a/frontend/components/screen/ScreenGroupTreeView.tsx b/frontend/components/screen/ScreenGroupTreeView.tsx index 46a96847..8e5e95a5 100644 --- a/frontend/components/screen/ScreenGroupTreeView.tsx +++ b/frontend/components/screen/ScreenGroupTreeView.tsx @@ -185,10 +185,10 @@ export function ScreenGroupTreeView({ const [isSyncCompanySelectOpen, setIsSyncCompanySelectOpen] = useState(false); // 현재 사용자가 최고 관리자인지 확인 - const isSuperAdmin = user?.companyCode === "*"; - + const isSuperAdmin = user?.company_code === "*"; + // 실제 사용할 회사 코드 (props → 선택 → 사용자 기본값) - const effectiveCompanyCode = companyCode || selectedCompanyCode || (isSuperAdmin ? "" : user?.companyCode) || ""; + const effectiveCompanyCode = companyCode || selectedCompanyCode || (isSuperAdmin ? "" : user?.company_code) || ""; // 그룹 목록 및 그룹별 화면 로드 useEffect(() => { @@ -208,7 +208,7 @@ export function ScreenGroupTreeView({ // 미분류 화면들 (어떤 그룹에도 속하지 않은 화면) const getUngroupedScreens = (): ScreenDefinition[] => { const groupedIds = getGroupedScreenIds(); - return screens.filter((screen) => !groupedIds.has(screen.screenId)); + return screens.filter((screen) => !groupedIds.has(screen.screen_id)); }; // 그룹에 속한 화면들 (display_order 오름차순 정렬) @@ -216,7 +216,7 @@ export function ScreenGroupTreeView({ const group = groups.find((g) => g.id === groupId); if (!group?.screens) { const screenIds = groupScreensMap.get(groupId) || []; - return screens.filter((screen) => screenIds.includes(screen.screenId)); + return screens.filter((screen) => screenIds.includes(screen.screen_id)); } // 그룹의 screens 배열에서 display_order 정보를 가져와서 정렬 @@ -225,7 +225,7 @@ export function ScreenGroupTreeView({ .map((s) => s.screen_id); return sortedScreenIds - .map((id) => screens.find((screen) => screen.screenId === id)) + .map((id) => screens.find((screen) => screen.screen_id === id)) .filter((screen): screen is ScreenDefinition => screen !== undefined); }; @@ -259,7 +259,7 @@ export function ScreenGroupTreeView({ if (onScreenSelectInGroup) { onScreenSelectInGroup( { id: group.id, name: group.group_name, company_code: group.company_code }, - screen.screenId + screen.screen_id ); } else { // fallback: 기존 동작 @@ -297,8 +297,8 @@ export function ScreenGroupTreeView({ } // 최고 관리자가 아니면 바로 상태 조회 - if (!isSuperAdmin && user?.companyCode) { - const response = await getMenuScreenSyncStatus(user.companyCode); + if (!isSuperAdmin && user?.company_code) { + const response = await getMenuScreenSyncStatus(user.company_code); if (response.success && response.data) { setSyncStatus(response.data); } @@ -323,7 +323,7 @@ export function ScreenGroupTreeView({ // 동기화 실행 const handleSync = async (direction: "screen-to-menu" | "menu-to-screen") => { // 사용할 회사 코드 결정 - const targetCompanyCode = isSuperAdmin ? selectedCompanyCode : user?.companyCode; + const targetCompanyCode = isSuperAdmin ? selectedCompanyCode : user?.company_code; if (!targetCompanyCode) { toast.error("회사를 선택해주세요."); @@ -550,9 +550,9 @@ export function ScreenGroupTreeView({ setDeleteProgress({ current: currentStep, total: totalSteps, - message: `화면 삭제 중: ${screen.screenName}` + message: `화면 삭제 중: ${screen.screen_name}` }); - await screenApi.deleteScreen(screen.screenId, "그룹 삭제와 함께 삭제", true); // force: true로 의존성 무시 + await screenApi.deleteScreen(screen.screen_id, "그룹 삭제와 함께 삭제", true); // force: true로 의존성 무시 } console.log(`✅ 그룹 및 하위 그룹 내 화면 ${allScreens.length}개 삭제 완료`); } @@ -619,8 +619,8 @@ export function ScreenGroupTreeView({ try { setIsScreenDeleting(true); const { screenApi } = await import("@/lib/api/screen"); - await screenApi.deleteScreen(deletingScreen.screenId, "사용자 요청으로 삭제"); - toast.success(`"${deletingScreen.screenName}" 화면이 삭제되었습니다`); + await screenApi.deleteScreen(deletingScreen.screen_id, "사용자 요청으로 삭제"); + toast.success(`"${deletingScreen.screen_name}" 화면이 삭제되었습니다`); await loadGroupsData(); window.dispatchEvent(new CustomEvent("screen-list-refresh")); } catch (error) { @@ -636,17 +636,17 @@ export function ScreenGroupTreeView({ // 화면 수정 모달 열기 (이름 변경 + 그룹 이동) const handleOpenEditScreenModal = (screen: ScreenDefinition) => { setEditingScreen(screen); - setEditScreenName(screen.screenName); - + setEditScreenName(screen.screen_name); + // 현재 화면이 속한 그룹 정보 찾기 let currentGroupId: number | null = null; let currentScreenRole: string = ""; let currentDisplayOrder: number = 1; - + // 현재 화면이 속한 그룹 찾기 for (const group of groups) { if (group.screens && Array.isArray(group.screens)) { - const screenInfo = group.screens.find((s: any) => Number(s.screen_id) === Number(screen.screenId)); + const screenInfo = group.screens.find((s: any) => Number(s.screen_id) === Number(screen.screen_id)); if (screenInfo) { currentGroupId = group.id; currentScreenRole = screenInfo.screen_role || ""; @@ -668,7 +668,7 @@ export function ScreenGroupTreeView({ let currentGroupId: number | null = null; for (const group of groups) { if (group.screens && Array.isArray(group.screens)) { - const found = group.screens.find((s: any) => Number(s.screen_id) === Number(screen.screenId)); + const found = group.screens.find((s: any) => Number(s.screen_id) === Number(screen.screen_id)); if (found) { currentGroupId = group.id; break; @@ -736,15 +736,15 @@ export function ScreenGroupTreeView({ try { // 1. 화면 이름이 변경되었으면 업데이트 - if (editScreenName.trim() && editScreenName !== editingScreen.screenName) { - await screenApi.updateScreen(editingScreen.screenId, { + if (editScreenName.trim() && editScreenName !== editingScreen.screen_name) { + await screenApi.updateScreen(editingScreen.screen_id, { screenName: editScreenName.trim(), }); } // 2. 현재 그룹에서 제거 const currentGroupId = Array.from(groupScreensMap.entries()).find(([_, screenIds]) => - screenIds.includes(editingScreen.screenId) + screenIds.includes(editingScreen.screen_id) )?.[0]; if (currentGroupId) { @@ -752,7 +752,7 @@ export function ScreenGroupTreeView({ const currentGroup = groups.find((g) => g.id === currentGroupId); if (currentGroup && currentGroup.screens) { const screenGroupScreen = currentGroup.screens.find( - (s: any) => s.screen_id === editingScreen.screenId + (s: any) => s.screen_id === editingScreen.screen_id ); if (screenGroupScreen) { await removeScreenFromGroup(screenGroupScreen.id); @@ -764,7 +764,7 @@ export function ScreenGroupTreeView({ if (selectedGroupForMove !== null) { await addScreenToGroup({ group_id: selectedGroupForMove, - screen_id: editingScreen.screenId, + screen_id: editingScreen.screen_id, screen_role: screenRole, display_order: displayOrder, is_default: "N", @@ -1295,20 +1295,20 @@ export function ScreenGroupTreeView({ ) : ( grandScreens.map((screen) => (
handleScreenClickInGroup(screen, grandChild)} onDoubleClick={() => handleScreenDoubleClick(screen)} onContextMenu={(e) => handleContextMenu(e, screen)} > - {screen.screenName} + {screen.screen_name} - {screen.screenCode} + {screen.screen_code}
)) @@ -1331,20 +1331,20 @@ export function ScreenGroupTreeView({ ) : ( childScreens.map((screen) => (
handleScreenClickInGroup(screen, childGroup)} onDoubleClick={() => handleScreenDoubleClick(screen)} onContextMenu={(e) => handleContextMenu(e, screen)} > - {screen.screenName} + {screen.screen_name} - {screen.screenCode} + {screen.screen_code}
)) @@ -1367,20 +1367,20 @@ export function ScreenGroupTreeView({ ) : ( groupScreens.map((screen) => (
handleScreenClickInGroup(screen, group)} onDoubleClick={() => handleScreenDoubleClick(screen)} onContextMenu={(e) => handleContextMenu(e, screen)} > - {screen.screenName} + {screen.screen_name} - {screen.screenCode} + {screen.screen_code}
)) @@ -1417,20 +1417,20 @@ export function ScreenGroupTreeView({
{ungroupedScreens.map((screen) => (
handleScreenClick(screen)} onDoubleClick={() => handleScreenDoubleClick(screen)} onContextMenu={(e) => handleContextMenu(e, screen)} > - {screen.screenName} + {screen.screen_name} - {screen.screenCode} + {screen.screen_code}
))} @@ -1639,7 +1639,7 @@ export function ScreenGroupTreeView({

- "{deletingScreen?.screenName}" 화면을 정말 삭제하시겠습니까? + "{deletingScreen?.screen_name}" 화면을 정말 삭제하시겠습니까?

⚠️ 화면과 연결된 플로우, 레이아웃 데이터가 모두 삭제됩니다. 삭제된 화면은 휴지통으로 이동됩니다. diff --git a/frontend/components/screen/ScreenRelationFlow.tsx b/frontend/components/screen/ScreenRelationFlow.tsx index f0f60920..563b9da1 100644 --- a/frontend/components/screen/ScreenRelationFlow.tsx +++ b/frontend/components/screen/ScreenRelationFlow.tsx @@ -183,7 +183,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 그룹 또는 화면이 변경될 때 포커스 초기화 useEffect(() => { setFocusedScreenId(null); - }, [selectedGroup?.id, screen?.screenId]); + }, [selectedGroup?.id, screen?.screen_id]); // 외부에서 전달된 초기 포커스 ID 적용 (화면 이동 없이 강조만) useEffect(() => { @@ -286,35 +286,35 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 화면-테이블 매핑 저장 (포커스 시 연결선 강조용) const newScreenTableMap: Record = {}; screenList.forEach((scr: any) => { - if (scr.tableName) { - newScreenTableMap[scr.screenId] = scr.tableName; + if (scr.table_name) { + newScreenTableMap[scr.screen_id] = scr.table_name; } }); setScreenTableMap(newScreenTableMap); // 관계 데이터 로드 (첫 번째 화면 기준) const [joinsRes, flowsRes, relationsRes] = await Promise.all([ - getFieldJoins(screenList[0].screenId).catch(() => ({ success: false, data: [] })), + getFieldJoins(screenList[0].screen_id).catch(() => ({ success: false, data: [] })), getDataFlows().catch(() => ({ success: false, data: [] })), - getTableRelations({ screen_id: screenList[0].screenId }).catch(() => ({ success: false, data: [] })), + getTableRelations({ screen_id: screenList[0].screen_id }).catch(() => ({ success: false, data: [] })), ]); const joins = joinsRes.success ? joinsRes.data || [] : []; const flows = flowsRes.success ? flowsRes.data || [] : []; const relations = relationsRes.success ? relationsRes.data || [] : []; - + // 데이터 흐름에서 연결된 화면들 추가 (개별 화면 모드에서만 - 그룹 모드에서는 그룹 내 화면만 표시) if (!selectedGroup && screen) { flows.forEach((flow: any) => { - if (flow.source_screen_id === screen.screenId && flow.target_screen_id) { - const exists = screenList.some((s) => s.screenId === flow.target_screen_id); + if (flow.source_screen_id === screen.screen_id && flow.target_screen_id) { + const exists = screenList.some((s) => s.screen_id === flow.target_screen_id); if (!exists) { screenList.push({ - screenId: flow.target_screen_id, - screenName: flow.target_screen_name || `화면 ${flow.target_screen_id}`, - screenCode: "", - tableName: "", - companyCode: screen.companyCode, + screen_id: flow.target_screen_id, + screen_name: flow.target_screen_name || `화면 ${flow.target_screen_id}`, + screen_code: "", + table_name: "", + company_code: screen.company_code, isActive: "Y", createdDate: new Date(), updatedDate: new Date(), @@ -325,7 +325,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId } // 화면 레이아웃 요약 정보 로드 - const screenIds = screenList.map((s) => s.screenId); + const screenIds = screenList.map((s) => s.screen_id); let layoutSummaries: Record = {}; let subTablesData: Record = {}; try { @@ -359,14 +359,14 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 화면별 사용 컬럼 정보 추출 (layoutSummaries에서) const usedColumnsMap: Record> = {}; screenList.forEach((screenItem) => { - const layout = layoutSummaries[screenItem.screenId]; + const layout = layoutSummaries[screenItem.screen_id]; if (layout && layout.layoutItems) { - const mainTable = screenItem.tableName; + const mainTable = screenItem.table_name; if (mainTable) { // layoutItems에서 사용 컬럼과 조인 컬럼 추출 const allUsedColumns: string[] = []; const allJoinColumns: string[] = []; - + layout.layoutItems.forEach((item) => { // usedColumns 배열에서 추출 (columns_config에서 가져온 컬럼명) if (item.usedColumns && Array.isArray(item.usedColumns)) { @@ -389,13 +389,13 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId allUsedColumns.push(item.bindField); } }); - - if (!usedColumnsMap[screenItem.screenId]) { - usedColumnsMap[screenItem.screenId] = {}; + + if (!usedColumnsMap[screenItem.screen_id]) { + usedColumnsMap[screenItem.screen_id] = {}; } // 사용 컬럼과 조인 컬럼을 별도 키로 저장 - usedColumnsMap[screenItem.screenId][mainTable] = allUsedColumns; - usedColumnsMap[screenItem.screenId][`${mainTable}__join`] = allJoinColumns; + usedColumnsMap[screenItem.screen_id][mainTable] = allUsedColumns; + usedColumnsMap[screenItem.screen_id][`${mainTable}__join`] = allJoinColumns; } } }); @@ -418,18 +418,18 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId }; screenList.forEach((scr: any, idx) => { - const isMain = screen && scr.screenId === screen.screenId; - const summary = layoutSummaries[scr.screenId]; + const isMain = screen && scr.screen_id === screen.screen_id; + const summary = layoutSummaries[scr.screen_id]; const roleLabel = getRoleLabel(scr.screenRole); - + // 포커스 여부 결정 (그룹 모드 & 개별 화면 모드 모두 지원) const isInGroup = !!selectedGroup; let isFocused: boolean; let isFaded: boolean; - + if (isInGroup) { // 그룹 모드: 클릭한 화면만 포커스 - isFocused = focusedScreenId === scr.screenId; + isFocused = focusedScreenId === scr.screen_id; isFaded = focusedScreenId !== null && !isFocused; } else { // 개별 화면 모드: 메인 화면(선택된 화면)만 포커스, 연결 화면은 흐리게 @@ -438,15 +438,15 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId } screenNodes.push({ - id: `screen-${scr.screenId}`, + id: `screen-${scr.screen_id}`, type: "screenNode", position: { x: screenStartX + idx * (NODE_WIDTH + NODE_GAP), y: SCREEN_Y }, data: { - label: scr.screenName, + label: scr.screen_name, subLabel: selectedGroup ? `${roleLabel} (#${scr.displayOrder || idx + 1})` : (isMain ? "메인 화면" : "연결 화면"), type: "screen", isMain: selectedGroup ? idx === 0 : !!isMain, - tableName: scr.tableName, + tableName: scr.table_name, layoutSummary: summary, // 화면 포커스 관련 속성 (그룹 모드 & 개별 모드 공통) isInGroup, @@ -464,8 +464,8 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 모든 화면의 메인 테이블 추가 screenList.forEach((scr) => { - if (scr.tableName) { - mainTableSet.add(scr.tableName); + if (scr.table_name) { + mainTableSet.add(scr.table_name); } }); @@ -577,10 +577,10 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 각 테이블이 어떤 화면들의 메인 테이블인지 매핑 const tableToScreensMap = new Map(); screenList.forEach((scr: any) => { - if (scr.tableName) { - const screens = tableToScreensMap.get(scr.tableName) || []; - screens.push(scr.screenName); - tableToScreensMap.set(scr.tableName, screens); + if (scr.table_name) { + const screens = tableToScreensMap.get(scr.table_name) || []; + screens.push(scr.screen_name); + tableToScreensMap.set(scr.table_name, screens); } }); @@ -702,8 +702,8 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId newEdges.push({ id: `edge-screen-flow-${i}`, - source: `screen-${currentScreen.screenId}`, - target: `screen-${nextScreen.screenId}`, + source: `screen-${currentScreen.screen_id}`, + target: `screen-${nextScreen.screen_id}`, sourceHandle: "right", targetHandle: "left", type: "animatedFlow", @@ -722,11 +722,11 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 각 화면 → 해당 메인 테이블 연결선 생성 (실선) // 모든 화면-테이블 연결은 동일한 스타일 (각 화면의 메인 테이블이므로) screenList.forEach((scr) => { - if (scr.tableName && mainTableSet.has(scr.tableName)) { + if (scr.table_name && mainTableSet.has(scr.table_name)) { newEdges.push({ - id: `edge-screen-table-${scr.screenId}`, - source: `screen-${scr.screenId}`, - target: `table-${scr.tableName}`, + id: `edge-screen-table-${scr.screen_id}`, + source: `screen-${scr.screen_id}`, + target: `table-${scr.table_name}`, sourceHandle: "bottom", targetHandle: "top", type: "animatedFlow", @@ -1018,15 +1018,15 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 테이블 관계 엣지 (추가 관계) - 참조용 화면(개별 모드: screen, 그룹 모드: screenList[0]) const refScreen = screen ?? screenList[0]; relations.forEach((rel: any, idx: number) => { - if (rel.table_name && rel.table_name !== refScreen.tableName) { + if (rel.table_name && rel.table_name !== refScreen.table_name) { // 화면 → 연결 테이블 const edgeExists = newEdges.some( - (e) => e.source === `screen-${refScreen.screenId}` && e.target === `table-${rel.table_name}` + (e) => e.source === `screen-${refScreen.screen_id}` && e.target === `table-${rel.table_name}` ); if (!edgeExists) { newEdges.push({ id: `edge-rel-${idx}`, - source: `screen-${refScreen.screenId}`, + source: `screen-${refScreen.screen_id}`, target: `table-${rel.table_name}`, sourceHandle: "bottom", targetHandle: "top", @@ -1044,12 +1044,12 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId // 데이터 흐름 엣지 (화면 간) flows - .filter((flow: any) => flow.source_screen_id === refScreen.screenId) + .filter((flow: any) => flow.source_screen_id === refScreen.screen_id) .forEach((flow: any, idx: number) => { if (flow.target_screen_id) { newEdges.push({ id: `edge-flow-${idx}`, - source: `screen-${refScreen.screenId}`, + source: `screen-${refScreen.screen_id}`, target: `screen-${flow.target_screen_id}`, sourceHandle: "right", targetHandle: "left", @@ -1937,7 +1937,7 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId const styledEdges = React.useMemo(() => { // 개별 화면 모드: 메인 화면의 연결선만 강조 if (!selectedGroup && screen) { - const mainScreenId = screen.screenId; + const mainScreenId = screen.screen_id; return edges.map((edge) => { // 화면 간 연결선 @@ -2418,8 +2418,8 @@ function ScreenRelationFlowInner({ screen, selectedGroup, initialFocusedScreenId {screen && !selectedGroup && ( <> - {screen.screenName} - {screen.screenCode} + {screen.screen_name} + {screen.screen_code} )} diff --git a/frontend/components/screen/TableSettingModal.tsx b/frontend/components/screen/TableSettingModal.tsx index 8701a54c..f250eca0 100644 --- a/frontend/components/screen/TableSettingModal.tsx +++ b/frontend/components/screen/TableSettingModal.tsx @@ -360,11 +360,11 @@ export function TableSettingModal({ screensResponse.data.forEach((screen: any) => { // 메인 테이블로 사용하는 경우 - if (screen.tableName === tableName) { + if (screen.table_name === tableName) { usingScreens.push({ - screenId: screen.screenId, - screenName: screen.screenName, - screenCode: screen.screenCode, + screenId: screen.screen_id, + screenName: screen.screen_name, + screenCode: screen.screen_code, tableRole: "main", }); } diff --git a/frontend/components/screen/config-panels/ButtonConfigPanel-fixed.tsx b/frontend/components/screen/config-panels/ButtonConfigPanel-fixed.tsx index 30b93cb4..2eba52b6 100644 --- a/frontend/components/screen/config-panels/ButtonConfigPanel-fixed.tsx +++ b/frontend/components/screen/config-panels/ButtonConfigPanel-fixed.tsx @@ -106,8 +106,8 @@ export const ButtonConfigPanel: React.FC = ({ component, if (response.data.success && Array.isArray(response.data.data)) { const screenList = response.data.data.map((screen: any) => ({ - id: screen.screenId, - name: screen.screenName, + id: screen.screen_id, + name: screen.screen_name, description: screen.description, })); setScreens(screenList); diff --git a/frontend/components/screen/config-panels/button-config/ActionTab.tsx b/frontend/components/screen/config-panels/button-config/ActionTab.tsx index 8f880ef2..decaa904 100644 --- a/frontend/components/screen/config-panels/button-config/ActionTab.tsx +++ b/frontend/components/screen/config-panels/button-config/ActionTab.tsx @@ -212,8 +212,8 @@ export const ActionTab: React.FC = ({ if (response.data.success && response.data.data) { const tables = response.data.data.map((table: any) => ({ - name: table.tableName, - label: table.displayName || table.tableName, + name: table.table_name, + label: table.display_name || table.table_name, })); setAvailableTables(tables); } @@ -249,8 +249,8 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { const columns = columnData.map((col: any) => { - const name = col.name || col.columnName; - const label = col.displayName || col.label || col.columnLabel || name; + const name = col.name || col.column_name; + const label = col.display_name || col.label || col.column_label || name; console.log(` - 컬럼: ${name} → "${label}"`); return { name, label }; }); @@ -276,8 +276,8 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { return columnData.map((col: any) => ({ - name: col.name || col.columnName, - label: col.displayName || col.label || col.columnLabel || col.name || col.columnName, + name: col.name || col.column_name, + label: col.display_name || col.label || col.column_label || col.name || col.column_name, })); } } @@ -370,10 +370,10 @@ export const ActionTab: React.FC = ({ try { const screenResponse = await apiClient.get(`/screen-management/screens/${targetScreenId}`); if (screenResponse.data.success && screenResponse.data.data) { - targetTableName = screenResponse.data.data.tableName || null; - } else if (screenResponse.data?.tableName) { + targetTableName = screenResponse.data.data.table_name || null; + } else if (screenResponse.data?.table_name) { // 직접 데이터 반환 형식인 경우 - targetTableName = screenResponse.data.tableName || null; + targetTableName = screenResponse.data.table_name || null; } } catch (error) { console.error("대상 화면 정보 로드 실패:", error); @@ -392,8 +392,8 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { const columns = columnData.map((col: any) => ({ - name: col.name || col.columnName, - label: col.displayName || col.label || col.columnLabel || col.name || col.columnName, + name: col.name || col.column_name, + label: col.display_name || col.label || col.column_label || col.name || col.column_name, })); setModalActionSourceColumns(columns); } @@ -414,8 +414,8 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { const columns = columnData.map((col: any) => ({ - name: col.name || col.columnName, - label: col.displayName || col.label || col.columnLabel || col.name || col.columnName, + name: col.name || col.column_name, + label: col.display_name || col.label || col.column_label || col.name || col.column_name, })); setModalActionTargetColumns(columns); } @@ -459,8 +459,8 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { const columns = columnData.map((col: any) => ({ - name: col.name || col.columnName, - label: col.displayName || col.label || col.columnLabel || col.name || col.columnName, + name: col.name || col.column_name, + label: col.display_name || col.label || col.column_label || col.name || col.column_name, })); setCurrentTableColumns(columns); } @@ -556,14 +556,12 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { const columns = columnData.map((col: any) => ({ - name: col.name || col.columnName || col.column_name, + name: col.name || col.column_name, label: - col.displayName || - col.label || - col.columnLabel || col.display_name || + col.label || + col.column_label || col.name || - col.columnName || col.column_name, })); setModalSourceColumns(columns); @@ -584,7 +582,7 @@ export const ActionTab: React.FC = ({ console.log("[openModalWithData] 타겟 화면 응답:", screenResponse.data); if (screenResponse.data.success && screenResponse.data.data) { - const targetTableName = screenResponse.data.data.tableName; + const targetTableName = screenResponse.data.data.table_name; console.log("[openModalWithData] 타겟 화면 테이블명:", targetTableName); if (targetTableName) { @@ -596,14 +594,12 @@ export const ActionTab: React.FC = ({ if (Array.isArray(columnData)) { const columns = columnData.map((col: any) => ({ - name: col.name || col.columnName || col.column_name, + name: col.name || col.column_name, label: - col.displayName || - col.label || - col.columnLabel || col.display_name || + col.label || + col.column_label || col.name || - col.columnName || col.column_name, })); setModalTargetColumns(columns); @@ -647,8 +643,8 @@ export const ActionTab: React.FC = ({ if (response.data.success && Array.isArray(response.data.data)) { const screenList = response.data.data.map((screen: any) => ({ - id: screen.screenId, - name: screen.screenName, + id: screen.screen_id, + name: screen.screen_name, description: screen.description, })); setScreens(screenList); @@ -721,8 +717,8 @@ export const ActionTab: React.FC = ({ // ID 컬럼과 날짜 관련 컬럼 제외 const filteredColumns = columnData .filter((col: any) => { - const colName = col.columnName.toLowerCase(); - const dataType = col.dataType?.toLowerCase() || ""; + const colName = col.column_name.toLowerCase(); + const dataType = col.data_type?.toLowerCase() || ""; // ID 컬럼 제외 (id, _id로 끝나는 컬럼) if (colName === "id" || colName.endsWith("_id")) { @@ -747,7 +743,7 @@ export const ActionTab: React.FC = ({ return true; }) - .map((col: any) => col.columnName); + .map((col: any) => col.column_name); setTableColumns(filteredColumns); } @@ -3935,12 +3931,12 @@ const MasterDetailExcelUploadConfig: React.FC<{ const response = await apiClient.get(`/table-management/tables/${masterTable}/columns`); if (response.data?.success && response.data?.data?.columns) { const cols = response.data.data.columns.map((col: any) => ({ - columnName: col.columnName || col.column_name, - columnLabel: col.displayName || col.columnLabel || col.column_label || col.columnName || col.column_name, - inputType: col.inputType || col.input_type || "text", - referenceTable: col.referenceTable || col.reference_table, - referenceColumn: col.referenceColumn || col.reference_column, - displayColumn: col.displayColumn || col.display_column, + columnName: col.column_name, + columnLabel: col.display_name || col.column_label || col.column_name, + inputType: col.input_type || "text", + referenceTable: col.reference_table, + referenceColumn: col.reference_column, + displayColumn: col.display_column, })); setMasterColumns(cols); } @@ -3968,8 +3964,8 @@ const MasterDetailExcelUploadConfig: React.FC<{ const response = await apiClient.get(`/table-management/tables/${field.referenceTable}/columns`); if (response.data?.success && response.data?.data?.columns) { const cols = response.data.data.columns.map((c: any) => ({ - name: c.columnName || c.column_name, - label: c.displayName || c.columnLabel || c.column_label || c.columnName || c.column_name, + name: c.column_name, + label: c.display_name || c.column_label || c.column_name, })); setRefTableColumns((prev) => ({ ...prev, @@ -4004,11 +4000,11 @@ const MasterDetailExcelUploadConfig: React.FC<{ if (response.data?.success && response.data?.data?.columns) { const columns = response.data.data.columns; // referenceTable이 마스터 테이블인 컬럼 찾기 - const fkColumn = columns.find((col: any) => col.referenceTable === masterTable); + const fkColumn = columns.find((col: any) => col.reference_table === masterTable); if (fkColumn) { - const detailFk = fkColumn.columnName || fkColumn.column_name; - const masterKey = fkColumn.referenceColumn || fkColumn.reference_column; + const detailFk = fkColumn.column_name; + const masterKey = fkColumn.reference_column; setRelationInfo({ masterTable, diff --git a/frontend/components/v2/config-panels/V2ButtonConfigPanel.tsx b/frontend/components/v2/config-panels/V2ButtonConfigPanel.tsx index 5405b24e..dd9ef0de 100644 --- a/frontend/components/v2/config-panels/V2ButtonConfigPanel.tsx +++ b/frontend/components/v2/config-panels/V2ButtonConfigPanel.tsx @@ -335,8 +335,8 @@ export const V2ButtonConfigPanel: React.FC = ({ const response = await apiClient.get("/table-management/tables"); if (response.data.success && response.data.data) { const tables = response.data.data.map((t: any) => ({ - name: t.tableName || t.name, - label: t.displayName || t.tableLabel || t.label || t.tableName || t.name, + name: t.table_name || t.name, + label: t.display_name || t.table_label || t.label || t.table_name || t.name, })); setAvailableTables(tables); } @@ -357,8 +357,8 @@ export const V2ButtonConfigPanel: React.FC = ({ if (!Array.isArray(columnData) && columnData?.data) columnData = columnData.data; if (Array.isArray(columnData)) { return columnData.map((col: any) => ({ - name: col.name || col.columnName, - label: col.displayName || col.label || col.columnLabel || col.name || col.columnName, + name: col.name || col.column_name, + label: col.display_name || col.label || col.column_label || col.name || col.column_name, })); } } @@ -444,8 +444,8 @@ export const V2ButtonConfigPanel: React.FC = ({ const response = await apiClient.get("/screen-management/screens?size=1000"); if (response.data.success && response.data.data) { const screenList = response.data.data.map((s: any) => ({ - id: s.id || s.screenId, - name: s.name || s.screenName, + id: s.id || s.screen_id, + name: s.name || s.screen_name, description: s.description || "", })); setScreens(screenList); diff --git a/frontend/components/v2/config-panels/V2ItemRoutingConfigPanel.tsx b/frontend/components/v2/config-panels/V2ItemRoutingConfigPanel.tsx index 6b85429b..85b7c56f 100644 --- a/frontend/components/v2/config-panels/V2ItemRoutingConfigPanel.tsx +++ b/frontend/components/v2/config-panels/V2ItemRoutingConfigPanel.tsx @@ -83,7 +83,13 @@ function ColumnCombobox({ value, onChange, tableName, placeholder }: { try { const { tableManagementApi } = await import("@/lib/api/tableManagement"); const res = await tableManagementApi.getColumnList(tableName); - if (res.success && res.data?.columns) setColumns(res.data.columns); + if (res.success && res.data?.columns) setColumns( + (res.data.columns as any[]).map((c) => ({ + columnName: c.column_name, + displayName: c.display_name, + dataType: c.data_type, + })) + ); } catch { /* ignore */ } finally { setLoading(false); } }; load(); @@ -138,7 +144,7 @@ function ScreenCombobox({ value, onChange }: { value?: number; onChange: (v?: nu const res = await screenApi.getScreens({ page: 1, size: 1000 }); if (res.data) { setScreens(res.data.map((s: any) => ({ - screenId: s.screenId, screenName: s.screenName || `화면 ${s.screenId}`, screenCode: s.screenCode || "", + screenId: s.screen_id, screenName: s.screen_name || `화면 ${s.screen_id}`, screenCode: s.screen_code || "", }))); } } catch { /* ignore */ } finally { setLoading(false); } @@ -298,7 +304,7 @@ export const V2ItemRoutingConfigPanel: React.FC = const { tableManagementApi } = await import("@/lib/api/tableManagement"); const res = await tableManagementApi.getTableList(); if (res.success && res.data) { - setTables(res.data.map((t: any) => ({ tableName: t.tableName, displayName: t.displayName || t.tableName }))); + setTables(res.data.map((t: any) => ({ tableName: t.table_name, displayName: t.display_name || t.table_name }))); } } catch { /* ignore */ } finally { setLoadingTables(false); } }; diff --git a/frontend/components/vehicle/VehicleReport.tsx b/frontend/components/vehicle/VehicleReport.tsx index 2bca91d3..a6b5037d 100644 --- a/frontend/components/vehicle/VehicleReport.tsx +++ b/frontend/components/vehicle/VehicleReport.tsx @@ -548,9 +548,9 @@ export default function VehicleReport() { ) : ( driverData.map((row) => ( - + - {row.userName} + {row.user_name} {row.tripCount} diff --git a/frontend/contexts/MenuContext.tsx b/frontend/contexts/MenuContext.tsx index 1cd82a41..109264d1 100644 --- a/frontend/contexts/MenuContext.tsx +++ b/frontend/contexts/MenuContext.tsx @@ -100,10 +100,10 @@ export function MenuProvider({ children }: { children: ReactNode }) { }; useEffect(() => { - // user.companyCode가 변경되면 메뉴 다시 로드 - // console.log("🔄 MenuContext: user.companyCode 변경 감지, 메뉴 재로드", user?.companyCode); + // user.company_code가 변경되면 메뉴 다시 로드 + // console.log("🔄 MenuContext: user.company_code 변경 감지, 메뉴 재로드", user?.company_code); loadMenus(); - }, [user?.companyCode]); // companyCode 변경 시 재로드 + }, [user?.company_code]); // company_code 변경 시 재로드 return ( {children} diff --git a/frontend/hooks/useAuth.ts b/frontend/hooks/useAuth.ts index 4e261722..d975eda7 100644 --- a/frontend/hooks/useAuth.ts +++ b/frontend/hooks/useAuth.ts @@ -4,20 +4,17 @@ import { apiCall } from "@/lib/api/client"; import { AuthLogger } from "@/lib/authLogger"; interface UserInfo { - userId: string; user_id?: string; - userName: string; user_name?: string; userNameEng?: string; userNameCn?: string; deptCode?: string; - deptName?: string; + dept_name?: string; positionCode?: string; - positionName?: string; + position_name?: string; email?: string; tel?: string; cellPhone?: string; - userType?: string; user_type?: string; userTypeName?: string; authName?: string; @@ -26,7 +23,6 @@ interface UserInfo { isAdmin: boolean; sabun?: string; photo?: string | null; - companyCode?: string; company_code?: string; } @@ -129,10 +125,10 @@ export const useAuth = () => { const data = response.data; return { ...data, - user_type: data.user_type ?? data.userType, - company_code: data.company_code ?? data.companyCode, - user_id: data.user_id ?? data.userId, - user_name: data.user_name ?? data.userName, + user_type: data.user_type, + company_code: data.company_code, + user_id: data.user_id, + user_name: data.user_name, }; } @@ -197,23 +193,23 @@ export const useAuth = () => { if (userInfo) { setUser(userInfo); - const isAdminFromUser = userInfo.userId === "plm_admin" || userInfo.userType === "ADMIN"; + const isAdminFromUser = userInfo.user_id === "plm_admin" || userInfo.user_type === "ADMIN"; const finalAuthStatus = { isLoggedIn: true, isAdmin: authStatusData.isAdmin || isAdminFromUser, }; setAuthStatus(finalAuthStatus); - AuthLogger.log("AUTH_CHECK_SUCCESS", `사용자: ${userInfo.userId}, 인증: ${finalAuthStatus.isLoggedIn}`); + AuthLogger.log("AUTH_CHECK_SUCCESS", `사용자: ${userInfo.user_id}, 인증: ${finalAuthStatus.isLoggedIn}`); } else { AuthLogger.log("AUTH_CHECK_FAIL", "userInfo 조회 실패 → 토큰 기반 임시 인증 유지 시도"); try { const payload = JSON.parse(atob(token.split(".")[1])); const tempUser: UserInfo = { - userId: payload.userId || payload.id || "unknown", - userName: payload.userName || payload.name || "사용자", - companyCode: payload.companyCode || payload.company_code || "", - isAdmin: payload.userId === "plm_admin" || payload.userType === "ADMIN", + user_id: payload.user_id || payload.id || "unknown", + user_name: payload.user_name || payload.name || "사용자", + company_code: payload.company_code || "", + isAdmin: payload.user_id === "plm_admin" || payload.user_type === "ADMIN", }; setUser(tempUser); @@ -233,10 +229,10 @@ export const useAuth = () => { try { const payload = JSON.parse(atob(token.split(".")[1])); const tempUser: UserInfo = { - userId: payload.userId || payload.id || "unknown", - userName: payload.userName || payload.name || "사용자", - companyCode: payload.companyCode || payload.company_code || "", - isAdmin: payload.userId === "plm_admin" || payload.userType === "ADMIN", + user_id: payload.user_id || payload.id || "unknown", + user_name: payload.user_name || payload.name || "사용자", + company_code: payload.company_code || "", + isAdmin: payload.user_id === "plm_admin" || payload.user_type === "ADMIN", }; setUser(tempUser); @@ -448,9 +444,9 @@ export const useAuth = () => { isLoggedIn: authStatus.isLoggedIn, isAdmin: authStatus.isAdmin, - userId: user?.userId, - userName: user?.userName, - companyCode: user?.companyCode || user?.company_code, + userId: user?.user_id, + userName: user?.user_name, + companyCode: user?.company_code, login, logout, diff --git a/frontend/hooks/useLogin.ts b/frontend/hooks/useLogin.ts index 01231441..95e675df 100644 --- a/frontend/hooks/useLogin.ts +++ b/frontend/hooks/useLogin.ts @@ -15,7 +15,7 @@ export const useLogin = () => { // 상태 관리 const [formData, setFormData] = useState({ - userId: "", + user_id: "", password: "", }); const [isLoading, setIsLoading] = useState(false); @@ -64,7 +64,7 @@ export const useLogin = () => { * 입력값 검증 */ const validateForm = useCallback((): string | null => { - if (!formData.userId.trim()) { + if (!formData.user_id.trim()) { return FORM_VALIDATION.MESSAGES.USER_ID_REQUIRED; } if (!formData.password.trim()) { @@ -117,7 +117,7 @@ export const useLogin = () => { firstMenuPath?: string; popLandingPath?: string; }>("POST", AUTH_CONFIG.ENDPOINTS.LOGIN, { - userId: formData.userId, + userId: formData.user_id, password: formData.password, }); diff --git a/frontend/hooks/useMenu.ts b/frontend/hooks/useMenu.ts index 5908be63..31d390fc 100644 --- a/frontend/hooks/useMenu.ts +++ b/frontend/hooks/useMenu.ts @@ -115,7 +115,7 @@ export const useMenu = (user: any, authLoading: boolean) => { if (assignedScreens.length > 0) { const firstScreen = assignedScreens[0]; - router.push(`/screens/${firstScreen.screenId}?menuObjid=${menuObjid}`); + router.push(`/screens/${firstScreen.screen_id}?menuObjid=${menuObjid}`); return; } } diff --git a/frontend/hooks/useProfile.ts b/frontend/hooks/useProfile.ts index f96593f5..33e7d298 100644 --- a/frontend/hooks/useProfile.ts +++ b/frontend/hooks/useProfile.ts @@ -155,10 +155,10 @@ export const useProfile = (user: any, refreshUserData: () => Promise, refr ...prev, isOpen: true, formData: { - userName: user.userName || "", + userName: user.user_name || "", email: user.email || "", - deptName: user.deptName || "", - positionName: user.positionName || "", + deptName: user.dept_name || "", + positionName: user.position_name || "", locale: user.locale || "KR", // 기본값을 KR로 설정 }, selectedImage: user.photo || null, diff --git a/frontend/hooks/useScreenDataTransfer.ts b/frontend/hooks/useScreenDataTransfer.ts index 73332aa0..799aee93 100644 --- a/frontend/hooks/useScreenDataTransfer.ts +++ b/frontend/hooks/useScreenDataTransfer.ts @@ -260,7 +260,7 @@ export function useConfiguredDataTransfer(config: ScreenDataTransferConfig) { const { source, target, trigger, condition } = config; const { sendData } = useScreenDataTransfer({ - screenId: source.screenId, + screenId: source.screen_id, componentId: source.componentId, }); @@ -307,11 +307,11 @@ export function useConfiguredDataTransfer(config: ScreenDataTransferConfig) { // 전달 sendData(sourceData, { - targetScreenId: target.screenId, + targetScreenId: target.screen_id, mappings: target.mappings, trigger, }); - }, [source.fields, target.screenId, target.mappings, trigger, condition, sendData]); + }, [source.fields, target.screen_id, target.mappings, trigger, condition, sendData]); return { transfer }; } diff --git a/frontend/lib/api/auditLog.ts b/frontend/lib/api/auditLog.ts index dd8c94d7..56fd79e2 100644 --- a/frontend/lib/api/auditLog.ts +++ b/frontend/lib/api/auditLog.ts @@ -19,8 +19,8 @@ export interface AuditLogEntry { } export interface AuditLogFilters { - companyCode?: string; - userId?: string; + company_code?: string; + user_id?: string; resourceType?: string; action?: string; tableName?: string; @@ -48,8 +48,8 @@ export async function getAuditLogs( limit: number; }> { const params = new URLSearchParams(); - if (filters.companyCode) params.append("companyCode", filters.companyCode); - if (filters.userId) params.append("userId", filters.userId); + if (filters.company_code) params.append("companyCode", filters.company_code); + if (filters.user_id) params.append("userId", filters.user_id); if (filters.resourceType) params.append("resourceType", filters.resourceType); if (filters.action) params.append("action", filters.action); if (filters.tableName) params.append("tableName", filters.tableName); diff --git a/frontend/lib/api/file.ts b/frontend/lib/api/file.ts index 79726ea9..e5e0b29f 100644 --- a/frontend/lib/api/file.ts +++ b/frontend/lib/api/file.ts @@ -42,7 +42,7 @@ export const uploadFiles = async (params: { autoLink?: boolean; columnName?: string; isVirtualFileColumn?: boolean; - companyCode?: string; // 🔒 멀티테넌시: 회사 코드 + company_code?: string; // 🔒 멀티테넌시: 회사 코드 isRecordMode?: boolean; // 🆕 레코드 모드 플래그 }): Promise => { const formData = new FormData(); @@ -66,7 +66,7 @@ export const uploadFiles = async (params: { if (params.autoLink !== undefined) formData.append("auto_link", params.autoLink.toString()); if (params.columnName) formData.append("column_name", params.columnName); if (params.isVirtualFileColumn !== undefined) formData.append("is_virtual_file_column", params.isVirtualFileColumn.toString()); - if (params.companyCode) formData.append("company_code", params.companyCode); // 🔒 멀티테넌시 + if (params.company_code) formData.append("company_code", params.company_code); // 🔒 멀티테넌시 // 🆕 레코드 모드 플래그 추가 (백엔드에서 attachments 컬럼 자동 업데이트용) if (params.isRecordMode !== undefined) formData.append("is_record_mode", params.isRecordMode.toString()); diff --git a/frontend/lib/api/globalFile.ts b/frontend/lib/api/globalFile.ts index cd519514..5fa08ac4 100644 --- a/frontend/lib/api/globalFile.ts +++ b/frontend/lib/api/globalFile.ts @@ -79,7 +79,7 @@ export class GlobalFileManager { static registerFiles(files: FileInfo[], context: { uploadPage: string; componentId: string; - screenId?: number; + screen_id?: number; }): void { files.forEach(file => { const globalFileInfo: GlobalFileInfo = { @@ -87,7 +87,7 @@ export class GlobalFileManager { uploadPage: context.uploadPage, uploadTime: new Date().toISOString(), componentId: context.componentId, - screen_id: context.screenId, + screen_id: context.screen_id, accessible: true, }; this.registerFile(globalFileInfo); diff --git a/frontend/lib/api/multiTableExcel.ts b/frontend/lib/api/multiTableExcel.ts index faa75a2b..d2a76b99 100644 --- a/frontend/lib/api/multiTableExcel.ts +++ b/frontend/lib/api/multiTableExcel.ts @@ -64,7 +64,7 @@ export async function autoDetectMultiTableConfig( ): Promise<{ success: boolean; data?: TableChainConfig; message?: string }> { try { const params: Record = { rootTable }; - if (screenId) params.screenId = screenId; + if (screenId) params.screen_id = screenId; const response = await apiClient.get("/data/multi-table/auto-detect", { params, diff --git a/frontend/lib/api/multilang.ts b/frontend/lib/api/multilang.ts index 076a4948..9f71fe6c 100644 --- a/frontend/lib/api/multilang.ts +++ b/frontend/lib/api/multilang.ts @@ -177,14 +177,14 @@ export async function getLanguages(): Promise> { * 다국어 키 목록 조회 */ export async function getLangKeys(params?: { - companyCode?: string; + company_code?: string; menuCode?: string; categoryId?: number; searchText?: string; }): Promise> { try { const queryParams = new URLSearchParams(); - if (params?.companyCode) queryParams.append("companyCode", params.companyCode); + if (params?.company_code) queryParams.append("companyCode", params.company_code); if (params?.menuCode) queryParams.append("menuCode", params.menuCode); if (params?.categoryId) queryParams.append("categoryId", params.categoryId.toString()); if (params?.searchText) queryParams.append("searchText", params.searchText); diff --git a/frontend/lib/api/screen.ts b/frontend/lib/api/screen.ts index 5e9d688b..9ae2f820 100644 --- a/frontend/lib/api/screen.ts +++ b/frontend/lib/api/screen.ts @@ -13,12 +13,12 @@ import { function mapRawScreen(raw: any): ScreenDefinition { const createdRaw = raw.createdDate ?? raw.created_date; const updatedRaw = raw.updatedDate ?? raw.updated_date; - const screenId = raw.screenId ?? raw.screen_id; + const screenId = raw.screen_id ?? raw["screenId"]; const screenName = raw.screenName ?? raw.screen_name; const screenCode = raw.screenCode ?? raw.screen_code; const tableName = raw.tableName ?? raw.table_name; const tableLabel = raw.tableLabel ?? raw.table_label; - const companyCode = raw.companyCode ?? raw.company_code; + const companyCode = raw.company_code ?? raw["companyCode"]; const isActive = raw.isActive ?? raw.is_active; const createdDate = createdRaw ? new Date(createdRaw) : undefined; const updatedDate = updatedRaw ? new Date(updatedRaw) : undefined; diff --git a/frontend/lib/api/vehicleTrip.ts b/frontend/lib/api/vehicleTrip.ts index 436e4589..9978dad6 100644 --- a/frontend/lib/api/vehicleTrip.ts +++ b/frontend/lib/api/vehicleTrip.ts @@ -257,8 +257,8 @@ export interface SummaryReport { } export interface DriverStat { - userId: string; - userName: string; + user_id: string; + user_name: string; tripCount: number; completedCount: number; totalDistance: number; diff --git a/frontend/lib/authLogger.ts b/frontend/lib/authLogger.ts index f30284ab..02bfb5a9 100644 --- a/frontend/lib/authLogger.ts +++ b/frontend/lib/authLogger.ts @@ -56,7 +56,7 @@ function getTokenSummary(): string { const remainHour = Math.floor(remainMin / 60); const min = remainMin % 60; - return `유효(${remainHour}h${min}m 남음, user:${payload.userId})`; + return `유효(${remainHour}h${min}m 남음, user:${payload.user_id})`; } catch { return "파싱실패"; } diff --git a/frontend/lib/registry/components/conditional-container/ConditionalSectionViewer.tsx b/frontend/lib/registry/components/conditional-container/ConditionalSectionViewer.tsx index d55e12d0..c3c9c742 100644 --- a/frontend/lib/registry/components/conditional-container/ConditionalSectionViewer.tsx +++ b/frontend/lib/registry/components/conditional-container/ConditionalSectionViewer.tsx @@ -81,7 +81,7 @@ export function ConditionalSectionViewer({ setComponents(layout.components || []); setScreenInfo({ id: screenId, - tableName: screen.tableName, + tableName: screen.table_name, }); setScreenResolution(layout.screenResolution || null); } catch (error) { @@ -196,7 +196,7 @@ export function ConditionalSectionViewer({ tableName={screenInfo?.tableName} userId={userId} userName={userName} - companyCode={user?.companyCode} + companyCode={user?.company_code} formData={enhancedFormData} onFormDataChange={onFormDataChange} groupedData={groupedData} diff --git a/frontend/lib/registry/components/mail-recipient-selector/MailRecipientSelectorComponent.tsx b/frontend/lib/registry/components/mail-recipient-selector/MailRecipientSelectorComponent.tsx index 505d6f4d..611a491e 100644 --- a/frontend/lib/registry/components/mail-recipient-selector/MailRecipientSelectorComponent.tsx +++ b/frontend/lib/registry/components/mail-recipient-selector/MailRecipientSelectorComponent.tsx @@ -150,13 +150,13 @@ export const MailRecipientSelectorComponent: React.FC< // 수신자 추가 (내부 사용자) const addInternalRecipient = useCallback( (user: InternalUser, type: "to" | "cc") => { - const email = user.email || `${user.userId}@company.com`; + const email = user.email || `${user.user_id}@company.com`; const newRecipient: Recipient = { - id: `internal-${user.userId}`, + id: `internal-${user.user_id}`, email, - name: user.userName, + name: user.user_name, type: "internal", - userId: user.userId, + userId: user.user_id, }; if (type === "to") { @@ -254,7 +254,7 @@ export const MailRecipientSelectorComponent: React.FC< const isUserSelected = useCallback( (user: InternalUser, type: "to" | "cc") => { const recipients = type === "to" ? toRecipients : ccRecipients; - const userEmail = user.email || `${user.userId}@company.com`; + const userEmail = user.email || `${user.user_id}@company.com`; return recipients.some((r) => r.email === userEmail); }, [toRecipients, ccRecipients] @@ -317,13 +317,13 @@ export const MailRecipientSelectorComponent: React.FC< 검색 결과가 없습니다. {internalUsers.map((user, index) => { - const userEmail = user.email || `${user.userId}@company.com`; + const userEmail = user.email || `${user.user_id}@company.com`; const selected = isUserSelected(user, type); - const uniqueKey = `${user.userId}-${index}`; + const uniqueKey = `${user.user_id}-${index}`; return ( { if (!selected) { addInternalRecipient(user, type); @@ -336,7 +336,7 @@ export const MailRecipientSelectorComponent: React.FC< >

- {user.userName} + {user.user_name} {userEmail} {user.deptName && ` | ${user.deptName}`} diff --git a/frontend/lib/registry/components/mail-recipient-selector/types.ts b/frontend/lib/registry/components/mail-recipient-selector/types.ts index abfc4c9f..7f2a577e 100644 --- a/frontend/lib/registry/components/mail-recipient-selector/types.ts +++ b/frontend/lib/registry/components/mail-recipient-selector/types.ts @@ -53,10 +53,10 @@ export interface MailRecipientSelectorProps { isInteractive?: boolean; } -// 내부 사용자 정보 (API 응답 - camelCase) +// 내부 사용자 정보 (API 응답 - snake_case) export interface InternalUser { - userId: string; - userName: string; + user_id: string; + user_name: string; email?: string; deptName?: string; positionName?: string; diff --git a/frontend/lib/registry/components/related-data-buttons/RelatedDataButtonsConfigPanel.tsx b/frontend/lib/registry/components/related-data-buttons/RelatedDataButtonsConfigPanel.tsx index 437ea625..a1ef05fc 100644 --- a/frontend/lib/registry/components/related-data-buttons/RelatedDataButtonsConfigPanel.tsx +++ b/frontend/lib/registry/components/related-data-buttons/RelatedDataButtonsConfigPanel.tsx @@ -40,9 +40,9 @@ const ScreenSelector: React.FC = ({ value, onChange, placeh const response = await screenApi.getScreens({ size: 500 }); if (response.data) { setScreens(response.data.map((s: any) => ({ - screenId: s.screenId, - screenName: s.screenName || s.name || `화면 ${s.screenId}`, - tableName: s.tableName || s.table_name, + screenId: s.screen_id, + screenName: s.screen_name || s.name || `화면 ${s.screen_id}`, + tableName: s.table_name, }))); } } catch (error) { @@ -132,7 +132,7 @@ export const RelatedDataButtonsConfigPanel: React.FC ({ - tableName: t.tableName || t.table_name, + tableName: t.table_name, displayName: t.tableLabel || t.table_label || t.displayName, }))); } @@ -196,8 +196,8 @@ export const RelatedDataButtonsConfigPanel: React.FC ({ columnName: col.column_name || col.columnName, @@ -131,12 +131,12 @@ export function ScreenSplitPanelConfigPanel({ config = {}, onChange }: ScreenSpl const screenData = await screenApi.getScreen(localConfig.rightScreenId); // 1. 메인 화면의 테이블 (있는 경우) - if (screenData?.tableName) { - const columnsResponse = await getTableColumns(screenData.tableName); + if (screenData?.table_name) { + const columnsResponse = await getTableColumns(screenData.table_name); if (columnsResponse.success && columnsResponse.data?.columns) { tables.push({ - tableName: screenData.tableName, - screenName: screenData.screenName || "메인 화면", + tableName: screenData.table_name, + screenName: screenData.screen_name || "메인 화면", columns: columnsResponse.data.columns.map((col: any) => ({ columnName: col.column_name || col.columnName, columnLabel: col.column_label || col.columnLabel || col.column_name || col.columnName, @@ -192,20 +192,20 @@ export function ScreenSplitPanelConfigPanel({ config = {}, onChange }: ScreenSpl for (const embeddedScreenId of embeddedScreenIds) { try { const embeddedScreen = await screenApi.getScreen(embeddedScreenId); - if (embeddedScreen?.tableName) { + if (embeddedScreen?.table_name) { // 이미 추가된 테이블인지 확인 - if (!tables.find(t => t.tableName === embeddedScreen.tableName)) { - const columnsResponse = await getTableColumns(embeddedScreen.tableName); + if (!tables.find(t => t.tableName === embeddedScreen.table_name)) { + const columnsResponse = await getTableColumns(embeddedScreen.table_name); if (columnsResponse.success && columnsResponse.data?.columns) { tables.push({ - tableName: embeddedScreen.tableName, - screenName: embeddedScreen.screenName || `화면 ${embeddedScreenId}`, + tableName: embeddedScreen.table_name, + screenName: embeddedScreen.screen_name || `화면 ${embeddedScreenId}`, columns: columnsResponse.data.columns.map((col: any) => ({ columnName: col.column_name || col.columnName, columnLabel: col.column_label || col.columnLabel || col.column_name || col.columnName, })), }); - console.log("✅ 테이블 추가:", embeddedScreen.tableName); + console.log("✅ 테이블 추가:", embeddedScreen.table_name); } } } diff --git a/frontend/lib/registry/components/split-panel-layout/SplitPanelLayoutConfigPanel.tsx b/frontend/lib/registry/components/split-panel-layout/SplitPanelLayoutConfigPanel.tsx index 6e305501..31187288 100644 --- a/frontend/lib/registry/components/split-panel-layout/SplitPanelLayoutConfigPanel.tsx +++ b/frontend/lib/registry/components/split-panel-layout/SplitPanelLayoutConfigPanel.tsx @@ -91,15 +91,15 @@ const GroupByColumnsSelector: React.FC<{ ) : (
{columns.map((col) => ( -
+
toggleColumn(col.columnName)} + id={`groupby-${col.column_name}`} + checked={selectedColumns.includes(col.column_name)} + onCheckedChange={() => toggleColumn(col.column_name)} /> -
))} diff --git a/frontend/lib/registry/components/split-panel-layout2/ActionButtonConfigModal.tsx b/frontend/lib/registry/components/split-panel-layout2/ActionButtonConfigModal.tsx index 5efd59b8..84e51c01 100644 --- a/frontend/lib/registry/components/split-panel-layout2/ActionButtonConfigModal.tsx +++ b/frontend/lib/registry/components/split-panel-layout2/ActionButtonConfigModal.tsx @@ -218,9 +218,9 @@ export const ActionButtonConfigModal: React.FC = ( } const transformedScreens = screenList.map((s: any) => ({ - screen_id: s.screenId ?? s.screen_id ?? s.id, - screen_name: s.screenName ?? s.screen_name ?? s.name ?? `화면 ${s.screenId || s.screen_id || s.id}`, - screen_code: s.screenCode ?? s.screen_code ?? s.code ?? "", + screen_id: s.screen_id, + screen_name: s.screen_name ?? `화면 ${s.screen_id}`, + screen_code: s.screen_code ?? "", })); setScreens(transformedScreens); diff --git a/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2ConfigPanel.tsx b/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2ConfigPanel.tsx index 7a529cc9..9d4469cd 100644 --- a/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2ConfigPanel.tsx +++ b/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2ConfigPanel.tsx @@ -131,10 +131,9 @@ export const SplitPanelLayout2ConfigPanel: React.FC 0) { - // 백엔드에서 카멜케이스(tableName)로 반환하므로 둘 다 처리 const transformedTables = tableList.map((t: any) => ({ - table_name: t.tableName ?? t.table_name ?? t.name ?? "", - table_comment: t.displayName ?? t.table_comment ?? t.description ?? "", + table_name: t.table_name ?? t.name ?? "", + table_comment: t.display_name ?? t.table_comment ?? t.description ?? "", })); console.log("[loadTables] 변환된 테이블 목록:", transformedTables); setTables(transformedTables); @@ -171,11 +170,10 @@ export const SplitPanelLayout2ConfigPanel: React.FC 0) { - // 백엔드에서 카멜케이스(screenId, screenName)로 반환하므로 둘 다 처리 const transformedScreens = screenList.map((s: any) => ({ - screen_id: s.screenId ?? s.screen_id ?? s.id, - screen_name: s.screenName ?? s.screen_name ?? s.name ?? `화면 ${s.screenId || s.screen_id || s.id}`, - screen_code: s.screenCode ?? s.screen_code ?? s.code ?? "", + screen_id: s.screen_id, + screen_name: s.screen_name ?? `화면 ${s.screen_id}`, + screen_code: s.screen_code ?? "", })); console.log("[loadScreens] 변환된 화면 목록:", transformedScreens); setScreens(transformedScreens); @@ -213,11 +211,10 @@ export const SplitPanelLayout2ConfigPanel: React.FC 0) { - // 백엔드에서 카멜케이스(columnName)로 반환하므로 둘 다 처리 const transformedColumns = columnList.map((c: any) => ({ - column_name: c.columnName ?? c.column_name ?? c.name ?? "", - data_type: c.dataType ?? c.data_type ?? c.type ?? "", - column_comment: c.displayName ?? c.column_comment ?? c.label ?? "", + column_name: c.column_name ?? c.name ?? "", + data_type: c.data_type ?? c.type ?? "", + column_comment: c.display_name ?? c.column_comment ?? c.label ?? "", })); console.log(`[loadColumns] ${side} 변환된 컬럼 목록:`, transformedColumns); @@ -279,9 +276,9 @@ export const SplitPanelLayout2ConfigPanel: React.FC ({ - column_name: c.columnName ?? c.column_name ?? c.name ?? "", - data_type: c.dataType ?? c.data_type ?? c.type ?? "", - column_comment: c.displayName ?? c.column_comment ?? c.label ?? "", + column_name: c.column_name ?? c.name ?? "", + data_type: c.data_type ?? c.type ?? "", + column_comment: c.display_name ?? c.column_comment ?? c.label ?? "", })); } @@ -619,9 +616,9 @@ export const SplitPanelLayout2ConfigPanel: React.FC ({ - column_name: c.columnName ?? c.column_name ?? c.name ?? "", - data_type: c.dataType ?? c.data_type ?? c.type ?? "", - column_comment: c.displayName ?? c.column_comment ?? c.label ?? "", + column_name: c.column_name ?? c.name ?? "", + data_type: c.data_type ?? c.type ?? "", + column_comment: c.display_name ?? c.column_comment ?? c.label ?? "", })); setJoinTableColumns(transformedColumns); } catch (error) { diff --git a/frontend/lib/registry/components/v2-file-upload/FileUploadComponent.tsx b/frontend/lib/registry/components/v2-file-upload/FileUploadComponent.tsx index 5f6638b7..f9b0e0d2 100644 --- a/frontend/lib/registry/components/v2-file-upload/FileUploadComponent.tsx +++ b/frontend/lib/registry/components/v2-file-upload/FileUploadComponent.tsx @@ -623,7 +623,7 @@ const FileUploadComponent: React.FC = ({ } // 🔒 현재 사용자의 회사 코드 가져오기 (멀티테넌시 격리) - const userCompanyCode = user?.companyCode || (window as any).__user__?.companyCode; + const userCompanyCode = user?.company_code || (window as any).__user__?.company_code; // 🔑 레코드 모드일 때는 effectiveTableName을 우선 사용 const finalLinkedTable = effectiveIsRecordMode diff --git a/frontend/lib/registry/components/v2-item-routing/ItemRoutingConfigPanel.tsx b/frontend/lib/registry/components/v2-item-routing/ItemRoutingConfigPanel.tsx index f6fefd2e..c1092be5 100644 --- a/frontend/lib/registry/components/v2-item-routing/ItemRoutingConfigPanel.tsx +++ b/frontend/lib/registry/components/v2-item-routing/ItemRoutingConfigPanel.tsx @@ -24,20 +24,20 @@ import { ItemRoutingConfig, ProcessColumnDef } from "./types"; import { defaultConfig } from "./config"; interface TableInfo { - tableName: string; - displayName?: string; + table_name: string; + display_name?: string; } interface ColumnInfo { - columnName: string; - displayName?: string; + column_name: string; + display_name?: string; dataType?: string; } interface ScreenInfo { - screenId: number; - screenName: string; - screenCode: string; + screen_id: number; + screen_name: string; + screen_code: string; } // 테이블 셀렉터 Combobox @@ -53,7 +53,7 @@ function TableSelector({ loading: boolean; }) { const [open, setOpen] = useState(false); - const selected = tables.find((t) => t.tableName === value); + const selected = tables.find((t) => t.table_name === value); return ( @@ -68,7 +68,7 @@ function TableSelector({ {loading ? "로딩 중..." : selected - ? selected.displayName || selected.tableName + ? selected.display_name || selected.table_name : "테이블 선택"} @@ -83,10 +83,10 @@ function TableSelector({ {tables.map((t) => ( { - onChange(t.tableName); + onChange(t.table_name); setOpen(false); }} className="text-xs" @@ -94,16 +94,16 @@ function TableSelector({
- {t.displayName || t.tableName} + {t.display_name || t.table_name} - {t.displayName && ( + {t.display_name && ( - {t.tableName} + {t.table_name} )}
@@ -157,7 +157,7 @@ function ColumnSelector({ load(); }, [tableName]); - const selected = columns.find((c) => c.columnName === value); + const selected = columns.find((c) => c.column_name === value); return ( @@ -174,7 +174,7 @@ function ColumnSelector({ : !tableName ? "테이블 먼저 선택" : selected - ? selected.displayName || selected.columnName + ? selected.display_name || selected.column_name : label || "컬럼 선택"} @@ -189,10 +189,10 @@ function ColumnSelector({ {columns.map((c) => ( { - onChange(c.columnName); + onChange(c.column_name); setOpen(false); }} className="text-xs" @@ -200,16 +200,16 @@ function ColumnSelector({
- {c.displayName || c.columnName} + {c.display_name || c.column_name} - {c.displayName && ( + {c.display_name && ( - {c.columnName} + {c.column_name} )}
@@ -243,9 +243,9 @@ function ScreenSelector({ const res = await screenApi.getScreens({ page: 1, size: 1000 }); setScreens( res.data.map((s: any) => ({ - screenId: s.screenId, - screenName: s.screenName, - screenCode: s.screenCode, + screen_id: s.screen_id, + screen_name: s.screen_name, + screen_code: s.screen_code ?? "", })) ); } catch { @@ -257,7 +257,7 @@ function ScreenSelector({ load(); }, []); - const selected = screens.find((s) => s.screenId === value); + const selected = screens.find((s) => s.screen_id === value); return ( @@ -272,7 +272,7 @@ function ScreenSelector({ {loading ? "로딩 중..." : selected - ? `${selected.screenName} (${selected.screenId})` + ? `${selected.screen_name} (${selected.screen_id})` : "화면 선택"} @@ -287,10 +287,10 @@ function ScreenSelector({ {screens.map((s) => ( { - onChange(s.screenId === value ? undefined : s.screenId); + onChange(s.screen_id === value ? undefined : s.screen_id); setOpen(false); }} className="text-xs" @@ -298,13 +298,13 @@ function ScreenSelector({
- {s.screenName} + {s.screen_name} - {s.screenCode} (ID: {s.screenId}) + {s.screen_code} (ID: {s.screen_id})
@@ -352,8 +352,8 @@ function ProcessColumnSelector({ cols.push( ...res2.data.columns.map((c: any) => ({ ...c, - columnName: c.columnName, - displayName: `[${processTable}] ${c.displayName || c.columnName}`, + column_name: c.column_name, + display_name: `[${processTable}] ${c.display_name || c.column_name}`, })) ); } @@ -368,7 +368,7 @@ function ProcessColumnSelector({ loadAll(); }, [tableName, processTable]); - const selected = columns.find((c) => c.columnName === value); + const selected = columns.find((c) => c.column_name === value); return ( @@ -379,7 +379,7 @@ function ProcessColumnSelector({ className="h-7 w-24 justify-between text-[10px]" disabled={loading} > - {selected ? selected.displayName || selected.columnName : value || "선택"} + {selected ? selected.display_name || selected.column_name : value || "선택"} @@ -393,10 +393,10 @@ function ProcessColumnSelector({ {columns.map((c) => ( { - onChange(c.columnName); + onChange(c.column_name); setOpen(false); }} className="text-xs" @@ -404,10 +404,10 @@ function ProcessColumnSelector({ - {c.displayName || c.columnName} + {c.display_name || c.column_name} ))} diff --git a/frontend/lib/registry/pop-components/pop-work-detail/PopWorkDetailComponent.tsx b/frontend/lib/registry/pop-components/pop-work-detail/PopWorkDetailComponent.tsx index 963d2148..02cf0eb9 100644 --- a/frontend/lib/registry/pop-components/pop-work-detail/PopWorkDetailComponent.tsx +++ b/frontend/lib/registry/pop-components/pop-work-detail/PopWorkDetailComponent.tsx @@ -237,7 +237,7 @@ export function PopWorkDetailComponent({ ...(isPassed !== null ? [{ type: "data-update", targetTable: "process_work_result", targetColumn: "is_passed", value: isPassed, items: [{ id: rowId }] }] : []), - { type: "data-update", targetTable: "process_work_result", targetColumn: "recorded_by", value: user?.userId ?? "", items: [{ id: rowId }] }, + { type: "data-update", targetTable: "process_work_result", targetColumn: "recorded_by", value: user?.user_id ?? "", items: [{ id: rowId }] }, { type: "data-update", targetTable: "process_work_result", targetColumn: "recorded_at", value: new Date().toISOString(), items: [{ id: rowId }] }, ], data: { items: [{ id: rowId }], fieldValues: {} }, @@ -251,7 +251,7 @@ export function PopWorkDetailComponent({ result_value: resultValue, status: newStatus, is_passed: isPassed, - recorded_by: user?.userId ?? null, + recorded_by: user?.user_id ?? null, recorded_at: new Date().toISOString(), } : r @@ -267,7 +267,7 @@ export function PopWorkDetailComponent({ }); } }, - [user?.userId] + [user?.user_id] ); // ======================================== diff --git a/frontend/lib/services/enhancedFormService.ts b/frontend/lib/services/enhancedFormService.ts index ea6be5eb..975775bb 100644 --- a/frontend/lib/services/enhancedFormService.ts +++ b/frontend/lib/services/enhancedFormService.ts @@ -70,7 +70,7 @@ export class EnhancedFormService { console.log("🚀 향상된 폼 저장 시작:", { tableName, - screenId: screenInfo.screenId, + screenId: screenInfo.screen_id ?? screenInfo.screenId, dataKeys: Object.keys(formData), componentsCount: components.length, }); @@ -105,7 +105,7 @@ export class EnhancedFormService { // 3. 서버 저장 수행 const saveStart = performance.now(); - const saveResult = await this.performServerSave(screenInfo.screenId, tableName, processedData, options); + const saveResult = await this.performServerSave(screenInfo.screen_id ?? screenInfo.screenId, tableName, processedData, options); saveTime = performance.now() - saveStart; if (!saveResult.success) { diff --git a/frontend/lib/utils/buttonActions.ts b/frontend/lib/utils/buttonActions.ts index 6ab0c123..64441182 100644 --- a/frontend/lib/utils/buttonActions.ts +++ b/frontend/lib/utils/buttonActions.ts @@ -3358,7 +3358,7 @@ export class ButtonActionExecutor { } // 3. 동적 모달 제목 생성 - let finalTitle = config.modalTitle || screenInfo?.screenName || "데이터 등록"; + let finalTitle = config.modalTitle || (screenInfo?.screen_name ?? screenInfo?.screenName) || "데이터 등록"; // 블록 기반 제목 처리 if (config.modalTitleBlocks?.length) { diff --git a/frontend/types/auth.ts b/frontend/types/auth.ts index 574eff59..c308efd7 100644 --- a/frontend/types/auth.ts +++ b/frontend/types/auth.ts @@ -3,7 +3,7 @@ */ export interface LoginFormData { - userId: string; + user_id: string; password: string; } diff --git a/frontend/types/userHistory.ts b/frontend/types/userHistory.ts index f51f68c5..6b43bc98 100644 --- a/frontend/types/userHistory.ts +++ b/frontend/types/userHistory.ts @@ -2,23 +2,23 @@ export interface UserHistory { no?: number; // 순번 (프론트엔드에서 추가) - rowNum?: number; // 행 번호 (쿼리에서 생성) + row_num?: number; // 행 번호 (쿼리에서 생성) - // USER_INFO_HISTORY 테이블 컬럼들 (camelCase) + // USER_INFO_HISTORY 테이블 컬럼들 (snake_case) sabun?: string; // 사번 - userId: string; // 사용자 ID - userName?: string; // 사용자 이름 - deptCode?: string; // 부서 코드 - deptName?: string; // 부서명 - userTypeName?: string; // 사용자 타입명 (회사명) - historyType?: string; // 이력유형 + user_id: string; // 사용자 ID + user_name?: string; // 사용자 이름 + dept_code?: string; // 부서 코드 + dept_name?: string; // 부서명 + user_type_name?: string; // 사용자 타입명 (회사명) + history_type?: string; // 이력유형 writer?: string; // 작성자 ID - regDate?: string; // 등록일시 + reg_date?: string; // 등록일시 status?: string; // 상태 // 조인된 컬럼들 - writerName?: string; // 작성자명 (JOIN으로 가져옴) - regDateTitle?: string; // 작성일 (YYYY-MM-DD 형식) + writer_name?: string; // 작성자명 (JOIN으로 가져옴) + reg_date_title?: string; // 작성일 (YYYY-MM-DD 형식) } // API 응답 타입 diff --git a/frontend/types/v2-form.ts b/frontend/types/v2-form.ts index 0b1d074d..ad04f4cd 100644 --- a/frontend/types/v2-form.ts +++ b/frontend/types/v2-form.ts @@ -175,14 +175,14 @@ export type DataTransferTrigger = export interface ScreenDataTransferConfig { // 소스 (데이터를 보내는 쪽) source: { - screenId?: number; + screen_id?: number; componentId?: string; fields: string[]; // 전달할 필드들 }; - + // 타겟 (데이터를 받는 쪽) target: { - screenId?: number; + screen_id?: number; componentId?: string; mappings: FieldMapping[]; };