176 lines
6.0 KiB
TypeScript
176 lines
6.0 KiB
TypeScript
import { useState } from 'react';
|
|
import { ArrowRight } from 'lucide-react';
|
|
import {
|
|
HOME_SECTION,
|
|
HOME_SECTION_HEADING,
|
|
PORTAL_MORE_LINK,
|
|
} from '@/lib/portal-presentation';
|
|
|
|
const contexts = [
|
|
{
|
|
key: 'clusters',
|
|
href: '/clusters',
|
|
title: 'Clusters',
|
|
description: 'Cadeias de valor e lacunas produtivas.',
|
|
image: 'clusters-agroindustria',
|
|
alt: 'Triagem de produtos agrícolas numa unidade de transformação com área de cultivo ao fundo.',
|
|
},
|
|
{
|
|
key: 'corredores',
|
|
href: '/corredores',
|
|
title: 'Corredores',
|
|
description: 'Territórios, logística e conexões.',
|
|
image: 'corredores-logisticos-v2',
|
|
alt: 'Terminal de mercadorias junto à água, com contentores, uma grua e vias de acesso.',
|
|
},
|
|
{
|
|
key: 'projectos',
|
|
href: '/projectos-ancora',
|
|
title: 'Projectos âncora',
|
|
description: 'Projectos estruturantes e relações.',
|
|
image: 'projectos-ancora',
|
|
alt: 'Equipa de engenharia acompanha o planeamento de uma instalação de energia solar.',
|
|
},
|
|
{
|
|
key: 'educacao',
|
|
href: '/educacao',
|
|
title: 'Educação',
|
|
description: 'Investimentos em competências e formação.',
|
|
image: 'educacao-formacao',
|
|
alt: 'Jovens desenvolvem competências de electrónica e informática numa aula de formação técnica.',
|
|
},
|
|
{
|
|
key: 'documentos',
|
|
href: '/documentos',
|
|
title: 'Documentos e Formulários',
|
|
description:
|
|
'Legislação, procedimentos, formulários e materiais de apoio.',
|
|
image: 'documentos-formularios',
|
|
alt: 'Profissional analisa documentação empresarial organizada numa secretária de escritório.',
|
|
},
|
|
];
|
|
|
|
function ContextImage({
|
|
image,
|
|
alt,
|
|
preview,
|
|
}: {
|
|
image: string;
|
|
alt: string;
|
|
preview: boolean;
|
|
}) {
|
|
const [fallback, setFallback] = useState(0);
|
|
const base = `/images/investment-context/${image}`;
|
|
|
|
return (
|
|
<div className="aspect-video w-full shrink-0 overflow-hidden bg-slate-100">
|
|
{fallback < 2 ? (
|
|
<img
|
|
src={`${base}${fallback ? '-fallback' : ''}.webp`}
|
|
srcSet={
|
|
fallback
|
|
? undefined
|
|
: `${base}-480.webp 480w, ${base}.webp 960w`
|
|
}
|
|
sizes={
|
|
preview
|
|
? '(min-width: 1152px) 266px, (min-width: 1024px) 25vw, (min-width: 640px) 50vw, 100vw'
|
|
: '(min-width: 1152px) 357px, (min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw'
|
|
}
|
|
alt={alt}
|
|
width={960}
|
|
height={540}
|
|
loading="lazy"
|
|
decoding="async"
|
|
className="h-full w-full object-cover object-center"
|
|
onError={() =>
|
|
setFallback((current) => Math.min(current + 1, 2))
|
|
}
|
|
/>
|
|
) : (
|
|
<span
|
|
role="img"
|
|
aria-label={alt}
|
|
className="flex h-full items-center justify-center px-5 text-center text-sm text-slate-600"
|
|
>
|
|
Imagem indisponível
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function InvestmentContextGrid({
|
|
preview = false,
|
|
}: {
|
|
preview?: boolean;
|
|
}) {
|
|
const visibleContexts = preview ? contexts.slice(0, 4) : contexts;
|
|
|
|
return (
|
|
<nav
|
|
aria-label="Contextos de investimento"
|
|
className={
|
|
preview
|
|
? 'grid gap-4 sm:grid-cols-2 lg:grid-cols-4'
|
|
: 'grid gap-5 sm:grid-cols-2 lg:grid-cols-3'
|
|
}
|
|
>
|
|
{visibleContexts.map((context) => (
|
|
<a
|
|
key={context.key}
|
|
href={context.href}
|
|
aria-labelledby={`context-${context.key}-title`}
|
|
aria-describedby={`context-${context.key}-description`}
|
|
className="flex h-full min-w-0 flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm transition-colors hover:border-blue-700 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-blue-700"
|
|
>
|
|
<ContextImage
|
|
image={context.image}
|
|
alt={context.alt}
|
|
preview={preview}
|
|
/>
|
|
<div className="flex flex-1 flex-col gap-1.5 p-4">
|
|
<h3
|
|
id={`context-${context.key}-title`}
|
|
className="text-lg leading-6 font-bold text-slate-900"
|
|
>
|
|
{context.title}
|
|
</h3>
|
|
<p
|
|
id={`context-${context.key}-description`}
|
|
className="text-sm leading-5 text-slate-600"
|
|
>
|
|
{context.description}
|
|
</p>
|
|
</div>
|
|
</a>
|
|
))}
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
export default function InvestmentContextCards() {
|
|
return (
|
|
<section
|
|
aria-labelledby="investment-context-heading"
|
|
className={`${HOME_SECTION} space-y-4`}
|
|
>
|
|
<h2
|
|
id="investment-context-heading"
|
|
className={HOME_SECTION_HEADING}
|
|
>
|
|
Encontre o contexto do seu investimento
|
|
</h2>
|
|
<InvestmentContextGrid preview />
|
|
<div className="flex justify-center">
|
|
<a
|
|
href="/contextos-de-investimento"
|
|
className={PORTAL_MORE_LINK}
|
|
>
|
|
Ver mais <ArrowRight size={14} aria-hidden="true" />
|
|
</a>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|