Spaces:
Sleeping
Sleeping
File size: 5,621 Bytes
ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 84d4394 ea9ca44 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | import React, { useEffect, useState } from 'react';
import { supabase } from '../../supabaseClient';
// ✅ Accept 'onNavigate' as a prop from the parent
export default function UpcomingInterviews({ onNavigate }) {
const [interviews, setInterviews] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchInterviews = async () => {
try {
const { data, error } = await supabase
.from('interviews')
.select(`
id,
scheduled_time,
status,
applications (
profiles ( full_name )
)
`)
.gte('scheduled_time', new Date().toISOString())
.order('scheduled_time', { ascending: true })
.limit(3);
if (error) throw error;
setInterviews(data || []);
} catch (error) {
console.error('Error fetching interviews:', error);
} finally {
setLoading(false);
}
};
fetchInterviews();
}, []);
const formatDate = (dateString) => {
if (!dateString) return { date: 'N/A', time: '' };
const date = new Date(dateString);
return {
date: date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),
time: date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' })
};
};
return (
<div style={{
backgroundColor: 'rgba(239, 68, 68, 0.05)',
border: '1px solid rgba(239, 68, 68, 0.2)',
borderRadius: '1rem',
padding: '1.5rem',
color: 'white',
height: '100%',
display: 'flex',
flexDirection: 'column'
}}>
<h2 style={{ fontSize: '1.25rem', fontWeight: 'bold', marginBottom: '1.5rem' }}>Upcoming Interviews</h2>
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', flexGrow: 1 }}>
{loading ? (
<p style={{ color: '#9CA3AF', textAlign: 'center' }}>Loading...</p>
) : interviews.length === 0 ? (
<p style={{ color: '#9CA3AF', textAlign: 'center' }}>No upcoming interviews.</p>
) : (
interviews.map((item) => {
const { date, time } = formatDate(item.scheduled_time);
const name = item.applications?.profiles?.full_name || 'Candidate';
return (
<div key={item.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingBottom: '0.75rem', borderBottom: '1px solid rgba(255,255,255,0.1)' }}>
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
{/* Icon Box */}
<div style={{
width: '40px', height: '40px', borderRadius: '50%',
backgroundColor: 'rgba(239, 68, 68, 0.1)', color: '#c82121',
display: 'flex', alignItems: 'center', justifyContent: 'center'
}}>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line></svg>
</div>
<div>
<div style={{ fontWeight: '600', fontSize: '1rem' }}>{name}</div>
<div style={{ fontSize: '0.85rem', color: '#9CA3AF' }}>{date} • {time}</div>
</div>
</div>
<button style={{
padding: '0.4rem 1rem', borderRadius: '2rem',
border: '1px solid #EF4444', background: 'transparent',
color: '#d8bdbd', fontSize: '0.75rem', cursor: 'pointer', fontWeight: 'bold'
}}>
View
</button>
</div>
);
})
)}
</div>
{/* ✅ UPDATED BUTTON: Uses onNavigate prop */}
<button
onClick={() => {
if (onNavigate) {
onNavigate('interviews'); // Switch to Interviews Tab
} else {
console.error("onNavigate prop is missing!");
}
}}
style={{
marginTop: '1.5rem',
background: 'none',
border: 'none',
color: '#EF4444',
fontSize: '0.9rem',
cursor: 'pointer',
textAlign: 'center',
width: '100%',
fontWeight: '500'
}}
>
View All Interviews →
</button>
</div>
);
} |