160 lines
4.3 KiB
TypeScript
160 lines
4.3 KiB
TypeScript
import { Link } from '@inertiajs/react';
|
|
import { cloneElement, isValidElement, useId, type ReactNode } from 'react';
|
|
import { Layout } from '../portfolio/shared';
|
|
|
|
export type Option = { id: string | number; name: string };
|
|
export type Territory = {
|
|
id: string;
|
|
name: string;
|
|
location_type: string;
|
|
parent_id: string | null;
|
|
};
|
|
export type Source = {
|
|
type: string;
|
|
target_id: string;
|
|
title: string;
|
|
href: string;
|
|
};
|
|
export type Catalogues = {
|
|
types: Record<string, string>;
|
|
criteria: Record<string, string>;
|
|
sectors: Option[];
|
|
territories: Territory[];
|
|
organizations: Option[];
|
|
sources?: Source[];
|
|
};
|
|
export type Partnership = {
|
|
id: number;
|
|
title: string;
|
|
status: string;
|
|
version: number;
|
|
kind: string;
|
|
partnership_type: string | null;
|
|
sector_id: number | null;
|
|
organization_id?: string | null;
|
|
deadline: string | null;
|
|
offer: string | null;
|
|
seeking: string | null;
|
|
payload: {
|
|
summary?: string;
|
|
requirements?: string;
|
|
mandatory?: string[];
|
|
confidentiality?: string;
|
|
consent?: boolean;
|
|
availability?: string;
|
|
};
|
|
};
|
|
export type Match = {
|
|
score_min: number | null;
|
|
score_max: number | null;
|
|
eligibility: string;
|
|
criteria: {
|
|
code: string;
|
|
label: string;
|
|
weight: number;
|
|
state: string;
|
|
mandatory: boolean;
|
|
evidence: string | null;
|
|
explanation: string;
|
|
}[];
|
|
};
|
|
export type Interest = {
|
|
id: number;
|
|
user_id: number;
|
|
partnership_id: number;
|
|
version: number;
|
|
proposal: string;
|
|
status: string;
|
|
decision_reason: string | null;
|
|
organization_id: string | null;
|
|
payload: {
|
|
capacity?: string;
|
|
availability?: string;
|
|
contribution?: string;
|
|
conflicts?: string;
|
|
consent?: boolean;
|
|
};
|
|
assessment: Record<string, { state: string; evidence?: string }>;
|
|
match: Match;
|
|
room_id: number | null;
|
|
};
|
|
export const labels: Record<string, string> = {
|
|
draft: 'Rascunho',
|
|
pending: 'Submetida — legado',
|
|
submitted: 'Submetida',
|
|
returned: 'Devolvida',
|
|
rejected: 'Rejeitada',
|
|
published: 'Publicada',
|
|
suspended: 'Suspensa',
|
|
archived: 'Arquivada',
|
|
withdrawn: 'Retirada',
|
|
clarification: 'Em esclarecimento',
|
|
shortlisted: 'Lista curta',
|
|
negotiation: 'Em negociação',
|
|
agreement_recorded: 'Acordo registado',
|
|
agreed: 'Confirmado pelas partes',
|
|
execution: 'Em execução',
|
|
closed: 'Concluída',
|
|
cancelled: 'Cancelada',
|
|
progress: 'Em curso',
|
|
completed: 'Concluído',
|
|
met: 'Comprovadamente cumprido',
|
|
unmet: 'Comprovadamente incumprido',
|
|
unknown: 'Informação insuficiente',
|
|
};
|
|
export const control = 'w-full rounded border bg-background p-2';
|
|
export const button =
|
|
'inline-flex rounded bg-emerald-800 px-4 py-2 text-white disabled:opacity-50';
|
|
export function Frame({
|
|
title,
|
|
children,
|
|
}: {
|
|
title: string;
|
|
children: ReactNode;
|
|
}) {
|
|
return (
|
|
<Layout title={title} mainLandmark={false}>
|
|
<nav className="mb-6 flex flex-wrap gap-5 underline">
|
|
<Link href="/parcerias">Catálogo</Link>
|
|
<Link href="/parcerias/painel">O meu painel</Link>
|
|
<Link href="/parcerias/criar">Preparar parceria</Link>
|
|
<Link href="/como-investir">Como investir</Link>
|
|
<Link href="/simulador-fiscal">
|
|
Simulador e ficha de projeto
|
|
</Link>
|
|
</nav>
|
|
{children}
|
|
</Layout>
|
|
);
|
|
}
|
|
export function Errors({ errors }: { errors: Record<string, string> }) {
|
|
return (
|
|
<>
|
|
{Object.entries(errors).map(([key, message]) => (
|
|
<p role="alert" className="text-red-700" key={key}>
|
|
{message}
|
|
</p>
|
|
))}
|
|
</>
|
|
);
|
|
}
|
|
export function Field({
|
|
label,
|
|
children,
|
|
}: {
|
|
label: string;
|
|
children: ReactNode;
|
|
}) {
|
|
const id = useId();
|
|
return (
|
|
<label className="block space-y-2">
|
|
<span id={id} className="font-medium">
|
|
{label}
|
|
</span>
|
|
{isValidElement<{ 'aria-labelledby'?: string }>(children)
|
|
? cloneElement(children, { 'aria-labelledby': id })
|
|
: children}
|
|
</label>
|
|
);
|
|
}
|