@@ -37,8 +37,12 @@ export default function CarrersPage() {
3737 const [ loading , setLoading ] = useState ( true ) ;
3838 const [ search , setSearch ] = useState ( '' ) ;
3939 const [ audience , setAudience ] = useState < 'all' | 'Students' | 'Professionals' | 'Both' > ( 'all' ) ;
40+ const [ workplace , setWorkplace ] = useState < 'all' | 'Remote' | 'Hybrid' | 'Onsite' > ( 'all' ) ;
41+ const [ employment , setEmployment ] = useState < 'all' | 'Internship' | 'Full-time' | 'Part-time' | 'Contract' > ( 'all' ) ;
4042 const [ applyOpen , setApplyOpen ] = useState ( false ) ;
4143 const [ selectedJob , setSelectedJob ] = useState < JobDoc | null > ( null ) ;
44+ const [ detailsOpen , setDetailsOpen ] = useState ( false ) ;
45+ const [ detailsJob , setDetailsJob ] = useState < JobDoc | null > ( null ) ;
4246
4347 useEffect ( ( ) => {
4448 fetch ( '/api/jobs' )
@@ -51,6 +55,8 @@ export default function CarrersPage() {
5155 const q = search . trim ( ) . toLowerCase ( ) ;
5256 return jobs . filter ( ( j ) => {
5357 if ( audience !== 'all' && ( j . audience || 'Both' ) !== audience ) return false ;
58+ if ( workplace !== 'all' && ( j . workplaceType || 'Remote' ) !== workplace ) return false ;
59+ if ( employment !== 'all' && ( j . employmentType || 'Full-time' ) !== employment ) return false ;
5460 if ( ! q ) return true ;
5561 return (
5662 j . title ?. toLowerCase ( ) . includes ( q ) ||
@@ -59,13 +65,18 @@ export default function CarrersPage() {
5965 ( j . tags || [ ] ) . join ( ' ' ) . toLowerCase ( ) . includes ( q )
6066 ) ;
6167 } ) ;
62- } , [ jobs , search , audience ] ) ;
68+ } , [ jobs , search , audience , workplace , employment ] ) ;
6369
6470 const openApply = ( job : JobDoc ) => {
6571 setSelectedJob ( job ) ;
6672 setApplyOpen ( true ) ;
6773 } ;
6874
75+ const openDetails = ( job : JobDoc ) => {
76+ setDetailsJob ( job ) ;
77+ setDetailsOpen ( true ) ;
78+ } ;
79+
6980 const copyToClipboard = async ( text : string ) => {
7081 try {
7182 await navigator . clipboard . writeText ( text ) ;
@@ -79,7 +90,7 @@ export default function CarrersPage() {
7990 < div className = "max-w-3xl" >
8091 < h1 className = "text-3xl sm:text-4xl font-bold" > Careers</ h1 >
8192 < p className = "text-muted-foreground mt-3" >
82- Hand-picked opportunities for students and professionals from our community .
93+ Hand-picked opportunities for students and professionals across Dev Weekends and Dev Weekends partner companies .
8394 </ p >
8495 </ div >
8596
@@ -101,6 +112,29 @@ export default function CarrersPage() {
101112 < SelectItem value = "Both" > Both</ SelectItem >
102113 </ SelectContent >
103114 </ Select >
115+ < Select value = { workplace } onValueChange = { ( v ) => setWorkplace ( v as any ) } >
116+ < SelectTrigger className = "w-[180px]" >
117+ < SelectValue placeholder = "Workplace" />
118+ </ SelectTrigger >
119+ < SelectContent >
120+ < SelectItem value = "all" > All Workplaces</ SelectItem >
121+ < SelectItem value = "Remote" > Remote</ SelectItem >
122+ < SelectItem value = "Hybrid" > Hybrid</ SelectItem >
123+ < SelectItem value = "Onsite" > Onsite</ SelectItem >
124+ </ SelectContent >
125+ </ Select >
126+ < Select value = { employment } onValueChange = { ( v ) => setEmployment ( v as any ) } >
127+ < SelectTrigger className = "w-[180px]" >
128+ < SelectValue placeholder = "Employment" />
129+ </ SelectTrigger >
130+ < SelectContent >
131+ < SelectItem value = "all" > All Employment</ SelectItem >
132+ < SelectItem value = "Internship" > Internship</ SelectItem >
133+ < SelectItem value = "Full-time" > Full-time</ SelectItem >
134+ < SelectItem value = "Part-time" > Part-time</ SelectItem >
135+ < SelectItem value = "Contract" > Contract</ SelectItem >
136+ </ SelectContent >
137+ </ Select >
104138 < div className = "flex-1" />
105139 < Button asChild variant = "outline" >
106140 < Link href = "https://linktr.ee/DevWeekends" target = "_blank" rel = "noopener noreferrer" >
@@ -159,9 +193,14 @@ export default function CarrersPage() {
159193 ) : null }
160194 </ CardContent >
161195 < CardFooter className = "pt-0" >
162- < Button className = "w-full" onClick = { ( ) => openApply ( job ) } >
163- Apply
164- </ Button >
196+ < div className = "w-full flex flex-col sm:flex-row gap-2" >
197+ < Button className = "w-full" variant = "outline" onClick = { ( ) => openDetails ( job ) } >
198+ Read more
199+ </ Button >
200+ < Button className = "w-full" onClick = { ( ) => openApply ( job ) } >
201+ Apply
202+ </ Button >
203+ </ div >
165204 </ CardFooter >
166205 </ Card >
167206 ) ;
@@ -170,6 +209,73 @@ export default function CarrersPage() {
170209 ) }
171210 </ div >
172211
212+ < Dialog
213+ open = { detailsOpen }
214+ onOpenChange = { ( open ) => {
215+ setDetailsOpen ( open ) ;
216+ if ( ! open ) setDetailsJob ( null ) ;
217+ } }
218+ >
219+ < DialogContent className = "w-[calc(100vw-1.5rem)] sm:w-full max-w-2xl max-h-[90vh] overflow-hidden p-4 sm:p-6 grid-rows-[auto,1fr]" >
220+ < DialogHeader >
221+ < DialogTitle > Job Details</ DialogTitle >
222+ < DialogDescription >
223+ { detailsJob ? (
224+ < >
225+ { detailsJob . title } @ { detailsJob . company }
226+ </ >
227+ ) : (
228+ 'Job details'
229+ ) }
230+ </ DialogDescription >
231+ </ DialogHeader >
232+
233+ < div className = "min-h-0 overflow-y-auto pr-1 space-y-4" >
234+ < div className = "text-sm text-muted-foreground space-y-1" >
235+ < div >
236+ < span className = "text-foreground font-semibold" > Company:</ span > { ' ' }
237+ < span className = "text-foreground" > { detailsJob ?. company || '' } </ span >
238+ </ div >
239+ < div >
240+ < span className = "text-foreground font-semibold" > Location:</ span > { ' ' }
241+ < span > { detailsJob ?. location || 'Not specified' } </ span >
242+ </ div >
243+ < div >
244+ < span className = "text-foreground font-semibold" > Deadline:</ span > { ' ' }
245+ < span >
246+ { detailsJob ?. deadline ? new Date ( detailsJob . deadline ) . toLocaleDateString ( ) : 'Not specified' }
247+ </ span >
248+ </ div >
249+ </ div >
250+
251+ < div className = "space-y-2" >
252+ < div className = "text-sm font-semibold" > Description</ div >
253+ < div className = "text-sm whitespace-pre-wrap" > { detailsJob ?. description || '' } </ div >
254+ </ div >
255+
256+ < div className = "space-y-2" >
257+ < div className = "text-sm font-semibold" > Requirements</ div >
258+ < div className = "text-sm whitespace-pre-wrap" >
259+ { detailsJob ?. requirements ?. trim ( ) ? detailsJob . requirements : 'Not provided' }
260+ </ div >
261+ </ div >
262+
263+ { Array . isArray ( detailsJob ?. tags ) && detailsJob ! . tags ! . length > 0 ? (
264+ < div className = "space-y-2" >
265+ < div className = "text-sm font-semibold" > Tags</ div >
266+ < div className = "flex flex-wrap gap-1" >
267+ { detailsJob ! . tags ! . map ( ( t , idx ) => (
268+ < Badge key = { `details-${ detailsJob ! . _id } -${ idx } ` } variant = "outline" >
269+ { t }
270+ </ Badge >
271+ ) ) }
272+ </ div >
273+ </ div >
274+ ) : null }
275+ </ div >
276+ </ DialogContent >
277+ </ Dialog >
278+
173279 < Dialog
174280 open = { applyOpen }
175281 onOpenChange = { ( open ) => {
0 commit comments