'use client'; import React, { useState } from 'react'; import { useRouter } from 'next/navigation'; import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { formatDistanceToNow } from 'date-fns'; import { CheckCircle, Clock, ShieldAlert, Filter, Search, User, Mail, Video as VideoIcon, Tv } from 'lucide-react'; import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Input } from '@/components/ui/input'; import { updateRequestStatus } from '@/actions/submit-request'; import { toast } from 'sonner'; import Image from 'next/image'; interface Request { id: string; videoId: string; creatorId: string; viewerName: string | null; viewerEmail: string | null; note: string; imageUrl: string | null; status: string; createdAt: Date; video: { title: string; channel: { channelName: string; }; }; creator: { name: string | null; }; } interface AdminRequestListProps { requests: Request[]; forcedStatus?: string; hideFilters?: boolean; } export function AdminRequestList({ requests: initialRequests, forcedStatus, hideFilters }: AdminRequestListProps) { const router = useRouter(); const [requests, setRequests] = useState(initialRequests); const [filterStatus, setFilterStatus] = useState(forcedStatus || 'PENDING'); const [sortBy, setSortBy] = useState('date'); const [searchQuery, setSearchQuery] = useState(''); const stats = { pending: requests.filter(r => r.status === 'PENDING').length, fulfilled: requests.filter(r => r.status === 'FULFILLED').length, dismissed: requests.filter(r => r.status === 'DISMISSED').length, }; const filteredRequests = requests.filter(r => { if (r.status !== filterStatus) return false; if (searchQuery) { const query = searchQuery.toLowerCase(); return ( r.note.toLowerCase().includes(query) || (r.viewerName?.toLowerCase().includes(query) ?? false) || (r.viewerEmail?.toLowerCase().includes(query) ?? false) || (r.video.title.toLowerCase().includes(query)) || (r.video.channel.channelName.toLowerCase().includes(query)) ); } return true; }).sort((a, b) => { if (sortBy === 'date') { return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); } return 0; }); const handleStatusUpdate = async (id: string, newStatus: 'PENDING' | 'FULFILLED' | 'DISMISSED') => { try { const result = await updateRequestStatus(id, newStatus); if (result.success) { setRequests(prev => prev.map(r => r.id === id ? { ...r, status: newStatus } : r)); toast.success(`Request marked as ${newStatus.toLowerCase()}`); router.refresh(); } else { toast.error(result.error || 'Failed to update status'); } } catch (err) { toast.error('Failed to update request status'); } }; // Update internal status if forcedStatus changes React.useEffect(() => { if (forcedStatus) { setFilterStatus(forcedStatus); } }, [forcedStatus]); return (
{/* Filter Bar */} {!hideFilters && (
setSearchQuery(e.target.value)} className="pl-9 h-9 bg-background/50" />
Showing {filteredRequests.length} of {requests.filter(r => r.status === filterStatus).length} {filterStatus.toLowerCase()} requests
)} {filteredRequests.length > 0 ? (
{filteredRequests.map((request) => ( {request.imageUrl && (
Requested product
)}
{request.status}
{request.video.channel.channelName}
{formatDistanceToNow(new Date(request.createdAt), { addSuffix: true })}
{request.note}
"{request.video.title}"
From: {request.viewerName || 'Anonymous'}
{request.viewerEmail && (
{request.viewerEmail}
)}
))}
) : (

No requests found

Try adjusting your filters or search query.

)}
); }