Files
compras/resources/js/pages/candidate/profile.tsx
T
nala c6373365bf
tests / ci (push) Canceled after 0s
commit9
2026-10-30 20:02:30 +02:00

218 lines
8.8 KiB
TypeScript

import { Head, Link, router, useForm } from '@inertiajs/react';
import { FormErrors, controlClass } from '@/components/procurement';
import { Button } from '@/components/ui/button';
type Data = {
name: string;
phone: string | null;
summary: string;
availability: { province: string; district: string; locality: string };
};
export default function Profile({
companyId,
email,
profile,
emailVerified = false,
emailDeliveryAvailable = false,
accessStatus,
opportunities = [],
submissions = [],
}: {
companyId: number;
email: string;
profile: { version: number; data: Data };
emailVerified?: boolean;
emailDeliveryAvailable?: boolean;
accessStatus?: string | null;
opportunities?: { id: number; title: string; closes_on: string }[];
submissions?: { id: number; reference: string; created_at: string }[];
}) {
const form = useForm({
version: profile.version,
...profile.data,
phone: profile.data.phone ?? '',
reason: '',
});
return (
<>
<Head title="O meu perfil" />
<section className="mx-auto max-w-3xl space-y-3 p-6">
<h2 className="text-xl font-semibold">
Oportunidades publicadas
</h2>
{opportunities.map((item) => (
<p key={item.id}>
<Link
className="underline"
href={`/candidaturas/${companyId}/oportunidades/${item.id}`}
>
{item.title} · {item.closes_on}
</Link>
</p>
))}
<h2 className="text-xl font-semibold">
As minhas candidaturas
</h2>
{submissions.map((item) => (
<p key={item.id}>
<Link
className="underline"
href={`/candidaturas/${companyId}/submissoes/${item.id}`}
>
{item.reference} · {item.created_at}
</Link>
</p>
))}
</section>
<main className="mx-auto max-w-3xl space-y-6 p-6">
<p>SGC · Área do candidato</p>
<h1 className="text-3xl font-semibold">O meu perfil</h1>
<p>
{email} · versão {profile.version}
</p>
<p>
{emailVerified
? 'Email confirmado. A identidade ainda depende de verificação própria.'
: 'Email ainda não confirmado. A entrada comprova apenas o acesso à conta.'}{' '}
Pode candidatar-se às oportunidades publicadas. O envio de
anexos ainda está em desenvolvimento.
</p>
{!emailVerified && (
<Button
variant="outline"
disabled={!emailDeliveryAvailable}
onClick={() =>
router.post(
`/candidaturas/${companyId}/pedir-confirmacao`,
)
}
>
Pedir confirmação do email
</Button>
)}
{!emailVerified && !emailDeliveryAvailable && (
<p>
O envio de email ainda não está configurado; pode
continuar a preparar o perfil.
</p>
)}
{accessStatus === 'requested' && (
<p>
Se o envio estiver disponível, receberá uma ligação
temporária de confirmação.
</p>
)}
<form
className="space-y-4"
onSubmit={(e) => {
e.preventDefault();
form.post(`/candidaturas/${companyId}/perfil`, {
preserveScroll: true,
preserveState: false,
});
}}
>
<FormErrors errors={form.errors} />
<label className="grid gap-2">
Nome completo
<input
className={controlClass}
required
minLength={3}
maxLength={200}
value={form.data.name}
onChange={(e) =>
form.setData('name', e.target.value)
}
/>
</label>
<label className="grid gap-2">
Telefone
<input
className={controlClass}
maxLength={50}
value={form.data.phone}
onChange={(e) =>
form.setData('phone', e.target.value)
}
/>
</label>
<label className="grid gap-2">
Resumo profissional
<textarea
className={controlClass}
required
minLength={10}
maxLength={5000}
value={form.data.summary}
onChange={(e) =>
form.setData('summary', e.target.value)
}
/>
</label>
<fieldset className="grid gap-3 sm:grid-cols-3">
<legend>
Local de disponibilidade para trabalhar ou prestar
serviço
</legend>
{(['province', 'district', 'locality'] as const).map(
(key) => (
<label className="grid gap-2" key={key}>
{
{
province: 'Província',
district: 'Distrito',
locality: 'Localidade',
}[key]
}
<input
className={controlClass}
required
maxLength={150}
value={form.data.availability[key]}
onChange={(e) =>
form.setData('availability', {
...form.data.availability,
[key]: e.target.value,
})
}
/>
</label>
),
)}
</fieldset>
<p className="text-sm">
Disponibilidade é distinta da morada. Actualizar o
perfil cria uma versão para usos futuros, preservando as
anteriores.
</p>
<label className="grid gap-2">
Motivo da actualização
<textarea
className={controlClass}
required
minLength={10}
maxLength={4000}
value={form.data.reason}
onChange={(e) =>
form.setData('reason', e.target.value)
}
/>
</label>
<Button disabled={form.processing}>
Guardar nova versão do perfil
</Button>
</form>
<Button
variant="outline"
onClick={() =>
router.post(`/candidaturas/${companyId}/sair`)
}
>
Sair da área do candidato
</Button>
</main>
</>
);
}