Polish mobile auth and garage layout

This commit is contained in:
VPN SaaS Dev
2026-05-13 05:03:49 +09:00
parent 7fd4ab768f
commit 0eb503083a
4 changed files with 187 additions and 15 deletions

View File

@@ -513,7 +513,7 @@ async function ensureUser() {
hideAuthOverlay();
return;
}
showTelegramOpenHint();
await showTelegramLogin();
throw new Error("Требуется вход через Telegram");
}
@@ -527,18 +527,27 @@ function showTelegramOpenHint() {
const slot = document.querySelector("#telegramLoginSlot");
const link = document.querySelector("#telegramLoginLink");
const message = document.querySelector("#authMessage");
const note = document.querySelector("#authNote");
overlay?.classList.remove("hidden");
document.body.classList.add("auth-required");
const botUsername = state.authConfig?.bot_username;
if (message) {
message.textContent = "Это приложение открывается через Telegram-бота. Откройте Mini App из Telegram.";
message.textContent = botUsername
? "Откройте CarPass через Telegram. Бот привяжет гараж к вашему аккаунту и покажет кнопку Mini App."
: "Это приложение открывается через Telegram-бота. Настройте BOT_USERNAME на сервере.";
}
if (slot && !slot.dataset.ready) slot.textContent = "";
if (note) {
note.textContent = isMobileBrowser()
? "После перехода в Telegram нажмите в боте кнопку «Открыть гараж»."
: "На компьютере можно войти кнопкой Telegram ниже или открыть бота.";
}
if (slot) slot.textContent = "";
if (!botUsername) {
return;
}
if (link) {
link.href = `https://t.me/${botUsername}`;
link.href = telegramBotUrl(botUsername);
link.target = isMobileBrowser() ? "_self" : "_blank";
link.classList.remove("hidden");
}
}
@@ -549,6 +558,11 @@ async function showTelegramLogin() {
if (!slot || slot.dataset.ready) return;
const botUsername = state.authConfig?.bot_username;
if (!botUsername) return;
if (isMobileBrowser()) {
slot.innerHTML = `<span class="telegram-login-help">В мобильном браузере авторизация проходит через Telegram-бота.</span>`;
slot.dataset.ready = "true";
return;
}
window.onTelegramAuth = async (user) => {
state.user = await api("/users/telegram-login", {
method: "POST",
@@ -573,6 +587,14 @@ async function showTelegramLogin() {
slot.appendChild(script);
}
function isMobileBrowser() {
return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);
}
function telegramBotUrl(botUsername) {
return `https://t.me/${botUsername}?start=garage`;
}
async function savePushSubscription(subscription) {
if (!state.user || !subscription) return;
await api(`/users/${state.user.id}/push-subscriptions`, {
@@ -750,7 +772,7 @@ function renderCars() {
(car) => `
<button class="car-item ${car.id === state.selectedCarId ? "active" : ""}" data-car="${car.id}">
<span class="car-badge">${(car.make || car.name).slice(0, 2).toUpperCase()}</span>
<span>
<span class="car-copy">
<strong>${car.name}</strong>
<small>${[car.make, car.model, car.trim, car.year, car.fuel_type].filter(Boolean).join(" ") || t("Без деталей")}</small>
</span>
@@ -1333,6 +1355,15 @@ document.querySelector("#refreshBtn").addEventListener("click", (event) => {
});
});
document.querySelector("#telegramRetryBtn")?.addEventListener("click", () => {
runAction(document.querySelector("#telegramRetryBtn"), "Обновляю данные...", async () => {
await ensureUser();
await loadCatalog();
initCarCatalog();
await loadCars();
});
});
document.querySelector("#periodPreset").addEventListener("change", async (event) => {
await runAction(event.currentTarget, "Обновляю данные...", async () => {
applyPeriodPreset(event.currentTarget.value);