Files
Investidor-V2/resources/js/layouts/portal-navigation.tsx
T
2026-10-20 11:39:25 +02:00

194 lines
8.3 KiB
TypeScript

import { Link, usePage } from '@inertiajs/react';
import { createContext, useContext } from 'react';
import { PortalGroupedMenu } from '@/components/portal-grouped-menu';
import { TempoUiProvider } from '@/components/tempo-brand';
import { TempoFooter } from '@/components/tempo-footer';
import type { ReactNode } from 'react';
import {
NavigationContextProvider,
NavigationContextSummary,
} from '@/components/navigation-context';
const MenuPlacement = createContext(false);
export const portalLinks = [
['/', 'Início'],
['/oportunidades', 'Oportunidades de Investimento'],
['/educacao', 'Educação'],
['/sectores', 'Sectores Prioritários'],
['/como-investir', 'Como Investir'],
['/terra-duat', 'Terra e DUAT'],
['/legislacao', 'Legislação e Incentivos'],
['/documentos', 'Documentos e Formulários'],
['/apoio', 'Apoio ao Investidor'],
] as const;
const names: Record<string, string> = {
'/sobre': 'Sobre nós',
'/contacto': 'Contacto',
'/politica-de-privacidade': 'Política de Privacidade',
'/termos-de-uso': 'Termos de Uso',
'/porque-investir': 'Porquê investir em Moçambique',
'/investimentos/iniciar': 'Iniciar ou continuar investimento',
'/explorar/agronegocio': 'Explorar agronegócio',
'/agronegocio': 'Artigo de agronegócio',
'/investidor/negocios': 'Os meus negócios',
'/management/negocios': 'Revisão de negócios',
...Object.fromEntries(portalLinks),
'/investidor/terra-duat': 'Os meus pedidos Terra e DUAT',
'/management/terra-duat': 'Gestão de Terra e DUAT',
'/parcerias': 'Bolsa de Parcerias',
'/simulador-fiscal': 'Simulador Fiscal',
'/balcao-virtual': 'Balcão Virtual',
'/investidor/manifestacoes': 'Manifestações e favoritos',
'/investidor/profile': 'Perfil e empresas',
'/investidor/notifications': 'Notificações',
'/management/investment/references': 'Referências e formulários',
'/management/investment/zones': 'Gestão de ZEE, ZFI e parques',
'/formularios/investidor': 'Formulário de investidor',
'/formularios/empresa': 'Formulário de empresa',
'/manifestar-interesse': 'Manifestar interesse',
'/carteira': 'Corredores, clusters e projectos',
'/investidor': 'O meu painel',
'/investimentos': 'Os meus investimentos',
'/login': 'Entrar',
'/register': 'Criar conta',
'/dashboard': 'Painel',
'/acesso-gestao': 'Acesso à gestão',
'/management/portfolio': 'Carteira de investimento',
'/management/ai': 'Assistência',
'/management/interests': 'Pedidos de interesse',
'/management/portal-services': 'Documentos e parcerias',
};
export default function PortalNavigation({
children,
}: {
children: ReactNode;
}) {
const { url, props, component } = usePage();
const printable = component === 'land-assistance/print';
const portalShell =
['welcome', 'PortalInvestidor', 'management-access'].includes(
component,
) ||
[
'qa/',
'portal/',
'investment/',
'portfolio/',
'desk/',
'investor-path/',
'auth/',
'land-assistance/',
].some((prefix) => component.startsWith(prefix));
const path = url.split('?')[0];
const parent = Object.keys(names)
.filter((p) => p !== '/' && path.startsWith(`${p}/`))
.sort((a, b) => b.length - a.length)[0];
const pageProps = props as {
record?: { title?: string; name?: string };
zone?: { name?: string };
sector?: { name?: string };
initialOpportunity?: { title?: string };
};
const title =
names[path] ??
pageProps.record?.title ??
pageProps.record?.name ??
pageProps.zone?.name ??
pageProps.sector?.name ??
pageProps.initialOpportunity?.title ??
(path.includes('/edit')
? 'Editar registo'
: path.startsWith('/management')
? 'Gestão do portal'
: path.startsWith('/settings')
? 'Definições da conta'
: 'Detalhes');
return (
<TempoUiProvider>
<NavigationContextProvider>
<MenuPlacement.Provider value={true}>
<div className="min-h-screen [&_button]:scroll-mb-24 [&_input]:scroll-mb-24 [&_select]:scroll-mb-24 [&_textarea]:scroll-mb-24">
<nav
aria-label="Atalho para o conteúdo"
className={printable ? 'print:hidden' : undefined}
>
<a
href="#portal-content"
className="sr-only focus:not-sr-only focus:block focus:bg-white focus:p-4 focus:text-emerald-900"
>
Saltar para o conteúdo
</a>
</nav>
{portalShell && (
<div
className={
printable ? 'print:hidden' : undefined
}
>
<PortalMenu primary />
</div>
)}
{path !== '/' && (
<nav
aria-label="Caminho de navegação"
className={`bg-background text-foreground flex flex-wrap items-center gap-2 border-b px-5 py-3 text-sm ${printable ? 'print:hidden' : ''}`}
>
<>
<Link href="/" className="underline">
Início
</Link>
<span aria-hidden="true">/</span>
{parent && (
<>
<Link
href={parent}
className="underline"
>
{names[parent]}
</Link>
<span aria-hidden="true">/</span>
</>
)}
<span aria-current="page">{title}</span>
</>
</nav>
)}
<div id="portal-content" tabIndex={-1}>
{portalShell && (
<div
className={
printable ? 'print:hidden' : undefined
}
>
<NavigationContextSummary />
</div>
)}
{children}
</div>
<aside
aria-label="Contacto de apoio ao investidor"
className={printable ? 'print:hidden' : undefined}
>
<a
href="/apoio"
className="mx-3 mt-4 block max-w-[calc(100%-1.5rem)] rounded-xl bg-emerald-800 px-5 py-3 text-center text-sm font-semibold text-white shadow-xl focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-emerald-600"
>
Contactar Apoio ao Investidor
</a>
</aside>
<div className={printable ? 'print:hidden' : undefined}>
<TempoFooter />
</div>
</div>
</MenuPlacement.Provider>
</NavigationContextProvider>
</TempoUiProvider>
);
}
export function PortalMenu({ primary = false }: { primary?: boolean }) {
const placed = useContext(MenuPlacement);
return placed && !primary ? null : <PortalGroupedMenu />;
}