File size: 9,287 Bytes
ea9ca44
 
 
 
 
 
 
 
 
 
 
 
6e5bfbf
 
 
 
 
 
 
 
 
ea9ca44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e5bfbf
ea9ca44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6e5bfbf
ea9ca44
 
6e5bfbf
 
 
ea9ca44
 
6e5bfbf
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
import React from 'react';
import ReactDOM from 'react-dom';
import { motion, AnimatePresence } from 'framer-motion';

// --- Icons ---
const BuildingIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ marginRight: '4px' }}><rect x="4" y="2" width="16" height="20" rx="2" ry="2"></rect><line x1="9" y1="22" x2="9" y2="2"></line><path d="M5 12h14"></path><path d="M5 7h14"></path><path d="M5 17h14"></path></svg>);
const LocationIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ marginRight: '4px' }}><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>);
const MoneyIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ marginRight: '4px' }}><line x1="12" y1="1" x2="12" y2="23"></line><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path></svg>);
const CloseIcon = () => (<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>);
const CheckIcon = () => (<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>);

const JobDetail = ({ job, onClose, onApply, isApplied, isApplying }) => {
    // Determine if the job is expired based on the deadline string
    const isExpired = React.useMemo(() => {
        if (!job || !job.deadline || job.deadline === 'Open') return false;
        const deadlineDate = new Date(job.deadline);
        const today = new Date();
        today.setHours(0, 0, 0, 0);
        return deadlineDate < today;
    }, [job]);

    // Portal renders this outside the main app flow
    return ReactDOM.createPortal(
        <AnimatePresence>
            {job && (
                <motion.div
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    exit={{ opacity: 0 }}
                    style={{
                        position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
                        backgroundColor: 'rgba(0,0,0,0.8)',
                        zIndex: 9999,
                        display: 'flex', justifyContent: 'center', alignItems: 'center', padding: '1rem',
                        backdropFilter: 'blur(4px)'
                    }}
                    onClick={onClose}
                >
                    <motion.div
                        initial={{ scale: 0.95, y: 20 }}
                        animate={{ scale: 1, y: 0 }}
                        exit={{ scale: 0.95, y: 20 }}
                        style={{
                            backgroundColor: '#1e293b', width: '100%', maxWidth: '650px', maxHeight: '90vh',
                            borderRadius: '1rem', overflow: 'hidden', display: 'flex', flexDirection: 'column',
                            border: '1px solid #374151',
                            boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5)'
                        }}
                        onClick={(e) => e.stopPropagation()}
                    >
                        {/* Modal Header */}
                        <div style={{ padding: '1.5rem', borderBottom: '1px solid #374151', display: 'flex', justifyContent: 'space-between', alignItems: 'start', backgroundColor: '#0f172a' }}>
                            <div>
                                <h2 style={{ fontSize: '1.5rem', fontWeight: 'bold', color: 'white', marginBottom: '0.5rem', margin: 0 }}>{job.title}</h2>
                                <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', color: '#FBBF24', fontWeight: '600', marginTop: '0.5rem' }}>
                                    <BuildingIcon /> {job.company}
                                </div>
                            </div>
                            <button onClick={onClose} style={{ background: 'transparent', border: 'none', color: '#9ca3af', cursor: 'pointer' }}><CloseIcon /></button>
                        </div>

                        {/* Modal Content */}
                        <div style={{ padding: '2rem', overflowY: 'auto', color: '#d1d5db', lineHeight: '1.6' }}>
                            <div style={{ display: 'flex', gap: '1rem', marginBottom: '2rem', flexWrap: 'wrap' }}>
                                <span style={{ backgroundColor: 'rgba(255,255,255,0.05)', padding: '0.5rem 1rem', borderRadius: '0.5rem', display: 'flex', alignItems: 'center', fontSize: '0.9rem' }}><LocationIcon /> {job.location}</span>
                                <span style={{ backgroundColor: 'rgba(255,255,255,0.05)', padding: '0.5rem 1rem', borderRadius: '0.5rem', display: 'flex', alignItems: 'center', fontSize: '0.9rem' }}><MoneyIcon /> {job.salary}</span>
                                <span style={{ backgroundColor: 'rgba(59, 130, 246, 0.1)', color: '#60A5FA', padding: '0.5rem 1rem', borderRadius: '99px', fontSize: '0.85rem', fontWeight: 'bold' }}>{job.type}</span>
                            </div>

                            <h3 style={{ color: 'white', fontSize: '1.1rem', fontWeight: 'bold', marginBottom: '0.75rem' }}>About the Role</h3>
                            <p style={{ marginBottom: '2rem', whiteSpace: 'pre-line' }}>{job.description || "No description provided."}</p>

                            {/* Safe Skills Rendering */}
                            {job.skills && job.skills.length > 0 && (
                                <>
                                    <h3 style={{ color: 'white', fontSize: '1.1rem', fontWeight: 'bold', marginBottom: '0.75rem' }}>Skills Required</h3>
                                    <div style={{ display: 'flex', gap: '0.5rem', flexWrap: 'wrap', marginBottom: '2rem' }}>
                                        {job.skills.map((skill, index) => (
                                            <span key={index} style={{ fontSize: '0.85rem', padding: '0.25rem 0.75rem', backgroundColor: 'rgba(251, 191, 36, 0.1)', color: '#FBBF24', borderRadius: '999px' }}>{skill}</span>
                                        ))}
                                    </div>
                                </>
                            )}

                            <div style={{ fontSize: '0.9rem', color: '#6b7280', marginTop: '1rem', borderTop: '1px solid rgba(255,255,255,0.05)', paddingTop: '1rem' }}>
                                Posted: {job.postedAt} • Deadline: <span style={{ color: isExpired ? '#ef4444' : '#d1d5db' }}>{job.deadline}</span>
                            </div>
                        </div>

                        {/* Modal Footer */}
                        <div style={{ padding: '1rem 1.5rem', borderTop: '1px solid #374151', backgroundColor: '#0f172a', display: 'flex', justifyContent: 'flex-end', gap: '1rem' }}>
                            <button onClick={onClose} style={{ padding: '0.75rem 1.5rem', background: 'transparent', color: 'white', border: '1px solid #4b5563', borderRadius: '0.5rem', cursor: 'pointer' }}>Close</button>
                            
                            {/* Logic for Apply Button */}
                            {isApplied ? (
                                <button disabled style={{ padding: '0.75rem 2rem', backgroundColor: 'rgba(16, 185, 129, 0.15)', color: '#34D399', border: '1px solid #10B981', borderRadius: '0.5rem', fontWeight: 'bold', cursor: 'default', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
                                    <CheckIcon /> Applied
                                </button>
                            ) : (
                                <button 
                                    onClick={() => onApply && onApply(job.id)}
                                    disabled={isApplying || isExpired}
                                    style={{ 
                                        padding: '0.75rem 2rem', 
                                        backgroundColor: (isApplying || isExpired) ? '#4b5563' : '#FBBF24', 
                                        color: (isApplying || isExpired) ? '#d1d5db' : '#1a202c', 
                                        border: 'none', borderRadius: '0.5rem', fontWeight: 'bold', cursor: (isApplying || isExpired) ? 'not-allowed' : 'pointer' 
                                    }}
                                >
                                    {isApplying ? 'Applying...' : (isExpired ? 'Expired' : 'Apply Now')}
                                </button>
                            )}
                        </div>
                    </motion.div>
                </motion.div>
            )}
        </AnimatePresence>,
        document.body
    );
};

export default JobDetail;