'use client' import { useState, useMemo } from 'react' import { useDebounce } from '@/hooks/use-debounce' import Link from 'next/link' import { trpc } from '@/lib/trpc/client' import { Button } from '@/components/ui/button' import { Card, CardContent, } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Skeleton } from '@/components/ui/skeleton' import { Input } from '@/components/ui/input' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Plus, FileText, Video, Link as LinkIcon, File, Pencil, ExternalLink, Search, } from 'lucide-react' const resourceTypeIcons = { PDF: FileText, VIDEO: Video, DOCUMENT: File, LINK: LinkIcon, OTHER: File, } const cohortColors: Record = { ALL: 'bg-gray-100 text-gray-800', SEMIFINALIST: 'bg-blue-100 text-blue-800', FINALIST: 'bg-purple-100 text-purple-800', } export default function LearningHubPage() { const { data, isLoading } = trpc.learningResource.list.useQuery({ perPage: 50 }) const resources = data?.data const [search, setSearch] = useState('') const debouncedSearch = useDebounce(search, 300) const [typeFilter, setTypeFilter] = useState('all') const [cohortFilter, setCohortFilter] = useState('all') const filteredResources = useMemo(() => { if (!resources) return [] return resources.filter((resource) => { const matchesSearch = !debouncedSearch || resource.title.toLowerCase().includes(debouncedSearch.toLowerCase()) const matchesType = typeFilter === 'all' || resource.resourceType === typeFilter const matchesCohort = cohortFilter === 'all' || resource.cohortLevel === cohortFilter return matchesSearch && matchesType && matchesCohort }) }, [resources, debouncedSearch, typeFilter, cohortFilter]) if (isLoading) { return (
{/* Toolbar skeleton */}
{/* Resource list skeleton */}
{[...Array(5)].map((_, i) => (
))}
) } return (
{/* Header */}

Learning Hub

Manage educational resources for jury members

{/* Toolbar */}
setSearch(e.target.value)} className="pl-9" />
{/* Results count */} {resources && (

{filteredResources.length} of {resources.length} resources

)} {/* Resource List */} {filteredResources.length > 0 ? (
{filteredResources.map((resource) => { const Icon = resourceTypeIcons[resource.resourceType as keyof typeof resourceTypeIcons] || File return (

{resource.title}

{!resource.isPublished && ( Draft )}
{resource.cohortLevel} {resource.resourceType} - {resource._count.accessLogs} views
{resource.externalUrl && ( )}
) })}
) : resources && resources.length > 0 ? (

No resources match your filters

) : (

No resources yet

Add learning materials like videos, documents, and links for program participants.

)}
) }