96 lines
3.5 KiB
TypeScript
96 lines
3.5 KiB
TypeScript
import { Controller, useFormContext } from 'react-hook-form'
|
|
import type { DB } from '@heygermany/sdk'
|
|
import { ApplicationCandidateData, ApplicationCandidateEducation, CandidateDocumentTypes } from '@heygermany/sdk'
|
|
import { FileUpload } from '../../ui/FileUpload'
|
|
import { useUploadCandidateFiles } from '@/hooks/useUploadCandidateFiles'
|
|
import { CandidateSection } from './CandidateSection'
|
|
import { Alert, Box, List, Text, ThemeIcon } from '@pikku/mantine/core'
|
|
import { useI18n } from '@/context/i18n-provider'
|
|
import { IconCheck, IconInfoCircle } from '@tabler/icons-react'
|
|
import { asI18n } from '@pikku/react'
|
|
|
|
export const TrainingCertificates: React.FunctionComponent<{ candidate: ApplicationCandidateData }> = ({ candidate }) => {
|
|
const t = useI18n()
|
|
const { control, trigger, formState: { errors } } = useFormContext<ApplicationCandidateEducation>()
|
|
const { uploadFiles, deleteFile } = useUploadCandidateFiles(candidate.candidateId, CandidateDocumentTypes.EDUCATION, trigger)
|
|
const uploadedEducationDocuments = [...candidate.education]
|
|
const i18n = (key: string) => t(key as any)
|
|
const educationCopy = {
|
|
title: i18n('jobs.educationdocuments.title'),
|
|
example: i18n('jobs.educationdocuments.example'),
|
|
description: i18n('jobs.educationdocuments.description'),
|
|
validationRequired: i18n('jobs.educationdocuments.validation.required'),
|
|
validationMaxFiles: i18n('jobs.educationdocuments.validation.maxfiles'),
|
|
checklistTitle: i18n('jobs.educationdocuments.checklist.title'),
|
|
checklist: [
|
|
i18n('jobs.educationdocuments.checklist.item1'),
|
|
i18n('jobs.educationdocuments.checklist.item2'),
|
|
i18n('jobs.educationdocuments.checklist.item3')
|
|
]
|
|
}
|
|
|
|
const validateEducation = (files: DB.CandidateDocument[]): string | boolean => {
|
|
if (!files || files.length === 0) {
|
|
return educationCopy.validationRequired
|
|
} else if (files.length > 10) {
|
|
return educationCopy.validationMaxFiles
|
|
}
|
|
return true
|
|
}
|
|
|
|
return (
|
|
<CandidateSection
|
|
title={educationCopy.title}
|
|
example={educationCopy.example}
|
|
description={educationCopy.description}
|
|
>
|
|
<Box>
|
|
{educationCopy.checklist.length > 0 && (
|
|
<Alert
|
|
color="blue"
|
|
mb="md"
|
|
title={asI18n(educationCopy.checklistTitle)}
|
|
icon={<IconInfoCircle size={16} />}
|
|
>
|
|
<List size="sm" spacing="xs">
|
|
{educationCopy.checklist.map((item) => (
|
|
<List.Item
|
|
key={item}
|
|
icon={
|
|
<ThemeIcon size={18} radius="xl" color="blue.6">
|
|
<IconCheck size={12} />
|
|
</ThemeIcon>
|
|
}
|
|
>
|
|
{asI18n(item)}
|
|
</List.Item>
|
|
))}
|
|
</List>
|
|
</Alert>
|
|
)}
|
|
|
|
<Controller
|
|
name="education"
|
|
control={control}
|
|
rules={{
|
|
validate: () => validateEducation(uploadedEducationDocuments)
|
|
}}
|
|
render={() => (
|
|
<Box mt="xs">
|
|
<FileUpload
|
|
files={uploadedEducationDocuments.map((file: DB.CandidateDocument) => ({ id: file.documentId, fileName: file.fileName }))}
|
|
uploadFiles={uploadFiles}
|
|
deleteFile={deleteFile}
|
|
/>
|
|
</Box>
|
|
)}
|
|
/>
|
|
|
|
{errors.education && (
|
|
<Text size="sm" c="error" mt="xs">{asI18n(errors.education.message ?? '')}</Text>
|
|
)}
|
|
</Box>
|
|
</CandidateSection>
|
|
)
|
|
}
|