iris_backend / src /components /ScheduleInterviewModal.jsx
Muhammed Sameer
Initial commit - Iris Full (under development)
ea9ca44
import React, { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
// --- Icons ---
const CalendarIcon = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><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>;
const ClockIcon = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline></svg>;
const VideoIcon = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polygon points="23 7 16 12 23 17 23 7"></polygon><rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect></svg>;
const MapPinIcon = () => <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>;
// NEW ICON
const ChevronDownIcon = () => <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>;
export default function ScheduleInterviewModal({ isOpen, onClose, onConfirm, candidateName }) {
// --- State ---
const [date, setDate] = useState('');
const [time, setTime] = useState('10:00');
const [interviewType, setInterviewType] = useState('Technical');
const [mode, setMode] = useState('Online');
const [details, setDetails] = useState('');
const [interviewerName, setInterviewerName] = useState('Hiring Manager');
const [interviewerRole, setInterviewerRole] = useState('Technical Lead');
// Auto-fill Link for Online
// Auto-fill Link for Online
useEffect(() => {
if (mode === 'Online' && !details) {
const randomId = Math.random().toString(36).substring(7);
// OLD (Fake): setDetails(`https://meet.google.com/${randomId}-intv`);
// NEW (Working Real Video Call):
setDetails(`https://meet.jit.si/IRIS-Interview-${candidateName.replace(/\s+/g, '')}-${randomId}`);
} else if (mode === 'Offline' && details.includes('meet')) {
setDetails('');
}
}, [mode]);
const handleSubmit = () => {
if (!date || !time || !details) {
alert('Please fill in Date, Time, and Location/Link.');
return;
}
onConfirm({ date, time, interviewType, mode, details, interviewerName, interviewerRole });
};
if (!isOpen) return null;
// --- Styles ---
const overlayStyle = {
position: 'fixed', inset: 0, backgroundColor: 'rgba(0,0,0,0.85)',
backdropFilter: 'blur(8px)', display: 'flex', alignItems: 'center',
justifyContent: 'center', zIndex: 9999
};
// Modal Background: Dark Gray (#111827)
const modalStyle = {
width: '100%', maxWidth: '600px', backgroundColor: '#111827',
border: '1px solid #374151', borderRadius: '1.5rem', padding: '2.5rem',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.9)'
};
const labelStyle = {
display: 'flex', alignItems: 'center', gap: '6px', color: '#9ca3af',
fontSize: '0.85rem', fontWeight: '700', marginBottom: '0.6rem',
textTransform: 'uppercase', letterSpacing: '0.05em'
};
// Black Background (#000000) for high contrast
const inputStyle = {
width: '100%', padding: '0.875rem', borderRadius: '0.75rem',
border: '1px solid #4B5563', backgroundColor: '#5b0e1aa1',
color: '#FFFFFF', outline: 'none', fontSize: '1rem',
transition: 'all 0.2s', colorScheme: 'dark'
};
return (
<div style={overlayStyle}>
<style>
{`
/* FORCE ICONS TO BE BRIGHT WHITE */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
filter: invert(1) brightness(200%); /* Invert black to white & double brightness */
cursor: pointer;
opacity: 1; /* Maximum visibility */
}
/* Hover Effect */
input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover {
opacity: 0.8;
transform: scale(1.1); /* Slight zoom on hover */
}
/* Dropdown Options Background */
select option {
background-color: #000000;
color: white;
padding: 10px;
}
/* Focus States - Red Glow */
input:focus, select:focus {
border-color: #EF4444 !important;
box-shadow: 0 0 0 1px #EF4444;
background-color: #0a0a0a; /* Slightly lighter black on focus */
}
`}
</style>
<motion.div initial={{ scale: 0.95, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} style={modalStyle}>
{/* Header */}
<div style={{ marginBottom: '2rem', borderBottom: '1px solid #374151', paddingBottom: '1.5rem' }}>
<h2 style={{ fontSize: '1.75rem', fontWeight: 'bold', color: 'white', marginBottom: '0.25rem' }}>Schedule Interview</h2>
<p style={{ color: '#9ca3af', fontSize: '0.95rem' }}>Coordinate session with <span style={{ color: '#EF4444', fontWeight: 'bold' }}>{candidateName}</span></p>
</div>
<div style={{ display: 'grid', gap: '1.5rem' }}>
{/* 1. Date & Time */}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1.5rem' }}>
<div>
<label style={labelStyle}><CalendarIcon /> Date</label>
<input type="date" value={date} onChange={e => setDate(e.target.value)} style={inputStyle} />
</div>
<div>
<label style={labelStyle}><ClockIcon /> Time</label>
<input type="time" value={time} onChange={e => setTime(e.target.value)} style={inputStyle} />
</div>
</div>
{/* 2. Type & Mode */}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1.5rem' }}>
<div>
<label style={labelStyle}>Interview Type</label>
<div style={{ position: 'relative' }}>
<select value={interviewType} onChange={e => setInterviewType(e.target.value)} style={{...inputStyle, appearance: 'none', cursor: 'pointer'}}>
<option>Technical</option>
<option>HR Round</option>
<option>Managerial</option>
<option>Coding Test</option>
</select>
{/* UPDATED ICON HERE */}
<div style={{ position: 'absolute', right: '12px', top: '50%', transform: 'translateY(-50%)', pointerEvents: 'none', color: '#9ca3af' }}>
<ChevronDownIcon />
</div>
</div>
</div>
<div>
<label style={labelStyle}>Mode</label>
<div style={{ display: 'flex', borderRadius: '0.75rem', overflow: 'hidden', border: '1px solid #4B5563', backgroundColor: '#000000' }}>
<button onClick={() => setMode('Online')} style={{ flex: 1, padding: '0.875rem', background: mode === 'Online' ? '#EF4444' : 'transparent', color: 'white', border: 'none', cursor: 'pointer', display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '0.5rem', fontWeight: mode === 'Online' ? 'bold' : 'normal', transition: 'background 0.2s' }}>
<VideoIcon /> Online
</button>
<button onClick={() => setMode('Offline')} style={{ flex: 1, padding: '0.875rem', background: mode === 'Offline' ? '#D97706' : 'transparent', color: 'white', border: 'none', cursor: 'pointer', display: 'flex', justifyContent: 'center', alignItems: 'center', gap: '0.5rem', fontWeight: mode === 'Offline' ? 'bold' : 'normal', transition: 'background 0.2s' }}>
<MapPinIcon /> In-Person
</button>
</div>
</div>
</div>
{/* 3. Location / Link */}
<div>
<label style={labelStyle}>{mode === 'Online' ? 'Meeting Link' : 'Office Address'}</label>
<input
type="text"
value={details}
onChange={e => setDetails(e.target.value)}
placeholder={mode === 'Online' ? "https://meet.google.com/..." : "e.g., Conf Room A, 5th Floor"}
style={inputStyle}
/>
</div>
{/* 4. Interviewer Details */}
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '1.5rem' }}>
<div>
<label style={labelStyle}>Interviewer Name</label>
<input type="text" value={interviewerName} onChange={e => setInterviewerName(e.target.value)} style={inputStyle} />
</div>
<div>
<label style={labelStyle}>Role</label>
<input type="text" value={interviewerRole} onChange={e => setInterviewerRole(e.target.value)} style={inputStyle} />
</div>
</div>
</div>
{/* Footer Buttons */}
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '1rem', marginTop: '3rem', borderTop: '1px solid #374151', paddingTop: '1.5rem' }}>
<button onClick={onClose} style={{ padding: '0.75rem 1.5rem', borderRadius: '0.5rem', background: 'transparent', color: '#9ca3af', border: '1px solid #4B5563', cursor: 'pointer', fontSize: '0.95rem', fontWeight: '600', transition: 'all 0.2s' }}
onMouseOver={(e) => {e.target.style.color = 'white'; e.target.style.borderColor = 'white'}}
onMouseOut={(e) => {e.target.style.color = '#9ca3af'; e.target.style.borderColor = '#4B5563'}}>
Cancel
</button>
<button onClick={handleSubmit} style={{ padding: '0.75rem 2.5rem', borderRadius: '0.5rem', background: '#EF4444', color: 'white', border: 'none', fontWeight: 'bold', cursor: 'pointer', boxShadow: '0 4px 12px rgba(220, 38, 38, 0.4)', fontSize: '0.95rem', transform: 'translateY(0)', transition: 'transform 0.1s' }}
onMouseDown={(e) => e.target.style.transform = 'translateY(1px)'}
onMouseUp={(e) => e.target.style.transform = 'translateY(0)'}>
Confirm Schedule
</button>
</div>
</motion.div>
</div>
);
}