"use client" import { useEffect, useMemo, useState } from "react" import Link from "next/link" import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Switch } from "@/components/ui/switch" import { Plus, Search, Edit, Trash2, Eye, ChevronLeft, ChevronRight, Loader2 } from "lucide-react" import { adminJobsApi, jobsApi, type AdminJob } from "@/lib/api" import { useTranslation } from "@/lib/i18n" import { ConfirmModal } from "@/components/confirm-modal" type EditForm = { title: string description: string location: string employmentType: string workMode: string workingHours: string salaryMin: string salaryMax: string salaryType: string currency: string salaryNegotiable: boolean languageLevel: string visaSupport: boolean status: string isFeatured: boolean } const defaultEditForm: EditForm = { title: "", description: "", location: "", employmentType: "", workMode: "", workingHours: "", salaryMin: "", salaryMax: "", salaryType: "monthly", currency: "BRL", salaryNegotiable: false, languageLevel: "", visaSupport: false, status: "open", isFeatured: false, } export default function AdminJobsPage() { const { t } = useTranslation() const [searchTerm, setSearchTerm] = useState("") const [jobs, setJobs] = useState([]) const [isViewDialogOpen, setIsViewDialogOpen] = useState(false) const [isEditDialogOpen, setIsEditDialogOpen] = useState(false) const [selectedJob, setSelectedJob] = useState(null) const [editForm, setEditForm] = useState(defaultEditForm) const [isLoading, setIsLoading] = useState(true) const [isSaving, setIsSaving] = useState(false) const [errorMessage, setErrorMessage] = useState(null) const [deleteConfirmDialog, setDeleteConfirmDialog] = useState<{ isOpen: boolean, jobId: string | null }>({ isOpen: false, jobId: null }) const [page, setPage] = useState(1) const [limit] = useState(10) const [totalPages, setTotalPages] = useState(1) const [totalJobs, setTotalJobs] = useState(0) const loadJobs = async (targetPage = page) => { try { setIsLoading(true) setErrorMessage(null) const jobsData = await adminJobsApi.list({ limit, page: targetPage }) setJobs(jobsData.data ?? []) if (jobsData.pagination) { setTotalPages(Math.ceil((jobsData.pagination.total || 0) / limit)) setTotalJobs(jobsData.pagination.total || 0) } } catch (error) { console.error("Failed to load jobs:", error) setErrorMessage(t('admin.jobs.table.error')) setJobs([]) } finally { setIsLoading(false) } } useEffect(() => { loadJobs() }, [page, limit]) const filteredJobs = useMemo( () => jobs.filter( (job) => job.title.toLowerCase().includes(searchTerm.toLowerCase()) || job.companyName.toLowerCase().includes(searchTerm.toLowerCase()), ), [jobs, searchTerm], ) const activeJobs = useMemo( () => jobs.filter((job) => ["published", "open", "active"].includes(job.status?.toLowerCase() ?? "")).length, [jobs], ) const totalApplications = useMemo( () => jobs.reduce((sum, job) => sum + (job.applicationsCount ?? 0), 0), [jobs], ) const handleViewJob = (job: AdminJob) => { setSelectedJob(job) setIsViewDialogOpen(true) } const handleEditJob = (job: AdminJob) => { setSelectedJob(job) setEditForm({ title: job.title ?? "", description: job.description ?? "", location: job.location ?? "", employmentType: job.employmentType ?? "", workMode: job.workMode ?? "", workingHours: job.workingHours ?? "", salaryMin: job.salaryMin != null ? String(job.salaryMin) : "", salaryMax: job.salaryMax != null ? String(job.salaryMax) : "", salaryType: job.salaryType ?? "monthly", currency: job.currency ?? "BRL", salaryNegotiable: job.salaryNegotiable ?? false, languageLevel: job.languageLevel ?? "", visaSupport: job.visaSupport ?? false, status: job.status ?? "open", isFeatured: job.isFeatured ?? false, }) setIsEditDialogOpen(true) } const handleDeleteJob = async (id: string) => { setDeleteConfirmDialog({ isOpen: true, jobId: id }) } const confirmDeleteJob = async () => { if (!deleteConfirmDialog.jobId) return try { await jobsApi.delete(deleteConfirmDialog.jobId) setJobs((prev) => prev.filter((job) => job.id !== deleteConfirmDialog.jobId)) } catch { alert(t('admin.jobs.deleteError')) } finally { setDeleteConfirmDialog({ isOpen: false, jobId: null }) } } const handleSaveEdit = async () => { if (!selectedJob) return setIsSaving(true) try { await jobsApi.update(selectedJob.id, { title: editForm.title || undefined, description: editForm.description || undefined, location: editForm.location || undefined, employmentType: (editForm.employmentType as any) || undefined, workMode: (editForm.workMode as any) || undefined, workingHours: editForm.workingHours || undefined, salaryMin: editForm.salaryMin ? parseFloat(editForm.salaryMin) : undefined, salaryMax: editForm.salaryMax ? parseFloat(editForm.salaryMax) : undefined, salaryType: (editForm.salaryType as any) || undefined, currency: (editForm.currency as any) || undefined, salaryNegotiable: editForm.salaryNegotiable, languageLevel: editForm.languageLevel || undefined, visaSupport: editForm.visaSupport, status: (editForm.status as any) || undefined, isFeatured: editForm.isFeatured, }) await loadJobs(page) setIsEditDialogOpen(false) } catch { alert(t('admin.jobs.updateError')) } finally { setIsSaving(false) } } const statusColor = (status: string) => { switch (status) { case "open": return "default" case "draft": return "secondary" case "closed": case "paused": return "outline" default: return "outline" } } return (
{/* Header */}

{t('admin.jobs.title')}

{t('admin.jobs.subtitle')}

setDeleteConfirmDialog({ isOpen: false, jobId: null })} onConfirm={confirmDeleteJob} title={t('admin.jobs.deleteConfirm')} description="Esta ação não pode ser desfeita e irá excluir a vaga permanentemente." /> {/* View Job Dialog */} {t('admin.jobs.details.title')} {t('admin.jobs.details.description')} {selectedJob && (

{selectedJob.title}

{selectedJob.companyName}

{selectedJob.status}

{selectedJob.applicationsCount ?? 0}

{selectedJob.employmentType ?? "-"}

{selectedJob.workMode ?? "-"}

{selectedJob.location ?? "-"}

{selectedJob.salaryNegotiable ? "Negociável" : selectedJob.salaryMin ? `${selectedJob.currency ?? ""} ${selectedJob.salaryMin}${selectedJob.salaryMax ? ` – ${selectedJob.salaryMax}` : ""}` : "-"}

{selectedJob.languageLevel || "-"}

{selectedJob.visaSupport ? "Sim" : "Não"}

{selectedJob.description || "-"}
)} {selectedJob && ( )}
{/* Edit Job Dialog */} {t('admin.jobs.edit.title')} {t('admin.jobs.edit.subtitle')}
{/* Title + Status */}
setEditForm({ ...editForm, title: e.target.value })} />
setEditForm({ ...editForm, location: e.target.value })} placeholder="Ex: Tokyo, Japan" />
{/* Employment + WorkMode */}
{/* Salary */}
setEditForm({ ...editForm, salaryMin: e.target.value })} placeholder="0" />
setEditForm({ ...editForm, salaryMax: e.target.value })} placeholder="0" />
{/* Language + WorkingHours */}
setEditForm({ ...editForm, workingHours: e.target.value })} placeholder="Ex: 40h/semana" />
{/* Toggles */}
setEditForm({ ...editForm, salaryNegotiable: v })} id="edit-negotiable" />
setEditForm({ ...editForm, visaSupport: v })} id="edit-visa" />
setEditForm({ ...editForm, isFeatured: v })} id="edit-featured" />
{/* Description */}