Integrar navbar e sobre dos programadores preservando identidade e acessos
This commit is contained in:
+62
-10
@@ -301,23 +301,42 @@
|
||||
}
|
||||
}
|
||||
@media (min-width: 1280px) {
|
||||
.tempo-header-inner {
|
||||
display: flex;
|
||||
min-height: 88px;
|
||||
gap: 0.75rem;
|
||||
/* Shared columns keep each portal area below its institutional link. */
|
||||
.tempo-header-layout {
|
||||
display: grid;
|
||||
grid-template-columns: auto repeat(4, max-content) minmax(0, 1fr) auto;
|
||||
column-gap: 0.25rem;
|
||||
max-width: 1440px;
|
||||
margin-inline: auto;
|
||||
padding-inline: 2rem;
|
||||
}
|
||||
.tempo-header-inner {
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: subgrid;
|
||||
min-height: 88px;
|
||||
column-gap: normal;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.tempo-logo-link {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
.tempo-header-logo {
|
||||
height: 64px;
|
||||
}
|
||||
.tempo-header[data-expanded] .tempo-primary-navigation,
|
||||
.tempo-primary-navigation {
|
||||
display: block;
|
||||
flex: 1;
|
||||
display: grid;
|
||||
grid-area: 1 / 2 / 2 / 6;
|
||||
grid-template-columns: subgrid;
|
||||
border: 0;
|
||||
}
|
||||
.tempo-primary-navigation > ul {
|
||||
justify-content: center;
|
||||
gap: 0.25rem;
|
||||
display: grid;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: subgrid;
|
||||
gap: normal;
|
||||
padding: 0;
|
||||
}
|
||||
.tempo-nav-trigger {
|
||||
@@ -332,6 +351,8 @@
|
||||
}
|
||||
.tempo-header-extras {
|
||||
display: flex;
|
||||
grid-area: 1 / 6;
|
||||
justify-self: end;
|
||||
flex-shrink: 0;
|
||||
padding: 0 0.75rem;
|
||||
border-top: 0;
|
||||
@@ -347,16 +368,47 @@
|
||||
.tempo-header-toggle {
|
||||
display: none;
|
||||
}
|
||||
.tempo-header-actions {
|
||||
grid-area: 1 / 7;
|
||||
}
|
||||
.tempo-section-bar {
|
||||
display: grid;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: subgrid;
|
||||
}
|
||||
.tempo-section-inner {
|
||||
padding-inline: 2rem;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: subgrid;
|
||||
gap: normal;
|
||||
max-width: none;
|
||||
margin: 0;
|
||||
padding-inline: 0;
|
||||
}
|
||||
.tempo-section-navigation {
|
||||
display: grid;
|
||||
grid-area: 1 / 2 / 2 / 5;
|
||||
grid-template-columns: subgrid;
|
||||
}
|
||||
.tempo-section-navigation > ul {
|
||||
display: grid;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: subgrid;
|
||||
gap: normal;
|
||||
}
|
||||
.tempo-section-navigation .tempo-nav-trigger {
|
||||
padding-inline: 1.25rem;
|
||||
padding-inline: 0.625rem;
|
||||
}
|
||||
.tempo-primary-navigation .tempo-nav-trigger,
|
||||
.tempo-section-navigation .tempo-nav-trigger {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.tempo-interest-button {
|
||||
padding-inline: 0.85rem;
|
||||
font-size: 0.8125rem;
|
||||
}
|
||||
.tempo-section-inner .tempo-interest-button {
|
||||
grid-area: 1 / 6 / 2 / -1;
|
||||
}
|
||||
}
|
||||
.tempo-header :is(a, button):focus-visible {
|
||||
outline: 2px solid #fff;
|
||||
|
||||
@@ -127,223 +127,237 @@ export function PortalGroupedMenu() {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="tempo-header-inner">
|
||||
<Link
|
||||
href="/"
|
||||
aria-label="InvesteMoz — início"
|
||||
className="tempo-logo-link"
|
||||
>
|
||||
<PortalProductIdentity />
|
||||
</Link>
|
||||
<nav
|
||||
id={institutionalId}
|
||||
aria-label="Navegação institucional"
|
||||
className="tempo-primary-navigation"
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<Link
|
||||
href="/"
|
||||
className="tempo-nav-trigger"
|
||||
aria-current={
|
||||
url.split('?')[0] === '/'
|
||||
? 'page'
|
||||
: undefined
|
||||
}
|
||||
data-current-group={
|
||||
url.split('?')[0] === '/' || undefined
|
||||
}
|
||||
>
|
||||
{t('Início')}
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://revista.tempo.co.mz/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="tempo-nav-trigger"
|
||||
aria-label={`${t('Revista Tempo')} — ${t('Abre num novo separador')}`}
|
||||
>
|
||||
{t('Revista Tempo')}
|
||||
<ArrowUpRight size={14} aria-hidden="true" />
|
||||
</a>
|
||||
</li>
|
||||
{[
|
||||
['/sobre', 'Sobre nós'],
|
||||
['/contacto', 'Contacto'],
|
||||
].map(([href, label]) => (
|
||||
<li key={href}>
|
||||
<div className="tempo-header-layout">
|
||||
<div className="tempo-header-inner">
|
||||
<Link
|
||||
href="/"
|
||||
aria-label="InvesteMoz — início"
|
||||
className="tempo-logo-link"
|
||||
>
|
||||
<PortalProductIdentity />
|
||||
</Link>
|
||||
<nav
|
||||
id={institutionalId}
|
||||
aria-label="Navegação institucional"
|
||||
className="tempo-primary-navigation"
|
||||
>
|
||||
<ul>
|
||||
<li>
|
||||
<Link
|
||||
href={href}
|
||||
href="/"
|
||||
className="tempo-nav-trigger"
|
||||
aria-current={
|
||||
url.split('?')[0] === href
|
||||
url.split('?')[0] === '/'
|
||||
? 'page'
|
||||
: undefined
|
||||
}
|
||||
data-current-group={
|
||||
url.split('?')[0] === href || undefined
|
||||
url.split('?')[0] === '/' || undefined
|
||||
}
|
||||
>
|
||||
{t(label)}
|
||||
{t('Início')}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
<div id={toolsId} className="tempo-header-extras">
|
||||
<div className="tempo-header-utilities">
|
||||
<div className="flex items-center gap-1">
|
||||
<TempoWeather />
|
||||
<TempoLanguageSelector />
|
||||
</div>
|
||||
<TempoSocialLinks />
|
||||
</div>
|
||||
</div>
|
||||
<div className="tempo-header-actions">
|
||||
{props.auth?.user ? (
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger className="tempo-login-button">
|
||||
<UserRound size={16} aria-hidden="true" />
|
||||
<span className="max-w-24 truncate">
|
||||
{props.auth.user.name || t('A minha área')}
|
||||
</span>
|
||||
<ChevronDown size={12} aria-hidden="true" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
sideOffset={12}
|
||||
collisionPadding={12}
|
||||
className="tempo-dropdown max-h-[75vh] w-72 max-w-[calc(100vw-1.5rem)] overflow-y-auto p-2"
|
||||
>
|
||||
<DropdownMenuLabel className="truncate text-xs text-slate-500">
|
||||
{props.auth.user.email}
|
||||
</DropdownMenuLabel>
|
||||
{items(accountGroups)}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
asChild
|
||||
className="tempo-menu-item text-red-700"
|
||||
<li>
|
||||
<a
|
||||
href="https://revista.tempo.co.mz/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="tempo-nav-trigger"
|
||||
aria-label={`${t('Revista Tempo')} — ${t('Abre num novo separador')}`}
|
||||
>
|
||||
{t('Revista Tempo')}
|
||||
<ArrowUpRight
|
||||
size={14}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
{[
|
||||
['/sobre', 'Sobre nós'],
|
||||
['/contacto', 'Contacto'],
|
||||
].map(([href, label]) => (
|
||||
<li key={href}>
|
||||
<Link
|
||||
href={logout()}
|
||||
as="button"
|
||||
type="button"
|
||||
disabled={loggingOut}
|
||||
data-test="portal-logout-button"
|
||||
onClick={() => router.flushAll()}
|
||||
onStart={() => setLoggingOut(true)}
|
||||
onFinish={() => setLoggingOut(false)}
|
||||
href={href}
|
||||
className="tempo-nav-trigger"
|
||||
aria-current={
|
||||
url.split('?')[0] === href
|
||||
? 'page'
|
||||
: undefined
|
||||
}
|
||||
data-current-group={
|
||||
url.split('?')[0] === href ||
|
||||
undefined
|
||||
}
|
||||
>
|
||||
<LogOut size={16} aria-hidden="true" />
|
||||
{loggingOut
|
||||
? 'A terminar sessão…'
|
||||
: t('Terminar sessão')}
|
||||
{t(label)}
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<Link href="/login" className="tempo-login-button">
|
||||
<UserRound size={15} aria-hidden="true" />
|
||||
{t('Entrar')}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
ref={toggle}
|
||||
type="button"
|
||||
className="tempo-header-toggle"
|
||||
aria-label={
|
||||
expanded
|
||||
? 'Fechar menu e ferramentas'
|
||||
: 'Abrir menu e ferramentas'
|
||||
}
|
||||
aria-expanded={expanded}
|
||||
aria-controls={`${institutionalId} ${toolsId}`}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
>
|
||||
{expanded ? (
|
||||
<X size={22} aria-hidden="true" />
|
||||
) : (
|
||||
<Menu size={22} aria-hidden="true" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className="tempo-section-bar">
|
||||
<div className="tempo-section-inner">
|
||||
<Link
|
||||
href="/investidor/manifestacoes"
|
||||
className="tempo-panel-summary"
|
||||
>
|
||||
<span>{t('O meu painel')}</span>
|
||||
<span
|
||||
className="tempo-panel-count"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>
|
||||
{requestCount}{' '}
|
||||
{t(
|
||||
requestCount === 1
|
||||
? 'pedido recebido'
|
||||
: 'pedidos recebidos',
|
||||
)}
|
||||
</span>
|
||||
</Link>
|
||||
<nav
|
||||
aria-label="Áreas do portal"
|
||||
className="tempo-section-navigation"
|
||||
>
|
||||
<ul>
|
||||
{groups
|
||||
.filter((group) =>
|
||||
[
|
||||
'discovery',
|
||||
'realization',
|
||||
'support',
|
||||
].includes(group.id),
|
||||
)
|
||||
.map((group) => (
|
||||
<li key={group.id}>
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger
|
||||
className="tempo-nav-trigger"
|
||||
data-current-group={
|
||||
current === group.id ||
|
||||
undefined
|
||||
}
|
||||
>
|
||||
{t(group.label)}
|
||||
<ChevronDown
|
||||
size={14}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{current === group.id && (
|
||||
<span className="sr-only">
|
||||
Grupo actual
|
||||
</span>
|
||||
)}
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="start"
|
||||
sideOffset={8}
|
||||
collisionPadding={12}
|
||||
className="tempo-dropdown max-h-[min(75vh,36rem)] w-72 max-w-[calc(100vw-1.5rem)] overflow-y-auto p-2"
|
||||
>
|
||||
{items(group.children ?? [])}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</li>
|
||||
))}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
<Link
|
||||
href="/manifestar-interesse"
|
||||
className="tempo-interest-button"
|
||||
<div id={toolsId} className="tempo-header-extras">
|
||||
<div className="tempo-header-utilities">
|
||||
<div className="flex items-center gap-1">
|
||||
<TempoWeather />
|
||||
<TempoLanguageSelector />
|
||||
</div>
|
||||
<TempoSocialLinks />
|
||||
</div>
|
||||
</div>
|
||||
<div className="tempo-header-actions">
|
||||
{props.auth?.user ? (
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger className="tempo-login-button">
|
||||
<UserRound size={16} aria-hidden="true" />
|
||||
<span className="max-w-24 truncate">
|
||||
{props.auth.user.name ||
|
||||
t('A minha área')}
|
||||
</span>
|
||||
<ChevronDown size={12} aria-hidden="true" />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
sideOffset={12}
|
||||
collisionPadding={12}
|
||||
className="tempo-dropdown max-h-[75vh] w-72 max-w-[calc(100vw-1.5rem)] overflow-y-auto p-2"
|
||||
>
|
||||
<DropdownMenuLabel className="truncate text-xs text-slate-500">
|
||||
{props.auth.user.email}
|
||||
</DropdownMenuLabel>
|
||||
{items(accountGroups)}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem
|
||||
asChild
|
||||
className="tempo-menu-item text-red-700"
|
||||
>
|
||||
<Link
|
||||
href={logout()}
|
||||
as="button"
|
||||
type="button"
|
||||
disabled={loggingOut}
|
||||
data-test="portal-logout-button"
|
||||
onClick={() => router.flushAll()}
|
||||
onStart={() => setLoggingOut(true)}
|
||||
onFinish={() =>
|
||||
setLoggingOut(false)
|
||||
}
|
||||
>
|
||||
<LogOut
|
||||
size={16}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{loggingOut
|
||||
? 'A terminar sessão…'
|
||||
: t('Terminar sessão')}
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<Link href="/login" className="tempo-login-button">
|
||||
<UserRound size={15} aria-hidden="true" />
|
||||
{t('Entrar')}
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
ref={toggle}
|
||||
type="button"
|
||||
className="tempo-header-toggle"
|
||||
aria-label={
|
||||
expanded
|
||||
? 'Fechar menu e ferramentas'
|
||||
: 'Abrir menu e ferramentas'
|
||||
}
|
||||
aria-expanded={expanded}
|
||||
aria-controls={`${institutionalId} ${toolsId}`}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
>
|
||||
{t('Manifestar interesse')}
|
||||
</Link>
|
||||
{expanded ? (
|
||||
<X size={22} aria-hidden="true" />
|
||||
) : (
|
||||
<Menu size={22} aria-hidden="true" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className="tempo-section-bar">
|
||||
<div className="tempo-section-inner">
|
||||
<Link
|
||||
href="/investidor/manifestacoes"
|
||||
className="tempo-panel-summary"
|
||||
>
|
||||
<span>{t('O meu painel')}</span>
|
||||
<span
|
||||
className="tempo-panel-count"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>
|
||||
{requestCount}{' '}
|
||||
{t(
|
||||
requestCount === 1
|
||||
? 'pedido recebido'
|
||||
: 'pedidos recebidos',
|
||||
)}
|
||||
</span>
|
||||
</Link>
|
||||
<nav
|
||||
aria-label="Áreas do portal"
|
||||
className="tempo-section-navigation"
|
||||
>
|
||||
<ul>
|
||||
{groups
|
||||
.filter((group) =>
|
||||
[
|
||||
'discovery',
|
||||
'realization',
|
||||
'support',
|
||||
].includes(group.id),
|
||||
)
|
||||
.map((group) => (
|
||||
<li key={group.id}>
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger
|
||||
className="tempo-nav-trigger"
|
||||
data-current-group={
|
||||
current === group.id ||
|
||||
undefined
|
||||
}
|
||||
>
|
||||
{t(group.label)}
|
||||
<ChevronDown
|
||||
size={14}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
{current === group.id && (
|
||||
<span className="sr-only">
|
||||
Grupo actual
|
||||
</span>
|
||||
)}
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="start"
|
||||
sideOffset={8}
|
||||
collisionPadding={12}
|
||||
className="tempo-dropdown max-h-[min(75vh,36rem)] w-72 max-w-[calc(100vw-1.5rem)] overflow-y-auto p-2"
|
||||
>
|
||||
{items(
|
||||
group.children ?? [],
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</nav>
|
||||
<Link
|
||||
href="/manifestar-interesse"
|
||||
className="tempo-interest-button"
|
||||
>
|
||||
{t('Manifestar interesse')}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -5,7 +5,6 @@ import { AboutStory } from '@/components/institutional-source/AboutStory';
|
||||
import { MissionVision } from '@/components/institutional-source/MissionVision';
|
||||
import { CompanyValues } from '@/components/institutional-source/CompanyValues';
|
||||
import BackButton from '@/components/institutional-source/BackButton';
|
||||
import { AdvertisementSlot } from '@/components/institutional-source/source-advertisement-slot';
|
||||
|
||||
const AboutPage: React.FC = () => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
@@ -45,29 +44,11 @@ const AboutPage: React.FC = () => {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<AdvertisementSlot
|
||||
page="about"
|
||||
position="top"
|
||||
slot="about_top"
|
||||
limit={1}
|
||||
fallbackToUnslotted
|
||||
className=""
|
||||
/>
|
||||
|
||||
<div className="text-white">
|
||||
<AboutStory />
|
||||
<MissionVision />
|
||||
<CompanyValues />
|
||||
</div>
|
||||
|
||||
<AdvertisementSlot
|
||||
page="about"
|
||||
position="bottom"
|
||||
slot="about_bottom"
|
||||
limit={2}
|
||||
fallbackToUnslotted
|
||||
className="py-4"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user