vehicle list: цветной чип статуса (На линии / ДТП / Ремонт / Бронь)
VehicleSummary.status (cars_v2.element_status) рендерится как цветной
pill справа от гос.номера. Палитра по семантике:
emerald — На линии (норма)
amber — Ремонтируется / Ждет ремонта
red — ДТП
blue — Бронь / Выкуп / На продаже / Подготовка на продажу / Ждет
доставки до офиса (admin-операции)
muted — Простой и неизвестные статусы
Чип появляется в Home (списке машин) и в шапке VehicleCard. Backend
сторона — PremiumCRM 92d4317.
This commit is contained in:
@@ -8,6 +8,10 @@ export interface VehicleSummary {
|
|||||||
model?: string | null;
|
model?: string | null;
|
||||||
year?: number | null;
|
year?: number | null;
|
||||||
last_inspection_at?: string | null;
|
last_inspection_at?: string | null;
|
||||||
|
/** Текущий статус машины из 1C Element (cars_v2.element_status):
|
||||||
|
'На линии' / 'Простой' / 'Ремонтируется' / 'Ждет ремонта' / 'ДТП' /
|
||||||
|
'Бронь' / 'Выкуп' / 'На продаже' / etc. NULL если не задан. */
|
||||||
|
status?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VehicleDetail extends VehicleSummary {
|
export interface VehicleDetail extends VehicleSummary {
|
||||||
|
|||||||
@@ -10,6 +10,38 @@ const ACTION_TITLES: Record<string, string> = {
|
|||||||
repair: "Ремонт",
|
repair: "Ремонт",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Группа цветов по семантике статуса. Палитра подсчитана из Tailwind с
|
||||||
|
// прозрачностью, чтобы чип не перебивал гос.номер. Tone:
|
||||||
|
// ok — на линии (зелёный)
|
||||||
|
// idle — простой (серый)
|
||||||
|
// repair — в ремонте / ждёт ремонта (янтарный)
|
||||||
|
// alert — ДТП (красный)
|
||||||
|
// admin — выкуп / на продаже / бронь / подготовка к продаже / ждёт доставки
|
||||||
|
// sold — продана (не отображается — отфильтрована из выдачи)
|
||||||
|
const STATUS_TONE: Record<string, string> = {
|
||||||
|
"На линии": "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300",
|
||||||
|
"Простой": "bg-muted text-muted-foreground",
|
||||||
|
"Ремонтируется": "bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300",
|
||||||
|
"Ждет ремонта": "bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300",
|
||||||
|
"ДТП": "bg-red-100 text-red-800 dark:bg-red-900/40 dark:text-red-300",
|
||||||
|
"Бронь": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"Выкуп": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"На продаже": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"Подготовка на продажу": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"Ждет доставки до офиса": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
};
|
||||||
|
|
||||||
|
function StatusChip({ status }: { status: string }) {
|
||||||
|
const tone =
|
||||||
|
STATUS_TONE[status] ??
|
||||||
|
"bg-muted text-muted-foreground";
|
||||||
|
return (
|
||||||
|
<span className={`inline-flex items-center text-xs font-medium px-2 py-0.5 rounded-full ${tone}`}>
|
||||||
|
{status}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [q, setQ] = useState("");
|
const [q, setQ] = useState("");
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
@@ -63,7 +95,10 @@ export default function Home() {
|
|||||||
navigate(`/vehicles/${v.id}${action ? `?action=${action}` : ""}`)
|
navigate(`/vehicles/${v.id}${action ? `?action=${action}` : ""}`)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<div className="font-semibold text-lg">{v.license_plate}</div>
|
<div className="font-semibold text-lg">{v.license_plate}</div>
|
||||||
|
{v.status && <StatusChip status={v.status} />}
|
||||||
|
</div>
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
{[v.make, v.model, v.year].filter(Boolean).join(" ") || "—"}
|
{[v.make, v.model, v.year].filter(Boolean).join(" ") || "—"}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -110,7 +110,29 @@ export default function VehicleCard() {
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<Card className="p-4">
|
<Card className="p-4">
|
||||||
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<div className="text-xl font-semibold">{v.license_plate}</div>
|
<div className="text-xl font-semibold">{v.license_plate}</div>
|
||||||
|
{v.status && (
|
||||||
|
<span
|
||||||
|
className={`inline-flex items-center text-xs font-medium px-2 py-0.5 rounded-full ${
|
||||||
|
{
|
||||||
|
"На линии": "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300",
|
||||||
|
"Простой": "bg-muted text-muted-foreground",
|
||||||
|
"Ремонтируется": "bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300",
|
||||||
|
"Ждет ремонта": "bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300",
|
||||||
|
"ДТП": "bg-red-100 text-red-800 dark:bg-red-900/40 dark:text-red-300",
|
||||||
|
"Бронь": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"Выкуп": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"На продаже": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"Подготовка на продажу": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
"Ждет доставки до офиса": "bg-blue-100 text-blue-800 dark:bg-blue-900/40 dark:text-blue-300",
|
||||||
|
}[v.status] ?? "bg-muted text-muted-foreground"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{v.status}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
{[v.make, v.model, v.year].filter(Boolean).join(" ") || "—"}
|
{[v.make, v.model, v.year].filter(Boolean).join(" ") || "—"}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user