System ogłoszeń i aplikacji o pracę.
1interface Job {
2 id: number;
3 title: string;
4 company: string;
5 location: string;
6 salary: string;
7 type: 'full-time' | 'part-time' | 'contract';
8 posted: string;
9}
10
11function JobBoard() {
12 const [jobs, setJobs] = useState<Job[]>([]);
13 const [filters, setFilters] = useState({
14 location: '',
15 type: '',
16 salary: ''
17 });
18
19 const filteredJobs = jobs.filter(job => {
20 if (filters.location && !job.location.includes(filters.location)) return false;
21 if (filters.type && job.type !== filters.type) return false;
22 return true;
23 });
24
25 return (
26 <div>
27 <div className="mb-4 flex gap-4">
28 <input
29 onChange={(e) => setFilters({...filters, location: e.target.value})}
30 className="border rounded px-3 py-2"
31 />
32 <select
33 onChange={(e) => setFilters({...filters, type: e.target.value as any})}
34 className="border rounded px-3 py-2"
35 >
36 <option value="">All Types</option>
37 <option value="full-time">Full Time</option>
38 <option value="part-time">Part Time</option>
39 <option value="contract">Contract</option>
40 </select>
41 </div>
42
43 <div className="space-y-4">
44 {filteredJobs.map(job => (
45 <div key={job.id} className="border rounded p-4">
46 <h3 className="font-bold text-lg">{job.title}</h3>
47 <p className="text-gray-600">{job.company} • {job.location}</p>
48 <p className="text-green-600 font-medium">{job.salary}</p>
49 <button className="mt-2 bg-blue-600 text-white px-4 py-2 rounded">
50 Apply Now
51 </button>
52 </div>
53 ))}
54 </div>
55 </div>
56 );
57}1function ApplicationForm({ jobId }: { jobId: number }) {
2 const [formData, setFormData] = useState({
3 name: '',
4 email: '',
5 phone: '',
6 resume: null as File | null,
7 coverLetter: ''
8 });
9
10 const handleSubmit = async (e: React.FormEvent) => {
11 e.preventDefault();
12 const data = new FormData();
13 Object.entries(formData).forEach(([key, value]) => {
14 if (value) data.append(key, value);
15 });
16
17 await fetch(`/api/jobs/${jobId}/apply`, {
18 method: 'POST',
19 body: data
20 });
21 };
22
23 return (
24 <form onSubmit={handleSubmit} className="space-y-4">
25 <input
26 onChange={(e) => setFormData({...formData, name: e.target.value})}
27 required
28 className="w-full border rounded px-3 py-2"
29 />
30 <input
31 type="email"
32 onChange={(e) => setFormData({...formData, email: e.target.value})}
33 required
34 className="w-full border rounded px-3 py-2"
35 />
36 <input
37 type="file"
38 accept=".pdf,.doc,.docx"
39 onChange={(e) => setFormData({...formData, resume: e.target.files?.[0] || null})}
40 required
41 />
42 <textarea
43 onChange={(e) => setFormData({...formData, coverLetter: e.target.value})}
44 rows={6}
45 className="w-full border rounded px-3 py-2"
46 />
47 <button type="submit" className="bg-blue-600 text-white px-6 py-2 rounded">
48 Submit Application
49 </button>
50 </form>
51 );
52}Do zobaczenia! 🚀