From 76b8d9795fbfa869f23cf4ad883308d4ab47b6bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Tue, 3 Feb 2026 20:17:30 +0900 Subject: [PATCH] =?UTF-8?q?feat:=EC=B0=A8=EB=9F=89=EC=A0=95=EB=B9=84?= =?UTF-8?q?=EC=9D=B4=EB=A0=A5=20=EA=B2=80=EC=83=89=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=B0=8F=20=EC=83=88=EB=A1=9C=EA=B3=A0=EC=B9=A8=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 검색 버튼 클릭 또는 엔터키로 검색 실행 - 새로고침 버튼 추가 (로딩 시 회전 애니메이션) - 필터 변경 시 자동 검색 제거 Co-Authored-By: Claude Opus 4.5 --- .../finance/vehicle-maintenance.blade.php | 93 ++++++++++++------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/resources/views/finance/vehicle-maintenance.blade.php b/resources/views/finance/vehicle-maintenance.blade.php index e068757e..c6430029 100644 --- a/resources/views/finance/vehicle-maintenance.blade.php +++ b/resources/views/finance/vehicle-maintenance.blade.php @@ -44,6 +44,7 @@ const DollarSign = createIcon('dollar-sign'); const Fuel = createIcon('fuel'); const Car = createIcon('car'); +const RefreshCw = createIcon('refresh-cw'); function VehicleMaintenanceManagement() { const [loading, setLoading] = useState(true); @@ -75,6 +76,7 @@ function VehicleMaintenanceManagement() { }; const loadMaintenances = async () => { + setLoading(true); try { const params = new URLSearchParams({ start_date: dateRange.start, @@ -95,16 +97,11 @@ function VehicleMaintenanceManagement() { } }; + // 초기 로드 useEffect(() => { - loadVehicles(); + loadVehicles().then(() => loadMaintenances()); }, []); - useEffect(() => { - if (vehicles.length > 0 || !loading) { - loadMaintenances(); - } - }, [dateRange, filterCategory, filterVehicle]); - const [searchTerm, setSearchTerm] = useState(''); const [filterCategory, setFilterCategory] = useState('all'); const [filterVehicle, setFilterVehicle] = useState('all'); @@ -119,6 +116,18 @@ function VehicleMaintenanceManagement() { const categories = ['주유', '정비', '보험', '세차', '주차', '통행료', '검사', '기타']; + // 검색 실행 + const handleSearch = () => { + loadMaintenances(); + }; + + // 엔터키 핸들러 + const handleKeyDown = (e) => { + if (e.key === 'Enter') { + handleSearch(); + } + }; + // 차량 표시용 헬퍼 const getVehicleDisplay = (vehicleId) => { const v = vehicles.find(v => v.id === vehicleId); @@ -145,18 +154,9 @@ function VehicleMaintenanceManagement() { }; const parseInputCurrency = (value) => String(value).replace(/[^\d]/g, ''); - // API에서 이미 필터링된 데이터를 받으므로 클라이언트 측에서는 검색어만 필터링 - const filteredMaintenances = maintenances.filter(item => { - if (!searchTerm) return true; - const search = searchTerm.toLowerCase(); - return (item.description || '').toLowerCase().includes(search) || - (item.vendor || '').toLowerCase().includes(search) || - (item.plateNumber || '').toLowerCase().includes(search); - }); - - const totalAmount = filteredMaintenances.reduce((sum, item) => sum + item.amount, 0); - const fuelAmount = filteredMaintenances.filter(m => m.category === '주유').reduce((sum, item) => sum + item.amount, 0); - const maintenanceAmount = filteredMaintenances.filter(m => m.category === '정비').reduce((sum, item) => sum + item.amount, 0); + const totalAmount = maintenances.reduce((sum, item) => sum + item.amount, 0); + const fuelAmount = maintenances.filter(m => m.category === '주유').reduce((sum, item) => sum + item.amount, 0); + const maintenanceAmount = maintenances.filter(m => m.category === '정비').reduce((sum, item) => sum + item.amount, 0); const otherAmount = totalAmount - fuelAmount - maintenanceAmount; // 유지비 등록/수정 @@ -192,7 +192,6 @@ function VehicleMaintenanceManagement() { vendor: formData.vendor, memo: formData.memo }; - console.log('저장 요청:', payload); const url = modalMode === 'add' ? '/finance/vehicle-maintenance' : `/finance/vehicle-maintenance/${editingItem.id}`; const method = modalMode === 'add' ? 'POST' : 'PUT'; const response = await fetch(url, { @@ -200,9 +199,7 @@ function VehicleMaintenanceManagement() { headers: { 'Content-Type': 'application/json', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify(payload) }); - console.log('응답 상태:', response.status); const result = await response.json(); - console.log('응답 데이터:', result); if (result.success) { await loadMaintenances(); setShowModal(false); @@ -239,7 +236,7 @@ function VehicleMaintenanceManagement() { const handleDownload = () => { const rows = [['차량 유지비', `${dateRange.start} ~ ${dateRange.end}`], [], ['날짜', '차량', '구분', '내용', '금액', '주행거리', '업체'], - ...filteredMaintenances.map(item => [item.date, getVehicleDisplay(item.vehicleId), item.category, item.description, item.amount, item.mileage, item.vendor])]; + ...maintenances.map(item => [item.date, getVehicleDisplay(item.vehicleId), item.category, item.description, item.amount, item.mileage, item.vendor])]; const csvContent = rows.map(row => row.join(',')).join('\n'); const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `차량유지비_${dateRange.start}_${dateRange.end}.csv`; link.click(); @@ -270,7 +267,7 @@ function VehicleMaintenanceManagement() {
총 유지비

{formatCurrency(totalAmount)}원

-

{filteredMaintenances.length}건

+

{maintenances.length}건

주유비
@@ -288,21 +285,45 @@ function VehicleMaintenanceManagement() { {/* 필터 */}
-
-
+
+
- setSearchTerm(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-amber-500" /> + setSearchTerm(e.target.value)} + onKeyDown={handleKeyDown} + className="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-amber-500" + />
- -
- setDateRange(prev => ({ ...prev, start: e.target.value }))} className="flex-1 px-2 py-2 border border-gray-300 rounded-lg text-sm" /> - ~ - setDateRange(prev => ({ ...prev, end: e.target.value }))} className="flex-1 px-2 py-2 border border-gray-300 rounded-lg text-sm" /> -
+ + setDateRange(prev => ({ ...prev, start: e.target.value }))} className="px-3 py-2 border border-gray-300 rounded-lg text-sm" /> + ~ + setDateRange(prev => ({ ...prev, end: e.target.value }))} className="px-3 py-2 border border-gray-300 rounded-lg text-sm" /> + +
@@ -321,9 +342,11 @@ function VehicleMaintenanceManagement() { - {filteredMaintenances.length === 0 ? ( + {loading ? ( + 로딩 중... + ) : maintenances.length === 0 ? ( 데이터가 없습니다. - ) : filteredMaintenances.map(item => { + ) : maintenances.map(item => { const vehicle = vehicles.find(v => v.id === item.vehicleId); return ( handleEdit(item)}>