|
1 | 1 | 'use client'; |
2 | | -import React, { useState } from 'react'; |
| 2 | +import React, { useEffect, useState } from 'react'; |
3 | 3 | import { Input } from '@/components/ui/input'; |
4 | 4 | import gradient from '@/public/assets/jobBoard/gradient.svg'; |
5 | 5 | import Image from 'next/image'; |
6 | 6 | import { Search } from 'lucide-react'; |
7 | 7 | import { Map } from 'lucide-react'; |
8 | 8 |
|
| 9 | +const jobData = [ |
| 10 | + { id: 1, title: 'Frontend Developer', location: 'Davao' }, |
| 11 | + { id: 2, title: 'Backend Developer', location: 'Cebu' }, |
| 12 | + { id: 3, title: 'UI/UX Designer', location: 'Manila' }, |
| 13 | + { id: 4, title: 'Data Analyst', location: 'Davao' }, |
| 14 | +]; |
| 15 | + |
9 | 16 | export const JobBoard = () => { |
10 | | - const [placeholder, setPlaceholder] = useState(''); |
| 17 | + const [jobs, setJobs] = useState(jobData); |
| 18 | + const [searchTerm, setSearchTerm] = useState(''); |
| 19 | + const [location, setLocation] = useState(''); |
| 20 | + const filteredJobs = jobData.filter( |
| 21 | + (job) => |
| 22 | + job.title.toLowerCase().includes(searchTerm.toLowerCase()) && |
| 23 | + (location === '' || job.location === location) |
| 24 | + ); |
11 | 25 |
|
| 26 | + useEffect(() => { |
| 27 | + const filtered = jobs.filter( |
| 28 | + (job) => |
| 29 | + job.title.toLowerCase().includes(searchTerm.toLowerCase()) && |
| 30 | + job.location.toLowerCase().includes(location.toLowerCase()) |
| 31 | + ); |
| 32 | + setJobs(filtered); |
| 33 | + }, [searchTerm, location, jobs]); |
12 | 34 | return ( |
13 | 35 | <div className="lg:h-[680px] md:h-[670px] sm:h-[300px]"> |
14 | 36 | {/* HERO SECTION */} |
@@ -41,50 +63,65 @@ export const JobBoard = () => { |
41 | 63 | </p> |
42 | 64 |
|
43 | 65 | {/* SEARCH BAR */} |
44 | | - <div className="w-[362px] md:w-[867px] h-[33px] md:h-[74px] lg:w-[867px] bg-white flex flex-row items-center rounded-[64px] mt-3 p-100"> |
45 | | - <div className="w-full flex flex-row justify-center gap-2 md:gap-x-60 "> |
46 | | - <div className="flex flex-row items-center -ml-1 gap-x-2 md:pl-6"> |
47 | | - <Search className="w-[18px] md:w-[30px] md:h-[30px] h-[18px] text-medium-dark-green stroke-[4]" /> |
| 66 | + <div className="w-[362px] md:w-[867px] h-[33px] md:h-[74px] lg:w-[867px] bg-white flex items-center rounded-[64px] mt-3 p-3 overflow-hidden shadow-md"> |
| 67 | + <div className="flex w-full justify-center gap-6 px-4 md:px-6"> |
| 68 | + <div className="flex items-center gap-2"> |
| 69 | + <Search className="w-[18px] md:w-[30px] h-[18px] md:h-[30px] text-medium-dark-green stroke-[4]" /> |
48 | 70 | <Input |
49 | 71 | type="text" |
50 | 72 | placeholder="Job title or keyword" |
51 | 73 | variant="underline" |
52 | | - className="-ml-2 w-[120px] md:w-[180px] h-[11px] text-[9px] md:text-[14px] font-[600] text-dark-green/45 border-b-0 text-left" |
53 | | - value={placeholder} |
54 | | - onChange={() => {}} |
| 74 | + className="w-[180px] md:w-[280px] text-[14px] font-semibold text-dark-green/45 border-b-0" |
| 75 | + value={searchTerm} |
| 76 | + onChange={(e) => setSearchTerm(e.target.value)} |
55 | 77 | /> |
56 | 78 | </div> |
57 | 79 |
|
58 | | - <div className="flex flex-row md:pr-5"> |
59 | | - <div className="flex flex-row items-center gap-1 translate-x-3"> |
60 | | - <div className="flex flex-row gap-x-3"> |
61 | | - {/* VERTICAL LINE */} |
62 | | - <div className="w-[1px] md:w-[3px] sm:h-[20px] md:h-[30px] bg-dark-green/45"></div> |
63 | | - |
64 | | - <Map className="md:-translate-y-0.75 w-[18px] h-[18px] md:w-[30px] md:h-[30px] text-medium-dark-green stroke-[3]" /> |
65 | | - </div> |
66 | | - |
67 | | - <Input |
68 | | - type="text" |
69 | | - placeholder="Add country or city" |
70 | | - variant="underline" |
71 | | - className="-ml-3 w-[120px] md:w-[200px] h-[11px] text-[9px] md:text-[14px] font-[600] text-dark-green/45 border-b-0 text-left" |
72 | | - value={placeholder} |
73 | | - onChange={() => {}} |
74 | | - /> |
| 80 | + <div className="flex items-center gap-2"> |
| 81 | + <div className="flex items-center gap-2"> |
| 82 | + <div className="w-[3px] h-[30px] bg-dark-green/45"></div> |
| 83 | + <Map className="w-[18px] md:w-[30px] h-[18px] md:h-[30px] text-medium-dark-green stroke-[3]" /> |
75 | 84 | </div> |
76 | | - |
77 | | - <button className="w-[56px] h-[13px] md:w-[160px] md:h-[54px] bg-medium-dark-green text-white text-[9px] md:text-[14px] rounded-[24px] mt-1"> |
| 85 | + <select |
| 86 | + value={location} |
| 87 | + onChange={(e) => setLocation(e.target.value)} |
| 88 | + className="text-[14px] font-semibold text-dark-green/45 bg-transparent focus:outline-none" |
| 89 | + > |
| 90 | + <option value="">Add country or city</option> |
| 91 | + {Array.from(new Set(jobData.map((job) => job.location))).map( |
| 92 | + (loc) => ( |
| 93 | + <option key={loc} value={loc}> |
| 94 | + {loc} |
| 95 | + </option> |
| 96 | + ) |
| 97 | + )} |
| 98 | + </select> |
| 99 | + <button className="w-[160px] h-[54px] bg-medium-dark-green text-white rounded-[24px]"> |
78 | 100 | Search |
79 | 101 | </button> |
80 | 102 | </div> |
81 | 103 | </div> |
82 | 104 | </div> |
83 | 105 | </div> |
84 | 106 |
|
85 | | - {/* CARDS SECTION */} |
86 | | - |
87 | | - {/* FOOTER */} |
| 107 | + {/* JOB CARDS SECTION */} |
| 108 | + <section className="px-4 md:px-10 py-10 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> |
| 109 | + {filteredJobs.length > 0 ? ( |
| 110 | + filteredJobs.map((job) => ( |
| 111 | + <div |
| 112 | + key={job.id} |
| 113 | + className="bg-white rounded-lg p-6 shadow-md hover:shadow-lg transition" |
| 114 | + > |
| 115 | + <h3 className="text-lg font-bold text-dark-green">{job.title}</h3> |
| 116 | + <p className="text-sm text-gray-600">{job.location}</p> |
| 117 | + </div> |
| 118 | + )) |
| 119 | + ) : ( |
| 120 | + <p className="text-center text-gray-500 col-span-full"> |
| 121 | + No jobs found. |
| 122 | + </p> |
| 123 | + )} |
| 124 | + </section> |
88 | 125 | </div> |
89 | 126 | ); |
90 | 127 | }; |
0 commit comments