feat: migrate to Next.js for Mini App and enhance project structure
- 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.
This commit is contained in:
63
webapp-next/src/hooks/use-app-init.ts
Normal file
63
webapp-next/src/hooks/use-app-init.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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]);
|
||||
}
|
||||
Reference in New Issue
Block a user