/** * @ai-summary Admin desktop page for managing community station submissions */ import React, { useState, useCallback } from 'react'; import { Box, Paper, Tabs, Tab, Select, MenuItem, FormControl, InputLabel, useMediaQuery, useTheme, Grid, Typography, } from '@mui/material'; import { AdminSectionHeader } from '../components/AdminSectionHeader'; import { CommunityStationReviewQueue } from '../components/CommunityStationReviewQueue'; import { CommunityStationsList } from '../../stations/components/CommunityStationsList'; import { usePendingSubmissions, useAllCommunitySubmissions, useReviewStation, } from '../../stations/hooks/useCommunityStations'; import toast from 'react-hot-toast'; interface TabPanelProps { children?: React.ReactNode; index: number; value: number; } const TabPanel: React.FC = ({ children, value, index }) => { if (value !== index) { return null; } return (
{children}
); }; /** * Admin page for reviewing and managing community station submissions * Desktop layout with tab navigation and status filtering */ export const AdminCommunityStationsPage: React.FC = () => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const [tabValue, setTabValue] = useState(0); const [statusFilter, setStatusFilter] = useState(''); const [page, setPage] = useState(0); // Hooks const pendingSubmissions = usePendingSubmissions(page, 50); const allSubmissions = useAllCommunitySubmissions(statusFilter || undefined, page, 50); const reviewMutation = useReviewStation(); // Determine which data to display const displayData = tabValue === 0 ? pendingSubmissions : allSubmissions; const stations = displayData.data?.stations || []; const totalPages = displayData.data?.total ? Math.ceil(displayData.data.total / 50) : 1; // Handle approval const handleApprove = useCallback( async (id: string) => { try { await reviewMutation.mutateAsync({ id, decision: { status: 'approved' }, }); toast.success('Station approved'); } catch (error: any) { toast.error(error?.response?.data?.message || 'Failed to approve station'); } }, [reviewMutation] ); // Handle rejection const handleReject = useCallback( async (id: string, reason: string) => { try { await reviewMutation.mutateAsync({ id, decision: { status: 'rejected', rejectionReason: reason }, }); toast.success('Station rejected'); } catch (error: any) { toast.error(error?.response?.data?.message || 'Failed to reject station'); } }, [reviewMutation] ); return ( {/* Header */} {/* Main content */} setTabValue(newValue)} indicatorColor="primary" textColor="primary" aria-label="admin community stations tabs" variant={isMobile ? 'scrollable' : 'standard'} > {/* Pending tab */} {/* All submissions tab */} Filter by Status {/* Stats card */} {pendingSubmissions.data && ( {pendingSubmissions.data.total} Pending Review {allSubmissions.data && ( <> {allSubmissions.data.stations.filter((s) => s.status === 'approved').length} Approved {allSubmissions.data.stations.filter((s) => s.status === 'rejected').length} Rejected {allSubmissions.data.total} Total Submitted )} )} ); }; export default AdminCommunityStationsPage;