import React, { useMemo, useState } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { Box, Button, Checkbox, SimpleGrid, Stack, Text } from '@pikku/mantine/core'
import type { DB } from '@heygermany/sdk'
import {
ApplicationCandidateData,
CandidateDocumentTypes,
LanguageCodes,
ProfessionalRecognitionStatuses,
} from '@heygermany/sdk'
import { useI18n } from '@/context/i18n-provider'
import { pikku } from '@/pikku/http'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { EnumSelect } from '@/components/common/EnumSelect'
import { FileUpload } from '@/components/ui/FileUpload'
import { useUploadCandidateFiles } from '@/hooks/useUploadCandidateFiles'
import { useLocation, useParams } from '@tanstack/react-router'
import { CountrySearch } from '../form/CountrySearch'
interface ApplicantProfileForm {
nationality: string
currentResidence: string
professionalRecognitionStatus: DB.ProfessionalRecognitionStatus | null
qualificationStatusGermany: DB.NurseRecognitionGermany | null
recognitionLikelihood: DB.RecognitionLikelihood | null
languagesSpoken: string[]
}
export const ApplicantProfile: React.FunctionComponent = () => {
const params = useParams({ strict: false })
const searchParams = useLocation({ select: (l) => new URLSearchParams(l.searchStr) })
const candidateIdFromUrl = params.candidateId as string | undefined
const candidateIdFromQuery = searchParams.get('candidateId')
const candidateId = candidateIdFromUrl || candidateIdFromQuery || undefined
// Fetch existing candidate data
const { data: candidate } = useQuery({
queryKey: ['candidate', candidateId],
queryFn: async () => {
if (candidateId) {
return await pikku().get('/candidate/:candidateId', { candidateId })
}
return await pikku().get('/candidate')
},
})
if (!candidate) {
return null
}
return
}
const ApplicantProfileInner: React.FunctionComponent<{ candidate: ApplicationCandidateData }> = ({ candidate }) => {
const t = useI18n()
const queryClient = useQueryClient()
const [isSaving, setIsSaving] = useState(false)
// Update mutation
const updateMutation = useMutation({
mutationFn: async (data: ApplicantProfileForm) => {
if (!candidate?.candidateId) {
throw new Error('Candidate ID not found')
}
setIsSaving(true)
// Create a minimum delay promise (2 seconds)
const minDelay = new Promise(resolve => setTimeout(resolve, 2000))
// Update candidate profile
const updatePromise = pikku().patch(`/candidate/:candidateId`, {
candidateId: candidate.candidateId,
...data,
languagesSpoken: data.languagesSpoken as DB.LanguageCode[],
})
// Wait for both the update and minimum delay
await Promise.all([updatePromise, minDelay])
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['candidate'] })
setIsSaving(false)
// Show success notification or redirect
},
onError: () => {
setIsSaving(false)
},
})
const { control, handleSubmit, trigger, formState: { errors } } = useForm({
defaultValues: {
nationality: candidate.nationality || '',
currentResidence: candidate.currentResidence || '',
professionalRecognitionStatus: candidate.professionalRecognitionStatus || null,
qualificationStatusGermany: candidate.qualificationStatusGermany || null,
recognitionLikelihood: candidate.recognitionLikelihood || null,
languagesSpoken: candidate.languagesSpoken || [],
},
})
// File upload for CV (using WORK_EXPERIENCE document type)
const { uploadFiles, deleteFile } = useUploadCandidateFiles(
candidate.candidateId,
CandidateDocumentTypes.WORK_EXPERIENCE,
trigger
)
// Available languages (sorted alphabetically, English first)
const selectEnums = t.getEnumOptions(LanguageCodes, 'languagecode')
const availableLanguages = useMemo(() => {
// English first, then sort rest alphabetically by label
const english = selectEnums.find(l => l.value === 'en')!
const others = selectEnums.filter(l => l.value !== 'en').sort((a, b) => a.label.localeCompare(b.label))
return [english, ...others]
}, [t, selectEnums])
return (
<>
{t('jobs.profile.description')}
>
)
}
export default ApplicantProfile