feat: enhance Mini App design guidelines and refactor layout components

- Updated Mini App design guidelines to include detailed instructions on UI changes, accessibility rules, and verification processes.
- Refactored multiple components to utilize `MiniAppScreen` and `MiniAppScreenContent` for consistent layout structure across the application.
- Improved error handling in `GlobalError` and `NotFound` components by integrating new layout components for better user experience.
- Introduced new hooks for admin functionality, streamlining access checks and data loading processes.
- Enhanced documentation to reflect changes in design policies and component usage, ensuring clarity for future development.
This commit is contained in:
2026-03-06 17:51:33 +03:00
parent 43cd3bbd7d
commit fa22976e75
38 changed files with 1166 additions and 512 deletions

View File

@@ -6,64 +6,54 @@
"use client";
import { useEffect } from "react";
import { useAdminPage, AdminDutyList, ReassignSheet } from "@/components/admin";
import { useTranslation } from "@/i18n/use-translation";
import { useAppStore } from "@/store/app-store";
import { MonthNavHeader } from "@/components/calendar/MonthNavHeader";
import { AccessDeniedScreen } from "@/components/states/AccessDeniedScreen";
import { LoadingState } from "@/components/states/LoadingState";
import { ErrorState } from "@/components/states/ErrorState";
const OUTER_CLASS =
"content-safe min-h-[var(--tg-viewport-stable-height,100vh)] bg-background";
const INNER_CLASS =
"mx-auto flex w-full max-w-[var(--max-width-app)] flex-col";
import { MiniAppScreen, MiniAppScreenContent, MiniAppStickyHeader } from "@/components/layout/MiniAppScreen";
import { useScreenReady } from "@/hooks/use-screen-ready";
export default function AdminPage() {
const { t, monthName } = useTranslation();
const admin = useAdminPage();
const setAppContentReady = useAppStore((s) => s.setAppContentReady);
// Signal ready so Telegram hides loader when opening /admin directly.
useEffect(() => {
setAppContentReady(true);
}, [setAppContentReady]);
useScreenReady(true);
if (!admin.isAllowed) {
return (
<div className={OUTER_CLASS}>
<div className={INNER_CLASS}>
<MiniAppScreen>
<MiniAppScreenContent>
<AccessDeniedScreen primaryAction="reload" />
</div>
</div>
</MiniAppScreenContent>
</MiniAppScreen>
);
}
if (admin.adminCheckComplete === null) {
return (
<div className={OUTER_CLASS}>
<div className={INNER_CLASS}>
<MiniAppScreen>
<MiniAppScreenContent>
<div className="py-4 flex flex-col items-center gap-2">
<LoadingState />
<p className="text-sm text-muted-foreground">{t("admin.loading_users")}</p>
</div>
</div>
</div>
</MiniAppScreenContent>
</MiniAppScreen>
);
}
if (admin.adminAccessDenied) {
return (
<div className={OUTER_CLASS}>
<div className={INNER_CLASS}>
<MiniAppScreen>
<MiniAppScreenContent>
<div className="flex flex-col gap-4 py-6">
<p className="text-muted-foreground">
{admin.adminAccessDeniedDetail ?? t("admin.access_denied")}
</p>
</div>
</div>
</div>
</MiniAppScreenContent>
</MiniAppScreen>
);
}
@@ -71,9 +61,9 @@ export default function AdminPage() {
const year = admin.adminMonth.getFullYear();
return (
<div className={OUTER_CLASS}>
<div className={INNER_CLASS}>
<header className="sticky top-[var(--app-safe-top)] z-10 flex flex-col items-center border-b border-border bg-background py-3">
<MiniAppScreen>
<MiniAppScreenContent>
<MiniAppStickyHeader className="flex flex-col items-center border-b border-border py-3">
<MonthNavHeader
month={admin.adminMonth}
disabled={admin.loading}
@@ -82,7 +72,7 @@ export default function AdminPage() {
titleAriaLabel={`${t("admin.title")}, ${monthName(month)} ${year}`}
className="w-full px-1"
/>
</header>
</MiniAppStickyHeader>
{admin.successMessage && (
<p className="mt-3 text-sm text-[var(--duty)]" role="status" aria-live="polite">
@@ -135,7 +125,7 @@ export default function AdminPage() {
onCloseAnimationEnd={admin.closeReassign}
t={t}
/>
</div>
</div>
</MiniAppScreenContent>
</MiniAppScreen>
);
}