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:
@@ -11,6 +11,8 @@ import { useTranslation } from "@/i18n/use-translation";
|
||||
import { AccessDeniedScreen } from "@/components/states/AccessDeniedScreen";
|
||||
import { LoadingState } from "@/components/states/LoadingState";
|
||||
import { ErrorState } from "@/components/states/ErrorState";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ChevronLeft as ChevronLeftIcon, ChevronRight as ChevronRightIcon } from "lucide-react";
|
||||
|
||||
const PAGE_WRAPPER_CLASS =
|
||||
"content-safe mx-auto flex min-h-[var(--tg-viewport-stable-height,100vh)] w-full max-w-[var(--max-width-app)] flex-col bg-background px-3 pb-6";
|
||||
@@ -50,27 +52,54 @@ export default function AdminPage() {
|
||||
);
|
||||
}
|
||||
|
||||
const month = admin.currentMonth.getMonth();
|
||||
const year = admin.currentMonth.getFullYear();
|
||||
const month = admin.adminMonth.getMonth();
|
||||
const year = admin.adminMonth.getFullYear();
|
||||
|
||||
return (
|
||||
<div className={PAGE_WRAPPER_CLASS}>
|
||||
<header className="sticky top-0 z-10 flex flex-col items-center border-b bg-[var(--header-bg)] py-3">
|
||||
<h1
|
||||
className="m-0 flex flex-col items-center justify-center gap-0 leading-none"
|
||||
aria-label={`${t("admin.title")}, ${monthName(month)} ${year}`}
|
||||
>
|
||||
<span className="text-xs font-normal leading-none text-muted">
|
||||
{year}
|
||||
</span>
|
||||
<span className="text-[1.1rem] font-semibold leading-tight sm:text-[1.25rem]">
|
||||
{monthName(month)}
|
||||
</span>
|
||||
</h1>
|
||||
<div className="flex w-full items-center justify-between px-1">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
className="size-10 rounded-[10px] bg-surface text-accent hover:bg-[var(--surface-hover)] focus-visible:outline-accent active:scale-95 disabled:opacity-50"
|
||||
aria-label={t("nav.prev_month")}
|
||||
disabled={admin.loading}
|
||||
onClick={admin.onPrevMonth}
|
||||
>
|
||||
<ChevronLeftIcon className="size-5" aria-hidden />
|
||||
</Button>
|
||||
<h1
|
||||
className="m-0 flex flex-col items-center justify-center gap-0 leading-none"
|
||||
aria-label={`${t("admin.title")}, ${monthName(month)} ${year}`}
|
||||
>
|
||||
<span className="text-xs font-normal leading-none text-muted">
|
||||
{year}
|
||||
</span>
|
||||
<span className="text-[1.1rem] font-semibold leading-tight sm:text-[1.25rem]">
|
||||
{monthName(month)}
|
||||
</span>
|
||||
</h1>
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
size="icon"
|
||||
className="size-10 rounded-[10px] bg-surface text-accent hover:bg-[var(--surface-hover)] focus-visible:outline-accent active:scale-95 disabled:opacity-50"
|
||||
aria-label={t("nav.next_month")}
|
||||
disabled={admin.loading}
|
||||
onClick={admin.onNextMonth}
|
||||
>
|
||||
<ChevronRightIcon className="size-5" aria-hidden />
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground m-0 mt-1">
|
||||
{admin.loading ? "…" : t("admin.duties_count", { count: String(admin.dutyOnly.length) })}
|
||||
</p>
|
||||
</header>
|
||||
|
||||
{admin.successMessage && (
|
||||
<p className="mt-3 text-sm text-[var(--duty)]" role="status">
|
||||
<p className="mt-3 text-sm text-[var(--duty)]" role="status" aria-live="polite">
|
||||
{admin.successMessage}
|
||||
</p>
|
||||
)}
|
||||
@@ -96,7 +125,7 @@ export default function AdminPage() {
|
||||
{t("admin.reassign_duty")}: {t("admin.select_user")}
|
||||
</p>
|
||||
<AdminDutyList
|
||||
duties={admin.visibleDuties}
|
||||
groups={admin.visibleGroups}
|
||||
hasMore={admin.hasMore}
|
||||
sentinelRef={admin.sentinelRef}
|
||||
onSelectDuty={admin.openReassign}
|
||||
@@ -112,7 +141,7 @@ export default function AdminPage() {
|
||||
setSelectedUserId={admin.setSelectedUserId}
|
||||
users={admin.usersForSelect}
|
||||
saving={admin.saving}
|
||||
reassignError={admin.reassignError}
|
||||
reassignErrorKey={admin.reassignErrorKey}
|
||||
onReassign={admin.handleReassign}
|
||||
onRequestClose={admin.requestCloseSheet}
|
||||
onCloseAnimationEnd={admin.closeReassign}
|
||||
|
||||
Reference in New Issue
Block a user