seed vehicle trims catalog

This commit is contained in:
VPN SaaS Dev
2026-05-12 04:44:19 +09:00
parent f7a3b8be54
commit b5012ec6e7
9 changed files with 335 additions and 21 deletions

View File

@@ -614,11 +614,50 @@ async function loadCatalog() {
function initCarCatalog() {
const makeSelect = document.querySelector("#makeSelect");
const modelSelect = document.querySelector("#modelSelect");
const trimSelect = document.querySelector("#trimSelect");
const fuelTypeSelect = document.querySelector("#fuelTypeSelect");
const preview = document.querySelector("#catalogPreview");
const makes = [...state.catalog].sort((a, b) => a.name.localeCompare(b.name, "ru"));
makeSelect.innerHTML = `<option value="">${t("Выбери марку")}</option>` + makes
.map((make) => `<option value="${make.name}">${make.name}</option>`)
.join("");
function selectedModel() {
const make = state.catalog.find((item) => item.name === makeSelect.value);
return make?.models.find((model) => model.name === modelSelect.value) || null;
}
function syncPreview() {
const model = selectedModel();
const trim = model?.trims?.find((item) => item.name === trimSelect.value);
if (!model) {
preview.innerHTML = `<strong>${t("Выбери модель")}</strong><span>Покажем кузов, топливо, привод и годы выпуска.</span>`;
return;
}
const chips = [
trim?.body_type,
trim?.fuel_type,
trim?.transmission,
trim?.drive_type,
trim?.year_from && trim?.year_to ? `${trim.year_from}-${trim.year_to}` : null,
].filter(Boolean);
preview.innerHTML = `
<strong>${makeSelect.value} ${model.name}${trim ? ` · ${trim.name}` : ""}</strong>
<span>${chips.length ? chips.join(" · ") : "Базовые параметры можно уточнить позже"}</span>
`;
if (trim?.fuel_type && !fuelTypeSelect.value) fuelTypeSelect.value = trim.fuel_type;
}
function syncTrims() {
const model = selectedModel();
const trims = model?.trims || [];
trimSelect.disabled = !trims.length;
trimSelect.innerHTML = trims.length
? `<option value="">Комплектация не выбрана</option>` + trims.map((trim) => `<option value="${trim.name}">${trim.name}</option>`).join("")
: `<option value="">Сначала модель</option>`;
syncPreview();
}
function syncModels() {
const make = makeSelect.value;
const models = state.catalog.find((item) => item.name === make)?.models || [];
@@ -626,24 +665,32 @@ function initCarCatalog() {
modelSelect.innerHTML = models.length
? `<option value="">${t("Выбери модель")}</option>` + models.map((model) => `<option value="${model.name}">${model.name}</option>`).join("")
: `<option value="">${t("Сначала марка")}</option>`;
syncTrims();
}
makeSelect.addEventListener("change", syncModels);
modelSelect.addEventListener("change", syncTrims);
trimSelect.addEventListener("change", syncPreview);
syncModels();
}
function resetCarCatalog() {
document.querySelector("#makeSelect").value = "";
const modelSelect = document.querySelector("#modelSelect");
const trimSelect = document.querySelector("#trimSelect");
modelSelect.disabled = true;
modelSelect.innerHTML = `<option value="">${t("Сначала марка")}</option>`;
trimSelect.disabled = true;
trimSelect.innerHTML = `<option value="">Сначала модель</option>`;
document.querySelector("#catalogPreview").innerHTML =
`<strong>${t("Выбери модель")}</strong><span>Покажем кузов, топливо, привод и годы выпуска.</span>`;
}
function updateHero(stats) {
const car = selectedCar();
document.querySelector("#selectedCarTitle").textContent = car?.name || t("Не выбран");
document.querySelector("#selectedCarMeta").textContent = car
? [car.make, car.model, car.year].filter(Boolean).join(" ") || t("Без деталей")
? [car.make, car.model, car.trim, car.year].filter(Boolean).join(" ") || t("Без деталей")
: t("Добавь авто или выбери из списка");
document.querySelector("#summaryTotal").textContent = money(stats?.total_cost);
document.querySelector("#summaryConsumption").textContent = stats?.avg_consumption_l_per_100km
@@ -670,7 +717,7 @@ function renderCars() {
<span class="car-badge">${(car.make || car.name).slice(0, 2).toUpperCase()}</span>
<span>
<strong>${car.name}</strong>
<small>${[car.make, car.model, car.year].filter(Boolean).join(" ") || t("Без деталей")}</small>
<small>${[car.make, car.model, car.trim, car.year].filter(Boolean).join(" ") || t("Без деталей")}</small>
</span>
</button>
`,
@@ -1084,7 +1131,9 @@ document.querySelector("#carForm").addEventListener("submit", async (event) => {
name: data.name,
make: data.make || null,
model: data.model || null,
trim: data.trim || null,
year: data.year ? Number(data.year) : null,
fuel_type: data.fuel_type || null,
}),
});
form.reset();

View File

@@ -1199,6 +1199,28 @@ select {
gap: 10px;
}
.catalog-preview {
align-self: stretch;
display: grid;
gap: 6px;
padding: 12px;
border: 1px solid var(--line);
border-radius: 8px;
background:
linear-gradient(135deg, rgba(18, 115, 95, 0.08), rgba(47, 111, 159, 0.08)),
#fff;
}
.catalog-preview strong {
color: var(--text);
font-size: 14px;
}
.catalog-preview span {
color: var(--muted);
font-size: 12px;
}
@keyframes toastIn {
from {
opacity: 0;