feat: ESLint 정리 및 전체 코드 품질 개선

- eslint.config.mjs 규칙 강화 및 정리
- 전역 unused import/변수 제거 (312개 파일)
- next.config.ts, middleware, proxy route 개선
- CopyableCell molecule 추가
- 회계/결재/HR/생산/건설/품질/영업 등 전 도메인 lint 정리
- IntegratedListTemplateV2, DataTable, MobileCard 등 공통 컴포넌트 개선
- execute-server-action 에러 핸들링 보강
This commit is contained in:
유병철
2026-03-11 10:27:10 +09:00
parent 924726cba1
commit 81affdc441
315 changed files with 1977 additions and 1344 deletions

View File

@@ -7,7 +7,7 @@ import { Button } from "@/components/ui/button";
import { ChevronLeft, ChevronRight, LucideIcon } from "lucide-react";
import { StatusBadge, StatusType } from "@/components/molecules/StatusBadge";
import { IconWithBadge } from "@/components/molecules/IconWithBadge";
import { TableActions, TableAction } from "@/components/molecules/TableActions";
import { TableActions } from "@/components/molecules/TableActions";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import { formatNumber } from '@/lib/utils/amount';
@@ -100,20 +100,22 @@ function renderCell<T>(column: Column<T>, value: any, row: T, index?: number): R
case "number":
return <span className="font-mono">{formatNumber(formattedValue)}</span>;
case "currency":
case "currency": {
const locale = column.currencyConfig?.locale || "ko-KR";
const currency = column.currencyConfig?.currency || "KRW";
const currencyValue = typeof formattedValue === "number"
? formattedValue.toLocaleString(locale, { style: "currency", currency })
: formattedValue;
return <span className="font-mono">{currencyValue}</span>;
}
case "date":
case "date": {
if (!formattedValue) return "-";
const dateValue = new Date(formattedValue);
return <span className="text-sm">{dateValue.toLocaleDateString("ko-KR")}</span>;
}
case "datetime":
case "datetime": {
if (!formattedValue) return "-";
const datetimeValue = new Date(formattedValue);
return (
@@ -121,6 +123,7 @@ function renderCell<T>(column: Column<T>, value: any, row: T, index?: number): R
{datetimeValue.toLocaleDateString("ko-KR")} {datetimeValue.toLocaleTimeString("ko-KR", { hour: "2-digit", minute: "2-digit" })}
</span>
);
}
case "status":
return (
@@ -141,7 +144,7 @@ function renderCell<T>(column: Column<T>, value: any, row: T, index?: number): R
</Badge>
);
case "icon":
case "icon": {
const IconComponent = formattedValue as LucideIcon;
return IconComponent ? (
<IconWithBadge
@@ -151,6 +154,7 @@ function renderCell<T>(column: Column<T>, value: any, row: T, index?: number): R
size={column.iconConfig?.size}
/>
) : null;
}
case "iconBadge":
// value should be { icon, label, badge }
@@ -168,10 +172,11 @@ function renderCell<T>(column: Column<T>, value: any, row: T, index?: number): R
}
return formattedValue;
case "actions":
case "actions": {
// render 함수가 TableAction[] 배열을 반환해야 함
const actions = Array.isArray(formattedValue) ? formattedValue : [];
return actions.length > 0 ? <TableActions actions={actions} /> : null;
}
case "custom":
// 커스텀 타입은 이미 render 함수에서 처리됨

View File

@@ -1,13 +1,14 @@
'use client';
import { ReactNode, ComponentType, memo, useState } from 'react';
import { Card, CardContent } from '@/components/ui/card';
import {} from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Checkbox } from '@/components/ui/checkbox';
import { Separator } from '@/components/ui/separator';
import { cn } from '@/lib/utils';
import { LucideIcon, ChevronDown } from 'lucide-react';
import { ChevronDown } from 'lucide-react';
import type { LucideIcon } from 'lucide-react';
type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline';
@@ -121,7 +122,7 @@ export interface MobileCardProps {
export function MobileCard({
// 공통
title,
id,
id: _id,
subtitle,
description,
icon,

View File

@@ -17,8 +17,8 @@ export function SearchFilter({
searchValue,
onSearchChange,
searchPlaceholder = "검색",
filterButton = true,
onFilterClick,
filterButton: _filterButton = true,
onFilterClick: _onFilterClick,
extraActions
}: SearchFilterProps) {
const [isMobile, setIsMobile] = useState(false);