195 lines
8.3 KiB
TypeScript
195 lines
8.3 KiB
TypeScript
import { Link, useForm, usePage } from '@inertiajs/react';
|
|
import { searchTerritoryHref } from '@/lib/search-territory';
|
|
import { catalogueDetailHref } from '@/lib/catalogue-context';
|
|
import { Management } from '../management/shared';
|
|
import type { Paginated } from '../management/shared';
|
|
import { Layout, Field, control, button, Pagination, kind } from './shared';
|
|
import type { Dossier } from './shared';
|
|
import {
|
|
TerritoryFields,
|
|
type TerritoryOption,
|
|
} from '@/components/investment-territory';
|
|
export default function Index({
|
|
records,
|
|
management,
|
|
filters,
|
|
territorySelection = [],
|
|
}: {
|
|
records: Paginated<Dossier>;
|
|
management: boolean;
|
|
filters: {
|
|
q?: string;
|
|
kind?: string;
|
|
province_id?: string;
|
|
district_id?: string;
|
|
admin_post_id?: string;
|
|
locality_id?: string;
|
|
};
|
|
territorySelection?: TerritoryOption[];
|
|
}) {
|
|
const form = useForm({
|
|
q: filters.q ?? '',
|
|
kind: filters.kind ?? '',
|
|
province_id: filters.province_id ?? '',
|
|
district_id: filters.district_id ?? '',
|
|
admin_post_id: filters.admin_post_id ?? '',
|
|
locality_id: filters.locality_id ?? '',
|
|
});
|
|
const base = management ? '/management/portfolio' : '/carteira';
|
|
const { url } = usePage();
|
|
const Frame = management ? Management : Layout;
|
|
return (
|
|
<Frame title="Corredores, clusters e projectos âncora">
|
|
<p>
|
|
Explore o território, identifique os elos da cadeia de valor e
|
|
acompanhe o seu interesse numa única conta.
|
|
</p>
|
|
{management && (
|
|
<p className="rounded border border-amber-500 p-3">
|
|
Matriz documental para revisão. Rascunhos não aparecem no
|
|
portal público. Pontuações não são recomendações
|
|
personalizadas.
|
|
</p>
|
|
)}
|
|
<form
|
|
className="flex flex-wrap items-end gap-3"
|
|
onSubmit={(e) => {
|
|
e.preventDefault();
|
|
form.get(base);
|
|
}}
|
|
>
|
|
<Field label="Pesquisar">
|
|
<input
|
|
className={control}
|
|
value={form.data.q}
|
|
onChange={(e) => form.setData('q', e.target.value)}
|
|
/>
|
|
</Field>
|
|
<Field label="Explorar por">
|
|
<select
|
|
className={control}
|
|
value={form.data.kind}
|
|
onChange={(e) => form.setData('kind', e.target.value)}
|
|
>
|
|
<option value="">Toda a carteira</option>
|
|
<option value="corridor">Corredores</option>
|
|
<option value="cluster">Matriz de clusters</option>
|
|
<option value="project">Projectos âncora</option>
|
|
</select>
|
|
</Field>
|
|
<TerritoryFields
|
|
initial={territorySelection}
|
|
onChange={(path) =>
|
|
form.setData((current) => ({
|
|
...current,
|
|
province_id: path[0]?.id ?? '',
|
|
district_id: path[1]?.id ?? '',
|
|
admin_post_id: path[2]?.id ?? '',
|
|
locality_id: path[3]?.id ?? '',
|
|
}))
|
|
}
|
|
/>
|
|
<button className={button}>Pesquisar</button>
|
|
</form>
|
|
<div className="grid gap-4 md:grid-cols-2">
|
|
{records.data.map((r) => (
|
|
<article
|
|
key={r.id}
|
|
className="space-y-3 rounded-xl border p-5"
|
|
>
|
|
<p className="text-sm">
|
|
{kind(r)} · {r.content.code}
|
|
{management &&
|
|
` · ${r.publication_status === 'published' ? 'Publicado' : 'Rascunho'}`}
|
|
</p>
|
|
<h2 className="text-xl font-semibold">
|
|
<Link
|
|
className="underline"
|
|
href={catalogueDetailHref(
|
|
`${base}/${r.id}`,
|
|
new URLSearchParams(
|
|
Object.entries(filters).filter(
|
|
([, value]) => Boolean(value),
|
|
) as [string, string][],
|
|
).toString(),
|
|
)}
|
|
>
|
|
{r.title}
|
|
</Link>
|
|
</h2>
|
|
<p>
|
|
{r.content.description ??
|
|
r.content.focus ??
|
|
r.content.anchors}
|
|
</p>
|
|
{(r.content.location || r.content.region) && (
|
|
<p>
|
|
Localização:{' '}
|
|
{r.content.location ?? r.content.region}
|
|
</p>
|
|
)}
|
|
{r.content.priority && (
|
|
<p>
|
|
{r.content.priority}{' '}
|
|
<span className="text-sm">
|
|
(proposta documental)
|
|
</span>
|
|
</p>
|
|
)}
|
|
<Link
|
|
className="underline"
|
|
href={catalogueDetailHref(
|
|
`${base}/${r.id}`,
|
|
new URLSearchParams(
|
|
Object.entries(filters).filter(
|
|
([, value]) => Boolean(value),
|
|
) as [string, string][],
|
|
).toString(),
|
|
)}
|
|
>
|
|
Consultar ficha
|
|
</Link>
|
|
{!management &&
|
|
(r.corridor_id || r.cluster_id || r.project_id) && (
|
|
<Link
|
|
className="ml-4 underline"
|
|
href={searchTerritoryHref(`/oportunidades?${new URLSearchParams(r.corridor_id ? { corridor_id: r.corridor_id } : r.cluster_id ? { cluster_id: r.cluster_id } : { project_id: r.project_id! })}`, url)}
|
|
>
|
|
Ver oportunidades associadas
|
|
</Link>
|
|
)}
|
|
</article>
|
|
))}
|
|
</div>
|
|
{!records.data.length && (
|
|
<div className="space-y-3 rounded-xl border p-5" role="status">
|
|
<p>
|
|
Ainda não existem fichas publicadas para esta pesquisa.
|
|
Os filtros activos foram mantidos.
|
|
</p>
|
|
<p>
|
|
Esta lista contém dossiers territoriais documentados;
|
|
não representa concursos abertos nem confirma
|
|
disponibilidade de infra-estruturas ou incentivos.
|
|
</p>
|
|
<nav
|
|
aria-label="Alternativas de exploração"
|
|
className="flex flex-wrap gap-4"
|
|
>
|
|
<Link className="underline" href={searchTerritoryHref('/oportunidades', url)}>
|
|
Ver oportunidades publicadas
|
|
</Link>
|
|
<Link className="underline" href={searchTerritoryHref('/zonas', url)}>
|
|
Consultar ZEE, ZFI e parques
|
|
</Link>
|
|
<Link className="underline" href="/Simulador">
|
|
Transformar uma ideia num projecto
|
|
</Link>
|
|
</nav>
|
|
</div>
|
|
)}
|
|
<Pagination page={records} />
|
|
</Frame>
|
|
);
|
|
}
|