import React, { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { supabase } from '../supabaseClient'; import ApplicantLayout from '../components/ApplicantLayout'; // --- ICONS --- const ClockIcon = () => ; const MapPinIcon = () => ; const VideoIcon = () => ; const BriefcaseIcon = () => ; const CalendarIcon = () => ; const ListIcon = () => ; const ChevronLeft = () => ; const ChevronRight = () => ; // --- INTERNAL CALENDAR COMPONENT --- function InternalCalendar({ interviews }) { const [currentDate, setCurrentDate] = useState(new Date()); const [selectedDate, setSelectedDate] = useState(new Date()); const selectedInterviews = interviews.filter(i => { if (!i.scheduled_time) return false; return new Date(i.scheduled_time).toDateString() === selectedDate.toDateString(); }); const daysInMonth = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0).getDate(); const firstDayOfMonth = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1).getDay(); const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; const hasInterview = (day) => { const checkDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), day); return interviews.some(i => { if (!i.scheduled_time) return false; return new Date(i.scheduled_time).toDateString() === checkDate.toDateString(); }); }; return (

{monthNames[currentDate.getMonth()]} {currentDate.getFullYear()}

{['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'].map(d =>
{d}
)} {Array.from({ length: firstDayOfMonth }).map((_, i) =>
)} {Array.from({ length: daysInMonth }).map((_, i) => { const day = i + 1; const dateObj = new Date(currentDate.getFullYear(), currentDate.getMonth(), day); const isSel = selectedDate.toDateString() === dateObj.toDateString(); const isToday = new Date().toDateString() === dateObj.toDateString(); const hasEvt = hasInterview(day); return (
setSelectedDate(dateObj)} style={{ height: '40px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', borderRadius: '50%', cursor: 'pointer', position: 'relative', backgroundColor: isSel ? '#FBBF24' : 'transparent', color: isSel ? '#1a202c' : (isToday ? '#FBBF24' : 'white'), fontWeight: isSel || isToday ? 'bold' : 'normal', border: isToday && !isSel ? '1px solid #FBBF24' : 'none' }}> {day} {hasEvt && !isSel &&
}
); })}

{selectedDate.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' })}

{selectedInterviews.length > 0 ? selectedInterviews.map(i => (
{i.applications.jobs.title}
{new Date(i.scheduled_time).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} • {i.mode}
@ {i.applications.jobs.companies.name}
{i.meeting_link && Join Meeting} {/* Show location in Calendar view too if available */} {i.mode === 'Offline' && i.location &&
📍 {i.location}
}
)) :

No interviews on this date.

}
); } // --- MAIN PAGE COMPONENT --- export default function ApplicantInterview({ onNavigate }) { const [interviews, setInterviews] = useState([]); const [loading, setLoading] = useState(true); const [showCalendar, setShowCalendar] = useState(false); useEffect(() => { const fetchInterviews = async () => { setLoading(true); try { const { data: { user } } = await supabase.auth.getUser(); if (user) { const { data, error } = await supabase .from('interviews') .select(` id, scheduled_time, status, interview_type, mode, meeting_link, location, applications!inner ( user_id, jobs ( title, companies ( name ) ) ) `) .eq('applications.user_id', user.id) .order('scheduled_time', { ascending: true }); if (error) throw error; setInterviews(data || []); } } catch (error) { console.error('Error fetching interviews:', error); } finally { setLoading(false); } }; fetchInterviews(); }, []); const getStatusStyles = (status) => { switch (status) { case 'Scheduled': return { bg: 'rgba(59, 130, 246, 0.15)', text: '#60A5FA', border: '#3B82F6' }; case 'Completed': return { bg: 'rgba(16, 185, 129, 0.15)', text: '#34D399', border: '#10B981' }; case 'Rescheduled': return { bg: 'rgba(245, 158, 11, 0.15)', text: '#FBBF24', border: '#F59E0B' }; case 'Cancelled': return { bg: 'rgba(239, 68, 68, 0.15)', text: '#F87171', border: '#EF4444' }; default: return { bg: 'rgba(107, 114, 128, 0.15)', text: '#9CA3AF', border: '#6B7280' }; } }; const formatDateTime = (dateString) => { if (!dateString) return { datePart: 'N/A', timePart: 'N/A' }; const date = new Date(dateString); return { datePart: date.toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', year: 'numeric' }), timePart: date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', timeZoneName: 'short' }) }; }; return (
{/* Header */}

{showCalendar ? 'Interview Calendar' : 'Upcoming Interviews'}

{showCalendar ? 'View your schedule by month.' : 'Track your upcoming sessions and status.'}

{loading ? (
Loading...
) : ( {showCalendar ? ( ) : ( /* --- LIST VIEW --- */ {interviews.length > 0 ? interviews.map((interview) => { const styles = getStatusStyles(interview.status); const { datePart, timePart } = formatDateTime(interview.scheduled_time); return (
{/* Job Info */}

{interview.applications?.jobs?.title || 'Unknown Role'}

{interview.status}
{interview.applications?.jobs?.companies?.name || 'Unknown Company'} {interview.interview_type} Interview
{/* Date Info */}
{datePart}
{timePart}
{/* Action: Link OR Location */}
{interview.mode === 'Online' ? : } {interview.mode}
{/* LOCATION DISPLAY */} {interview.mode !== 'Online' && interview.location && (
📍 {interview.location}
)} {/* ONLINE LINK */} {interview.mode === 'Online' && interview.meeting_link && ( Join )}
); }) : (

No upcoming interviews found.

)}
)}
)}
); }