diff --git a/INDEX.md b/INDEX.md index 18081a0..3195f7f 100644 --- a/INDEX.md +++ b/INDEX.md @@ -226,7 +226,8 @@ DB 도메인별: | [payroll-api.md](frontend/api-specs/payroll-api.md) | 급여관리 API 전체 명세 (18개 엔드포인트) | | [barobill-api.md](frontend/api-specs/barobill-api.md) | 바로빌 회계 데이터 API 명세 (42개 엔드포인트) | | [equipment-api.md](requests/equipment-frontend-request.md) | 설비관리 React 프론트엔드 구현 요청 (26개 엔드포인트 + 화면 가이드) | -| [vehicle-api.md](frontend/api-specs/vehicle-api.md) | 차량관리 API 명세 (17개 엔드포인트: 차량목록, 차량일지, 정비이력) | +| [vehicle-api.md](frontend/api-specs/vehicle-api.md) | 차량관리 API 명세 (20개 엔드포인트: 차량목록, 차량일지, 정비이력, 사진) | +| [vehicle-react-implementation.md](plans/vehicle-react-implementation.md) | 차량관리 React 구현 요청서 (3개 메뉴, 컴포넌트 구조, 타입 정의) | ### frontend/integration/ — 프론트엔드 개발 가이드 diff --git a/plans/vehicle-react-implementation.md b/plans/vehicle-react-implementation.md new file mode 100644 index 0000000..ed42f62 --- /dev/null +++ b/plans/vehicle-react-implementation.md @@ -0,0 +1,727 @@ +# 차량관리 React 구현 요청서 + +> **작성일**: 2026-03-12 +> **요청자**: R&D 실장 +> **대상**: 프론트엔드 개발자 +> **우선순위**: 🟡 중요 +> **API 상태**: 이관 진행중 (사진 API 구현 완료, CRUD API 구현 예정) + +--- + +## 1. 개요 + +MNG에서 운영중인 차량관리 3개 메뉴를 React(Next.js)로 구현한다. +멀티테넌트 지원을 위한 이관 작업이며, API는 순차적으로 제공된다. + +### 1.1 구현 대상 + +| 메뉴 | 설명 | 난이도 | +|------|------|:------:| +| **차량목록** | 법인/렌트/리스 차량 등록 관리 + 사진 | 중 | +| **차량일지** | 운행기록 CRUD + 월별 통계 | 중 | +| **정비이력** | 정비/주유/보험 비용 관리 + 카테고리별 집계 | 중 | + +### 1.2 참고 문서 + +| 문서 | 경로 | 용도 | +|------|------|------| +| **API 명세** (필독) | `docs/frontend/api-specs/vehicle-api.md` | 전체 엔드포인트, 데이터 모델, UI 가이드 | +| 차량목록 기능 상세 | `docs/features/card-vehicle/corporate-vehicles.md` | MNG 기존 동작 | +| 차량일지 기능 상세 | `docs/features/card-vehicle/vehicle-logs.md` | MNG 기존 동작 | +| 정비이력 기능 상세 | `docs/features/card-vehicle/vehicle-maintenance.md` | MNG 기존 동작 | + +--- + +## 2. 파일 구조 (제안) + +``` +src/ +├── app/[locale]/(protected)/ +│ ├── vehicles/ # 차량목록 +│ │ ├── page.tsx # 목록 페이지 +│ │ ├── create/page.tsx # 등록 페이지 +│ │ └── [id]/ +│ │ ├── page.tsx # 상세 페이지 +│ │ └── edit/page.tsx # 수정 페이지 +│ │ +│ ├── vehicle-logs/ # 차량일지 +│ │ └── page.tsx # 목록 + 등록/수정 모달 +│ │ +│ └── vehicle-maintenance/ # 정비이력 +│ └── page.tsx # 목록 + 등록/수정 모달 +│ +├── components/vehicles/ # 차량 관련 컴포넌트 +│ ├── VehicleListClient.tsx # 차량목록 클라이언트 +│ ├── VehicleForm.tsx # 차량 등록/수정 폼 +│ ├── VehiclePhotoSection.tsx # 사진 업로드/관리 영역 +│ ├── VehicleDetailView.tsx # 차량 상세 뷰 +│ ├── VehicleLogListClient.tsx # 차량일지 클라이언트 +│ ├── VehicleLogModal.tsx # 차량일지 등록/수정 모달 +│ ├── VehicleMaintenanceListClient.tsx # 정비이력 클라이언트 +│ └── VehicleMaintenanceModal.tsx # 정비이력 등록/수정 모달 +│ +├── lib/api/ +│ └── vehicle.ts # 차량 관련 Server Action +│ +├── hooks/ +│ ├── useVehicleList.ts # 차량목록 훅 +│ ├── useVehicleLogs.ts # 차량일지 훅 +│ └── useVehicleMaintenance.ts # 정비이력 훅 +│ +└── types/ + └── vehicle.ts # 차량 관련 타입 정의 +``` + +--- + +## 3. 메뉴별 구현 상세 + +### 3.1 차량목록 + +#### 화면 구성 + +``` +┌─ PageHeader ────────────────────────── +│ 제목: "차량목록" +│ [검색] [Excel 다운로드] [+ 차량 등록] +│ +├─ StatCards (4열) ───────────────────── +│ 총 차량 | 법인 취득가 | 월 렌트/리스비 | 총 주행거리 +│ +├─ 필터 바 ───────────────────────────── +│ 소유형태: [전체] [법인] [렌트] [리스] ← 탭 or 버튼 그룹 +│ 상태: [전체] [운행중] [정비중] [처분] +│ +├─ DataTable ─────────────────────────── +│ 차량번호 | 차종/모델 | 소유형태(배지) | 운전자 | 주행거리 | 상태(배지) +│ └─ 행 클릭 → /vehicles/{id} 상세 페이지 +│ +└─ 빈 상태: EmptyState "등록된 차량이 없습니다." +``` + +#### API 호출 + +```typescript +// lib/api/vehicle.ts +export async function getVehicles(filters) { + return executePaginatedAction({ + url: buildApiUrl('/api/v1/corporate-vehicles', filters), + transform: mapVehicleResponse, + errorMessage: '차량 목록 조회 실패', + }); +} +``` + +#### 요약 카드 계산 (프론트엔드에서 처리) + +| 카드 | 계산식 | +|------|--------| +| 총 차량 | 목록 전체 건수 | +| 법인 취득가 | `ownership_type === 'corporate'`인 차량의 `purchase_price` 합계 | +| 월 렌트/리스비 | `ownership_type in ('rent','lease')`인 차량의 `monthly_rent + monthly_rent_tax` 합계 | +| 총 주행거리 | 전체 차량의 `total_mileage` 합계 | + +#### 등록/수정 폼 — 조건부 필드 + +`ownership_type` 값에 따라 폼 하단 필드가 변경된다: + +| 소유형태 | 표시 필드 | +|---------|----------| +| `corporate` (법인) | 취득일자, 취득가액 | +| `rent` / `lease` | 계약일자, 렌트/리스사, 연락처, 계약기간, 약정주행거리, 차량가액, 잔존가치, 보증금, 월렌트료(공급가), 월렌트료(부가세), 보험사, 보험사 연락처 | + +#### 사진 기능 (차량 상세/수정 페이지) + +``` +┌─ 사진 영역 ────────────────────────── +│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ +│ │ 📷 │ │ 📷 │ │ 📷 │ │ + │ +│ │ 사진1 │ │ 사진2 │ │ 사진3 │ │ 추가 │ +│ └──────┘ └──────┘ └──────┘ └──────┘ +│ 3 / 10장 +└────────────────────────────────────── +``` + +| 기능 | 설명 | +|------|------| +| 업로드 | `POST /{id}/photos`, `multipart/form-data`, `files[]` 다중 선택 | +| 삭제 | `DELETE /{id}/photos/{fileId}`, 각 사진에 X 버튼 | +| 제한 | 최대 10장, 10MB/파일, jpg/jpeg/png/gif/bmp/webp | +| 미리보기 | 업로드 전 FileReader API로 미리보기 | +| 확대 보기 | 사진 클릭 시 모달 확대 (선택 구현) | +| 카운터 | `{현재 수} / 10장` 표시, 10장 도달 시 추가 버튼 비활성화 | + +#### 배지 색상 + +**소유형태 (`ownership_type`)**: + +| 값 | 라벨 | 색상 | +|----|------|------| +| `corporate` | 법인 | purple | +| `rent` | 렌트 | blue | +| `lease` | 리스 | green | + +**상태 (`status`)**: + +| 값 | 라벨 | 색상 | +|----|------|------| +| `active` | 운행중 | green | +| `maintenance` | 정비중 | yellow | +| `disposed` | 처분 | red | + +--- + +### 3.2 차량일지 + +#### 화면 구성 + +``` +┌─ PageHeader ────────────────────────── +│ 차량: [드롭다운 ▼] (현재 주행거리: 17,350 km) +│ [2026년 ▼] [3월 ▼] [CSV 다운로드] [+ 기록 추가] +│ +├─ StatCards (4열) ───────────────────── +│ 출근 (5건 / 125km) | 퇴근 (5건 / 130km) | 업무 (10건 / 280km) | 비업무 (2건 / 45km) +│ +├─ DataTable ─────────────────────────── +│ 날짜 | 차량 | 부서/이름 | 용도(배지) | 출발지 | 도착지 | 거리(km) | 비고 | 작업 +│ └─ 작업: [복사] [수정] [삭제] +│ +└─ 등록/수정 모달 (StandardDialog) +``` + +#### API 호출 + +```typescript +// 목록 조회 +getVehicleLogs({ vehicle_id, year, month, trip_type, search }) + +// 통계 조회 (별도 API) +getVehicleLogSummary({ vehicle_id, year, month }) + +// 차량 드롭다운 +getVehicleDropdown() // GET /api/v1/corporate-vehicles/dropdown +``` + +#### 통계 카드 (summary API 응답 사용) + +API 응답 `data.byType`의 각 항목에서 `count`와 `distance`를 표시한다. +`data.total`로 전체 합계도 표시 가능하다. + +#### 등록/수정 모달 + +``` +┌─ 모달 ──────────────────────────────── +│ 차량: [드롭다운 ▼] +│ 날짜: [2026-03-12] 부서: [영업부] +│ 운전자: [홍길동] 용도: [업무용 ▼] +│ +│ ── 출발지 ── +│ 유형: [회사 ▼] 이름: [본사] 주소: [서울시 강남구...] +│ +│ ── 도착지 ── [↕ 출발↔도착 교환] +│ 유형: [거래처 ▼] 이름: [거래처A] 주소: [경기도 성남시...] +│ +│ 운행거리: [45] km +│ +│ 비고: [거래처방문 ] +│ [거래처방문] [제조시설등] [회의참석] [판촉활동] [교육등] ← 프리셋 버튼 +│ +│ [삭제] [취소] [저장] +└─────────────────────────────────────── +``` + +#### 특수 기능 (프론트엔드 로직) + +| 기능 | 동작 | +|------|------| +| **기록 복사** | 기존 행의 데이터를 모달에 채워서 열기 (날짜만 오늘로 변경). API는 일반 POST | +| **출발↔도착 교환** | 출발지/도착지 필드 swap + `tripType` 자동 전환 (`commute_to` ↔ `commute_from`) | +| **비고 프리셋** | 5개 버튼 클릭 시 비고 input에 텍스트 삽입 | +| **왕복 용도** | `commute_round`, `business_round`, `personal_round` 선택 시 편도의 2배로 `distance_km` 자동 제안 (선택) | + +#### 용도 배지 색상 + +| 값 | 라벨 | 색상 | +|----|------|------| +| `commute_to` | 출근용 | green | +| `commute_from` | 퇴근용 | blue | +| `business` | 업무용 | purple | +| `personal` | 비업무 | gray | +| `commute_round` | 출퇴근 왕복 | green | +| `business_round` | 업무용 왕복 | purple | +| `personal_round` | 비업무 왕복 | gray | + +#### 위치 유형 드롭다운 + +| 값 | 라벨 | +|----|------| +| `home` | 자택 | +| `office` | 회사 | +| `client` | 거래처 | +| `other` | 기타 | + +--- + +### 3.3 정비이력 + +#### 화면 구성 + +``` +┌─ PageHeader ────────────────────────── +│ 제목: "정비이력" +│ [새로고침] [CSV 다운로드] [+ 정비 등록] +│ +├─ StatCards (4열) ───────────────────── +│ 총 정비비용 | 주유비 | 정비비 | 기타비용 +│ +├─ 필터 영역 ─────────────────────────── +│ 기간: [시작일] ~ [종료일] (기본: 최근 3개월) +│ 카테고리: [전체] [주유] [정비] [보험] [세차] [주차] [통행료] [검사] [기타] +│ 차량: [드롭다운 ▼] +│ 검색: [설명, 업체명 검색...] +│ +├─ DataTable ─────────────────────────── +│ 날짜 | 차량 | 카테고리(배지) | 설명 | 금액 | 주행거리 | 작업 +│ └─ 작업: [수정] [삭제] +│ +└─ 등록/수정 모달 (StandardDialog) +``` + +#### 요약 카드 계산 (조회된 목록 데이터 기준) + +| 카드 | 계산식 | +|------|--------| +| 총 정비비용 | 전체 `amount` 합계 | +| 주유비 | `category === '주유'`인 `amount` 합계 | +| 정비비 | `category === '정비'`인 `amount` 합계 | +| 기타비용 | 총 정비비용 - 주유비 - 정비비 | + +#### 등록/수정 모달 + +``` +┌─ 모달 ──────────────────────────────── +│ 차량: [드롭다운 ▼] +│ 날짜: [2026-03-10] +│ 카테고리: [주유 ▼] +│ 설명: [LPG 충전] +│ 금액: [85,000] 원 ← currency 포맷 +│ 주행거리: [17,350] km +│ 업체명: [SK에너지 강남점] +│ 메모: [ ] +│ +│ [삭제] [취소] [저장] +└─────────────────────────────────────── +``` + +#### 카테고리 배지 색상 + +| 카테고리 | 색상 | +|---------|------| +| 주유 | amber | +| 정비 | blue | +| 보험 | emerald | +| 세차 | cyan | +| 주차 | purple | +| 통행료 | orange | +| 검사 | indigo | +| 기타 | gray | + +#### 부수 효과 안내 + +정비 등록/수정 시 `mileage` 값이 있으면 해당 차량의 기준 주행거리가 자동 갱신된다. +프론트엔드에서는 별도 처리 불필요 (API가 자동 처리). + +--- + +## 4. 타입 정의 + +```typescript +// types/vehicle.ts + +// ─── 차량 ─── +export interface CorporateVehicle { + id: number; + plateNumber: string; + model: string; + vehicleType: string; + ownershipType: 'corporate' | 'rent' | 'lease'; + year?: number; + driver?: string; + status: 'active' | 'maintenance' | 'disposed'; + mileage: number; + memo?: string; + // 법인 전용 + purchaseDate?: string; + purchasePrice?: number; + // 렌트/리스 전용 + contractDate?: string; + rentCompany?: string; + rentCompanyTel?: string; + rentPeriod?: string; + agreedMileage?: string; + vehiclePrice?: number; + residualValue?: number; + deposit?: number; + monthlyRent?: number; + monthlyRentTax?: number; + insuranceCompany?: string; + insuranceCompanyTel?: string; + // 계산 필드 + logDistance: number; + totalMileage: number; +} + +export interface VehicleDropdownItem { + id: number; + plateNumber: string; + model: string; +} + +// ─── 차량 사진 ─── +export interface VehiclePhoto { + id: number; + fileName: string; + filePath: string; + fileUrl: string; + fileSize: number; + mimeType: string; + createdAt: string; +} + +// ─── 운행기록 ─── +export interface VehicleLog { + id: number; + logDate: string; + vehicleId: number; + plateNumber: string; + model: string; + department?: string; + driverName: string; + tripType: TripType; + departureType?: LocationType; + departureName?: string; + departureAddress?: string; + arrivalType?: LocationType; + arrivalName?: string; + arrivalAddress?: string; + distanceKm: number; + note?: string; +} + +export type TripType = + | 'commute_to' | 'commute_from' + | 'business' | 'personal' + | 'commute_round' | 'business_round' | 'personal_round'; + +export type LocationType = 'home' | 'office' | 'client' | 'other'; + +export interface VehicleLogSummary { + byType: Record; + total: { count: number; distance: number }; +} + +// ─── 정비이력 ─── +export interface VehicleMaintenance { + id: number; + date: string; + vehicleId: number; + plateNumber: string; + model: string; + category: MaintenanceCategory; + description?: string; + amount: number; + mileage?: number; + vendor?: string; + memo?: string; +} + +export type MaintenanceCategory = + | '주유' | '정비' | '보험' | '세차' + | '주차' | '통행료' | '검사' | '기타'; +``` + +--- + +## 5. API 호출 예시 + +```typescript +// lib/api/vehicle.ts +'use server'; + +import { buildApiUrl } from '@/lib/api/query-params'; +import { executePaginatedAction, executeServerAction } from '@/lib/api/execute-server-action'; + +// ─── 차량 목록 ─── +export async function getVehicles(params: { + ownership_type?: string; + vehicle_type?: string; + status?: string; + search?: string; +}) { + return executePaginatedAction({ + url: buildApiUrl('/api/v1/corporate-vehicles', params), + transform: mapVehicleResponse, + errorMessage: '차량 목록 조회 실패', + }); +} + +// ─── 차량 드롭다운 ─── +export async function getVehicleDropdown() { + return executeServerAction({ + url: buildApiUrl('/api/v1/corporate-vehicles/dropdown'), + errorMessage: '차량 목록 조회 실패', + }); +} + +// ─── 차량 등록 ─── +export async function createVehicle(data: Record) { + return executeServerAction({ + url: buildApiUrl('/api/v1/corporate-vehicles'), + options: { method: 'POST', body: JSON.stringify(data) }, + errorMessage: '차량 등록 실패', + }); +} + +// ─── 차량 사진 ─── +export async function getVehiclePhotos(vehicleId: number) { + return executeServerAction({ + url: buildApiUrl(`/api/v1/corporate-vehicles/${vehicleId}/photos`), + errorMessage: '사진 조회 실패', + }); +} + +// ─── 운행기록 목록 ─── +export async function getVehicleLogs(params: { + vehicle_id?: number; + year?: number; + month?: number; + trip_type?: string; + search?: string; +}) { + return executePaginatedAction({ + url: buildApiUrl('/api/v1/vehicle-logs', params), + transform: (item) => item, // camelCase 그대로 + errorMessage: '운행기록 조회 실패', + }); +} + +// ─── 운행기록 통계 ─── +export async function getVehicleLogSummary(params: { + vehicle_id?: number; + year?: number; + month?: number; +}) { + return executeServerAction({ + url: buildApiUrl('/api/v1/vehicle-logs/summary', params), + errorMessage: '운행 통계 조회 실패', + }); +} + +// ─── 정비이력 목록 ─── +export async function getMaintenances(params: { + vehicle_id?: number; + category?: string; + start_date?: string; + end_date?: string; + search?: string; +}) { + return executePaginatedAction({ + url: buildApiUrl('/api/v1/vehicle-maintenances', params), + transform: (item) => item, + errorMessage: '정비이력 조회 실패', + }); +} +``` + +--- + +## 6. 공통 컴포넌트 활용 가이드 + +기존 프로젝트에 구현된 공통 컴포넌트를 **반드시 재사용**한다. + +| 컴포넌트 | 위치 | 용도 | +|---------|------|------| +| `PageLayout` | `components/organisms/` | 페이지 기본 레이아웃 | +| `PageHeader` | `components/organisms/` | 페이지 헤더 (제목 + 액션 버튼) | +| `StatCards` | `components/organisms/` | 요약 통계 카드 | +| `DataTable` | `components/organisms/` | 데이터 테이블 | +| `EmptyState` | `components/organisms/` | 빈 상태 표시 | +| `StandardDialog` | `components/molecules/` | 모달 다이얼로그 | +| `FormField` | `components/molecules/` | 통합 폼 필드 (text, number, date, select, currency 등) | +| `StatusBadge` | `components/molecules/` | 상태 배지 | +| `DateRangeSelector` | `components/molecules/` | 기간 선택 | +| `SearchableSelectionModal` | `components/organisms/` | 검색형 선택 모달 | + +### 사용 예시 + +```tsx +// FormField 사용 (신규 폼 필수) + + + + +// StatusBadge 사용 + +``` + +--- + +## 7. 숫자/금액 포맷 + +| 항목 | 포맷 | 예시 | +|------|------|------| +| 금액 | 천단위 콤마 + "원" | `85,000원` | +| 거리 | 천단위 콤마 + "km" | `17,350 km` | +| 취득가 | 천단위 콤마 + "원" | `85,000,000원` | +| 월렌트료 | 천단위 콤마 + "원" | `1,200,000원` | + +기존 `lib/utils/amount.ts`의 포맷 함수를 사용한다. + +--- + +## 8. 사진 업로드 컴포넌트 구현 가이드 + +사진 업로드는 별도 컴포넌트(`VehiclePhotoSection`)로 분리한다. + +### 핵심 로직 + +```typescript +// 사진 업로드 (multipart/form-data) +async function uploadPhotos(vehicleId: number, files: File[]) { + const formData = new FormData(); + files.forEach(file => formData.append('files[]', file)); + + // Next.js 프록시를 통해 전송 + const res = await fetch(`/api/proxy/corporate-vehicles/${vehicleId}/photos`, { + method: 'POST', + body: formData, + // Content-Type 헤더를 직접 설정하지 않음 (브라우저가 boundary 자동 설정) + }); + return res.json(); +} +``` + +### 주의사항 + +``` +❌ Content-Type: multipart/form-data 직접 설정 금지 (boundary 누락됨) +❌ JSON.stringify(formData) 금지 +✅ FormData 객체를 body에 그대로 전달 +✅ 파일 선택 시 남은 수량(10 - 현재) 체크 후 초과분 차단 +``` + +--- + +## 9. 라우팅 및 메뉴 등록 + +### 페이지 라우트 + +| 경로 | 페이지 | +|------|--------| +| `/vehicles` | 차량 목록 | +| `/vehicles/create` | 차량 등록 | +| `/vehicles/{id}` | 차량 상세 | +| `/vehicles/{id}/edit` | 차량 수정 | +| `/vehicle-logs` | 차량일지 (모달 CRUD) | +| `/vehicle-maintenance` | 정비이력 (모달 CRUD) | + +### 메뉴 등록 + +메뉴 DB 등록은 별도 요청 예정. 개발 단계에서는 URL 직접 접근으로 테스트한다. + +--- + +## 10. 데이터 관계 요약 + +``` +corporate_vehicles (차량 마스터) + │ + ├── vehicle_logs (1:N) + │ 운행기록 → distance_km 합산 → 차량 total_mileage 계산 + │ + ├── vehicle_maintenances (1:N) + │ 정비기록 → mileage 입력 시 차량 기준 주행거리 자동 갱신 + │ + └── files (1:N, polymorphic) + 사진 → 최대 10장, R2 스토리지 + +총 주행거리 = mileage (정비 갱신 기준값) + SUM(vehicle_logs.distance_km) +``` + +--- + +## 11. 작업 순서 (권장) + +| 순서 | 작업 | 의존성 | +|:----:|------|--------| +| 1 | `types/vehicle.ts` 타입 정의 | 없음 | +| 2 | `lib/api/vehicle.ts` Server Action | 타입 정의 | +| 3 | **차량목록** 페이지 (가장 기본) | Server Action | +| 4 | 차량 사진 컴포넌트 | 차량목록 | +| 5 | **차량일지** 페이지 (드롭다운이 차량목록 API 사용) | 차량목록 API | +| 6 | **정비이력** 페이지 (드롭다운이 차량목록 API 사용) | 차량목록 API | + +--- + +## 12. 체크리스트 + +### 공통 +- [ ] 모든 페이지 `'use client'` 선언 +- [ ] `FormField` 컴포넌트 사용 (Label+Input 수동 조합 금지) +- [ ] `buildApiUrl` 사용 (new URLSearchParams 금지) +- [ ] 금액은 `currency` 포맷, 거리는 천단위 콤마 + km +- [ ] 빈 상태 표시 (`EmptyState` 컴포넌트) +- [ ] 에러 처리 (토스트 알림) + +### 차량목록 +- [ ] 소유형태별 조건부 폼 필드 (법인 vs 렌트/리스) +- [ ] 요약 카드 4개 (총 차량, 법인 취득가, 월 렌트/리스비, 총 주행거리) +- [ ] 소유형태/상태 배지 색상 +- [ ] 사진 업로드/삭제 (최대 10장, 카운터 표시) + +### 차량일지 +- [ ] 차량 드롭다운 (dropdown API) +- [ ] 연/월 선택 필터 +- [ ] 용도별 통계 카드 (summary API) +- [ ] 기록 복사 기능 (날짜만 오늘로) +- [ ] 출발↔도착 교환 기능 (tripType 자동 전환) +- [ ] 비고 프리셋 버튼 5개 + +### 정비이력 +- [ ] 기간 필터 (기본: 최근 3개월) +- [ ] 카테고리 필터 (8종) +- [ ] 요약 카드 4개 (총 정비비용, 주유비, 정비비, 기타비용) +- [ ] 카테고리별 배지 색상 (8종) +- [ ] 금액 currency 포맷 + +--- + +## 13. 질문/논의 사항 + +API 구현은 순차적으로 진행된다. +현재 **차량 사진 API**(#18~20)만 구현 완료 상태이며, +차량 CRUD(#1~6), 운행기록(#7~12), 정비이력(#13~17) API는 이관 진행 예정이다. + +API 완성 전에 타입 정의, 컴포넌트 구조, UI 레이아웃을 먼저 작업하고, +API 연동은 엔드포인트 완성 후 순차적으로 연결하면 된다. + +궁금한 사항은 `docs/frontend/api-specs/vehicle-api.md` 문서를 먼저 확인하고, +추가 질문은 Slack 또는 대면으로 요청한다. + +--- + +**최종 업데이트**: 2026-03-12