add vehicle service profile settings
This commit is contained in:
@@ -509,18 +509,25 @@ async function ensureUser() {
|
||||
|
||||
function hideAuthOverlay() {
|
||||
document.querySelector("#authOverlay")?.classList.add("hidden");
|
||||
document.body.classList.remove("auth-required");
|
||||
}
|
||||
|
||||
async function showTelegramLogin() {
|
||||
const overlay = document.querySelector("#authOverlay");
|
||||
const slot = document.querySelector("#telegramLoginSlot");
|
||||
const link = document.querySelector("#telegramLoginLink");
|
||||
overlay?.classList.remove("hidden");
|
||||
document.body.classList.add("auth-required");
|
||||
if (!slot || slot.dataset.ready) return;
|
||||
const botUsername = state.authConfig?.bot_username;
|
||||
if (!botUsername) {
|
||||
slot.textContent = "Telegram Login временно недоступен";
|
||||
return;
|
||||
}
|
||||
if (link) {
|
||||
link.href = `https://t.me/${botUsername}?start=web_login`;
|
||||
link.classList.remove("hidden");
|
||||
}
|
||||
window.onTelegramAuth = async (user) => {
|
||||
state.user = await api("/users/telegram-login", {
|
||||
method: "POST",
|
||||
@@ -538,6 +545,9 @@ async function showTelegramLogin() {
|
||||
script.setAttribute("data-radius", "8");
|
||||
script.setAttribute("data-request-access", "write");
|
||||
script.setAttribute("data-onauth", "onTelegramAuth(user)");
|
||||
script.addEventListener("error", () => {
|
||||
slot.textContent = "Кнопка Telegram не загрузилась. Используй вход ниже.";
|
||||
});
|
||||
slot.dataset.ready = "true";
|
||||
slot.appendChild(script);
|
||||
}
|
||||
@@ -565,6 +575,10 @@ function selectedCar() {
|
||||
return state.cars.find((car) => car.id === state.selectedCarId) || null;
|
||||
}
|
||||
|
||||
function numberOrNull(value) {
|
||||
return value === "" || value == null ? null : Number(value);
|
||||
}
|
||||
|
||||
function shiftMonths(base, count) {
|
||||
const copy = new Date(base);
|
||||
copy.setMonth(copy.getMonth() + count);
|
||||
@@ -690,7 +704,7 @@ function updateHero(stats) {
|
||||
const car = selectedCar();
|
||||
document.querySelector("#selectedCarTitle").textContent = car?.name || t("Не выбран");
|
||||
document.querySelector("#selectedCarMeta").textContent = car
|
||||
? [car.make, car.model, car.trim, car.year].filter(Boolean).join(" ") || t("Без деталей")
|
||||
? [car.make, car.model, car.trim, car.year, car.fuel_type].filter(Boolean).join(" ") || t("Без деталей")
|
||||
: t("Добавь авто или выбери из списка");
|
||||
document.querySelector("#summaryTotal").textContent = money(stats?.total_cost);
|
||||
document.querySelector("#summaryConsumption").textContent = stats?.avg_consumption_l_per_100km
|
||||
@@ -717,7 +731,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.trim, car.year].filter(Boolean).join(" ") || t("Без деталей")}</small>
|
||||
<small>${[car.make, car.model, car.trim, car.year, car.fuel_type].filter(Boolean).join(" ") || t("Без деталей")}</small>
|
||||
</span>
|
||||
</button>
|
||||
`,
|
||||
@@ -728,6 +742,45 @@ function renderCars() {
|
||||
});
|
||||
}
|
||||
|
||||
function setInputValue(form, name, value) {
|
||||
if (form?.elements[name]) form.elements[name].value = value ?? "";
|
||||
}
|
||||
|
||||
function fillCarProfileForm() {
|
||||
const form = document.querySelector("#carProfileForm");
|
||||
const hint = document.querySelector("#carProfileHint");
|
||||
const car = selectedCar();
|
||||
form.querySelectorAll("input, select, button").forEach((node) => {
|
||||
node.disabled = !car;
|
||||
});
|
||||
if (!car) {
|
||||
form.reset();
|
||||
hint.textContent = t("Выбери автомобиль, чтобы настроить жидкости, расход и сервисные нормы.");
|
||||
return;
|
||||
}
|
||||
hint.textContent = [car.make, car.model, car.trim, car.year].filter(Boolean).join(" ") || car.name;
|
||||
[
|
||||
"fuel_type",
|
||||
"target_consumption_l_per_100km",
|
||||
"fuel_tank_volume_l",
|
||||
"engine_oil_type",
|
||||
"engine_oil_volume_l",
|
||||
"transmission_fluid_type",
|
||||
"transmission_fluid_volume_l",
|
||||
"coolant_type",
|
||||
"brake_fluid_type",
|
||||
"tire_pressure_front_bar",
|
||||
"tire_pressure_rear_bar",
|
||||
].forEach((name) => setInputValue(form, name, car[name]));
|
||||
}
|
||||
|
||||
function openCarProfile() {
|
||||
document.querySelector("#userDrawer").classList.remove("hidden");
|
||||
document.querySelector("#carProfileSection").classList.remove("hidden");
|
||||
fillCarProfileForm();
|
||||
document.querySelector("#carProfileSection").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
}
|
||||
|
||||
function renderStats(stats) {
|
||||
const root = document.querySelector("#stats");
|
||||
if (!stats) {
|
||||
@@ -1051,6 +1104,7 @@ async function loadCars() {
|
||||
state.selectedCarId = state.cars[0]?.id || null;
|
||||
}
|
||||
renderCars();
|
||||
fillCarProfileForm();
|
||||
await loadSelectedCar();
|
||||
} finally {
|
||||
document.body.classList.remove("loading");
|
||||
@@ -1061,6 +1115,7 @@ async function loadCars() {
|
||||
async function selectCar(carId) {
|
||||
state.selectedCarId = carId;
|
||||
renderCars();
|
||||
fillCarProfileForm();
|
||||
await loadSelectedCar();
|
||||
}
|
||||
|
||||
@@ -1145,6 +1200,41 @@ document.querySelector("#carForm").addEventListener("submit", async (event) => {
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector("#carProfileForm").addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const form = event.currentTarget;
|
||||
const car = selectedCar();
|
||||
if (!car) {
|
||||
toast("Выбери автомобиль", "error");
|
||||
return;
|
||||
}
|
||||
await runAction(form.querySelector('button[type="submit"]'), "Сохраняю...", async () => {
|
||||
const data = formData(form);
|
||||
const updated = await api(`/cars/${car.id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({
|
||||
fuel_type: data.fuel_type || null,
|
||||
target_consumption_l_per_100km: numberOrNull(data.target_consumption_l_per_100km),
|
||||
fuel_tank_volume_l: numberOrNull(data.fuel_tank_volume_l),
|
||||
engine_oil_type: data.engine_oil_type || null,
|
||||
engine_oil_volume_l: numberOrNull(data.engine_oil_volume_l),
|
||||
transmission_fluid_type: data.transmission_fluid_type || null,
|
||||
transmission_fluid_volume_l: numberOrNull(data.transmission_fluid_volume_l),
|
||||
coolant_type: data.coolant_type || null,
|
||||
brake_fluid_type: data.brake_fluid_type || null,
|
||||
tire_pressure_front_bar: numberOrNull(data.tire_pressure_front_bar),
|
||||
tire_pressure_rear_bar: numberOrNull(data.tire_pressure_rear_bar),
|
||||
}),
|
||||
});
|
||||
state.cars = state.cars.map((item) => (item.id === updated.id ? updated : item));
|
||||
renderCars();
|
||||
fillCarProfileForm();
|
||||
await loadSelectedCar();
|
||||
toast("Параметры сохранены");
|
||||
haptic("success");
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector("#settingsForm").addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
const form = event.currentTarget;
|
||||
@@ -1272,6 +1362,8 @@ document.querySelector("#openCarFormBtn").addEventListener("click", () => {
|
||||
document.querySelector("#carFormSection").scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
});
|
||||
|
||||
document.querySelector("#openCarProfileBtn").addEventListener("click", openCarProfile);
|
||||
|
||||
document.querySelector("#openSettingsBtn").addEventListener("click", () => {
|
||||
document.querySelector("#settingsSection").classList.remove("hidden");
|
||||
document.querySelector("#localeSelect").value = state.user?.locale || "ru";
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
--shadow: 0 14px 40px rgba(24, 33, 31, 0.08);
|
||||
}
|
||||
|
||||
body.auth-required .shell {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
@@ -1194,6 +1198,24 @@ select {
|
||||
min-height: 46px;
|
||||
}
|
||||
|
||||
.telegram-login-link {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
min-height: 46px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
border-radius: 8px;
|
||||
background: #16806a;
|
||||
color: #fff;
|
||||
font-weight: 800;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.telegram-login-link.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.scan-form {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
|
||||
Reference in New Issue
Block a user