'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 { Switch } from '@/components/ui/switch'
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import {
Plus,
FileText,
Pencil,
ExternalLink,
Search,
GripVertical,
} from 'lucide-react'
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
type DragEndEvent,
} from '@dnd-kit/core'
import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
useSortable,
verticalListSortingStrategy,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { toast } from 'sonner'
type Resource = {
id: string
title: string
description: string | null
isPublished: boolean
sortOrder: number
externalUrl: string | null
objectKey: string | null
contentJson: unknown
accessJson: unknown
_count: { accessLogs: number }
program: { id: string; name: string; year: number } | null
}
function getAccessSummary(accessJson: unknown): string {
if (!accessJson || !Array.isArray(accessJson) || accessJson.length === 0) {
return 'Everyone'
}
const rule = accessJson[0] as { type: string; roles?: string[] }
if (rule.type === 'everyone') return 'Everyone'
if (rule.type === 'roles' && rule.roles) {
if (rule.roles.length === 1) return rule.roles[0].replace('_', ' ').toLowerCase()
return `${rule.roles.length} roles`
}
if (rule.type === 'jury_group') return 'Jury groups'
if (rule.type === 'round') return 'By round'
return 'Custom'
}
function SortableResourceCard({
resource,
onTogglePublished,
}: {
resource: Resource
onTogglePublished: (id: string, published: boolean) => void
}) {
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging,
} = useSortable({ id: resource.id })
const style = {
transform: CSS.Transform.toString(transform),
transition,
}
return (
{resource.title}
{!resource.isPublished && (
Manage educational resources for program participants
{filteredResources.length} of {resources.length} resources {reorderMutation.isPending && ' ยท Saving order...'}
)} {/* Resource List with DnD */} {filteredResources.length > 0 ? (No resources match your filters
Add learning materials like videos, documents, and links for program participants.