import React, { useEffect, useState } from 'react'; import { Box, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, FormControl, Select, MenuItem, InputLabel, Chip, IconButton, Dialog, AppBar, Toolbar, useMediaQuery, useTheme, Slide, } from '@mui/material'; import { KeyboardArrowUp as ArrowUpIcon, KeyboardArrowDown as ArrowDownIcon, Business as BusinessIcon, Work as WorkIcon, Schedule as ScheduleIcon, Close as CloseIcon, ArrowBack as ArrowBackIcon, } from '@mui/icons-material'; import { TransitionProps } from '@mui/material/transitions'; import { JobInfo } from 'components/ui/JobInfo'; import { Job } from 'types/types'; import { useAuth } from 'hooks/AuthContext'; import { useAppState, useSelectedJob } from 'hooks/GlobalContext'; import { Navigate, useNavigate, useParams } from 'react-router-dom'; type SortField = 'updatedAt' | 'createdAt' | 'company' | 'title'; type SortOrder = 'asc' | 'desc'; interface JobViewerProps { onSelect?: (job: Job) => void; } const Transition = React.forwardRef(function Transition( props: TransitionProps & { children: React.ReactElement; }, ref: React.Ref ) { return ; }); const JobViewer: React.FC = ({ onSelect }) => { const navigate = useNavigate(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down('md')); const isSmall = useMediaQuery(theme.breakpoints.down('sm')); const { apiClient } = useAuth(); const { selectedJob, setSelectedJob } = useSelectedJob(); const { setSnack } = useAppState(); const [jobs, setJobs] = useState([]); const [loading, setLoading] = useState(false); const [sortField, setSortField] = useState('updatedAt'); const [sortOrder, setSortOrder] = useState('desc'); const [mobileDialogOpen, setMobileDialogOpen] = useState(false); const { jobId } = useParams<{ jobId?: string }>(); useEffect(() => { const getJobs = async () => { setLoading(true); try { const results = await apiClient.getJobs(); const jobsData: Job[] = results.data || []; setJobs(jobsData); if (jobId) { const job = jobsData.find(j => j.id === jobId); if (job) { setSelectedJob(job); onSelect?.(job); setMobileDialogOpen(true); return; } } // Auto-select first job if none selected if (jobsData.length > 0 && !selectedJob) { const firstJob = sortJobs(jobsData, sortField, sortOrder)[0]; setSelectedJob(firstJob); onSelect?.(firstJob); } } catch (err) { setSnack('Failed to load jobs: ' + err); } finally { setLoading(false); } }; getJobs(); }, [apiClient, setSnack]); const sortJobs = (jobsList: Job[], field: SortField, order: SortOrder): Job[] => { return [...jobsList].sort((a, b) => { let aValue: any; let bValue: any; switch (field) { case 'updatedAt': aValue = a.updatedAt?.getTime() || 0; bValue = b.updatedAt?.getTime() || 0; break; case 'createdAt': aValue = a.createdAt?.getTime() || 0; bValue = b.createdAt?.getTime() || 0; break; case 'company': aValue = a.company?.toLowerCase() || ''; bValue = b.company?.toLowerCase() || ''; break; case 'title': aValue = a.title?.toLowerCase() || ''; bValue = b.title?.toLowerCase() || ''; break; default: return 0; } if (aValue < bValue) return order === 'asc' ? -1 : 1; if (aValue > bValue) return order === 'asc' ? 1 : -1; return 0; }); }; const handleSort = (field: SortField) => { if (sortField === field) { setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc'); } else { setSortField(field); setSortOrder('desc'); } }; const handleJobSelect = (job: Job) => { setSelectedJob(job); onSelect?.(job); setMobileDialogOpen(true); navigate(`/candidate/jobs/${job.id}`); }; const handleMobileDialogClose = () => { setMobileDialogOpen(false); }; const sortedJobs = sortJobs(jobs, sortField, sortOrder); const formatDate = (date: Date | undefined) => { if (!date) return 'N/A'; return new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', ...(isMobile ? {} : { year: 'numeric' }), ...(isSmall ? {} : { hour: '2-digit', minute: '2-digit' }), }).format(date); }; const getSortIcon = (field: SortField) => { if (sortField !== field) return null; return sortOrder === 'asc' ? ( ) : ( ); }; const JobList = () => ( Jobs ({jobs.length}) Sort by handleSort('company')} > {isSmall ? 'Co.' : isMobile ? 'Company' : 'Company'} {getSortIcon('company')} handleSort('title')} > Title {getSortIcon('title')} {!isMobile && ( handleSort('updatedAt')} > Updated {getSortIcon('updatedAt')} )} {isMobile ? 'Status' : 'Status'} {sortedJobs.map(job => ( handleJobSelect(job)} sx={{ cursor: 'pointer', height: isMobile ? 48 : 'auto', '&.Mui-selected': { backgroundColor: 'action.selected', }, '&:hover': { backgroundColor: 'action.hover', }, }} > {job.company || 'N/A'} {!isMobile && job.details?.location && ( {job.details.location.city},{' '} {job.details.location.state || job.details.location.country} )} {job.title || 'N/A'} {!isMobile && job.details?.employmentType && ( )} {!isMobile && ( {formatDate(job.updatedAt)} {job.createdAt && ( Created: {formatDate(job.createdAt)} )} )} ))}
); const JobDetails = ({ inDialog = false }: { inDialog?: boolean }) => ( {selectedJob ? ( ) : ( Select a job to view details )} ); return ( {selectedJob?.title} {selectedJob?.company} ); }; export { JobViewer };