'use client' import * as React from 'react' import Link from 'next/link' import { useRouter, useSearchParams } from 'next/navigation' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { PlusCircle, Search, Filter, MoreHorizontal, Eye, Edit, Clock, Users, MapPin, Building2, AlertTriangle, CheckCircle2, XCircle, ArrowUpDown, Download, RefreshCw, } from 'lucide-react' import { cn } from '@/lib/utils' import { requisitions, countries } from '@/lib/mock-data' import { STATUS_CONFIG, URGENCY_CONFIG, type Requisition, type RequisitionStatus } from '@/lib/types' function getDaysUntilDeadline(deadline: string): number { const now = new Date() const deadlineDate = new Date(deadline) return Math.ceil((deadlineDate.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)) } function formatDate(dateString: string): string { return new Date(dateString).toLocaleDateString('es-ES', { day: '2-digit', month: 'short', year: 'numeric', }) } interface RequisitionRowProps { requisition: Requisition } function RequisitionTableRow({ requisition }: RequisitionRowProps) { const status = STATUS_CONFIG[requisition.status] const urgency = URGENCY_CONFIG[requisition.urgency] const daysLeft = getDaysUntilDeadline(requisition.hardDeadline) const isOverdue = daysLeft < 0 const isAtRisk = daysLeft >= 0 && daysLeft <= 7 return ( {requisition.id} {requisition.positionName} {requisition.cityName}, {requisition.countryName} {requisition.vacanciesFilled} / {requisition.quantity} {status.label} {urgency.label} {requisition.departmentName} {isOverdue ? ( ) : isAtRisk ? ( ) : ( )} {isOverdue ? `${Math.abs(daysLeft)}d vencido` : `${daysLeft}d` } {formatDate(requisition.createdAt)} Acciones Ver detalles {requisition.status === 'borrador' && ( Editar )} {requisition.status === 'correccion_requerida' && ( Corregir y reenviar )} ) } export function RequisitionsListPage() { const router = useRouter() const searchParams = useSearchParams() const [searchTerm, setSearchTerm] = React.useState('') const [statusFilter, setStatusFilter] = React.useState('all') const [countryFilter, setCountryFilter] = React.useState('all') const [activeTab, setActiveTab] = React.useState('todas') // Check for filter param React.useEffect(() => { const filter = searchParams.get('filter') if (filter === 'urgent') { setActiveTab('urgentes') } }, [searchParams]) const filteredRequisitions = React.useMemo(() => { let filtered = [...requisitions] // Search filter if (searchTerm) { const term = searchTerm.toLowerCase() filtered = filtered.filter(r => r.id.toLowerCase().includes(term) || r.positionName.toLowerCase().includes(term) || r.cityName.toLowerCase().includes(term) || r.requesterName.toLowerCase().includes(term) ) } // Status filter if (statusFilter !== 'all') { filtered = filtered.filter(r => r.status === statusFilter) } // Country filter if (countryFilter !== 'all') { filtered = filtered.filter(r => r.countryId === countryFilter) } // Tab filter if (activeTab === 'abiertas') { filtered = filtered.filter(r => !['cerrado', 'cancelado'].includes(r.status)) } else if (activeTab === 'urgentes') { filtered = filtered.filter(r => { const daysLeft = getDaysUntilDeadline(r.hardDeadline) return !['cerrado', 'cancelado'].includes(r.status) && daysLeft <= 7 }) } else if (activeTab === 'cerradas') { filtered = filtered.filter(r => ['cerrado', 'cancelado'].includes(r.status)) } // Sort by date (newest first) filtered.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()) return filtered }, [searchTerm, statusFilter, countryFilter, activeTab]) const stats = React.useMemo(() => { const open = requisitions.filter(r => !['cerrado', 'cancelado'].includes(r.status)) const urgent = open.filter(r => getDaysUntilDeadline(r.hardDeadline) <= 7) const closed = requisitions.filter(r => ['cerrado', 'cancelado'].includes(r.status)) return { all: requisitions.length, open: open.length, urgent: urgent.length, closed: closed.length, } }, []) return ( {/* Header */} Requisiciones Gestiona y da seguimiento a todas las requisiciones de vacantes Nueva Requisición {/* Tabs */} Todas ({stats.all}) Abiertas ({stats.open}) Urgentes ({stats.urgent}) Cerradas ({stats.closed}) {/* Filters */} setSearchTerm(e.target.value)} className="pl-9" /> Todos los estados {Object.entries(STATUS_CONFIG).map(([key, config]) => ( {config.label} ))} Todos los países {countries.map((country) => ( {country.name} ))} {filteredRequisitions.length > 0 ? ( ID Posición Vacantes Estado Urgencia Departamento SLA Creada {filteredRequisitions.map((requisition) => ( ))} ) : ( No se encontraron requisiciones Intenta ajustar los filtros de búsqueda )} ) }
{requisition.positionName}
Gestiona y da seguimiento a todas las requisiciones de vacantes
Intenta ajustar los filtros de búsqueda