Files
Investidor-V2/resources/js/pages/procurement/index.tsx
T

197 lines
7.7 KiB
TypeScript

import { Link, useForm } from '@inertiajs/react';
import { Frame, card, button } from '@/pages/investment/shared';
import { Field, control, states, type Publication } from './shared';
type Choice = { id: string; name: string };
export default function Index({
items,
filters,
options,
regimes,
management,
}: {
items: {
data: { id: string; publication: Publication; state: string }[];
current_page: number;
links: { url: string | null; label: string; active: boolean }[];
};
filters: Record<string, string>;
options: Record<string, Choice[]>;
regimes: Record<string, string>;
management: boolean;
}) {
const form = useForm({
q: filters.q ?? '',
entity: filters.entity ?? '',
sector: filters.sector ?? '',
territory: filters.territory ?? '',
modality: filters.modality ?? '',
financier: filters.financier ?? '',
state: filters.state ?? '',
deadline_before: filters.deadline_before ?? '',
regime: filters.regime ?? '',
});
const query = new URLSearchParams(
Object.entries({ ...filters, page: String(items.current_page) }).filter(
([, v]) => v != null && v !== '',
),
).toString();
return (
<Frame title="Concursos e anúncios">
<p>
Procedimentos e actos divulgados pelas entidades responsáveis.
Uma oportunidade divulgada não é, por si, um concurso aberto.
</p>
<div className="flex flex-wrap gap-3">
<Link className="underline" href="/concursos/acompanhar">
Os concursos que acompanho
</Link>
{management && (
<Link className={button} href="/management/concursos">
Gerir concursos e anúncios
</Link>
)}
</div>
<form
className={`${card} grid gap-3 md:grid-cols-3`}
onSubmit={(e) => {
e.preventDefault();
form.get('/concursos', { preserveState: true });
}}
>
<Field label="Palavras-chave">
<input
className={control}
value={form.data.q}
onChange={(e) => form.setData('q', e.target.value)}
/>
</Field>
{(
[
'entity',
'sector',
'territory',
'modality',
'financier',
] as const
).map((key) => (
<Field
key={key}
label={
{
entity: 'Entidade',
sector: 'Sector',
territory: 'Localização',
modality: 'Modalidade',
financier: 'Financiador',
}[key]
}
>
<select
className={control}
value={form.data[key]}
onChange={(e) => form.setData(key, e.target.value)}
>
<option value="">Todos</option>
{(options[key] ?? []).map((o) => (
<option key={o.id} value={o.id}>
{o.name}
</option>
))}
</select>
</Field>
))}
<Field label="Regime">
<select
className={control}
value={form.data.regime}
onChange={(e) => form.setData('regime', e.target.value)}
>
<option value="">Todos</option>
{Object.entries(regimes).map(([v, l]) => (
<option key={v} value={v}>
{l}
</option>
))}
</select>
</Field>
<Field label="Estado">
<select
className={control}
value={form.data.state}
onChange={(e) => form.setData('state', e.target.value)}
>
<option value="">Todos</option>
{Object.entries(states).map(([v, l]) => (
<option key={v} value={v}>
{l}
</option>
))}
</select>
</Field>
<Field label="Prazo até (data local do procedimento)">
<input
className={control}
type="date"
value={form.data.deadline_before}
onChange={(e) =>
form.setData('deadline_before', e.target.value)
}
/>
</Field>
<button className={button}>Pesquisar</button>
</form>
{!items.data.length && (
<p role="status">Nenhum anúncio corresponde aos filtros.</p>
)}
<div className="grid gap-4 md:grid-cols-2">
{items.data.map((item) => (
<article key={item.id} className={card}>
<h2 className="text-xl font-semibold">
<Link
className="underline"
href={`/concursos/${item.id}${query ? '?' + query : ''}`}
>
{String(item.publication.payload.title)}
</Link>
</h2>
<p>
{String(item.publication.payload.organization_name)}{' '}
· {states[item.state]}
</p>
<p>
Entrega:{' '}
{String(item.publication.payload.deadline).replace(
'T',
' ',
)}{' '}
· {String(item.publication.payload.timezone)}
</p>
<p>{String(item.publication.payload.object)}</p>
</article>
))}
</div>
<nav aria-label="Paginação">
{items.links.map((link, i) =>
link.url ? (
<Link
key={i}
className={`mx-2 underline ${link.active ? 'font-bold' : ''}`}
href={link.url}
>
{link.label
.replace('&laquo;', '«')
.replace('&raquo;', '»')}
</Link>
) : (
<span key={i} className="mx-2">
{link.label
.replace('&laquo;', '«')
.replace('&raquo;', '»')}
</span>
),
)}
</nav>
</Frame>
);
}