22
33import { useState } from "react" ;
44import { useRouter } from "next/navigation" ;
5- import { Mail , Phone , Linkedin , Globe , FileText , Calendar , User , Github , Trash2 , Download , MoreVertical } from "lucide-react" ;
5+ import { H1 } from "@/components/shared/dashboard" ;
6+ import CustomBreadcrumb from "@/components/shared/dashboard/CustomBreadcrumb" ;
67import { Button } from "@/components/ui/button" ;
8+ import { useToast } from "@/components/ui/use-toast" ;
9+ import {
10+ Calendar ,
11+ Download ,
12+ FileText ,
13+ Github ,
14+ Globe ,
15+ Linkedin ,
16+ Mail ,
17+ MoreVertical ,
18+ Phone ,
19+ Trash2 ,
20+ User ,
21+ } from "lucide-react" ;
22+
723import { Badge } from "@codevs/ui/badge" ;
24+ import {
25+ DropdownMenu ,
26+ DropdownMenuContent ,
27+ DropdownMenuItem ,
28+ DropdownMenuTrigger ,
29+ } from "@codevs/ui/dropdown-menu" ;
830import {
931 Select ,
1032 SelectContent ,
1133 SelectItem ,
1234 SelectTrigger ,
1335 SelectValue ,
1436} from "@codevs/ui/select" ;
15- import { useToast } from "@/components/ui/use-toast" ;
37+
1638import ApplicationDetailsModal from "../../_components/ApplicationDetailsModal" ;
17- import CustomBreadcrumb from "@/components/shared/dashboard/CustomBreadcrumb" ;
18- import { H1 } from "@/components/shared/dashboard" ;
1939import { deleteJobApplication , updateApplicationStatus } from "../../actions" ;
20- import { DropdownMenu , DropdownMenuContent , DropdownMenuItem , DropdownMenuTrigger } from "@codevs/ui/dropdown-menu" ;
2140
2241interface JobApplication {
2342 id : string ;
@@ -34,7 +53,7 @@ interface JobApplication {
3453 experience ?: string ;
3554 resume_url ?: string ;
3655 applied_at : string ;
37- status : ' pending' | ' reviewing' | ' shortlisted' | ' rejected' | ' hired' ;
56+ status : " pending" | " reviewing" | " shortlisted" | " rejected" | " hired" ;
3857 notes ?: string ;
3958}
4059
@@ -44,18 +63,29 @@ interface JobApplicationsClientProps {
4463 applications : JobApplication [ ] ;
4564}
4665
47- export default function JobApplicationsClient ( { jobId, jobTitle, applications } : JobApplicationsClientProps ) {
66+ export default function JobApplicationsClient ( {
67+ jobId,
68+ jobTitle,
69+ applications,
70+ } : JobApplicationsClientProps ) {
4871 const router = useRouter ( ) ;
4972 const { toast } = useToast ( ) ;
50- const [ selectedApplication , setSelectedApplication ] = useState < JobApplication | null > ( null ) ;
73+ const [ selectedApplication , setSelectedApplication ] =
74+ useState < JobApplication | null > ( null ) ;
5175 const [ isDetailsModalOpen , setIsDetailsModalOpen ] = useState ( false ) ;
5276
53-
54-
55- const handleStatusChange = async ( applicationId : string , newStatus : string ) => {
77+ const handleStatusChange = async (
78+ applicationId : string ,
79+ newStatus : string ,
80+ ) => {
5681 const result = await updateApplicationStatus (
5782 applicationId ,
58- newStatus as 'pending' | 'reviewing' | 'shortlisted' | 'rejected' | 'hired'
83+ newStatus as
84+ | "pending"
85+ | "reviewing"
86+ | "shortlisted"
87+ | "rejected"
88+ | "hired" ,
5989 ) ;
6090
6191 if ( result . success ) {
@@ -75,15 +105,35 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
75105
76106 const getStatusBadge = ( status : string ) => {
77107 const statusConfig = {
78- pending : { color : "bg-yellow-500/10 text-yellow-400 border-yellow-500/20" , label : "Pending" } ,
79- reviewing : { color : "bg-blue-500/10 text-blue-400 border-blue-500/20" , label : "Reviewing" } ,
80- shortlisted : { color : "bg-green-500/10 text-green-400 border-green-500/20" , label : "Shortlisted" } ,
81- rejected : { color : "bg-red-500/10 text-red-400 border-red-500/20" , label : "Rejected" } ,
82- hired : { color : "bg-purple-500/10 text-purple-400 border-purple-500/20" , label : "Hired" } ,
108+ pending : {
109+ color : "bg-yellow-500/10 text-yellow-400 border-yellow-500/20" ,
110+ label : "Pending" ,
111+ } ,
112+ reviewing : {
113+ color : "bg-blue-500/10 text-blue-400 border-blue-500/20" ,
114+ label : "Reviewing" ,
115+ } ,
116+ shortlisted : {
117+ color : "bg-green-500/10 text-green-400 border-green-500/20" ,
118+ label : "Shortlisted" ,
119+ } ,
120+ rejected : {
121+ color : "bg-red-500/10 text-red-400 border-red-500/20" ,
122+ label : "Rejected" ,
123+ } ,
124+ hired : {
125+ color : "bg-purple-500/10 text-purple-400 border-purple-500/20" ,
126+ label : "Hired" ,
127+ } ,
83128 } ;
84129
85- const config = statusConfig [ status as keyof typeof statusConfig ] || statusConfig . pending ;
86- return < Badge variant = "outline" className = { config . color } > { config . label } </ Badge > ;
130+ const config =
131+ statusConfig [ status as keyof typeof statusConfig ] || statusConfig . pending ;
132+ return (
133+ < Badge variant = "outline" className = { config . color } >
134+ { config . label }
135+ </ Badge >
136+ ) ;
87137 } ;
88138
89139 const breadcrumbItems = [
@@ -110,7 +160,6 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
110160 }
111161 } ;
112162
113-
114163 return (
115164 < div className = "container mx-auto max-w-7xl p-6" >
116165 < div className = "mb-6" >
@@ -120,7 +169,8 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
120169 < div className = "mb-8" >
121170 < H1 > Applications for { jobTitle } </ H1 >
122171 < p className = "mt-2 text-gray-400" >
123- { applications . length } applicant{ applications . length !== 1 ? 's' : '' } found
172+ { applications . length } applicant{ applications . length !== 1 ? "s" : "" } { " " }
173+ found
124174 </ p >
125175 </ div >
126176
@@ -129,11 +179,21 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
129179 < table className = "w-full" >
130180 < thead className = "border-b border-gray-800" >
131181 < tr className = "text-left" >
132- < th className = "px-4 py-3 text-sm font-medium text-gray-300" > Applicant</ th >
133- < th className = "px-4 py-3 text-sm font-medium text-gray-300" > Contact</ th >
134- < th className = "px-4 py-3 text-sm font-medium text-gray-300" > Applied</ th >
135- < th className = "px-4 py-3 text-sm font-medium text-gray-300" > Status</ th >
136- < th className = "px-4 py-3 text-sm font-medium text-gray-300 text-right" > Actions</ th >
182+ < th className = "px-4 py-3 text-sm font-medium text-gray-300" >
183+ Applicant
184+ </ th >
185+ < th className = "px-4 py-3 text-sm font-medium text-gray-300" >
186+ Contact
187+ </ th >
188+ < th className = "px-4 py-3 text-sm font-medium text-gray-300" >
189+ Applied
190+ </ th >
191+ < th className = "px-4 py-3 text-sm font-medium text-gray-300" >
192+ Status
193+ </ th >
194+ < th className = "px-4 py-3 text-right text-sm font-medium text-gray-300" >
195+ Actions
196+ </ th >
137197 </ tr >
138198 </ thead >
139199 < tbody className = "divide-y divide-gray-800" >
@@ -155,7 +215,7 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
155215 href = { application . linkedin }
156216 target = "_blank"
157217 rel = "noopener noreferrer"
158- className = "text-xs text-gray-400 hover:text-white flex items-center gap-1 "
218+ className = "flex items-center gap-1 text-xs text-gray-400 hover:text-white"
159219 >
160220 < Linkedin className = "h-3 w-3" />
161221 </ a >
@@ -165,7 +225,7 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
165225 href = { application . github }
166226 target = "_blank"
167227 rel = "noopener noreferrer"
168- className = "text-xs text-gray-400 hover:text-white flex items-center gap-1 "
228+ className = "flex items-center gap-1 text-xs text-gray-400 hover:text-white"
169229 >
170230 < Github className = "h-3 w-3" />
171231 </ a >
@@ -175,7 +235,7 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
175235 href = { application . portfolio }
176236 target = "_blank"
177237 rel = "noopener noreferrer"
178- className = "text-xs text-gray-400 hover:text-white flex items-center gap-1 "
238+ className = "flex items-center gap-1 text-xs text-gray-400 hover:text-white"
179239 >
180240 < Globe className = "h-3 w-3" />
181241 </ a >
@@ -211,17 +271,44 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
211271 < td className = "px-4 py-3" >
212272 < Select
213273 defaultValue = { application . status }
214- onValueChange = { ( value ) => handleStatusChange ( application . id , value ) }
274+ onValueChange = { ( value ) =>
275+ handleStatusChange ( application . id , value )
276+ }
215277 >
216- < SelectTrigger className = "h-8 w-[120px] bg -gray-800 border -gray-700 text-xs text-white" >
278+ < SelectTrigger className = "h-8 w-[120px] border -gray-700 bg -gray-800 text-xs text-white" >
217279 < SelectValue className = "text-white" />
218280 </ SelectTrigger >
219- < SelectContent className = "bg-gray-800 border-gray-700 text-white" >
220- < SelectItem value = "pending" className = "text-gray-300 hover:text-white" > Pending</ SelectItem >
221- < SelectItem value = "reviewing" className = "text-gray-300 hover:text-white" > Reviewing</ SelectItem >
222- < SelectItem value = "shortlisted" className = "text-gray-300 hover:text-white" > Shortlisted</ SelectItem >
223- < SelectItem value = "rejected" className = "text-gray-300 hover:text-white" > Rejected</ SelectItem >
224- < SelectItem value = "hired" className = "text-gray-300 hover:text-white" > Hired</ SelectItem >
281+ < SelectContent className = "border-gray-700 bg-gray-800 text-white" >
282+ < SelectItem
283+ value = "pending"
284+ className = "text-gray-300 hover:text-white"
285+ >
286+ Pending
287+ </ SelectItem >
288+ < SelectItem
289+ value = "reviewing"
290+ className = "text-gray-300 hover:text-white"
291+ >
292+ Reviewing
293+ </ SelectItem >
294+ < SelectItem
295+ value = "shortlisted"
296+ className = "text-gray-300 hover:text-white"
297+ >
298+ Shortlisted
299+ </ SelectItem >
300+ < SelectItem
301+ value = "rejected"
302+ className = "text-gray-300 hover:text-white"
303+ >
304+ Rejected
305+ </ SelectItem >
306+ < SelectItem
307+ value = "hired"
308+ className = "text-gray-300 hover:text-white"
309+ >
310+ Hired
311+ </ SelectItem >
225312 </ SelectContent >
226313 </ Select >
227314 </ td >
@@ -250,34 +337,40 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
250337 < span className = "sr-only" > Open resume menu</ span >
251338 </ Button >
252339 </ DropdownMenuTrigger >
253- < DropdownMenuContent align = "end" className = "bg-gray-900 border-gray-800" >
340+ < DropdownMenuContent
341+ align = "end"
342+ className = "border-gray-800 bg-gray-900"
343+ >
254344 < DropdownMenuItem
255345 onClick = { async ( ) => {
256346 if ( application . resume_url ) {
257347 // If it's a full URL, open directly
258- if ( application . resume_url . startsWith ( 'http' ) ) {
348+ /* if (application.resume_url.startsWith('http')) {
259349 window.open(application.resume_url, '_blank');
260- } else {
261- // Otherwise, construct the Supabase storage URL
262- const supabaseUrl = process . env . NEXT_PUBLIC_SUPABASE_URL ;
263- const resumeUrl = ` ${ supabaseUrl } /storage/v1/object/public/resumes/ ${ application . resume_url } ` ;
264- window . open ( resumeUrl , '_blank' ) ;
265- }
350+ } else { */
351+ // Otherwise, construct the Supabase storage URL
352+ const supabaseUrl =
353+ process . env . NEXT_PUBLIC_SUPABASE_URL ;
354+ const resumeUrl = ` ${ supabaseUrl } /storage/v1/object/public/codebility/ ${ application . resume_url } ` ;
355+ window . open ( resumeUrl , "_blank" ) ;
266356 } else {
267357 toast ( {
268358 title : "No Resume" ,
269- description : "This applicant hasn't uploaded a resume" ,
359+ description :
360+ "This applicant hasn't uploaded a resume" ,
270361 } ) ;
271362 }
272363 } }
273- className = "text-gray-300 hover:text-white hover: bg-gray-800"
364+ className = "text-gray-300 hover:bg-gray-800 hover:text-white "
274365 >
275366 < Download className = "mr-2 h-4 w-4" />
276367 Download Resume
277368 </ DropdownMenuItem >
278369 < DropdownMenuItem
279- onClick = { ( ) => handleDeleteApplication ( application . id ) }
280- className = "text-red-400 hover:text-red-300 hover:bg-gray-800"
370+ onClick = { ( ) =>
371+ handleDeleteApplication ( application . id )
372+ }
373+ className = "text-red-400 hover:bg-gray-800 hover:text-red-300"
281374 >
282375 < Trash2 className = "mr-2 h-4 w-4" />
283376 Delete Application
@@ -298,7 +391,8 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
298391 < User className = "mb-4 h-12 w-12 text-gray-600" />
299392 < p className = "text-lg text-gray-400" > No applications yet</ p >
300393 < p className = "mt-2 text-sm text-gray-500" >
301- Applications will appear here when candidates apply for this position
394+ Applications will appear here when candidates apply for this
395+ position
302396 </ p >
303397 </ div >
304398 ) }
@@ -315,4 +409,4 @@ export default function JobApplicationsClient({ jobId, jobTitle, applications }:
315409 />
316410 </ div >
317411 ) ;
318- }
412+ }
0 commit comments