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

@@ -15,8 +15,6 @@ import dynamic from 'next/dynamic';
import { useRouter } from 'next/navigation';
import { Plus, Trash2, ClipboardCheck } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { getPresetStyle } from '@/lib/utils/status-config';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { DatePicker } from '@/components/ui/date-picker';
@@ -39,7 +37,7 @@ import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetai
import { qualityInspectionCreateConfig } from './inspectionConfig';
import { toast } from 'sonner';
import { createInspection } from './actions';
import { isOrderSpecSame, calculateOrderSummary } from './mockData';
import { calculateOrderSummary } from './mockData';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
const OrderSelectModal = dynamic(

View File

@@ -20,12 +20,10 @@ import {
Loader2,
Plus,
Trash2,
ChevronDown,
ClipboardCheck,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { getPresetStyle } from '@/lib/utils/status-config';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { DatePicker } from '@/components/ui/date-picker';
@@ -63,7 +61,6 @@ import {
import { getFqcStatus, type FqcStatusItem } from './fqcActions';
import {
statusColorMap,
isOrderSpecSame,
calculateOrderSummary,
buildRequestDocumentData,
buildReportDocumentData,
@@ -623,7 +620,7 @@ export function InspectionDetail({ id }: InspectionDetailProps) {
return (
<div className="space-y-4">
{groups.map((group, groupIndex) => (
{groups.map((group, _groupIndex) => (
<div key={group.orderNumber} className="border rounded-lg">
<div className="flex items-center gap-6 text-sm px-4 py-3 bg-muted/30 rounded-t-lg">
<span className="font-medium w-32">{group.orderNumber}</span>
@@ -694,7 +691,7 @@ export function InspectionDetail({ id }: InspectionDetailProps) {
return (
<div className="space-y-4">
{groups.map((group, groupIndex) => (
{groups.map((group, _groupIndex) => (
<div key={group.orderNumber} className="border rounded-lg">
<div className="flex items-center gap-6 text-sm px-4 py-3 bg-muted/30 rounded-t-lg">
<span className="font-medium w-32">{group.orderNumber}</span>

View File

@@ -20,7 +20,6 @@ import {
Loader2,
CheckCircle2,
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { getPresetStyle } from '@/lib/utils/status-config';
import { TableCell, TableRow } from '@/components/ui/table';
@@ -48,7 +47,7 @@ import { statusColorMap } from './mockData';
import { parseISO } from 'date-fns';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { getLocalDateString } from '@/lib/utils/date';
import type { ProductInspection, InspectionStats, InspectionStatus } from './types';
import type { ProductInspection, InspectionStatus } from './types';
const ITEMS_PER_PAGE = 20;
@@ -266,16 +265,16 @@ export function InspectionList() {
// 테이블 컬럼
columns: [
{ key: 'no', label: 'No.', className: 'w-[50px] text-center' },
{ key: 'qualityDocNumber', label: '품질관리서 번호', className: 'min-w-[120px]' },
{ key: 'siteName', label: '현장명', className: 'min-w-[100px]' },
{ key: 'client', label: '수주처', className: 'min-w-[80px]' },
{ key: 'locationCount', label: '개소', className: 'w-[60px] text-center' },
{ key: 'requiredInfo', label: '필수정보', className: 'w-[90px] text-center' },
{ key: 'inspectionPeriod', label: '검사기간', className: 'min-w-[140px]' },
{ key: 'inspector', label: '검사자', className: 'w-[80px] text-center' },
{ key: 'qualityDocNumber', label: '품질관리서 번호', className: 'min-w-[120px]', copyable: true },
{ key: 'siteName', label: '현장명', className: 'min-w-[100px]', copyable: true },
{ key: 'client', label: '수주처', className: 'min-w-[80px]', copyable: true },
{ key: 'locationCount', label: '개소', className: 'w-[60px] text-center', copyable: true },
{ key: 'requiredInfo', label: '필수정보', className: 'w-[90px] text-center', copyable: true },
{ key: 'inspectionPeriod', label: '검사기간', className: 'min-w-[140px]', copyable: true },
{ key: 'inspector', label: '검사자', className: 'w-[80px] text-center', copyable: true },
{ key: 'status', label: '상태', className: 'w-[70px] text-center' },
{ key: 'author', label: '작성자', className: 'w-[80px] text-center' },
{ key: 'receptionDate', label: '접수일', className: 'w-[100px] text-center' },
{ key: 'author', label: '작성자', className: 'w-[80px] text-center', copyable: true },
{ key: 'receptionDate', label: '접수일', className: 'w-[100px] text-center', copyable: true },
],
// 서버 사이드 페이지네이션

View File

@@ -72,7 +72,7 @@ export function ProductInspectionInputModal({
}: ProductInspectionInputModalProps) {
// FQC 모드 상태
const [fqcTemplate, setFqcTemplate] = useState<FqcTemplate | null>(null);
const [fqcDocData, setFqcDocData] = useState<FqcDocumentData[]>([]);
const [, setFqcDocData] = useState<FqcDocumentData[]>([]);
const [isLoadingFqc, setIsLoadingFqc] = useState(false);
const [isSaving, setIsSaving] = useState(false);

View File

@@ -60,7 +60,7 @@ function getSectionItemValue(
/** EAV 데이터에서 테이블 행 데이터 조회 */
function getTableRows(
data: FqcDocumentData[] | undefined,
columns: FqcTemplate['columns'],
_columns: FqcTemplate['columns'],
): Array<Record<string, string>> {
if (!data) return [];
// column_id가 있는 데이터만 필터 → row_index로 그룹핑

View File

@@ -357,24 +357,24 @@ export function PerformanceReportList() {
columnsPerTab: {
quarterly: [
{ key: 'no', label: '번호', className: 'w-[60px] text-center' },
{ key: 'qualityDocNumber', label: '품질관리서 번호', className: 'min-w-[130px]' },
{ key: 'createdDate', label: '작성일', className: 'w-[100px]' },
{ key: 'siteName', label: '현장명', className: 'min-w-[120px]' },
{ key: 'client', label: '수주처', className: 'min-w-[80px]' },
{ key: 'locationCount', label: '개소', className: 'w-[60px] text-center' },
{ key: 'requiredInfo', label: '필수정보', className: 'w-[90px] text-center' },
{ key: 'qualityDocNumber', label: '품질관리서 번호', className: 'min-w-[130px]', copyable: true },
{ key: 'createdDate', label: '작성일', className: 'w-[100px]', copyable: true },
{ key: 'siteName', label: '현장명', className: 'min-w-[120px]', copyable: true },
{ key: 'client', label: '수주처', className: 'min-w-[80px]', copyable: true },
{ key: 'locationCount', label: '개소', className: 'w-[60px] text-center', copyable: true },
{ key: 'requiredInfo', label: '필수정보', className: 'w-[90px] text-center', copyable: true },
{ key: 'confirmStatus', label: '확정상태', className: 'w-[80px] text-center' },
{ key: 'confirmDate', label: '확정일', className: 'w-[100px]' },
{ key: 'memo', label: '메모', className: 'min-w-[120px]' },
{ key: 'confirmDate', label: '확정일', className: 'w-[100px]', copyable: true },
{ key: 'memo', label: '메모', className: 'min-w-[120px]', copyable: true },
],
missed: [
{ key: 'no', label: '번호', className: 'w-[60px] text-center' },
{ key: 'qualityDocNumber', label: '품질관리서 번호', className: 'min-w-[130px]' },
{ key: 'siteName', label: '현장명', className: 'min-w-[120px]' },
{ key: 'client', label: '수주처', className: 'min-w-[80px]' },
{ key: 'locationCount', label: '개소', className: 'w-[60px] text-center' },
{ key: 'inspectionCompleteDate', label: '제품검사완료일', className: 'w-[120px]' },
{ key: 'memo', label: '메모', className: 'min-w-[120px]' },
{ key: 'qualityDocNumber', label: '품질관리서 번호', className: 'min-w-[130px]', copyable: true },
{ key: 'siteName', label: '현장명', className: 'min-w-[120px]', copyable: true },
{ key: 'client', label: '수주처', className: 'min-w-[80px]', copyable: true },
{ key: 'locationCount', label: '개소', className: 'w-[60px] text-center', copyable: true },
{ key: 'inspectionCompleteDate', label: '제품검사완료일', className: 'w-[120px]', copyable: true },
{ key: 'memo', label: '메모', className: 'min-w-[120px]', copyable: true },
],
},
columns: [], // columnsPerTab 사용