feat: Add banner toggle and soldout tracking to Cars page

- Add is_banner, soldout fields to Car model
- Add banner toggle API (POST /hero-banners/admin/toggle/{car_id})
- Add soldout APIs (POST/DELETE /cars/{car_id}/soldout)
- Add nightly soldout checker in agent (runs at 3:00 AM)
- Update Local Cars UI with banner checkbox and status column
- Remove hero-banners admin page (functionality moved to Cars page)
- Banner cars sorted to top with purple background
- Soldout cars displayed with gray overlay

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
AutonetSellCar Deploy
2025-12-31 12:50:40 +09:00
parent 9969554deb
commit c9fd7611a7
10 changed files with 579 additions and 40 deletions

View File

@@ -70,6 +70,22 @@ export const carsApi = {
const { data } = await api.get('/cars/models/', { params });
return data;
},
// Soldout APIs
markSoldout: async (carId: number): Promise<{ car_id: number; soldout: boolean; message: string }> => {
const { data } = await api.post(`/cars/${carId}/soldout`);
return data;
},
markAvailable: async (carId: number): Promise<{ car_id: number; soldout: boolean; message: string }> => {
const { data } = await api.delete(`/cars/${carId}/soldout`);
return data;
},
getSoldoutStats: async (): Promise<{ total_active: number; soldout: number; available: number; soldout_percentage: number }> => {
const { data } = await api.get('/cars/admin/soldout-stats');
return data;
},
};
// Auth API
@@ -187,6 +203,22 @@ export const heroBannersApi = {
const { data } = await api.put('/hero-banners/admin/settings', settings);
return data;
},
// Banner Toggle & Ordering
adminToggleBanner: async (carId: number): Promise<{ car_id: number; is_banner: boolean; banner_id?: number; message: string }> => {
const { data } = await api.post(`/hero-banners/admin/toggle/${carId}`);
return data;
},
adminReorderBanners: async (carIds: number[]): Promise<{ message: string; count: number }> => {
const { data } = await api.put('/hero-banners/admin/reorder', carIds);
return data;
},
adminGetBannerCars: async (): Promise<{ car_ids: number[]; count: number }> => {
const { data } = await api.get('/hero-banners/admin/banner-cars');
return data;
},
};
// Translations API