feat: enhance admin page and testing functionality

- Updated admin page to include navigation buttons for month selection, improving user experience.
- Refactored `AdminDutyList` to group duties by date, enhancing the display and organization of duties.
- Improved error handling in `ReassignSheet` by using i18n keys for error messages, ensuring better localization support.
- Enhanced tests for admin page and components to reflect recent changes, ensuring accuracy in functionality and accessibility.
- Added event dispatch for configuration loading in the app configuration, improving integration with the Telegram Mini App.
This commit is contained in:
2026-03-06 12:04:16 +03:00
parent 53a899ea26
commit 02a586a1c5
11 changed files with 324 additions and 113 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { useEffect } from "react";
import { createContext, useContext, useEffect, useState } from "react";
import {
init,
mountMiniAppSync,
@@ -12,6 +12,24 @@ import {
} from "@telegram-apps/sdk-react";
import { fixSurfaceContrast } from "@/hooks/use-telegram-theme";
import { applyAndroidPerformanceClass } from "@/lib/telegram-android-perf";
import { useAppStore } from "@/store/app-store";
import { getLang } from "@/i18n/messages";
import { useTranslation } from "@/i18n/use-translation";
const EVENT_CONFIG_LOADED = "dt-config-loaded";
export interface TelegramSdkContextValue {
/** True after init() and sync mounts have run; safe to use backButton etc. */
sdkReady: boolean;
}
const TelegramSdkContext = createContext<TelegramSdkContextValue>({
sdkReady: false,
});
export function useTelegramSdkReady(): TelegramSdkContextValue {
return useContext(TelegramSdkContext);
}
/**
* Wraps the app with Telegram Mini App SDK initialization.
@@ -22,12 +40,34 @@ import { applyAndroidPerformanceClass } from "@/lib/telegram-android-perf";
* lib/telegram-ready when the first visible screen has finished loading.
* Theme is set before first paint by the inline script in layout.tsx (URL hash);
* useTelegramTheme() in the app handles ongoing theme changes.
* Syncs lang from window.__DT_LANG on mount and when config.js fires dt-config-loaded.
*/
export function TelegramProvider({
children,
}: {
children: React.ReactNode;
}) {
const [sdkReady, setSdkReady] = useState(false);
const setLang = useAppStore((s) => s.setLang);
const lang = useAppStore((s) => s.lang);
const { t } = useTranslation();
// Sync lang from backend config: on mount and when config.js has loaded (all routes, including admin).
useEffect(() => {
if (typeof window === "undefined") return;
setLang(getLang());
const onConfigLoaded = () => setLang(getLang());
window.addEventListener(EVENT_CONFIG_LOADED, onConfigLoaded);
return () => window.removeEventListener(EVENT_CONFIG_LOADED, onConfigLoaded);
}, [setLang]);
// Apply lang to document (title and html lang) so all routes including admin get correct title.
useEffect(() => {
if (typeof document === "undefined") return;
document.documentElement.lang = lang;
document.title = t("app.title");
}, [lang, t]);
useEffect(() => {
const cleanup = init({ acceptCustomStyles: true });
@@ -46,6 +86,8 @@ export function TelegramProvider({
applyAndroidPerformanceClass();
setSdkReady(true);
let unbindViewportCssVars: (() => void) | undefined;
if (mountViewport.isAvailable()) {
mountViewport()
@@ -60,11 +102,16 @@ export function TelegramProvider({
}
return () => {
setSdkReady(false);
unbindViewportCssVars?.();
unmountViewport();
cleanup();
};
}, []);
return <>{children}</>;
return (
<TelegramSdkContext.Provider value={{ sdkReady }}>
{children}
</TelegramSdkContext.Provider>
);
}