차량 관리 (신규): - VehicleList/VehicleDetail: 차량 목록/상세 - ForkliftList/ForkliftDetail: 지게차 목록/상세 - VehicleLogList/VehicleLogDetail: 운행일지 목록/상세 - 관련 페이지 라우트 추가 (/vehicle-management/*) CEO 대시보드: - Enhanced 섹션 컴포넌트 적용 (아이콘 + 컬러 테마) - EnhancedStatusBoardSection, EnhancedDailyReportSection, EnhancedMonthlyExpenseSection - TodayIssueSection 개선 IntegratedDetailTemplate: - FieldInput, FieldRenderer 기능 확장 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
431 lines
12 KiB
TypeScript
431 lines
12 KiB
TypeScript
'use client';
|
|
|
|
/**
|
|
* 지게차 관리 상세 페이지 설정
|
|
* 레거시 5130 사이트 등록 폼 기준 (2025-01-28 스크린샷 검증)
|
|
*/
|
|
|
|
import { Truck } from 'lucide-react';
|
|
import type {
|
|
DetailConfig,
|
|
FieldDefinition,
|
|
SectionDefinition,
|
|
} from '@/components/templates/IntegratedDetailTemplate/types';
|
|
import type { Forklift, ForkliftFormData, PartsChangeRecord, ForkliftMaintenanceRecord } from '../types';
|
|
import { EditableTable, EditableColumn } from '@/components/common/EditableTable';
|
|
|
|
// ===== 부속품 교환 기록 테이블 컬럼 =====
|
|
const partsChangeColumns: EditableColumn<PartsChangeRecord>[] = [
|
|
{
|
|
key: 'date',
|
|
header: '교환일',
|
|
type: 'text',
|
|
placeholder: 'YYYY-MM-DD',
|
|
width: '140px',
|
|
},
|
|
{
|
|
key: 'mileage',
|
|
header: '주행거리',
|
|
type: 'text',
|
|
placeholder: '예: 5000',
|
|
width: '120px',
|
|
align: 'right',
|
|
},
|
|
{
|
|
key: 'cost',
|
|
header: '비용',
|
|
type: 'text',
|
|
placeholder: '예: 50,000',
|
|
width: '120px',
|
|
align: 'right',
|
|
},
|
|
];
|
|
|
|
// ===== 정비내역 테이블 컬럼 =====
|
|
const maintenanceColumns: EditableColumn<ForkliftMaintenanceRecord>[] = [
|
|
{
|
|
key: 'date',
|
|
header: '정비일자',
|
|
type: 'text',
|
|
placeholder: 'YYYY-MM-DD',
|
|
width: '140px',
|
|
},
|
|
{
|
|
key: 'description',
|
|
header: '정비내역 기록',
|
|
type: 'text',
|
|
placeholder: '정비 내용 입력',
|
|
},
|
|
{
|
|
key: 'cost',
|
|
header: '비용',
|
|
type: 'text',
|
|
placeholder: '예: 150,000',
|
|
width: '120px',
|
|
align: 'right',
|
|
},
|
|
];
|
|
|
|
// ===== 새 행 생성 함수 =====
|
|
let partsRecordIdCounter = 0;
|
|
const createNewPartsRecord = (): PartsChangeRecord => ({
|
|
id: `parts-${Date.now()}-${++partsRecordIdCounter}`,
|
|
date: '',
|
|
mileage: '',
|
|
cost: '',
|
|
});
|
|
|
|
let maintenanceRecordIdCounter = 0;
|
|
const createNewMaintenanceRecord = (): ForkliftMaintenanceRecord => ({
|
|
id: `maint-${Date.now()}-${++maintenanceRecordIdCounter}`,
|
|
date: '',
|
|
description: '',
|
|
cost: '',
|
|
});
|
|
|
|
// ===== 필드 정의 (5130 스크린샷 순서대로) =====
|
|
export const forkliftFields: FieldDefinition[] = [
|
|
// Row 1: 지게차번호, 차종, 구매유형
|
|
{
|
|
key: 'vehicleNumber',
|
|
label: '지게차번호',
|
|
type: 'text',
|
|
required: true,
|
|
placeholder: '지게차번호 입력',
|
|
validation: [
|
|
{ type: 'required', message: '지게차번호를 입력해주세요.' },
|
|
],
|
|
},
|
|
{
|
|
key: 'vehicleType',
|
|
label: '차종',
|
|
type: 'text',
|
|
required: true,
|
|
placeholder: '예: 3톤 디젤',
|
|
validation: [
|
|
{ type: 'required', message: '차종을 입력해주세요.' },
|
|
],
|
|
},
|
|
{
|
|
key: 'purchaseType',
|
|
label: '구매유형',
|
|
type: 'select',
|
|
placeholder: '구매유형 선택',
|
|
options: [
|
|
{ label: '리스', value: '리스' },
|
|
{ label: '렌트', value: '렌트' },
|
|
{ label: '회사 소유', value: '회사 소유' },
|
|
],
|
|
},
|
|
|
|
// Row 2: 담당자(정), 담당자(부)
|
|
{
|
|
key: 'managerMain',
|
|
label: '담당자(정)',
|
|
type: 'text',
|
|
placeholder: '담당자(정) 입력',
|
|
},
|
|
{
|
|
key: 'managerSub',
|
|
label: '담당자(부)',
|
|
type: 'text',
|
|
placeholder: '담당자(부) 입력',
|
|
},
|
|
|
|
// Row 3: 구입업체, 구입업체 연락처
|
|
{
|
|
key: 'purchaseCompany',
|
|
label: '구입업체',
|
|
type: 'text',
|
|
placeholder: '구입업체명 입력',
|
|
},
|
|
{
|
|
key: 'purchaseCompanyContact',
|
|
label: '구입업체 연락처',
|
|
type: 'text',
|
|
placeholder: '예: 031-123-4567',
|
|
},
|
|
|
|
// Row 4: 총 주행거리, 기록일
|
|
{
|
|
key: 'totalMileage',
|
|
label: '총 주행거리 (km)',
|
|
type: 'text',
|
|
placeholder: 'km',
|
|
},
|
|
{
|
|
key: 'mileageRecordDate',
|
|
label: '기록일',
|
|
type: 'date',
|
|
placeholder: '연도.월.일.',
|
|
},
|
|
|
|
// Row 5: 최초등록일, 구매일자
|
|
{
|
|
key: 'firstRegistrationDate',
|
|
label: '최초등록일',
|
|
type: 'date',
|
|
placeholder: '연도.월.일.',
|
|
},
|
|
{
|
|
key: 'purchaseDate',
|
|
label: '구매일자',
|
|
type: 'date',
|
|
placeholder: '연도.월.일.',
|
|
},
|
|
|
|
// 부속품 교환주기, 부속품 교환 기록 테이블
|
|
{
|
|
key: 'partsChangeCycle',
|
|
label: '부속품 교환주기(Km)',
|
|
type: 'text',
|
|
placeholder: 'Km',
|
|
},
|
|
{
|
|
key: 'partsChangeRecords',
|
|
label: '부속품 교환일',
|
|
type: 'custom',
|
|
gridSpan: 2,
|
|
formatValue: (value: unknown) => {
|
|
const records = (value as PartsChangeRecord[]) || [];
|
|
if (records.length === 0) return '기록 없음';
|
|
return records.map((record, index) =>
|
|
`${index + 1}. ${record.date} / 주행거리: ${record.mileage}km / 비용: ${record.cost}원`
|
|
).join('\n');
|
|
},
|
|
renderField: ({ value, onChange, mode }) => {
|
|
const records = (value as PartsChangeRecord[]) || [];
|
|
const isViewMode = mode === 'view';
|
|
|
|
if (isViewMode) {
|
|
if (records.length === 0) {
|
|
return <div className="text-muted-foreground">기록 없음</div>;
|
|
}
|
|
return (
|
|
<div className="space-y-1">
|
|
{records.map((record, index) => (
|
|
<div key={record.id} className="text-sm">
|
|
{index + 1}. {record.date} / 주행거리: {record.mileage}km / 비용: {record.cost}원
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<EditableTable
|
|
columns={partsChangeColumns}
|
|
data={records}
|
|
onChange={(newData) => onChange(newData)}
|
|
createNewRow={createNewPartsRecord}
|
|
addButtonLabel="부속품 교환일 추가"
|
|
emptyMessage="교환 기록이 없습니다. 기록을 추가해주세요."
|
|
showRowNumber={true}
|
|
compact={true}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
|
|
// 정비내역 테이블
|
|
{
|
|
key: 'maintenanceRecords',
|
|
label: '정비내역',
|
|
type: 'custom',
|
|
gridSpan: 2,
|
|
formatValue: (value: unknown) => {
|
|
const records = (value as ForkliftMaintenanceRecord[]) || [];
|
|
if (records.length === 0) return '기록 없음';
|
|
return records.map((record, index) =>
|
|
`${index + 1}. ${record.date}: ${record.description} (비용: ${record.cost}원)`
|
|
).join('\n');
|
|
},
|
|
renderField: ({ value, onChange, mode }) => {
|
|
const records = (value as ForkliftMaintenanceRecord[]) || [];
|
|
const isViewMode = mode === 'view';
|
|
|
|
if (isViewMode) {
|
|
if (records.length === 0) {
|
|
return <div className="text-muted-foreground">기록 없음</div>;
|
|
}
|
|
return (
|
|
<div className="space-y-1">
|
|
{records.map((record, index) => (
|
|
<div key={record.id} className="text-sm">
|
|
{index + 1}. {record.date}: {record.description} (비용: {record.cost}원)
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<EditableTable
|
|
columns={maintenanceColumns}
|
|
data={records}
|
|
onChange={(newData) => onChange(newData)}
|
|
createNewRow={createNewMaintenanceRecord}
|
|
addButtonLabel="정비내역 추가"
|
|
emptyMessage="정비 기록이 없습니다. 기록을 추가해주세요."
|
|
showRowNumber={true}
|
|
compact={true}
|
|
/>
|
|
);
|
|
},
|
|
},
|
|
|
|
// 비고
|
|
{
|
|
key: 'remarks',
|
|
label: '비고',
|
|
type: 'textarea',
|
|
placeholder: '비고 입력',
|
|
gridSpan: 2,
|
|
},
|
|
];
|
|
|
|
// ===== 섹션 정의 (5130 스크린샷 순서대로) =====
|
|
export const forkliftSections: SectionDefinition[] = [
|
|
{
|
|
id: 'basicInfo',
|
|
title: '기본 정보',
|
|
description: '지게차의 기본 정보를 입력하세요',
|
|
fields: ['vehicleNumber', 'vehicleType', 'purchaseType'],
|
|
},
|
|
{
|
|
id: 'managerInfo',
|
|
title: '담당자 정보',
|
|
description: '담당자 정보를 입력하세요',
|
|
fields: ['managerMain', 'managerSub'],
|
|
},
|
|
{
|
|
id: 'purchaseCompanyInfo',
|
|
title: '구입업체 정보',
|
|
description: '구입업체 관련 정보를 입력하세요',
|
|
fields: ['purchaseCompany', 'purchaseCompanyContact'],
|
|
},
|
|
{
|
|
id: 'mileageInfo',
|
|
title: '주행거리 정보',
|
|
description: '주행거리 관련 정보를 입력하세요',
|
|
fields: ['totalMileage', 'mileageRecordDate'],
|
|
},
|
|
{
|
|
id: 'purchaseInfo',
|
|
title: '등록/구매 정보',
|
|
description: '등록 및 구매 관련 정보를 입력하세요',
|
|
fields: ['firstRegistrationDate', 'purchaseDate'],
|
|
},
|
|
{
|
|
id: 'partsInfo',
|
|
title: '부속품 교환',
|
|
description: '부속품 교환 관련 정보를 입력하세요',
|
|
fields: ['partsChangeCycle', 'partsChangeRecords'],
|
|
},
|
|
{
|
|
id: 'maintenanceSection',
|
|
title: '정비내역',
|
|
description: '정비 관련 정보를 입력하세요',
|
|
fields: ['maintenanceRecords'],
|
|
},
|
|
{
|
|
id: 'remarksSection',
|
|
title: '비고',
|
|
description: '기타 정보를 입력하세요',
|
|
fields: ['remarks'],
|
|
},
|
|
];
|
|
|
|
// ===== 설정 =====
|
|
export const forkliftDetailConfig: DetailConfig<Forklift> = {
|
|
title: '지게차',
|
|
description: '지게차 정보를 관리합니다',
|
|
icon: Truck,
|
|
basePath: '/ko/vehicle-management/forklift',
|
|
fields: forkliftFields,
|
|
sections: forkliftSections,
|
|
gridColumns: 2,
|
|
actions: {
|
|
submitLabel: '저장',
|
|
cancelLabel: '취소',
|
|
showDelete: true,
|
|
deleteLabel: '삭제',
|
|
showEdit: true,
|
|
editLabel: '수정',
|
|
showBack: true,
|
|
backLabel: '목록',
|
|
deleteConfirmMessage: {
|
|
title: '지게차 삭제',
|
|
description: '이 지게차를 삭제하시겠습니까? 삭제된 데이터는 복구할 수 없습니다.',
|
|
},
|
|
},
|
|
transformInitialData: (data: Forklift) => ({
|
|
vehicleNumber: data.vehicleNumber || '',
|
|
vehicleType: data.vehicleType || '',
|
|
purchaseType: data.purchaseType || '',
|
|
managerMain: data.managerMain || '',
|
|
managerSub: data.managerSub || '',
|
|
purchaseCompany: data.purchaseCompany || '',
|
|
purchaseCompanyContact: data.purchaseCompanyContact || '',
|
|
totalMileage: data.totalMileage || '',
|
|
mileageRecordDate: data.mileageRecordDate || '',
|
|
firstRegistrationDate: data.firstRegistrationDate || '',
|
|
purchaseDate: data.purchaseDate || '',
|
|
partsChangeCycle: data.partsChangeCycle || '',
|
|
partsChangeRecords: data.partsChangeRecords || [],
|
|
maintenanceRecords: data.maintenanceRecords || [],
|
|
remarks: data.remarks || '',
|
|
}),
|
|
transformSubmitData: (formData): Partial<ForkliftFormData> => ({
|
|
vehicleNumber: formData.vehicleNumber as string,
|
|
vehicleType: formData.vehicleType as string,
|
|
purchaseType: formData.purchaseType as string,
|
|
managerMain: formData.managerMain as string,
|
|
managerSub: formData.managerSub as string,
|
|
purchaseCompany: formData.purchaseCompany as string,
|
|
purchaseCompanyContact: formData.purchaseCompanyContact as string,
|
|
totalMileage: formData.totalMileage as string,
|
|
mileageRecordDate: formData.mileageRecordDate as string,
|
|
firstRegistrationDate: formData.firstRegistrationDate as string,
|
|
purchaseDate: formData.purchaseDate as string,
|
|
partsChangeCycle: formData.partsChangeCycle as string,
|
|
partsChangeRecords: formData.partsChangeRecords as PartsChangeRecord[],
|
|
maintenanceRecords: formData.maintenanceRecords as ForkliftMaintenanceRecord[],
|
|
remarks: formData.remarks as string,
|
|
}),
|
|
};
|
|
|
|
// ===== 등록 페이지 Config =====
|
|
export const forkliftCreateConfig: DetailConfig = {
|
|
title: '지게차',
|
|
description: '지게차 정보를 입력하세요',
|
|
icon: Truck,
|
|
basePath: '/vehicle-management/forklift',
|
|
fields: forkliftFields,
|
|
sections: forkliftSections,
|
|
gridColumns: 2,
|
|
actions: {
|
|
showBack: true,
|
|
showSave: true,
|
|
submitLabel: '저장',
|
|
backLabel: '닫기',
|
|
},
|
|
};
|
|
|
|
// ===== 수정 페이지 Config =====
|
|
export const forkliftEditConfig: DetailConfig = {
|
|
title: '지게차',
|
|
description: '지게차 정보를 수정합니다',
|
|
icon: Truck,
|
|
basePath: '/vehicle-management/forklift',
|
|
fields: forkliftFields,
|
|
sections: forkliftSections,
|
|
gridColumns: 2,
|
|
actions: {
|
|
showBack: true,
|
|
showSave: true,
|
|
submitLabel: '저장',
|
|
backLabel: '닫기',
|
|
},
|
|
};
|