180 lines
7.0 KiB
TypeScript
180 lines
7.0 KiB
TypeScript
import { Link, useNavigate, useParams } from '@tanstack/react-router'
|
|
import { Button, Checkbox, Stack, TextInput, Text, Anchor, Alert } from "@pikku/mantine/core"
|
|
import { Controller, useForm } from "react-hook-form"
|
|
import { requestMagicLink } from "@/lib/auth"
|
|
import { pikku } from "@/pikku/http"
|
|
import { useMutation, useQueryClient } from "@tanstack/react-query"
|
|
import { useI18n } from "@/context/i18n-provider"
|
|
import { useState } from "react"
|
|
import { asI18n } from "@pikku/react"
|
|
|
|
export const StartApplication: React.FunctionComponent<{ initializing: boolean }> = ({ initializing }) => {
|
|
const navigate = useNavigate()
|
|
const params = useParams({ strict: false })
|
|
const lang = params.lang as string
|
|
const t = useI18n()
|
|
const [emailExists, setEmailExists] = useState(false)
|
|
const [existingEmail, setExistingEmail] = useState('')
|
|
const [hasError, setHasError] = useState(false)
|
|
const {
|
|
control,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm({
|
|
defaultValues: {
|
|
email: '',
|
|
fullName: '',
|
|
termsAndPrivacyAccepted: false
|
|
}
|
|
})
|
|
|
|
const queryClient = useQueryClient()
|
|
const mutation = useMutation({
|
|
mutationFn: async (data: any) => {
|
|
if (data.termsAndPrivacyAccepted && data.fullName && data.email) {
|
|
try {
|
|
await pikku().post('/candidate', {
|
|
name: data.fullName,
|
|
email: data.email
|
|
});
|
|
(window as any).fbq?.('trackCustom', 'StartApplication', {
|
|
source: 'check_my_qualification_button',
|
|
page: '/en/jobs/apply'
|
|
});
|
|
queryClient.invalidateQueries({ queryKey: ['candidate'] });
|
|
navigate({ to: `/${lang}/jobs/application` });
|
|
} catch (error: any) {
|
|
if (error.status === 409) {
|
|
setEmailExists(true)
|
|
setExistingEmail(data.email)
|
|
setHasError(false)
|
|
throw error
|
|
}
|
|
setHasError(true)
|
|
setEmailExists(false)
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
const sendMagicLinkMutation = useMutation({
|
|
mutationFn: async () => {
|
|
await requestMagicLink(existingEmail)
|
|
}
|
|
})
|
|
|
|
return (
|
|
<Stack component="form" gap="md" onSubmit={handleSubmit(data => mutation.mutateAsync(data))}>
|
|
<Controller
|
|
name="fullName"
|
|
control={control}
|
|
rules={{ required: t('jobs.startapplication.validation.fullnamerequired') }}
|
|
disabled={initializing}
|
|
render={({ field }) => (
|
|
<TextInput
|
|
id="fullName"
|
|
label={t('jobs.startapplication.fullname')}
|
|
error={errors.fullName?.message}
|
|
{...field}
|
|
/>
|
|
)}
|
|
/>
|
|
|
|
<Controller
|
|
name="email"
|
|
control={control}
|
|
rules={{
|
|
required: t('jobs.startapplication.validation.emailrequired'),
|
|
pattern: {
|
|
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
message: t('jobs.startapplication.validation.emailinvalid')
|
|
}
|
|
}}
|
|
disabled={initializing}
|
|
render={({ field }) => (
|
|
<TextInput
|
|
id="email"
|
|
type="email"
|
|
label={t('jobs.startapplication.email')}
|
|
autoComplete="email"
|
|
error={errors.email?.message}
|
|
{...field}
|
|
/>
|
|
)}
|
|
/>
|
|
|
|
<Controller
|
|
name="termsAndPrivacyAccepted"
|
|
control={control}
|
|
disabled={initializing}
|
|
rules={{ required: t('jobs.startapplication.validation.termsrequired') }}
|
|
render={({ field }) => (
|
|
<Checkbox
|
|
id="terms"
|
|
checked={field.value}
|
|
onChange={field.onChange}
|
|
disabled={field.disabled}
|
|
error={errors.termsAndPrivacyAccepted?.message}
|
|
label={
|
|
<Text size="sm">
|
|
{t('jobs.startapplication.termstext.prefix')}{asI18n(' ')}
|
|
<Anchor component={Link} to={`/${lang}/legal/terms-and-conditions`} size="sm">
|
|
{t('jobs.startapplication.termstext.terms')}
|
|
</Anchor>{asI18n(' ')}
|
|
{t('jobs.startapplication.termstext.and')}{asI18n(' ')}
|
|
<Anchor component={Link} to={`/${lang}/legal/privacy`} size="sm">
|
|
{t('jobs.startapplication.termstext.privacy')}
|
|
</Anchor>{asI18n(' ')}
|
|
{t('jobs.startapplication.termstext.suffix')}
|
|
</Text>
|
|
}
|
|
/>
|
|
)}
|
|
/>
|
|
|
|
{hasError && (
|
|
<Alert color="red" title={t('jobs.startapplication.error.title')}>
|
|
<Text size="sm">
|
|
{t('jobs.startapplication.error.message')}
|
|
</Text>
|
|
</Alert>
|
|
)}
|
|
|
|
{emailExists && (
|
|
<Alert color="blue" title={t('jobs.startapplication.emailexists.title')}>
|
|
<Text size="sm" mb="md">
|
|
{t('jobs.startapplication.emailexists.message')}
|
|
</Text>
|
|
<Button
|
|
size="sm"
|
|
variant="light"
|
|
onClick={() => sendMagicLinkMutation.mutate()}
|
|
loading={sendMagicLinkMutation.isPending}
|
|
disabled={sendMagicLinkMutation.isSuccess}
|
|
>
|
|
{sendMagicLinkMutation.isSuccess
|
|
? t('jobs.startapplication.emailexists.sent')
|
|
: t('jobs.startapplication.emailexists.button')}
|
|
</Button>
|
|
</Alert>
|
|
)}
|
|
|
|
<Stack gap="xs">
|
|
<Button
|
|
size="lg"
|
|
type="submit"
|
|
loading={mutation.isPending}
|
|
disabled={initializing || mutation.isPending}
|
|
px="xl"
|
|
>
|
|
{t('jobs.startapplication.checkqualification')}
|
|
</Button>
|
|
<Text size="sm" c="dimmed" ta="center">
|
|
{t('jobs.startapplication.freetext')}
|
|
</Text>
|
|
</Stack>
|
|
</Stack>
|
|
);
|
|
}
|