diff --git a/frontend/app/(main)/admin/audit-log/page.tsx b/frontend/app/(main)/admin/audit-log/page.tsx index aa72386f..74cb550b 100644 --- a/frontend/app/(main)/admin/audit-log/page.tsx +++ b/frontend/app/(main)/admin/audit-log/page.tsx @@ -69,33 +69,33 @@ const RESOURCE_TYPE_CONFIG: Record< string, { label: string; icon: React.ElementType; color: string } > = { - MENU: { label: "메뉴", icon: Layout, color: "bg-blue-100 text-blue-700" }, + MENU: { label: "메뉴", icon: Layout, color: "bg-primary/10 text-primary" }, SCREEN: { label: "화면", icon: Monitor, color: "bg-purple-100 text-purple-700" }, SCREEN_LAYOUT: { label: "레이아웃", icon: Monitor, color: "bg-purple-100 text-purple-700" }, - FLOW: { label: "플로우", icon: GitBranch, color: "bg-green-100 text-green-700" }, - FLOW_STEP: { label: "플로우 스텝", icon: GitBranch, color: "bg-green-100 text-green-700" }, - USER: { label: "사용자", icon: User, color: "bg-orange-100 text-orange-700" }, - ROLE: { label: "권한", icon: Shield, color: "bg-red-100 text-red-700" }, - PERMISSION: { label: "권한", icon: Shield, color: "bg-red-100 text-red-700" }, + FLOW: { label: "플로우", icon: GitBranch, color: "bg-emerald-100 text-emerald-700" }, + FLOW_STEP: { label: "플로우 스텝", icon: GitBranch, color: "bg-emerald-100 text-emerald-700" }, + USER: { label: "사용자", icon: User, color: "bg-amber-100 text-orange-700" }, + ROLE: { label: "권한", icon: Shield, color: "bg-destructive/10 text-destructive" }, + PERMISSION: { label: "권한", icon: Shield, color: "bg-destructive/10 text-destructive" }, COMPANY: { label: "회사", icon: Building2, color: "bg-indigo-100 text-indigo-700" }, CODE_CATEGORY: { label: "코드 카테고리", icon: Hash, color: "bg-cyan-100 text-cyan-700" }, CODE: { label: "코드", icon: Hash, color: "bg-cyan-100 text-cyan-700" }, - DATA: { label: "데이터", icon: Database, color: "bg-gray-100 text-gray-700" }, - TABLE: { label: "테이블", icon: Database, color: "bg-gray-100 text-gray-700" }, + DATA: { label: "데이터", icon: Database, color: "bg-muted text-foreground" }, + TABLE: { label: "테이블", icon: Database, color: "bg-muted text-foreground" }, NUMBERING_RULE: { label: "채번 규칙", icon: FileText, color: "bg-amber-100 text-amber-700" }, BATCH: { label: "배치", icon: RefreshCw, color: "bg-teal-100 text-teal-700" }, }; const ACTION_CONFIG: Record = { CREATE: { label: "생성", color: "bg-emerald-100 text-emerald-700" }, - UPDATE: { label: "수정", color: "bg-blue-100 text-blue-700" }, - DELETE: { label: "삭제", color: "bg-red-100 text-red-700" }, + UPDATE: { label: "수정", color: "bg-primary/10 text-primary" }, + DELETE: { label: "삭제", color: "bg-destructive/10 text-destructive" }, COPY: { label: "복사", color: "bg-violet-100 text-violet-700" }, - LOGIN: { label: "로그인", color: "bg-gray-100 text-gray-700" }, + LOGIN: { label: "로그인", color: "bg-muted text-foreground" }, STATUS_CHANGE: { label: "상태변경", color: "bg-amber-100 text-amber-700" }, BATCH_CREATE: { label: "배치생성", color: "bg-emerald-100 text-emerald-700" }, - BATCH_UPDATE: { label: "배치수정", color: "bg-blue-100 text-blue-700" }, - BATCH_DELETE: { label: "배치삭제", color: "bg-red-100 text-red-700" }, + BATCH_UPDATE: { label: "배치수정", color: "bg-primary/10 text-primary" }, + BATCH_DELETE: { label: "배치삭제", color: "bg-destructive/10 text-destructive" }, }; function formatDateTime(dateStr: string): string { @@ -203,12 +203,12 @@ function renderChanges(changes: Record) { 항목 {hasBefore && ( - + 변경 전 )} {hasAfter && ( - + 변경 후 )} @@ -234,7 +234,7 @@ function renderChanges(changes: Record) { {hasBefore && ( {row.beforeVal !== null ? ( - + {row.beforeVal} ) : ( @@ -245,7 +245,7 @@ function renderChanges(changes: Record) { {hasAfter && ( {row.afterVal !== null ? ( - + {row.afterVal} ) : ( diff --git a/frontend/app/(main)/admin/automaticMng/batchmngList/create/page.tsx b/frontend/app/(main)/admin/automaticMng/batchmngList/create/page.tsx index 1647523e..a4e1095c 100644 --- a/frontend/app/(main)/admin/automaticMng/batchmngList/create/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/batchmngList/create/page.tsx @@ -311,10 +311,10 @@ export default function BatchCreatePage() { {/* 매핑 설정 */}
{/* FROM 섹션 */} - - - FROM (원본 데이터베이스) -

+ + + FROM (원본 데이터베이스) +

1단계: 커넥션을 선택하세요 → 2단계: 테이블을 선택하세요 → 3단계: 컬럼을 클릭해서 매핑하세요

@@ -365,7 +365,7 @@ export default function BatchCreatePage() { {/* FROM 컬럼 목록 */} {fromTable && (
- +
{fromColumns.map((column) => (
handleFromColumnClick(column)} className={`p-3 border rounded cursor-pointer transition-colors ${ selectedFromColumn?.column_name === column.column_name - ? 'bg-green-100 border-green-300' - : 'hover:bg-gray-50 border-gray-200' + ? 'bg-emerald-100 border-green-300' + : 'hover:bg-muted border-border' }`} >
{column.column_name}
-
{column.data_type}
+
{column.data_type}
))} {fromColumns.length === 0 && fromTable && ( -
+
컬럼을 불러오는 중...
)} @@ -393,10 +393,10 @@ export default function BatchCreatePage() { {/* TO 섹션 */} - - - TO (대상 데이터베이스) -

+ + + TO (대상 데이터베이스) +

FROM에서 컬럼을 선택한 후, 여기서 대상 컬럼을 클릭하면 매핑됩니다

@@ -447,7 +447,7 @@ export default function BatchCreatePage() { {/* TO 컬럼 목록 */} {toTable && (
- +
{toColumns.map((column) => (
handleToColumnClick(column)} className={`p-3 border rounded cursor-pointer transition-colors ${ selectedFromColumn - ? 'hover:bg-red-50 border-gray-200' - : 'bg-gray-100 border-gray-300 cursor-not-allowed' + ? 'hover:bg-destructive/10 border-border' + : 'bg-muted border-input cursor-not-allowed' }`} >
{column.column_name}
-
{column.data_type}
+
{column.data_type}
))} {toColumns.length === 0 && toTable && ( -
+
컬럼을 불러오는 중...
)} @@ -484,22 +484,22 @@ export default function BatchCreatePage() {
{mappings.map((mapping, index) => ( -
+
{mapping.from_table_name}.{mapping.from_column_name}
-
+
{mapping.from_column_type}
- +
{mapping.to_table_name}.{mapping.to_column_name}
-
+
{mapping.to_column_type}
@@ -508,7 +508,7 @@ export default function BatchCreatePage() { variant="ghost" size="sm" onClick={() => removeMapping(index)} - className="text-red-600 hover:text-red-700" + className="text-destructive hover:text-destructive" > diff --git a/frontend/app/(main)/admin/automaticMng/batchmngList/edit/[id]/page.tsx b/frontend/app/(main)/admin/automaticMng/batchmngList/edit/[id]/page.tsx index c72bfc40..554cd9a5 100644 --- a/frontend/app/(main)/admin/automaticMng/batchmngList/edit/[id]/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/batchmngList/edit/[id]/page.tsx @@ -815,7 +815,7 @@ export default function BatchEditPage() { )} -

+

{authTokenMode === "direct" ? "API 호출 시 Authorization 헤더에 사용할 토큰을 입력하세요." : "auth_tokens 테이블에서 선택한 서비스의 최신 토큰을 사용합니다."} @@ -874,7 +874,7 @@ export default function BatchEditPage() { onChange={(e) => setDataArrayPath(e.target.value)} placeholder="response (예: data.items, results)" /> -

+

API 응답에서 배열 데이터가 있는 경로를 입력하세요. 비워두면 응답 전체를 사용합니다.
예시: response, data.items, result.list @@ -902,7 +902,7 @@ export default function BatchEditPage() { className="min-h-[100px]" rows={5} /> -

API 호출 시 함께 전송할 JSON 데이터를 입력하세요.

+

API 호출 시 함께 전송할 JSON 데이터를 입력하세요.

)} @@ -910,7 +910,7 @@ export default function BatchEditPage() {
-

특정 사용자나 조건으로 데이터를 조회할 때 사용합니다.

+

특정 사용자나 조건으로 데이터를 조회할 때 사용합니다.

@@ -967,26 +967,26 @@ export default function BatchEditPage() { } /> {apiParamSource === "dynamic" && ( -

+

동적값은 배치 실행 시 설정된 값으로 치환됩니다. 예: {"{{user_id}}"} → 실제 사용자 ID

)}
{apiParamType === "url" && ( -
-
URL 파라미터 예시
-
+
+
URL 파라미터 예시
+
엔드포인트: /api/users/{`{${apiParamName || "userId"}}`}
-
실제 호출: /api/users/{apiParamValue || "123"}
+
실제 호출: /api/users/{apiParamValue || "123"}
)} {apiParamType === "query" && ( -
-
쿼리 파라미터 예시
-
+
+
쿼리 파라미터 예시
+
실제 호출: {mappings[0]?.from_table_name || "/api/users"}?{apiParamName || "userId"}= {apiParamValue || "123"}
diff --git a/frontend/app/(main)/admin/automaticMng/flowMgmtList/[id]/page.tsx b/frontend/app/(main)/admin/automaticMng/flowMgmtList/[id]/page.tsx index c492a526..65acd785 100644 --- a/frontend/app/(main)/admin/automaticMng/flowMgmtList/[id]/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/flowMgmtList/[id]/page.tsx @@ -294,7 +294,7 @@ export default function FlowEditorPage() { onNodeDragStop={handleNodeDragStop} nodeTypes={nodeTypes} fitView - className="bg-gray-50" + className="bg-muted" > diff --git a/frontend/app/(main)/admin/automaticMng/flowMgmtList/page.tsx b/frontend/app/(main)/admin/automaticMng/flowMgmtList/page.tsx index d283f72d..6435274e 100644 --- a/frontend/app/(main)/admin/automaticMng/flowMgmtList/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/flowMgmtList/page.tsx @@ -996,7 +996,7 @@ export default function FlowManagementPage() {
{table.displayName || table.tableName} {table.description && ( - {table.description} + {table.description} )}
diff --git a/frontend/app/(main)/admin/automaticMng/mail/bulk-send/page.tsx b/frontend/app/(main)/admin/automaticMng/mail/bulk-send/page.tsx index e6a85942..4dc9626d 100644 --- a/frontend/app/(main)/admin/automaticMng/mail/bulk-send/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/mail/bulk-send/page.tsx @@ -409,7 +409,7 @@ example2@example.com,김철수,XYZ회사`; {recipients.length > 0 && (
- + {recipients.length}명의 수신자

diff --git a/frontend/app/(main)/admin/automaticMng/mail/dashboardList/page.tsx b/frontend/app/(main)/admin/automaticMng/mail/dashboardList/page.tsx index b51a464f..a6d48424 100644 --- a/frontend/app/(main)/admin/automaticMng/mail/dashboardList/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/mail/dashboardList/page.tsx @@ -101,8 +101,8 @@ export default function MailDashboardPage() { value: stats.totalAccounts, icon: Users, color: "blue", - bgColor: "bg-blue-100", - iconColor: "text-blue-600", + bgColor: "bg-primary/10", + iconColor: "text-primary", href: "/admin/mail/accounts", }, { @@ -110,8 +110,8 @@ export default function MailDashboardPage() { value: stats.totalTemplates, icon: FileText, color: "green", - bgColor: "bg-green-100", - iconColor: "text-green-600", + bgColor: "bg-emerald-100", + iconColor: "text-emerald-600", href: "/admin/mail/templates", }, { @@ -119,8 +119,8 @@ export default function MailDashboardPage() { value: stats.sentToday, icon: Send, color: "orange", - bgColor: "bg-orange-100", - iconColor: "text-orange-600", + bgColor: "bg-amber-100", + iconColor: "text-amber-600", href: "/admin/mail/sent", }, { diff --git a/frontend/app/(main)/admin/automaticMng/mail/receive/page.tsx b/frontend/app/(main)/admin/automaticMng/mail/receive/page.tsx index bcb2775b..9e11fca7 100644 --- a/frontend/app/(main)/admin/automaticMng/mail/receive/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/mail/receive/page.tsx @@ -438,8 +438,8 @@ export default function MailReceivePage() {

{testResult.success ? ( @@ -460,7 +460,7 @@ export default function MailReceivePage() {
{/* 검색 */}
- + - (검색어: {searchTerm}) + (검색어: {searchTerm}) )}
@@ -527,14 +527,14 @@ export default function MailReceivePage() { {loading ? ( - + 메일을 불러오는 중... ) : filteredAndSortedMails.length === 0 ? ( - +

{!selectedAccountId ? "메일 계정을 선택하세요" @@ -560,9 +560,9 @@ export default function MailReceivePage() { ) : ( - + - + 받은 메일함 ({filteredAndSortedMails.length}/{mails.length}개) @@ -573,14 +573,14 @@ export default function MailReceivePage() { key={mail.id} onClick={() => handleMailClick(mail)} className={`p-4 hover:bg-background transition-colors cursor-pointer ${ - !mail.isRead ? "bg-blue-50/30" : "" + !mail.isRead ? "bg-primary/10/30" : "" } ${selectedMailId === mail.id ? "bg-accent border-l-4 border-l-primary" : ""}`} >

{/* 읽음 표시 */}
{!mail.isRead && ( -
+
)}
@@ -598,7 +598,7 @@ export default function MailReceivePage() {
{mail.hasAttachments && ( - + )} {formatDate(mail.date)} @@ -882,14 +882,14 @@ export default function MailReceivePage() { ) : loadingDetail ? ( - + 메일을 불러오는 중... ) : ( - +

메일을 선택하면 내용이 표시됩니다

@@ -900,10 +900,10 @@ export default function MailReceivePage() {
{/* 안내 정보 */} - + - + 메일 수신 기능 완성! 🎉 @@ -913,81 +913,81 @@ export default function MailReceivePage() {

-

📬 기본 기능

+

📬 기본 기능

  • - + IMAP 프로토콜 메일 수신
  • - + 메일 목록 표시
  • - + 읽음/안읽음 상태
  • - + 첨부파일 유무 표시
-

📄 상세보기

+

📄 상세보기

  • - + HTML 본문 렌더링
  • - + 텍스트 본문 보기
  • - + 자동 읽음 처리
  • - + 첨부파일 다운로드
-

🔍 고급 기능

+

🔍 고급 기능

  • - + 통합 검색 (제목/발신자/내용)
  • - + 필터링 (읽음/첨부파일)
  • - + 정렬 (날짜/발신자)
  • - + 자동 새로고침 (30초)
-

🔒 보안

+

🔒 보안

  • - + XSS 방지 (DOMPurify)
  • - + 비밀번호 암호화
  • - + 안전한 파일명 생성
diff --git a/frontend/app/(main)/admin/automaticMng/mail/send/page.tsx b/frontend/app/(main)/admin/automaticMng/mail/send/page.tsx index cdd8feae..ad80ff48 100644 --- a/frontend/app/(main)/admin/automaticMng/mail/send/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/mail/send/page.tsx @@ -516,12 +516,12 @@ ${data.originalBody}`; toast({ title: (
- + 메일 발송 완료!
) as any, description: `${to.length}명${cc.length > 0 ? ` (참조 ${cc.length}명)` : ""}${bcc.length > 0 ? ` (숨은참조 ${bcc.length}명)` : ""}${attachments.length > 0 ? ` (첨부파일 ${attachments.length}개)` : ""}에게 메일이 성공적으로 발송되었습니다.`, - className: "border-green-500 bg-green-50", + className: "border-emerald-500 bg-emerald-50", }); // 알림 갱신 이벤트 발생 @@ -544,7 +544,7 @@ ${data.originalBody}`; toast({ title: (
- + 메일 발송 실패
) as any, @@ -781,7 +781,7 @@ ${data.originalBody}`; ) : ( <> - + {new Date(lastSaved).toLocaleTimeString('ko-KR', { hour: '2-digit', @@ -895,7 +895,7 @@ ${data.originalBody}`; {to.map((email) => (
{email} @@ -1222,7 +1222,7 @@ ${data.originalBody}`;
여백
@@ -1236,7 +1236,7 @@ ${data.originalBody}`; {component.logoSrc && 로고} {component.brandName}
- {component.sendDate} + {component.sendDate}
); @@ -1245,13 +1245,13 @@ ${data.originalBody}`; return (
{component.tableTitle && ( -
{component.tableTitle}
+
{component.tableTitle}
)} {component.rows?.map((row: any, i: number) => ( - - + + ))} @@ -1263,9 +1263,9 @@ ${data.originalBody}`; case 'alertBox': return (
{component.alertTitle &&
{component.alertTitle}
} @@ -1275,13 +1275,13 @@ ${data.originalBody}`; case 'divider': return ( -
+
); case 'footer': return ( -
- {component.companyName &&
{component.companyName}
} +
+ {component.companyName &&
{component.companyName}
} {(component.ceoName || component.businessNumber) && (
{component.ceoName && 대표: {component.ceoName}} @@ -1297,7 +1297,7 @@ ${data.originalBody}`; {component.email && Email: {component.email}}
)} - {component.copyright &&
{component.copyright}
} + {component.copyright &&
{component.copyright}
}
); @@ -1318,9 +1318,9 @@ ${data.originalBody}`; } })}
-
-

- +

+

+ 위 내용으로 메일이 발송됩니다

@@ -1396,7 +1396,7 @@ ${data.originalBody}`; onChange={handleFileSelect} className="hidden" /> - +

파일을 드래그하거나 클릭하여 선택하세요

@@ -1430,7 +1430,7 @@ ${data.originalBody}`; variant="ghost" size="sm" onClick={() => removeFile(index)} - className="flex-shrink-0 text-red-500 hover:text-red-600 hover:bg-red-50" + className="flex-shrink-0 text-destructive hover:text-destructive hover:bg-destructive/10" > @@ -1530,7 +1530,7 @@ ${data.originalBody}`;
{file.name} - ({formatFileSize(file.size)}) + ({formatFileSize(file.size)})
))}
diff --git a/frontend/app/(main)/admin/automaticMng/mail/sent/page.tsx b/frontend/app/(main)/admin/automaticMng/mail/sent/page.tsx index 229217d2..1af1c562 100644 --- a/frontend/app/(main)/admin/automaticMng/mail/sent/page.tsx +++ b/frontend/app/(main)/admin/automaticMng/mail/sent/page.tsx @@ -371,8 +371,8 @@ export default function SentMailPage() { {stats.successCount}

-
- +
+
@@ -387,8 +387,8 @@ export default function SentMailPage() { {stats.failedCount}

-
- +
+
@@ -403,8 +403,8 @@ export default function SentMailPage() { {stats.todayCount}

-
- +
+
diff --git a/frontend/app/(main)/admin/batch-management-new/page.tsx b/frontend/app/(main)/admin/batch-management-new/page.tsx index 6b282ed4..b7eeb969 100644 --- a/frontend/app/(main)/admin/batch-management-new/page.tsx +++ b/frontend/app/(main)/admin/batch-management-new/page.tsx @@ -592,19 +592,19 @@ export default function BatchManagementNewPage() {
setBatchType(option.value)} >
{option.value === "restapi-to-db" ? ( - + ) : ( - + )}
{option.label}
-
{option.description}
+
{option.description}
@@ -739,7 +739,7 @@ export default function BatchManagementNewPage() { )} -

+

{authTokenMode === "direct" ? "API 호출 시 Authorization 헤더에 사용할 토큰을 입력하세요." : "auth_tokens 테이블에서 선택한 서비스의 최신 토큰을 사용합니다."} @@ -782,7 +782,7 @@ export default function BatchManagementNewPage() { onChange={(e) => setDataArrayPath(e.target.value)} placeholder="response (예: data.items, results)" /> -

+

API 응답에서 배열 데이터가 있는 경로를 입력하세요. 비워두면 응답 전체를 사용합니다.
예시: response, data.items, result.list @@ -801,7 +801,7 @@ export default function BatchManagementNewPage() { className="min-h-[100px]" rows={5} /> -

API 호출 시 함께 전송할 JSON 데이터를 입력하세요.

+

API 호출 시 함께 전송할 JSON 데이터를 입력하세요.

)} @@ -809,7 +809,7 @@ export default function BatchManagementNewPage() {
-

특정 사용자나 조건으로 데이터를 조회할 때 사용합니다.

+

특정 사용자나 조건으로 데이터를 조회할 때 사용합니다.

@@ -868,26 +868,26 @@ export default function BatchManagementNewPage() { } /> {apiParamSource === "dynamic" && ( -

+

동적값은 배치 실행 시 설정된 값으로 치환됩니다. 예: {"{{user_id}}"} → 실제 사용자 ID

)}
{apiParamType === "url" && ( -
-
URL 파라미터 예시
-
+
+
URL 파라미터 예시
+
엔드포인트: /api/users/{`{${apiParamName || "userId"}}`}
-
실제 호출: /api/users/{apiParamValue || "123"}
+
실제 호출: /api/users/{apiParamValue || "123"}
)} {apiParamType === "query" && ( -
-
쿼리 파라미터 예시
-
+
+
쿼리 파라미터 예시
+
실제 호출: {fromEndpoint || "/api/users"}?{apiParamName || "userId"}= {apiParamValue || "123"}
@@ -899,9 +899,9 @@ export default function BatchManagementNewPage() { {/* API 호출 미리보기 정보 */} {fromApiUrl && fromEndpoint && ( -
-
API 호출 정보
-
+
+
API 호출 정보
+
{fromApiMethod} {fromApiUrl} {apiParamType === "url" && apiParamName && apiParamValue ? fromEndpoint.replace(`{${apiParamName}}`, apiParamValue) || fromEndpoint + `/${apiParamValue}` @@ -911,14 +911,14 @@ export default function BatchManagementNewPage() { : ""}
{((authTokenMode === "direct" && fromApiKey) || (authTokenMode === "db" && authServiceName)) && ( -
+
{authTokenMode === "direct" ? `Authorization: Bearer ${fromApiKey.substring(0, 15)}...` : `Authorization: DB 토큰 (${authServiceName})`}
)} {apiParamType !== "none" && apiParamName && apiParamValue && ( -
+
파라미터: {apiParamName} = {apiParamValue} ({apiParamSource === "static" ? "고정값" : "동적값"})
)} @@ -988,7 +988,7 @@ export default function BatchManagementNewPage() { setSelectedColumns(selectedColumns.filter((col) => col !== column.column_name)); } }} - className="rounded border-gray-300" + className="rounded border-input" />
{row.label}
{row.label} {row.value}
) : ( -
+
헤더가 없습니다. 헤더 추가 버튼을 클릭하여 추가하세요.
)} -

+

* 공통으로 사용할 HTTP 헤더를 설정합니다. 인증 헤더는 별도의 인증 설정에서 관리됩니다.

diff --git a/frontend/components/admin/LayoutFormModal.tsx b/frontend/components/admin/LayoutFormModal.tsx index ad17198d..3a5b3b19 100644 --- a/frontend/components/admin/LayoutFormModal.tsx +++ b/frontend/components/admin/LayoutFormModal.tsx @@ -239,30 +239,30 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh
1
기본 정보
-
+
2
템플릿 선택
-
-
+
+
3
@@ -305,7 +305,7 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh setFormData((prev) => ({ ...prev, category: category.id }))} > @@ -314,7 +314,7 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh
{category.name}
-
{category.description}
+
{category.description}
@@ -341,13 +341,13 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh
-

원하는 레이아웃 구조를 선택하세요

+

원하는 레이아웃 구조를 선택하세요

{LAYOUT_TEMPLATES.map((template) => ( setFormData((prev) => ({ @@ -364,8 +364,8 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh {template.zones}개 영역
{template.description}
-
예: {template.example}
-
{template.icon}
+
예: {template.example}
+
{template.icon}
@@ -418,7 +418,7 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh > - 개 영역 + 개 영역
@@ -428,17 +428,17 @@ export const LayoutFormModal: React.FC = ({ open, onOpenCh
{generationResult ? ( - + {generationResult.message} {generationResult.success && generationResult.files && (
생성된 파일들:
    {generationResult.files.map((file, index) => ( -
  • +
  • • {file}
  • ))} diff --git a/frontend/components/admin/MenuFormModal.tsx b/frontend/components/admin/MenuFormModal.tsx index c9940d78..7771ed76 100644 --- a/frontend/components/admin/MenuFormModal.tsx +++ b/frontend/components/admin/MenuFormModal.tsx @@ -748,7 +748,7 @@ export const MenuFormModal: React.FC = ({ {!isEdit && level !== 1 && ( -

    {getText(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SUBMENU_NOTE)}

    +

    {getText(MENU_MANAGEMENT_KEYS.FORM_COMPANY_SUBMENU_NOTE)}

    )}
@@ -817,7 +817,7 @@ export const MenuFormModal: React.FC = ({ }} >
{key.langKey}
- {key.description &&
{key.description}
} + {key.description &&
{key.description}
}
))}
@@ -825,7 +825,7 @@ export const MenuFormModal: React.FC = ({ )}
{selectedLangKeyInfo && ( -

+

{getText(MENU_MANAGEMENT_KEYS.FORM_LANG_KEY_SELECTED) .replace("{key}", selectedLangKeyInfo.langKey) .replace("{description}", selectedLangKeyInfo.description)} @@ -896,7 +896,7 @@ export const MenuFormModal: React.FC = ({ {/* 검색 입력 */}

- + = ({
handleScreenSelect(screen)} - className="cursor-pointer border-b px-3 py-2 last:border-b-0 hover:bg-gray-100" + className="cursor-pointer border-b px-3 py-2 last:border-b-0 hover:bg-muted" >
{screen.screenName}
-
{screen.screenCode}
+
{screen.screenCode}
-
ID: {screen.screenId || screen.id || "N/A"}
+
ID: {screen.screenId || screen.id || "N/A"}
))} @@ -933,7 +933,7 @@ export const MenuFormModal: React.FC = ({ (screen) => screen.screenName.toLowerCase().includes(screenSearchText.toLowerCase()) || screen.screenCode.toLowerCase().includes(screenSearchText.toLowerCase()), - ).length === 0 &&
검색 결과가 없습니다.
} + ).length === 0 &&
검색 결과가 없습니다.
}
)} @@ -942,7 +942,7 @@ export const MenuFormModal: React.FC = ({ {/* 선택된 화면 정보 표시 */} {selectedScreen && (
-
{selectedScreen.screenName}
+
{selectedScreen.screenName}
코드: {selectedScreen.screenCode}
생성된 URL: {formData.menuUrl}
@@ -971,7 +971,7 @@ export const MenuFormModal: React.FC = ({ {/* 검색창 */}
- + = ({
handleDashboardSelect(dashboard)} - className="cursor-pointer border-b px-3 py-2 last:border-b-0 hover:bg-gray-100" + className="cursor-pointer border-b px-3 py-2 last:border-b-0 hover:bg-muted" >
{dashboard.title}
{dashboard.description && ( -
{dashboard.description}
+
{dashboard.description}
)}
@@ -1012,7 +1012,7 @@ export const MenuFormModal: React.FC = ({ dashboard.title.toLowerCase().includes(dashboardSearchText.toLowerCase()) || (dashboard.description && dashboard.description.toLowerCase().includes(dashboardSearchText.toLowerCase())), - ).length === 0 &&
검색 결과가 없습니다.
} + ).length === 0 &&
검색 결과가 없습니다.
}
)} @@ -1021,7 +1021,7 @@ export const MenuFormModal: React.FC = ({ {/* 선택된 대시보드 정보 표시 */} {selectedDashboard && (
-
{selectedDashboard.title}
+
{selectedDashboard.title}
{selectedDashboard.description && (
설명: {selectedDashboard.description}
)} diff --git a/frontend/components/admin/MenuPermissionsTable.tsx b/frontend/components/admin/MenuPermissionsTable.tsx index 6cc887d2..61a7d577 100644 --- a/frontend/components/admin/MenuPermissionsTable.tsx +++ b/frontend/components/admin/MenuPermissionsTable.tsx @@ -745,7 +745,7 @@ export function MenuPermissionsTable({ permissions, onPermissionsChange, roleGro 생성 (C) handleSelectAll("createYn", checked as boolean)} - className="data-[state=checked]:bg-green-600" + className="data-[state=checked]:bg-emerald-600" />
@@ -754,7 +754,7 @@ export function MenuPermissionsTable({ permissions, onPermissionsChange, roleGro 조회 (R) handleSelectAll("readYn", checked as boolean)} - className="data-[state=checked]:bg-blue-600" + className="data-[state=checked]:bg-primary" />
@@ -772,7 +772,7 @@ export function MenuPermissionsTable({ permissions, onPermissionsChange, roleGro 삭제 (D) handleSelectAll("deleteYn", checked as boolean)} - className="data-[state=checked]:bg-red-600" + className="data-[state=checked]:bg-destructive" />
@@ -834,7 +834,7 @@ export function MenuPermissionsTable({ permissions, onPermissionsChange, roleGro handlePermissionChange(menu.menuObjid, "createYn", checked as boolean)} - className="data-[state=checked]:bg-green-600" + className="data-[state=checked]:bg-emerald-600" />
@@ -842,7 +842,7 @@ export function MenuPermissionsTable({ permissions, onPermissionsChange, roleGro handlePermissionChange(menu.menuObjid, "readYn", checked as boolean)} - className="data-[state=checked]:bg-blue-600" + className="data-[state=checked]:bg-primary" />
@@ -858,7 +858,7 @@ export function MenuPermissionsTable({ permissions, onPermissionsChange, roleGro handlePermissionChange(menu.menuObjid, "deleteYn", checked as boolean)} - className="data-[state=checked]:bg-red-600" + className="data-[state=checked]:bg-destructive" />
diff --git a/frontend/components/admin/RestApiConnectionModal.tsx b/frontend/components/admin/RestApiConnectionModal.tsx index 4c60c5af..eae5677d 100644 --- a/frontend/components/admin/RestApiConnectionModal.tsx +++ b/frontend/components/admin/RestApiConnectionModal.tsx @@ -564,7 +564,7 @@ export function RestApiConnectionModal({ isOpen, onClose, onSave, connection }: {testResult && (
@@ -572,17 +572,17 @@ export function RestApiConnectionModal({ isOpen, onClose, onSave, connection }: {testResult.success ? "성공" : "실패"} {testResult.response_time && ( - 응답 시간: {testResult.response_time}ms + 응답 시간: {testResult.response_time}ms )}

{testResult.message}

{testResult.status_code && ( -

상태 코드: {testResult.status_code}

+

상태 코드: {testResult.status_code}

)} - {testResult.error_details &&

{testResult.error_details}

} + {testResult.error_details &&

{testResult.error_details}

}
)}
diff --git a/frontend/components/admin/RoleDeleteModal.tsx b/frontend/components/admin/RoleDeleteModal.tsx index 9f3cf75a..8f7c6d3b 100644 --- a/frontend/components/admin/RoleDeleteModal.tsx +++ b/frontend/components/admin/RoleDeleteModal.tsx @@ -79,9 +79,9 @@ export function RoleDeleteModal({ isOpen, onClose, onSuccess, role }: RoleDelete
{/* 경고 메시지 */} -
+
- +

정말로 삭제하시겠습니까?

@@ -124,7 +124,7 @@ export function RoleDeleteModal({ isOpen, onClose, onSuccess, role }: RoleDelete

diff --git a/frontend/components/admin/RoleFormModal.tsx b/frontend/components/admin/RoleFormModal.tsx index cdeeccc5..b6e0fd0b 100644 --- a/frontend/components/admin/RoleFormModal.tsx +++ b/frontend/components/admin/RoleFormModal.tsx @@ -194,7 +194,7 @@ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleF {/* 권한 그룹명 */}
{isSuperAdmin ? ( <> @@ -345,10 +345,10 @@ export function RoleFormModal({ isOpen, onClose, onSuccess, editingRole }: RoleF
diff --git a/frontend/components/admin/ScreenAssignmentTab.tsx b/frontend/components/admin/ScreenAssignmentTab.tsx index 8513e410..f97bcaf5 100644 --- a/frontend/components/admin/ScreenAssignmentTab.tsx +++ b/frontend/components/admin/ScreenAssignmentTab.tsx @@ -223,7 +223,7 @@ export const ScreenAssignmentTab: React.FC = ({ menus
{selectedMenu && ( -
+

@@ -267,7 +267,7 @@ export const ScreenAssignmentTab: React.FC = ({ menus 할당된 화면 ({assignedScreens.length}개) - @@ -275,15 +275,15 @@ export const ScreenAssignmentTab: React.FC = ({ menus {loading ? ( -
로딩 중...
+
로딩 중...
) : assignedScreens.length === 0 ? ( -
할당된 화면이 없습니다. 화면을 할당해보세요.
+
할당된 화면이 없습니다. 화면을 할당해보세요.
) : (
{assignedScreens.map((screen) => (
@@ -298,7 +298,7 @@ export const ScreenAssignmentTab: React.FC = ({ menus

테이블: {screen.tableName} | 생성일: {screen.createdDate.toLocaleDateString()}

- {screen.description &&

{screen.description}

} + {screen.description &&

{screen.description}

}
@@ -330,7 +330,7 @@ export const ScreenAssignmentTab: React.FC = ({ menus
{/* 검색 */}
- + = ({ menus {/* 화면 목록 */}
{filteredAvailableScreens.length === 0 ? ( -
할당 가능한 화면이 없습니다.
+
할당 가능한 화면이 없습니다.
) : ( filteredAvailableScreens.map((screen) => (
setSelectedScreen(screen)} > @@ -385,7 +385,7 @@ export const ScreenAssignmentTab: React.FC = ({ menus setSelectedScreen(null)}>취소 - + 할당 해제 diff --git a/frontend/components/admin/SortableCodeItem.tsx b/frontend/components/admin/SortableCodeItem.tsx index 6d6da7d8..ade1a49e 100644 --- a/frontend/components/admin/SortableCodeItem.tsx +++ b/frontend/components/admin/SortableCodeItem.tsx @@ -116,7 +116,7 @@ export function SortableCodeItem({ }} onPointerDown={(e) => e.stopPropagation()} onMouseDown={(e) => e.stopPropagation()} - className="text-muted-foreground hover:text-foreground -ml-1 flex h-5 w-5 items-center justify-center rounded transition-colors hover:bg-gray-100" + className="text-muted-foreground hover:text-foreground -ml-1 flex h-5 w-5 items-center justify-center rounded transition-colors hover:bg-muted" title={isExpanded ? "접기" : "펼치기"} > {isExpanded ? : } @@ -135,12 +135,12 @@ export function SortableCodeItem({ )} {depth === 2 && ( - + 중분류 )} {depth === 3 && ( - + 소분류 )} @@ -196,7 +196,7 @@ export function SortableCodeItem({ onAddChild(); }} title="하위 코드 추가" - className="text-blue-600 hover:bg-blue-50 hover:text-blue-700" + className="text-primary hover:bg-primary/10 hover:text-primary" > diff --git a/frontend/components/admin/TableLogViewer.tsx b/frontend/components/admin/TableLogViewer.tsx index 9f0541b6..f5c7cf32 100644 --- a/frontend/components/admin/TableLogViewer.tsx +++ b/frontend/components/admin/TableLogViewer.tsx @@ -102,11 +102,11 @@ export function TableLogViewer({ tableName, open, onOpenChange }: TableLogViewer const getOperationBadge = (type: string) => { switch (type) { case "INSERT": - return 추가; + return 추가; case "UPDATE": - return 수정; + return 수정; case "DELETE": - return 삭제; + return 삭제; default: return {type}; } @@ -150,7 +150,7 @@ export function TableLogViewer({ tableName, open, onOpenChange }: TableLogViewer
- + {/* Radix UI Select v2.x: 빈 문자열 value="" 금지 → "__all__" 사용 */} setStartDate(e.target.value)} />
- + setEndDate(e.target.value)} />
- + setChangedBy(e.target.value)} />
- + setOriginalId(e.target.value)} />
@@ -204,7 +204,7 @@ export function TableLogViewer({ tableName, open, onOpenChange }: TableLogViewer
) : logs.length === 0 ? ( -
변경 이력이 없습니다.
+
변경 이력이 없습니다.
) : ( @@ -243,7 +243,7 @@ export function TableLogViewer({ tableName, open, onOpenChange }: TableLogViewer {/* 페이지네이션 */}
-
+
전체 {total}건 (페이지 {page} / {totalPages})
diff --git a/frontend/components/admin/TemplateImportExport.tsx b/frontend/components/admin/TemplateImportExport.tsx index e11dada6..5f3ff17e 100644 --- a/frontend/components/admin/TemplateImportExport.tsx +++ b/frontend/components/admin/TemplateImportExport.tsx @@ -157,12 +157,12 @@ export function TemplateImportExport({ onTemplateImported }: TemplateImportExpor
- -

템플릿 JSON 파일을 선택하세요

-

또는 아래에 JSON 내용을 직접 입력하세요

+ +

템플릿 JSON 파일을 선택하세요

+

또는 아래에 JSON 내용을 직접 입력하세요

@@ -196,7 +196,7 @@ export function TemplateImportExport({ onTemplateImported }: TemplateImportExpor - + 3. 템플릿 미리보기 diff --git a/frontend/components/admin/UserAuthEditModal.tsx b/frontend/components/admin/UserAuthEditModal.tsx index 34379b64..7ce04f4c 100644 --- a/frontend/components/admin/UserAuthEditModal.tsx +++ b/frontend/components/admin/UserAuthEditModal.tsx @@ -54,28 +54,28 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth label: "회사 관리자", description: "자기 회사 데이터 및 사용자 관리 가능", icon: , - color: "text-blue-600", + color: "text-primary", }, { value: "USER", label: "일반 사용자", description: "자기 회사 데이터 조회/수정만 가능", icon: , - color: "text-gray-600", + color: "text-muted-foreground", }, { value: "GUEST", label: "게스트", description: "제한된 조회 권한", icon: , - color: "text-green-600", + color: "text-emerald-600", }, { value: "PARTNER", label: "협력업체", description: "협력업체 전용 권한", icon: , - color: "text-orange-600", + color: "text-amber-600", }, ]; @@ -158,7 +158,7 @@ export function UserAuthEditModal({ isOpen, onClose, onSuccess, user }: UserAuth {/* 권한 선택 */}
@@ -474,7 +474,7 @@ export function UserFormModal({ isOpen, onClose, onSuccess, editingUser }: UserF {/* 중복확인 결과 메시지 */} {duplicateCheckMessage && (
{duplicateCheckMessage}
@@ -485,7 +485,7 @@ export function UserFormModal({ isOpen, onClose, onSuccess, editingUser }: UserF
{isSuperAdmin ? ( <> diff --git a/frontend/components/admin/UserPasswordResetModal.tsx b/frontend/components/admin/UserPasswordResetModal.tsx index 086b1556..e79d09ff 100644 --- a/frontend/components/admin/UserPasswordResetModal.tsx +++ b/frontend/components/admin/UserPasswordResetModal.tsx @@ -136,7 +136,7 @@ export function UserPasswordResetModal({ isOpen, onClose, userId, userName, onSu
{/* 대상 사용자 정보 */}
-
-
* 비밀번호는 영문, 숫자, 특수문자만 사용할 수 있습니다.
+
* 비밀번호는 영문, 숫자, 특수문자만 사용할 수 있습니다.
diff --git a/frontend/components/admin/dashboard/widgets/DriverListView.tsx b/frontend/components/admin/dashboard/widgets/DriverListView.tsx index 51862926..4f70e65b 100644 --- a/frontend/components/admin/dashboard/widgets/DriverListView.tsx +++ b/frontend/components/admin/dashboard/widgets/DriverListView.tsx @@ -59,7 +59,7 @@ export function DriverListView({ drivers, config, isCompact = false }: DriverLis return (
-
+
{visibleColumns.includes("status") && ( @@ -96,7 +96,7 @@ export function DriverListView({ drivers, config, isCompact = false }: DriverLis )} - + {drivers.map((driver) => { const statusColors = getStatusColor(driver.status); return ( diff --git a/frontend/components/admin/dashboard/widgets/ListWidget.tsx b/frontend/components/admin/dashboard/widgets/ListWidget.tsx index 194f7210..0561a38d 100644 --- a/frontend/components/admin/dashboard/widgets/ListWidget.tsx +++ b/frontend/components/admin/dashboard/widgets/ListWidget.tsx @@ -180,16 +180,16 @@ export function ListWidget({ element, onConfigUpdate }: ListWidgetProps) { const renderIcon = (icon?: string, color?: string) => { const colorClass = color === "blue" - ? "text-blue-600" + ? "text-primary" : color === "orange" - ? "text-orange-600" + ? "text-amber-600" : color === "green" - ? "text-green-600" + ? "text-emerald-600" : color === "red" - ? "text-red-600" + ? "text-destructive" : color === "purple" ? "text-purple-600" - : "text-gray-600"; + : "text-muted-foreground"; switch (icon) { case "truck": @@ -209,16 +209,16 @@ export function ListWidget({ element, onConfigUpdate }: ListWidgetProps) { const renderFieldGroup = (group: FieldGroup, data: Record) => { const colorClass = group.color === "blue" - ? "text-blue-600" + ? "text-primary" : group.color === "orange" - ? "text-orange-600" + ? "text-amber-600" : group.color === "green" - ? "text-green-600" + ? "text-emerald-600" : group.color === "red" - ? "text-red-600" + ? "text-destructive" : group.color === "purple" ? "text-purple-600" - : "text-gray-600"; + : "text-muted-foreground"; return (
diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx index 6ee36ca1..e4fd9a8a 100644 --- a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx +++ b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinEditor.tsx @@ -1592,11 +1592,11 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
도구: {[ - { type: "area" as ToolType, label: "영역", icon: Grid3x3, color: "text-blue-500" }, - { type: "location-bed" as ToolType, label: "베드", icon: Package, color: "text-blue-600" }, - { type: "location-stp" as ToolType, label: "정차", icon: Move, color: "text-gray-500" }, - // { type: "crane-gantry" as ToolType, label: "겐트리", icon: Combine, color: "text-green-500" }, - { type: "crane-mobile" as ToolType, label: "크레인", icon: Truck, color: "text-yellow-500" }, + { type: "area" as ToolType, label: "영역", icon: Grid3x3, color: "text-primary" }, + { type: "location-bed" as ToolType, label: "베드", icon: Package, color: "text-primary" }, + { type: "location-stp" as ToolType, label: "정차", icon: Move, color: "text-muted-foreground" }, + // { type: "crane-gantry" as ToolType, label: "겐트리", icon: Combine, color: "text-emerald-500" }, + { type: "crane-mobile" as ToolType, label: "크레인", icon: Truck, color: "text-amber-500" }, { type: "rack" as ToolType, label: "랙", icon: Box, color: "text-purple-500" }, ].map((tool) => { const Icon = tool.icon; @@ -1919,7 +1919,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi
{isLocationPlaced ? ( - + ) : locationType === "location-stp" ? ( ) : ( @@ -2052,7 +2052,7 @@ export default function DigitalTwinEditor({ layoutId, layoutName, onBack }: Digi {/* 중앙: 3D 캔버스 */} -
+
{isLoading ? (
diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx index ae98c795..cbb2517e 100644 --- a/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx +++ b/frontend/components/admin/dashboard/widgets/yard-3d/DigitalTwinViewer.tsx @@ -716,7 +716,7 @@ export default function DigitalTwinViewer({ layoutId }: DigitalTwinViewerProps)

)} {obj.materialCount !== undefined && obj.materialCount > 0 && ( -

+

자재: {obj.materialCount}개

)} @@ -802,7 +802,7 @@ export default function DigitalTwinViewer({ layoutId }: DigitalTwinViewerProps)

)} {locationObj.materialCount !== undefined && locationObj.materialCount > 0 && ( -

+

자재: {locationObj.materialCount}개

)} diff --git a/frontend/components/admin/dashboard/widgets/yard-3d/Yard3DCanvas.tsx b/frontend/components/admin/dashboard/widgets/yard-3d/Yard3DCanvas.tsx index ad8add20..c6fde7aa 100644 --- a/frontend/components/admin/dashboard/widgets/yard-3d/Yard3DCanvas.tsx +++ b/frontend/components/admin/dashboard/widgets/yard-3d/Yard3DCanvas.tsx @@ -1239,7 +1239,7 @@ export default function Yard3DCanvas({ }; return ( -
+
= { // Tailwind 색상 클래스 매핑 (아이콘용) export const OBJECT_COLOR_CLASSES: Record = { - area: "text-blue-500", - "location-bed": "text-blue-600", - "location-stp": "text-gray-500", - "location-temp": "text-orange-500", + area: "text-primary", + "location-bed": "text-primary", + "location-stp": "text-muted-foreground", + "location-temp": "text-amber-500", "location-dest": "text-emerald-500", "crane-mobile": "text-purple-500", - rack: "text-red-500", + rack: "text-destructive", }; // 기본 색상 export const DEFAULT_COLOR = "#3b82f6"; -export const DEFAULT_COLOR_CLASS = "text-blue-500"; +export const DEFAULT_COLOR_CLASS = "text-primary"; diff --git a/frontend/components/admin/multilang/CategoryTree.tsx b/frontend/components/admin/multilang/CategoryTree.tsx index 2e1238cf..9dca27ce 100644 --- a/frontend/components/admin/multilang/CategoryTree.tsx +++ b/frontend/components/admin/multilang/CategoryTree.tsx @@ -71,7 +71,7 @@ function CategoryNode({ ) ) : ( - + )} {/* 카테고리 이름 */} diff --git a/frontend/components/admin/multilang/KeyGenerateModal.tsx b/frontend/components/admin/multilang/KeyGenerateModal.tsx index c595adbc..536915ef 100644 --- a/frontend/components/admin/multilang/KeyGenerateModal.tsx +++ b/frontend/components/admin/multilang/KeyGenerateModal.tsx @@ -309,8 +309,8 @@ export function KeyGenerateModal({ preview?.exists ? "border-destructive bg-destructive/10" : preview?.isOverride - ? "border-blue-500 bg-blue-500/10" - : "border-green-500 bg-green-500/10" + ? "border-primary bg-primary/10" + : "border-emerald-500 bg-emerald-500/10" )}>
{previewLoading ? ( @@ -318,9 +318,9 @@ export function KeyGenerateModal({ ) : preview?.exists ? ( ) : preview?.isOverride ? ( - + ) : ( - + )} {generatedKeyPreview} @@ -332,7 +332,7 @@ export function KeyGenerateModal({

)} {preview?.isOverride && !preview?.exists && ( -

+

공통 키가 존재합니다. 회사별 오버라이드로 생성됩니다.

)} diff --git a/frontend/components/auth/ErrorMessage.tsx b/frontend/components/auth/ErrorMessage.tsx index 039c2ccd..ba4846a2 100644 --- a/frontend/components/auth/ErrorMessage.tsx +++ b/frontend/components/auth/ErrorMessage.tsx @@ -9,6 +9,6 @@ export function ErrorMessage({ message }: ErrorMessageProps) { if (!message) return null; return ( -
{message}
+
{message}
); } diff --git a/frontend/components/barcode/designer/BarcodeComponentPalette.tsx b/frontend/components/barcode/designer/BarcodeComponentPalette.tsx index e28ff12d..c9f22bdc 100644 --- a/frontend/components/barcode/designer/BarcodeComponentPalette.tsx +++ b/frontend/components/barcode/designer/BarcodeComponentPalette.tsx @@ -61,7 +61,7 @@ function DraggableItem({ return (
diff --git a/frontend/components/barcode/designer/BarcodeDesignerCanvas.tsx b/frontend/components/barcode/designer/BarcodeDesignerCanvas.tsx index 15136668..1eadfc32 100644 --- a/frontend/components/barcode/designer/BarcodeDesignerCanvas.tsx +++ b/frontend/components/barcode/designer/BarcodeDesignerCanvas.tsx @@ -51,7 +51,7 @@ export function BarcodeDesignerCanvas() { }), [widthPx, heightPx, components.length, addComponent, snapValueToGrid]); return ( -
+
{ diff --git a/frontend/components/barcode/designer/BarcodeLabelCanvasComponent.tsx b/frontend/components/barcode/designer/BarcodeLabelCanvasComponent.tsx index 3552f5fe..3567d916 100644 --- a/frontend/components/barcode/designer/BarcodeLabelCanvasComponent.tsx +++ b/frontend/components/barcode/designer/BarcodeLabelCanvasComponent.tsx @@ -202,7 +202,7 @@ export function BarcodeLabelCanvasComponent({ component }: Props) { }} /> ) : ( -
+
이미지
); @@ -244,7 +244,7 @@ export function BarcodeLabelCanvasComponent({ component }: Props) { {selected && component.type !== "line" && (
{ e.stopPropagation(); setIsResizing(true); diff --git a/frontend/components/barcode/designer/BarcodePrintPreviewModal.tsx b/frontend/components/barcode/designer/BarcodePrintPreviewModal.tsx index 0db9b65e..e732118c 100644 --- a/frontend/components/barcode/designer/BarcodePrintPreviewModal.tsx +++ b/frontend/components/barcode/designer/BarcodePrintPreviewModal.tsx @@ -151,7 +151,7 @@ export function BarcodePrintPreviewModal({

{/* 미리보기 캔버스 (축소) */} -
+
= ({ 엑셀 데이터 업로드 {isMasterDetail && ( - + 마스터-디테일 )} @@ -1322,15 +1322,15 @@ export const ExcelUploadModal: React.FC = ({ isDragOver ? "border-primary bg-primary/5" : file - ? "border-green-500 bg-green-50" + ? "border-emerald-500 bg-emerald-50" : "border-muted-foreground/25 hover:border-primary hover:bg-muted/50" )} > {file ? (
- +
-

{file.name}

+

{file.name}

클릭하여 다른 파일 선택

@@ -1561,11 +1561,11 @@ export const ExcelUploadModal: React.FC = ({ {/* 중복 체크 안내 */} {duplicateCheckCount > 0 ? ( -
+
- -
+ +

중복 키: {columnMappings .filter((m) => m.checkDuplicate && m.systemColumn) @@ -1581,12 +1581,12 @@ export const ExcelUploadModal: React.FC = ({

- 중복 시: + 중복 시:
- + {!recordId && } @@ -370,11 +370,11 @@ export function TableHistoryModal({ {detailRecords.map((record) => { const displayValue = getDisplayValue(record); return ( - + {!recordId && ( - - + + diff --git a/frontend/components/common/ValidationMessage.tsx b/frontend/components/common/ValidationMessage.tsx index b46653b7..e524dd38 100644 --- a/frontend/components/common/ValidationMessage.tsx +++ b/frontend/components/common/ValidationMessage.tsx @@ -10,7 +10,7 @@ interface ValidationMessageProps { export function ValidationMessage({ message, isValid, isLoading, className }: ValidationMessageProps) { if (isLoading) { - return

검사 중...

; + return

검사 중...

; } if (!message) { @@ -18,6 +18,6 @@ export function ValidationMessage({ message, isValid, isLoading, className }: Va } return ( -

{message}

+

{message}

); } diff --git a/frontend/components/dashboard/widgets/ListTestWidget.tsx b/frontend/components/dashboard/widgets/ListTestWidget.tsx index d1303d10..bc735833 100644 --- a/frontend/components/dashboard/widgets/ListTestWidget.tsx +++ b/frontend/components/dashboard/widgets/ListTestWidget.tsx @@ -212,16 +212,16 @@ export function ListTestWidget({ element }: ListTestWidgetProps) { const renderIcon = (icon?: string, color?: string) => { const colorClass = color === "blue" - ? "text-blue-600" + ? "text-primary" : color === "orange" - ? "text-orange-600" + ? "text-amber-600" : color === "green" - ? "text-green-600" + ? "text-emerald-600" : color === "red" - ? "text-red-600" + ? "text-destructive" : color === "purple" ? "text-purple-600" - : "text-gray-600"; + : "text-muted-foreground"; switch (icon) { case "truck": @@ -241,16 +241,16 @@ export function ListTestWidget({ element }: ListTestWidgetProps) { const renderFieldGroup = (group: FieldGroup, groupData: Record) => { const colorClass = group.color === "blue" - ? "text-blue-600" + ? "text-primary" : group.color === "orange" - ? "text-orange-600" + ? "text-amber-600" : group.color === "green" - ? "text-green-600" + ? "text-emerald-600" : group.color === "red" - ? "text-red-600" + ? "text-destructive" : group.color === "purple" ? "text-purple-600" - : "text-gray-600"; + : "text-muted-foreground"; return (
diff --git a/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx b/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx index 151c7eff..5a546dbf 100644 --- a/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx +++ b/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx @@ -1352,8 +1352,8 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { {/* 이동경로 날짜 선택 */} {selectedUserId && ( -
- 🛣️ +
+ 🛣️ - ({routePoints.length}개) -
@@ -1494,15 +1494,15 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { const parsed = JSON.parse(matchingPolygon.description); popupContent = `
- ${matchingPolygon.source ? `
📡 ${matchingPolygon.source}
` : ""} -
-
상세 정보
+ ${matchingPolygon.source ? `
📡 ${matchingPolygon.source}
` : ""} +
+
상세 정보
${popupFields .map((field) => { const value = parsed[field.fieldName]; if (value === undefined || value === null) return ""; - return `
${field.label}: ${value}
`; + return `
${field.label}: ${value}
`; }) .join("")}
@@ -1980,7 +1980,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { @@ -1996,10 +1996,10 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { {/* 운행 정보 */} {hasTripInfo && (
-
🚛 최근 운행
-
+
🚛 최근 운행
+
{(info.last_trip_start || info.last_trip_end) && ( -
+
시간:{" "} {formatDateTime(info.last_trip_start)} ~ {formatDateTime(info.last_trip_end)}
@@ -2007,20 +2007,20 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
{info.last_trip_distance !== undefined && info.last_trip_distance !== null && ( - 거리:{" "} - {formatDistance(info.last_trip_distance)} + 거리:{" "} + {formatDistance(info.last_trip_distance)} )} {info.last_trip_time !== undefined && info.last_trip_time !== null && ( - 소요:{" "} - {formatTime(info.last_trip_time)} + 소요:{" "} + {formatTime(info.last_trip_time)} )}
{/* 출발지/도착지 */} {(info.departure || info.arrival) && ( -
+
{info.departure && 출발: {info.departure}} {info.departure && info.arrival && " → "} {info.arrival && 도착: {info.arrival}} @@ -2033,10 +2033,10 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { {/* 공차 정보 */} {hasEmptyTripInfo && (
-
📦 최근 공차
-
+
📦 최근 공차
+
{(info.last_empty_start || info.last_empty_end) && ( -
+
시간:{" "} {formatDateTime(info.last_empty_start)} ~ {formatDateTime(info.last_empty_end)}
@@ -2044,13 +2044,13 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
{info.last_empty_distance !== undefined && info.last_empty_distance !== null && ( - 거리:{" "} + 거리:{" "} {formatDistance(info.last_empty_distance)} )} {info.last_empty_time !== undefined && info.last_empty_time !== null && ( - 소요:{" "} + 소요:{" "} {formatTime(info.last_empty_time)} )} @@ -2085,7 +2085,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { diff --git a/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx b/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx index 6234c984..dd73e6dd 100644 --- a/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx +++ b/frontend/components/dashboard/widgets/VehicleMapOnlyWidget.tsx @@ -357,7 +357,7 @@ export default function VehicleMapOnlyWidget({ element, refreshInterval = 30000
{/* 통계 정보 */} -
-
통계
+
+
통계
테이블 노드: @@ -83,7 +83,7 @@ export const DataFlowSidebar: React.FC = ({
메모리 관계: - {tempRelationships.length}개 + {tempRelationships.length}개
관계도 ID: @@ -98,7 +98,7 @@ export const DataFlowSidebar: React.FC = ({
{hasUnsavedChanges && ( -
⚠️ 저장되지 않은 변경사항이 있습니다
+
⚠️ 저장되지 않은 변경사항이 있습니다
)}
diff --git a/frontend/components/dataflow/EdgeInfoPanel.tsx b/frontend/components/dataflow/EdgeInfoPanel.tsx index 2fcfffd6..676755a2 100644 --- a/frontend/components/dataflow/EdgeInfoPanel.tsx +++ b/frontend/components/dataflow/EdgeInfoPanel.tsx @@ -24,7 +24,7 @@ export const EdgeInfoPanel: React.FC = ({ return (
= ({ }} > {/* 헤더 */} -
+
🔗 @@ -52,10 +52,10 @@ export const EdgeInfoPanel: React.FC = ({
{/* 관계 정보 요약 */} -
+
-
연결 유형
+
연결 유형
{edgeInfo.connectionType}
@@ -68,7 +68,7 @@ export const EdgeInfoPanel: React.FC = ({ {/* From 테이블 */}
FROM
-
{edgeInfo.fromTable}
+
{edgeInfo.fromTable}
{edgeInfo.fromColumns.map((column, index) => ( @@ -89,15 +89,15 @@ export const EdgeInfoPanel: React.FC = ({
{/* To 테이블 */} -
-
TO
-
{edgeInfo.toTable}
+
+
TO
+
{edgeInfo.toTable}
{edgeInfo.toColumns.map((column, index) => ( {column} @@ -108,16 +108,16 @@ export const EdgeInfoPanel: React.FC = ({
{/* 액션 버튼 */} -
+
diff --git a/frontend/components/dataflow/RelationshipListModal.tsx b/frontend/components/dataflow/RelationshipListModal.tsx index fbbc445b..d5ba9b9e 100644 --- a/frontend/components/dataflow/RelationshipListModal.tsx +++ b/frontend/components/dataflow/RelationshipListModal.tsx @@ -136,16 +136,16 @@ export const RelationshipListModal: React.FC = ({ return (
{/* 헤더 */} -
+
🔗
-
테이블 간 관계 목록
+
테이블 간 관계 목록
@@ -66,14 +66,14 @@ export const SelectedTablesPanel: React.FC = ({ index === 0 ? "border-l-4 border-emerald-400 bg-emerald-50" : index === 1 - ? "border-l-4 border-blue-400 bg-accent" + ? "border-l-4 border-primary/60 bg-accent" : "bg-muted" }`} >
{displayName} @@ -81,7 +81,7 @@ export const SelectedTablesPanel: React.FC = ({ {selectedNodes.length === 2 && (
{index === 0 ? "FROM" : "TO"} @@ -94,7 +94,7 @@ export const SelectedTablesPanel: React.FC = ({ {/* 연결 화살표 (마지막이 아닌 경우) */} {index < selectedNodes.length - 1 && (
-
+
)}
@@ -104,14 +104,14 @@ export const SelectedTablesPanel: React.FC = ({
{/* 액션 버튼 */} -
+
@@ -82,7 +82,7 @@ export const TableSelector: React.FC = ({ companyCode, onTab {/* 검색 입력 */}
- + = ({ companyCode, onTab
{loading ? (
-
테이블 목록을 불러오는 중...
+
테이블 목록을 불러오는 중...
) : filteredTables.length === 0 ? (
-
+
{searchTerm ? "검색 결과가 없습니다." : "등록된 테이블이 없습니다."}
@@ -114,14 +114,14 @@ export const TableSelector: React.FC = ({ companyCode, onTab !isSelected && handleAddTable(table)} >
{table.displayName} -
{table.columnCount}개 컬럼
+
{table.columnCount}개 컬럼
@@ -132,7 +132,7 @@ export const TableSelector: React.FC = ({ companyCode, onTab {isSelected && (추가됨)}
- {table.description &&

{table.description}

} + {table.description &&

{table.description}

}
@@ -142,7 +142,7 @@ export const TableSelector: React.FC = ({ companyCode, onTab
{/* 통계 정보 */} -
+
전체 테이블: {tables.length}개 {searchTerm && 검색 결과: {filteredTables.length}개} diff --git a/frontend/components/dataflow/condition/ConditionRenderer.tsx b/frontend/components/dataflow/condition/ConditionRenderer.tsx index 4cb5b915..6eec3455 100644 --- a/frontend/components/dataflow/condition/ConditionRenderer.tsx +++ b/frontend/components/dataflow/condition/ConditionRenderer.tsx @@ -63,7 +63,7 @@ export const ConditionRenderer: React.FC = ({ return (
{conditions.length === 0 ? ( -
+
조건을 추가하면 해당 조건을 만족할 때만 실행됩니다.
조건이 없으면 항상 실행됩니다. @@ -92,7 +92,7 @@ export const ConditionRenderer: React.FC = ({ )} {/* 그룹 레벨에 따른 들여쓰기 */}
( @@ -110,7 +110,7 @@ export const ConditionRenderer: React.FC = ({ return (
) diff --git a/frontend/components/dataflow/connection/ActionConditionRenderer.tsx b/frontend/components/dataflow/connection/ActionConditionRenderer.tsx index c902ae75..949aca04 100644 --- a/frontend/components/dataflow/connection/ActionConditionRenderer.tsx +++ b/frontend/components/dataflow/connection/ActionConditionRenderer.tsx @@ -114,7 +114,7 @@ export const ActionConditionRenderer: React.FC = ( value={settings.actions[actionIndex].conditions![condIndex - 1]?.logicalOperator || "AND"} onValueChange={(value: "AND" | "OR") => updateLogicalOperator(condIndex - 1, value)} > - + @@ -124,11 +124,11 @@ export const ActionConditionRenderer: React.FC = ( )}
- ( - 그룹 시작 + ( + 그룹 시작 )} -
+
)} - . + .
-
+
{/* 타겟 */} -
+
- . + . updateSplitConfig("sourceField", value)} @@ -99,7 +99,7 @@ export const ActionSplitConfig: React.FC = ({
- + updateSplitConfig("delimiter", e.target.value)} @@ -108,7 +108,7 @@ export const ActionSplitConfig: React.FC = ({ />
- + = ({ if (showUnmappedOnly) onShowUnmappedOnlyChange(false); }} className={`rounded px-2 py-1 text-xs transition-colors hover:cursor-pointer ${ - showMappedOnly ? "bg-gray-600 text-white" : "bg-gray-200 text-gray-700 hover:bg-gray-300" + showMappedOnly ? "bg-foreground/80 text-white" : "bg-muted/80 text-foreground hover:bg-muted/60" }`} > 설정됨 @@ -151,7 +151,7 @@ export const ColumnTableSection: React.FC = ({ if (showMappedOnly) onShowMappedOnlyChange(false); }} className={`rounded px-2 py-1 text-xs transition-colors hover:cursor-pointer ${ - showUnmappedOnly ? "bg-gray-600 text-white" : "bg-gray-200 text-gray-700 hover:bg-gray-300" + showUnmappedOnly ? "bg-foreground/80 text-white" : "bg-muted/80 text-foreground hover:bg-muted/60" }`} > 미설정 @@ -162,7 +162,7 @@ export const ColumnTableSection: React.FC = ({
{/* 컬럼 리스트 */} -
+
{filteredColumns.map((column) => { const isSelected = selectedColumn === column.columnName; const isClickable = isColumnClickable(column); @@ -184,16 +184,16 @@ export const ColumnTableSection: React.FC = ({
onColumnClick(column.columnName) : undefined} - className={`border-b border-gray-200 px-3 py-2 text-xs transition-colors ${ + className={`border-b border-border px-3 py-2 text-xs transition-colors ${ isSelected - ? "bg-gray-200 text-gray-800" + ? "bg-muted/80 text-foreground" : isMapped - ? "bg-gray-100 text-gray-700" + ? "bg-muted text-foreground" : oppositeSelectedColumn && !isTypeCompatible - ? "cursor-not-allowed bg-destructive/10 text-red-400 opacity-60" + ? "cursor-not-allowed bg-destructive/10 text-destructive/80 opacity-60" : isClickable - ? "cursor-pointer hover:bg-gray-50" - : "cursor-not-allowed bg-gray-100 text-gray-400" + ? "cursor-pointer hover:bg-muted" + : "cursor-not-allowed bg-muted text-muted-foreground/70" }`} >
@@ -204,24 +204,24 @@ export const ColumnTableSection: React.FC = ({ ? column.displayName : column.columnName} - {isSelected && } - {isMapped && } + {isSelected && } + {isMapped && } {oppositeSelectedColumn && !isTypeCompatible && ( - + )}
{column.dataType} {oppositeSelectedColumn && !isTypeCompatible && ( - (호환 불가) + (호환 불가) )}
{isMapped && mappedToColumn && ( -
→ {mappedToColumn}
+
→ {mappedToColumn}
)}
@@ -242,13 +242,13 @@ export const ColumnTableSection: React.FC = ({ return (
= ({ onClick={isClickable && isTypeCompatible ? () => onColumnClick(column.columnName) : undefined} className={`px-3 py-2 text-xs ${ isClickable && isTypeCompatible - ? "cursor-pointer hover:bg-gray-50" + ? "cursor-pointer hover:bg-muted" : oppositeSelectedColumn && !isTypeCompatible ? "cursor-not-allowed" : hasDefaultValue @@ -274,19 +274,19 @@ export const ColumnTableSection: React.FC = ({ ? column.displayName : column.columnName} - {isSelected && } + {isSelected && } {oppositeSelectedColumn && !isTypeCompatible && ( - + )}
{column.dataType} {oppositeSelectedColumn && !isTypeCompatible && ( - (호환 불가) + (호환 불가) )}
@@ -298,7 +298,7 @@ export const ColumnTableSection: React.FC = ({ e.stopPropagation(); onRemoveMapping?.(column.columnName); }} - className="flex-shrink-0 text-red-500 hover:text-red-700" + className="flex-shrink-0 text-destructive hover:text-destructive" title="매핑 제거" > ✕ @@ -312,7 +312,7 @@ export const ColumnTableSection: React.FC = ({ column={column} value={mapping?.defaultValue || ""} onChange={(value) => onDefaultValueChange(column.columnName, value)} - className="h-6 border-gray-200 text-xs focus:border-green-400 focus:ring-0" + className="h-6 border-border text-xs focus:border-green-400 focus:ring-0" placeholder="기본값 입력..." tableName={tableName} /> @@ -327,7 +327,7 @@ export const ColumnTableSection: React.FC = ({
{/* 하단 통계 */} -
+
{isFromTable ? "매핑됨" : "설정됨"}: {mappedCount}/{columns.length} diff --git a/frontend/components/dataflow/connection/ConnectionSelectionPanel.tsx b/frontend/components/dataflow/connection/ConnectionSelectionPanel.tsx index 9148a035..9ace97ee 100644 --- a/frontend/components/dataflow/connection/ConnectionSelectionPanel.tsx +++ b/frontend/components/dataflow/connection/ConnectionSelectionPanel.tsx @@ -179,23 +179,23 @@ export const ConnectionSelectionPanel: React.FC = -
-
+
+
-
+
-
-
+
+
-
+
diff --git a/frontend/components/dataflow/connection/ConnectionTypeSelector.tsx b/frontend/components/dataflow/connection/ConnectionTypeSelector.tsx index b4218bde..dede9fc7 100644 --- a/frontend/components/dataflow/connection/ConnectionTypeSelector.tsx +++ b/frontend/components/dataflow/connection/ConnectionTypeSelector.tsx @@ -19,11 +19,11 @@ export const ConnectionTypeSelector: React.FC = ({ className={`cursor-pointer rounded-lg border-2 p-3 text-center transition-colors ${ config.connectionType === "simple-key" ? "border-primary bg-accent" - : "border-gray-200 hover:border-gray-300" + : "border-border hover:border-input" }`} onClick={() => onConfigChange({ ...config, connectionType: "simple-key" })} > - +
단순 키값 연결
중계 테이블 생성
@@ -31,12 +31,12 @@ export const ConnectionTypeSelector: React.FC = ({
onConfigChange({ ...config, connectionType: "data-save" })} > - +
데이터 저장
필드 매핑 저장
@@ -44,15 +44,15 @@ export const ConnectionTypeSelector: React.FC = ({
{ console.log("🔄 [ConnectionTypeSelector] External call selected"); onConfigChange({ ...config, connectionType: "external-call" }); }} > - +
외부 호출
API/이메일 호출
diff --git a/frontend/components/dataflow/connection/ExternalCallSettings.tsx b/frontend/components/dataflow/connection/ExternalCallSettings.tsx index b109a645..88acf153 100644 --- a/frontend/components/dataflow/connection/ExternalCallSettings.tsx +++ b/frontend/components/dataflow/connection/ExternalCallSettings.tsx @@ -123,10 +123,10 @@ const handleTestExternalCall = async (settings: ExternalCallSettingsType) => { export const ExternalCallSettings: React.FC = ({ settings, onSettingsChange }) => { return ( -
+
- + 외부 호출 설정
@@ -424,7 +424,7 @@ export const InsertFieldMappingPanel: React.FC = ( setToShowMappedOnly(true); setToShowUnmappedOnly(false); }} - className="h-7 bg-green-100 text-xs text-green-700 hover:bg-green-200" + className="h-7 bg-emerald-100 text-xs text-emerald-700 hover:bg-emerald-200" > 매핑됨만 보기 @@ -440,12 +440,12 @@ export const InsertFieldMappingPanel: React.FC = ( {/* 매핑 통계 */} - +
-
매핑 진행 상황
+
매핑 진행 상황
총 {toTableColumns.length}개 컬럼 중{" "} @@ -457,7 +457,7 @@ export const InsertFieldMappingPanel: React.FC = (
-
+
{Math.round( (columnMappings.filter((m) => m.fromColumnName || (m.defaultValue && m.defaultValue.trim())).length / actualToColumns.length) * @@ -465,7 +465,7 @@ export const InsertFieldMappingPanel: React.FC = ( )} %
-
완료율
+
완료율
diff --git a/frontend/components/dataflow/connection/SimpleKeySettings.tsx b/frontend/components/dataflow/connection/SimpleKeySettings.tsx index 018fbb06..d22a58bf 100644 --- a/frontend/components/dataflow/connection/SimpleKeySettings.tsx +++ b/frontend/components/dataflow/connection/SimpleKeySettings.tsx @@ -38,7 +38,7 @@ export const SimpleKeySettings: React.FC = ({ return (
{/* 테이블 및 컬럼 선택 */} -
+
테이블 및 컬럼 선택
{/* 현재 선택된 테이블 표시 */} @@ -46,20 +46,20 @@ export const SimpleKeySettings: React.FC = ({
- + {availableTables.find((t) => t.tableName === selectedFromTable)?.displayName || selectedFromTable} - ({selectedFromTable}) + ({selectedFromTable})
- + {availableTables.find((t) => t.tableName === selectedToTable)?.displayName || selectedToTable} - ({selectedToTable}) + ({selectedToTable})
@@ -88,11 +88,11 @@ export const SimpleKeySettings: React.FC = ({ ? column.displayName : column.columnName} - ({column.dataType}) + ({column.dataType}) ))} {fromTableColumns.length === 0 && ( -
+
{selectedFromTable ? "컬럼을 불러오는 중..." : "테이블을 먼저 선택해주세요"}
)} @@ -121,11 +121,11 @@ export const SimpleKeySettings: React.FC = ({ ? column.displayName : column.columnName} - ({column.dataType}) + ({column.dataType}) ))} {toTableColumns.length === 0 && ( -
+
{selectedToTable ? "컬럼을 불러오는 중..." : "테이블을 먼저 선택해주세요"}
)} @@ -150,7 +150,7 @@ export const SimpleKeySettings: React.FC = ({ ); }) ) : ( - 선택된 컬럼 없음 + 선택된 컬럼 없음 )}
@@ -169,7 +169,7 @@ export const SimpleKeySettings: React.FC = ({ ); }) ) : ( - 선택된 컬럼 없음 + 선택된 컬럼 없음 )}
@@ -180,7 +180,7 @@ export const SimpleKeySettings: React.FC = ({ {/* 단순 키값 연결 설정 */}
- + 단순 키값 연결 설정
diff --git a/frontend/components/dataflow/connection/TableSelectionPanel.tsx b/frontend/components/dataflow/connection/TableSelectionPanel.tsx index 40d0ee4b..e67ed064 100644 --- a/frontend/components/dataflow/connection/TableSelectionPanel.tsx +++ b/frontend/components/dataflow/connection/TableSelectionPanel.tsx @@ -187,14 +187,14 @@ export const TableSelectionPanel: React.FC = ({ -
+
{title}
-
-
+
+
@@ -357,7 +357,7 @@ export const TableSelectionPanel: React.FC = ({ })()} {selectedFromTable === selectedToTable && ( - + 자기 자신 )} diff --git a/frontend/components/dataflow/connection/redesigned/DataConnectionDesigner.tsx b/frontend/components/dataflow/connection/redesigned/DataConnectionDesigner.tsx index cec7c238..2deeb78e 100644 --- a/frontend/components/dataflow/connection/redesigned/DataConnectionDesigner.tsx +++ b/frontend/components/dataflow/connection/redesigned/DataConnectionDesigner.tsx @@ -32,9 +32,9 @@ export const DataConnectionDesigner: React.FC = () => { const { isMobile, isTablet } = useResponsive(); return ( -
-
-

+
+
+

🎨 제어관리 - 데이터 연결 설정

@@ -43,7 +43,7 @@ export const DataConnectionDesigner: React.FC = () => {

-
+
setState(prev => ({ ...prev, connectionType: type }))} @@ -59,7 +59,7 @@ export const DataConnectionDesigner: React.FC = () => {
-
+
setState(prev => ({ ...prev, currentStep: step }))} diff --git a/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionButtons.tsx b/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionButtons.tsx index 18785aae..9d6839d8 100644 --- a/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionButtons.tsx +++ b/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionButtons.tsx @@ -102,7 +102,7 @@ const ActionButtons: React.FC = ({ state, actions }) => {
{state.fieldMappings.length}개 매핑 설정됨 {state.validationErrors.length > 0 && ( - ({state.validationErrors.length}개 오류) + ({state.validationErrors.length}개 오류) )}
)} diff --git a/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionSummaryPanel.tsx b/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionSummaryPanel.tsx index 8628135e..9ac4d1de 100644 --- a/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionSummaryPanel.tsx +++ b/frontend/components/dataflow/connection/redesigned/LeftPanel/ActionSummaryPanel.tsx @@ -44,9 +44,9 @@ const ActionSummaryPanel: React.FC = ({ state }) => { 액션 설정 {isConfigured ? ( - + ) : ( - + )} @@ -79,15 +79,15 @@ const ActionSummaryPanel: React.FC = ({ state }) => {
{actionConditions.length === 0 && ( -

⚠️ {actionType.toUpperCase()} 액션은 실행 조건이 필요합니다

+

⚠️ {actionType.toUpperCase()} 액션은 실행 조건이 필요합니다

)}
)} {/* INSERT 액션 안내 */} {actionType === "insert" && ( -
-

✅ INSERT 액션은 별도 조건 없이 모든 매핑된 데이터를 삽입합니다

+
+

✅ INSERT 액션은 별도 조건 없이 모든 매핑된 데이터를 삽입합니다

)} @@ -96,13 +96,13 @@ const ActionSummaryPanel: React.FC = ({ state }) => {
{isConfigured ? ( <> - - 설정 완료 + + 설정 완료 ) : ( <> - - 설정 필요 + + 설정 필요 )}
diff --git a/frontend/components/dataflow/connection/redesigned/LeftPanel/AdvancedSettings.tsx b/frontend/components/dataflow/connection/redesigned/LeftPanel/AdvancedSettings.tsx index fa2cc2ad..d2cb12ab 100644 --- a/frontend/components/dataflow/connection/redesigned/LeftPanel/AdvancedSettings.tsx +++ b/frontend/components/dataflow/connection/redesigned/LeftPanel/AdvancedSettings.tsx @@ -54,7 +54,7 @@ const AdvancedSettings: React.FC = ({ connectionType }) =

🔄 트랜잭션 설정

-
-
-

레코드작업
{displayValue ? ( - {displayValue} + {displayValue} ) : ( - )} @@ -382,8 +382,8 @@ export function TableHistoryModal({ )} {getOperationBadge(record.operation_type)} {record.changed_column}{record.old_value || "-"}{record.new_value || "-"}{record.old_value || "-"}{record.new_value || "-"} {record.changed_by} {formatDate(record.changed_at)}
-

{table.name}

+

{table.name}

{table.columns.length}개 컬럼

-

{table.rowCount?.toLocaleString()}개 행

+

{table.rowCount?.toLocaleString()}개 행

{selectedFromTable === table.name && ( @@ -149,11 +149,11 @@ export const TableStep: React.FC = ({ {/* TO 테이블 */}
-
- 2 +
+ 2
-

대상 테이블

- (TO) +

대상 테이블

+ (TO)
@@ -162,20 +162,20 @@ export const TableStep: React.FC = ({ key={table.name} className={`p-4 rounded-lg border-2 cursor-pointer transition-all duration-200 ${ selectedToTable === table.name - ? "border-green-500 bg-green-50 shadow-md" - : "border-gray-200 bg-white hover:border-green-300 hover:bg-green-25" + ? "border-emerald-500 bg-emerald-50 shadow-md" + : "border-border bg-white hover:border-green-300 hover:bg-green-25" }`} onClick={() => handleToTableSelect(table.name)} >
-
+
-

{table.name}

+

{table.name}

{table.columns.length}개 컬럼

-

{table.rowCount?.toLocaleString()}개 행

+

{table.rowCount?.toLocaleString()}개 행

{selectedToTable === table.name && ( - + )} @@ -188,7 +188,7 @@ export const TableStep: React.FC = ({
diff --git a/frontend/components/dataflow/external-call/ExternalCallPanel.tsx b/frontend/components/dataflow/external-call/ExternalCallPanel.tsx index ea8add8d..3feb48b7 100644 --- a/frontend/components/dataflow/external-call/ExternalCallPanel.tsx +++ b/frontend/components/dataflow/external-call/ExternalCallPanel.tsx @@ -222,7 +222,7 @@ const ExternalCallPanel: React.FC = ({
- + 외부 호출 설정 {isConfigValid ? "설정 완료" : "설정 필요"} diff --git a/frontend/components/dataflow/external-call/ExternalCallTestPanel.tsx b/frontend/components/dataflow/external-call/ExternalCallTestPanel.tsx index 811e4b60..f00d8e8c 100644 --- a/frontend/components/dataflow/external-call/ExternalCallTestPanel.tsx +++ b/frontend/components/dataflow/external-call/ExternalCallTestPanel.tsx @@ -208,7 +208,7 @@ const ExternalCallTestPanel: React.FC = ({
- + API 테스트 {testResult && ( @@ -253,9 +253,9 @@ const ExternalCallTestPanel: React.FC = ({
{testResult.success ? ( - + ) : ( - + )} 상태
@@ -264,7 +264,7 @@ const ExternalCallTestPanel: React.FC = ({
- + 상태 코드
{testResult.statusCode || "N/A"}
@@ -272,7 +272,7 @@ const ExternalCallTestPanel: React.FC = ({
- + 응답 시간
{testResult.responseTime}ms
@@ -402,8 +402,8 @@ const ExternalCallTestPanel: React.FC = ({ {testResult.statusCode && (
-
- {testResult.statusCode} +
+ {testResult.statusCode}
)} @@ -413,7 +413,7 @@ const ExternalCallTestPanel: React.FC = ({
- {testResult.responseTime}ms + {testResult.responseTime}ms
)} diff --git a/frontend/components/dataflow/external-call/FieldMappingEditor.tsx b/frontend/components/dataflow/external-call/FieldMappingEditor.tsx index f1fd22b8..c0882d54 100644 --- a/frontend/components/dataflow/external-call/FieldMappingEditor.tsx +++ b/frontend/components/dataflow/external-call/FieldMappingEditor.tsx @@ -188,9 +188,9 @@ export const FieldMappingEditor: React.FC = ({
{direction === "inbound" ? ( - + ) : ( - + )} = ({
{direction === "inbound" ? ( - + ) : ( - + )} {direction === "inbound" && currentTable ? ( @@ -339,7 +339,7 @@ export function AggregateProperties({ nodeId, data }: AggregatePropertiesProps)
{func.label}
-
{func.description}
+
{func.description}
))} @@ -349,7 +349,7 @@ export function AggregateProperties({ nodeId, data }: AggregatePropertiesProps) {/* 소스 필드 선택 */}
- + handleAggregationChange(index, "outputField", e.target.value)} placeholder="예: total_amount" className="mt-1 h-8 text-xs" /> -

+

집계 결과가 저장될 필드명입니다

{/* 출력 필드 라벨 */}
- + handleAggregationChange(index, "outputFieldLabel", e.target.value)} @@ -429,16 +429,16 @@ export function AggregateProperties({ nodeId, data }: AggregatePropertiesProps) 조건 추가
-

집계 결과에 대한 필터링 조건을 설정합니다 (선택 사항).

+

집계 결과에 대한 필터링 조건을 설정합니다 (선택 사항).

{havingConditions.length === 0 ? ( -
+
집계 후 필터링이 필요하면 조건을 추가하세요
) : (
{havingConditions.map((condition, index) => ( -
+
{/* 집계 결과 필드 선택 */} - = + = {targetLookupColumns.length > 0 ? ( ) : ( -
+
컬럼 로딩 중...
)}
-
+
비교 값 타입에서 "타겟 필드 (DB 기존값)"을 선택하면 이 테이블의 기존값과 비교합니다.
@@ -784,7 +784,7 @@ export function ConditionProperties({ nodeId, data }: ConditionPropertiesProps) {conditions.length > 0 ? (
{conditions.map((condition, index) => ( -
+
조건 #{index + 1} @@ -806,7 +806,7 @@ export function ConditionProperties({ nodeId, data }: ConditionPropertiesProps)
- + {availableFields.length > 0 ? ( ) : ( -
+
소스 노드를 연결하세요
)}
- + handleConditionChange(index, "valueType", value)} @@ -920,7 +920,7 @@ export function ConditionProperties({ nodeId, data }: ConditionPropertiesProps)
-