Files
thrilltrack-explorer/src-old/components/admin/AdminPageLayout.tsx

127 lines
3.5 KiB
TypeScript

import { ReactNode, useCallback } from 'react';
import { AdminLayout } from '@/components/layout/AdminLayout';
import { MFAGuard } from '@/components/auth/MFAGuard';
import { QueueSkeleton } from '@/components/moderation/QueueSkeleton';
import { useAdminGuard } from '@/hooks/useAdminGuard';
import { useAdminSettings } from '@/hooks/useAdminSettings';
import { useModerationStats } from '@/hooks/useModerationStats';
interface AdminPageLayoutProps {
/** Page title */
title: string;
/** Page description */
description: string;
/** Main content to render when authorized */
children: ReactNode;
/** Optional refresh handler */
onRefresh?: () => void;
/** Whether to require MFA (default: true) */
requireMFA?: boolean;
/** Number of skeleton items to show while loading */
skeletonCount?: number;
/** Whether to show refresh controls */
showRefreshControls?: boolean;
}
/**
* Reusable admin page layout with auth guards and common UI
*
* Handles:
* - Authentication & authorization checks
* - MFA enforcement
* - Loading states
* - Refresh controls and stats
* - Consistent header layout
*
* @example
* ```tsx
* <AdminPageLayout
* title="User Management"
* description="Manage user profiles and roles"
* onRefresh={handleRefresh}
* >
* <UserManagement />
* </AdminPageLayout>
* ```
*/
export function AdminPageLayout({
title,
description,
children,
onRefresh,
requireMFA = true,
skeletonCount = 5,
showRefreshControls = true,
}: AdminPageLayoutProps) {
const { isLoading, isAuthorized, needsMFA } = useAdminGuard(requireMFA);
const {
getAdminPanelRefreshMode,
getAdminPanelPollInterval,
} = useAdminSettings();
const refreshMode = getAdminPanelRefreshMode() as 'auto' | 'manual';
const pollInterval = getAdminPanelPollInterval() as number;
const { lastUpdated } = useModerationStats({
enabled: isAuthorized && showRefreshControls,
pollingEnabled: refreshMode === 'auto',
pollingInterval: pollInterval,
});
const handleRefreshClick = useCallback(() => {
onRefresh?.();
}, [onRefresh]);
// Loading state
if (isLoading) {
return (
<AdminLayout
onRefresh={showRefreshControls ? handleRefreshClick : undefined}
refreshMode={showRefreshControls ? (refreshMode as 'auto' | 'manual') : undefined}
pollInterval={showRefreshControls ? pollInterval : undefined}
lastUpdated={showRefreshControls ? (lastUpdated as Date) : undefined}
>
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold tracking-tight">{title}</h1>
<p className="text-muted-foreground mt-1">{description}</p>
</div>
<QueueSkeleton count={skeletonCount} />
</div>
</AdminLayout>
);
}
// Not authorized
if (!isAuthorized) {
return null;
}
// Main content
return (
<AdminLayout
onRefresh={showRefreshControls ? handleRefreshClick : undefined}
refreshMode={showRefreshControls ? (refreshMode as 'auto' | 'manual') : undefined}
pollInterval={showRefreshControls ? pollInterval : undefined}
lastUpdated={showRefreshControls ? (lastUpdated as Date) : undefined}
>
<MFAGuard>
<div className="space-y-6">
<div>
<h1 className="text-2xl font-bold tracking-tight">{title}</h1>
<p className="text-muted-foreground mt-1">{description}</p>
</div>
{children}
</div>
</MFAGuard>
</AdminLayout>
);
}