Files
Investidor-V2/resources/js/components/tempo-header-tools.tsx
T
paulomassigue 14ad2f60c5
tests / ci (push) Canceled after 0s
header:navbar e footer
2026-10-19 13:07:16 +02:00

142 lines
5.2 KiB
TypeScript

import { useEffect, useState } from 'react';
import { ChevronDown, CloudSun, Globe, MapPin } from 'lucide-react';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { useTempoUi } from '@/components/tempo-brand';
type Weather = { temp: number; description: string; humidity?: number };
export function TempoWeather() {
const { language } = useTempoUi();
const [weather, setWeather] = useState<Weather | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 8000);
fetch(`https://teste-info.tempo.co.mz/api/weather?lang=${language}`, {
signal: controller.signal,
credentials: 'omit',
})
.then((response) => (response.ok ? response.json() : null))
.then((data: { current?: Weather } | null) => {
if (data?.current && Number.isFinite(data.current.temp))
setWeather(data.current);
})
.catch(() => {
/* No guessed temperatures when the source is unavailable. */
})
.finally(() => {
clearTimeout(timer);
setLoading(false);
});
return () => {
clearTimeout(timer);
controller.abort();
};
}, [language]);
return (
<DropdownMenu modal={false}>
<DropdownMenuTrigger
className="tempo-utility-button"
aria-label="Temperatura em Maputo"
>
<CloudSun
size={19}
aria-hidden="true"
className="text-amber-300"
/>
<span>
{weather
? `${Math.round(weather.temp)}°C`
: loading
? '…'
: 'Maputo'}
</span>
<ChevronDown size={12} aria-hidden="true" />
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
sideOffset={12}
className="tempo-dropdown w-60 p-4"
>
<p className="mb-3 flex items-center gap-2 text-xs font-semibold text-slate-500">
<MapPin size={14} /> Maputo, Moçambique
</p>
{weather ? (
<>
<p className="text-3xl font-semibold text-slate-950">
{Math.round(weather.temp)}°C
</p>
<p className="mt-1 text-sm text-slate-600">
{weather.description}
</p>
{weather.humidity !== undefined && (
<p className="mt-3 text-xs text-slate-500">
Humidade: {weather.humidity}%
</p>
)}
</>
) : (
<p className="text-sm text-slate-600">
{loading
? 'A consultar a temperatura…'
: 'Temperatura temporariamente indisponível.'}
</p>
)}
<p className="mt-3 text-[11px] text-slate-400">
Meteorologia · Tempo
</p>
</DropdownMenuContent>
</DropdownMenu>
);
}
export function TempoLanguageSelector() {
const { language, setLanguage } = useTempoUi();
return (
<DropdownMenu modal={false}>
<DropdownMenuTrigger
className="tempo-utility-button"
aria-label="Idioma da navegação"
>
<Globe size={16} aria-hidden="true" />
<span className="text-xs font-semibold uppercase">
{language}
</span>
<ChevronDown size={12} aria-hidden="true" />
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
sideOffset={12}
className="tempo-dropdown min-w-44"
>
<DropdownMenuLabel className="text-xs text-slate-500">
Navegação institucional
</DropdownMenuLabel>
{[
['pt', 'Português'],
['en', 'English'],
['fr', 'Français'],
['es', 'Español'],
].map(([code, name]) => (
<DropdownMenuItem
key={code}
onSelect={() => setLanguage(code)}
className={`tempo-menu-item ${language === code ? 'bg-red-50 text-red-700' : ''}`}
>
<span className="w-6 text-[10px] font-bold uppercase">
{code}
</span>
{name}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
}