@@ -12,16 +12,21 @@ import { Plus, ArrowUpDown, SlidersHorizontal, Mail } from 'lucide-react';
1212import { use , useState } from 'react' ;
1313import useSearch from '@/lib/hooks/useSearch' ;
1414import Breadcrumbs from '@/lib/components/core/Breadcrumbs' ;
15- import { sendAssessmentInvitation } from '@/lib/api/assessments' ;
16- import { toast } from 'sonner' ;
1715
1816export default function CandidatesPage ( { params } : { params : Promise < { id : string } > } ) {
1917 const { id } = use ( params ) ;
2018 const [ isModalManualOpen , setIsModalManualOpen ] = useState ( false ) ;
2119 const [ isCSVModalOpen , setIsCSVModalOpen ] = useState ( false ) ;
22- const [ isSendingAssessments , setIsSendingAssessments ] = useState ( false ) ;
23- const { candidates, loading, error, positionTitle, createCandidate, batchCreateCandidates } =
24- useCandidates ( id ) ;
20+ const {
21+ candidates,
22+ loading,
23+ error,
24+ positionTitle,
25+ createCandidate,
26+ batchCreateCandidates,
27+ isSendingAssessments,
28+ handleSendAssessments,
29+ } = useCandidates ( id ) ;
2530 const { value : searchValue , onChange : onSearchChange } = useSearch ( 'applications' ) ;
2631
2732 const displayedCandidates = searchValue . trim ( ) . length
@@ -30,38 +35,6 @@ export default function CandidatesPage({ params }: { params: Promise<{ id: strin
3035 )
3136 : candidates ;
3237
33- const handleSendAssessments = async ( ) => {
34- try {
35- setIsSendingAssessments ( true ) ;
36- const result = await sendAssessmentInvitation ( id ) ;
37-
38- if ( result . totalSent > 0 ) {
39- toast . success (
40- `Successfully sent ${ result . totalSent } assessment invitation${ result . totalSent !== 1 ? 's' : '' } `
41- ) ;
42- }
43-
44- if ( result . totalFailed > 0 ) {
45- toast . error (
46- `Failed to send ${ result . totalFailed } invitation${ result . totalFailed !== 1 ? 's' : '' } `
47- ) ;
48- }
49-
50- if ( result . totalSent === 0 && result . totalFailed === 0 ) {
51- toast . info ( 'No candidates with pending assessments to send' ) ;
52- }
53- } catch ( err ) {
54- const errorMessage = ( err as Error ) . message ;
55- if ( errorMessage . includes ( 'does not have an assessment template assigned' ) ) {
56- toast . error ( 'This position does not have an assessment template assigned' ) ;
57- } else {
58- toast . error ( errorMessage || 'Failed to send assessment invitations' ) ;
59- }
60- } finally {
61- setIsSendingAssessments ( false ) ;
62- }
63- } ;
64-
6538 return (
6639 < >
6740 < div className = "flex max-h-screen flex-col gap-8 px-8 py-7 pb-20" >
@@ -128,28 +101,15 @@ export default function CandidatesPage({ params }: { params: Promise<{ id: strin
128101 </ TabsContent >
129102
130103 < TabsContent value = "assessment" >
131- < div className = "border-sarge-gray-200 flex items-center justify-between self-stretch rounded-lg border bg-white p-4" >
132- < div className = "flex flex-col gap-3" >
133- < span className = "text-sarge-gray-800 overflow-hidden text-lg leading-6 font-medium tracking-wide text-ellipsis" >
134- Software Engineer Assessment
135- </ span >
136- < div className = "flex items-center gap-3" >
137- < Chip variant = "neutral" > 10/10 sent</ Chip >
138- < Chip variant = "neutral" > 0/10 submitted</ Chip >
139- </ div >
140- </ div >
141- < div className = "flex items-end gap-3" >
142- < Button
143- className = "px-4 py-3"
144- onClick = { handleSendAssessments }
145- disabled = { isSendingAssessments }
146- >
147- < Mail className = "size-5" />
148- { isSendingAssessments
149- ? 'Sending...'
150- : 'Send to all candidates' }
151- </ Button >
152- </ div >
104+ < div className = "flex w-full justify-end" >
105+ < Button
106+ className = "px-4 py-3"
107+ onClick = { handleSendAssessments }
108+ disabled = { isSendingAssessments }
109+ >
110+ < Mail className = "size-5" />
111+ { isSendingAssessments ? 'Sending...' : 'Send to all candidates' }
112+ </ Button >
153113 </ div >
154114 </ TabsContent >
155115 </ Tabs >
0 commit comments