From 58811264088b12d314dab92fd7dd9ff02256ddeb Mon Sep 17 00:00:00 2001
From: AutonetSellCar Deploy
Date: Sun, 1 Feb 2026 21:13:55 +0900
Subject: [PATCH] feat: Add Request functionality to All Cars tab
- Add checkbox selection for cars in All Cars tab when requestId is present
- Add "Add to Request" button with selection count
- Add select all/deselect all functionality
- Highlight selected cars with blue ring
Co-Authored-By: Claude Opus 4.5
---
frontend/src/app/admin/cars/page.tsx | 146 ++++++++++++++++++++++++++-
1 file changed, 145 insertions(+), 1 deletion(-)
diff --git a/frontend/src/app/admin/cars/page.tsx b/frontend/src/app/admin/cars/page.tsx
index 5182a31..c272b22 100644
--- a/frontend/src/app/admin/cars/page.tsx
+++ b/frontend/src/app/admin/cars/page.tsx
@@ -151,6 +151,8 @@ export default function CarsAdminPage() {
const [allCarsLoading, setAllCarsLoading] = useState(false);
const [allCarsTotal, setAllCarsTotal] = useState(0);
const [allCarsPage, setAllCarsPage] = useState(1);
+ const [selectedAllCars, setSelectedAllCars] = useState>(new Set());
+ const [addingAllCarsToRequest, setAddingAllCarsToRequest] = useState(false);
// Carmodoo search state
const [makers, setMakers] = useState([]);
@@ -1093,6 +1095,92 @@ export default function CarsAdminPage() {
}
};
+ // All Cars 탭에서 Request에 추가하는 함수
+ const handleAddAllCarsToRequest = async () => {
+ if (!requestId) return;
+ if (selectedAllCars.size === 0) {
+ alert('Please select at least one car to add to the request.');
+ return;
+ }
+
+ if (!confirm(`${selectedAllCars.size}개의 차량을 추천 목록에 추가하시겠습니까?`)) {
+ return;
+ }
+
+ setAddingAllCarsToRequest(true);
+
+ try {
+ const selectedCarsList = allCars.filter(car => selectedAllCars.has(car.id));
+ let addedCount = 0;
+ let errorCount = 0;
+
+ for (const car of selectedCarsList) {
+ try {
+ const mainImage = car.images?.find((img) => img.is_main)?.url || car.images?.[0]?.url;
+ await vehicleRequestsApi.adminAddVehicle(parseInt(requestId), {
+ request_id: parseInt(requestId),
+ car_id: car.id, // 이미 로컬 DB에 있는 차량이므로 car_id 사용
+ car_data: {
+ id: car.id.toString(),
+ car_name: car.car_name,
+ maker_name: car.maker?.name,
+ model_name: car.model?.name,
+ year: car.year,
+ mileage: car.mileage,
+ final_price: car.final_price_krw || car.price_krw,
+ fuel: car.fuel,
+ transmission: car.transmission,
+ color: car.color,
+ main_image: mainImage,
+ },
+ is_approved: true,
+ });
+ addedCount++;
+ } catch (err) {
+ console.error(`Failed to add car ${car.id}:`, err);
+ errorCount++;
+ }
+ }
+
+ setSelectedAllCars(new Set());
+
+ if (errorCount > 0) {
+ alert(`${addedCount}개의 차량이 추천 목록에 추가되었습니다.\n(실패: ${errorCount}개)`);
+ } else {
+ alert(`${addedCount}개의 차량이 추천 목록에 추가되었습니다.`);
+ }
+
+ router.push('/admin/vehicle-requests');
+ } catch (err) {
+ console.error('Add to request failed:', err);
+ alert('추천 목록 추가에 실패했습니다.');
+ } finally {
+ setAddingAllCarsToRequest(false);
+ }
+ };
+
+ // All Cars 선택 토글
+ const toggleAllCarSelection = (carId: number) => {
+ setSelectedAllCars(prev => {
+ const newSet = new Set(prev);
+ if (newSet.has(carId)) {
+ newSet.delete(carId);
+ } else {
+ newSet.add(carId);
+ }
+ return newSet;
+ });
+ };
+
+ // All Cars 전체 선택/해제
+ const handleSelectAllAllCars = () => {
+ if (selectedAllCars.size === allCars.length) {
+ setSelectedAllCars(new Set());
+ } else {
+ setSelectedAllCars(new Set(allCars.map(car => car.id)));
+ }
+ };
+
const handleDeleteCar = async (carId: number) => {
if (!confirm('Are you sure you want to delete this car?')) {
return;
@@ -1700,6 +1788,45 @@ export default function CarsAdminPage() {
This shows the cars that are visible to users (is_displayed = true). This is the same view as the public /cars page.
+ {/* Selection Controls for Request Mode */}
+ {requestId && allCars.length > 0 && (
+
+
+
+
+ {selectedAllCars.size} selected
+
+
+
+
+ )}
+
{allCarsLoading ? (
@@ -1717,13 +1844,30 @@ export default function CarsAdminPage() {
{allCars.map((car) => {
const mainImage = getImageUrl(car.images?.find((img) => img.is_main)?.url || car.images?.[0]?.url);
+ const isSelected = selectedAllCars.has(car.id);
return (
handleCarClick(car)}
>
+ {/* Checkbox for Request Mode */}
+ {requestId && (
+
e.stopPropagation()}
+ >
+ toggleAllCarSelection(car.id)}
+ className="w-5 h-5 text-blue-600 rounded cursor-pointer"
+ />
+
+ )}
{mainImage ? (
