- Replaced the previous webapp with a new Mini App built using Next.js, improving performance and maintainability. - Updated the `.gitignore` to exclude Next.js build artifacts and node modules. - Revised documentation in `AGENTS.md`, `README.md`, and `architecture.md` to reflect the new Mini App structure and technology stack. - Enhanced Dockerfile to support the new build process for the Next.js application. - Updated CI workflow to build and test the Next.js application. - Added new configuration options for the Mini App, including `MINI_APP_SHORT_NAME` for improved deep linking. - Refactored frontend testing setup to accommodate the new structure and testing framework. - Removed legacy webapp files and dependencies to streamline the project.
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
/**
|
|
* Application initialization: language sync, access-denied logic, deep link routing.
|
|
* Runs effects that depend on Telegram auth (isAllowed, startParam); caller provides those.
|
|
*/
|
|
|
|
"use client";
|
|
|
|
import { useEffect } from "react";
|
|
import { useAppStore } from "@/store/app-store";
|
|
import { getLang } from "@/i18n/messages";
|
|
import { useTranslation } from "@/i18n/use-translation";
|
|
import { RETRY_DELAY_MS } from "@/lib/constants";
|
|
|
|
export interface UseAppInitParams {
|
|
/** Whether the user is allowed (localhost or has valid initData). */
|
|
isAllowed: boolean;
|
|
/** Telegram Mini App start_param (e.g. "duty" for current duty deep link). */
|
|
startParam: string | undefined;
|
|
}
|
|
|
|
/**
|
|
* Syncs language from backend config, applies document lang/title, handles access denied
|
|
* when not allowed, and routes to current duty view when opened via startParam=duty.
|
|
*/
|
|
export function useAppInit({ isAllowed, startParam }: UseAppInitParams): void {
|
|
const setLang = useAppStore((s) => s.setLang);
|
|
const lang = useAppStore((s) => s.lang);
|
|
const setAccessDenied = useAppStore((s) => s.setAccessDenied);
|
|
const setLoading = useAppStore((s) => s.setLoading);
|
|
const setCurrentView = useAppStore((s) => s.setCurrentView);
|
|
const { t } = useTranslation();
|
|
|
|
// Sync lang from backend config (window.__DT_LANG).
|
|
useEffect(() => {
|
|
if (typeof window === "undefined") return;
|
|
setLang(getLang());
|
|
}, [setLang]);
|
|
|
|
// Apply lang to document (title and html lang) for accessibility and i18n.
|
|
useEffect(() => {
|
|
if (typeof document === "undefined") return;
|
|
document.documentElement.lang = lang;
|
|
document.title = t("app.title");
|
|
}, [lang, t]);
|
|
|
|
// When not allowed (no initData and not localhost), show access denied after delay.
|
|
useEffect(() => {
|
|
if (isAllowed) {
|
|
setAccessDenied(false);
|
|
return;
|
|
}
|
|
const id = setTimeout(() => {
|
|
setAccessDenied(true);
|
|
setLoading(false);
|
|
}, RETRY_DELAY_MS);
|
|
return () => clearTimeout(id);
|
|
}, [isAllowed, setAccessDenied, setLoading]);
|
|
|
|
// When opened via deep link startParam=duty, show current duty view first.
|
|
useEffect(() => {
|
|
if (startParam === "duty") setCurrentView("currentDuty");
|
|
}, [startParam, setCurrentView]);
|
|
}
|