Fixes light theme + Topbar strings

This commit is contained in:
litoral05
2026-06-01 14:15:30 +01:00
parent 99924ac1df
commit f197898fbb
2 changed files with 89 additions and 41 deletions
+5 -3
View File
@@ -300,9 +300,9 @@ function pageTitle(page: AppPage | null) {
return "Gráficos Gerais"; return "Gráficos Gerais";
case "meteo": case "meteo":
return "Previsões"; return "Previsões Meteorológicas";
case "meteoCharts": case "meteoCharts":
return "Gráficos"; return "Gráficos Meteorológicos";
case "synoptic": case "synoptic":
return "Sinótico"; return "Sinótico";
@@ -315,11 +315,13 @@ function pageTitle(page: AppPage | null) {
// ALL CLIMATE PAGES // ALL CLIMATE PAGES
case "climate": case "climate":
case "climateCharts":
case "climateLighting": case "climateLighting":
case "climateVentilation": case "climateVentilation":
return "Clima"; return "Clima";
case "climateCharts":
return "Gráficos Climáticos";
// ALL IRRIGATION / REGA PAGES // ALL IRRIGATION / REGA PAGES
case "irrigation": case "irrigation":
case "irrigationCharts": case "irrigationCharts":
+75 -29
View File
@@ -202,7 +202,7 @@ export function MeteoPage({ theme, onOpenMeteoCharts }: MeteoPageProps) {
); );
return ( return (
<div className="space-y-4 pb-4"> <div className={theme === "dark" ? "space-y-4 pb-4 text-slate-100" : "space-y-4 pb-4 text-slate-950"}>
<WeatherHeroPanel <WeatherHeroPanel
theme={theme} theme={theme}
forecast={forecast} forecast={forecast}
@@ -477,7 +477,7 @@ function formatAccumulatedValue(value: number | null, unit?: string) {
if (unit === "Wh/m²") { if (unit === "Wh/m²") {
return { return {
value: value.toFixed(1), value: (value / 1000).toFixed(2),
unit: "kWh/m²", unit: "kWh/m²",
}; };
} }
@@ -611,19 +611,31 @@ function WeatherHeroPanel({
<img <img
src={heroBackground} src={heroBackground}
alt="" alt=""
className="absolute inset-0 h-full w-full object-cover opacity-75" className={isDark ? "absolute inset-0 h-full w-full object-cover opacity-75" : "absolute inset-0 h-full w-full object-cover opacity-90"}
style={{ objectPosition: "center 20%" }} style={{ objectPosition: "center 20%" }}
/> />
<div className="absolute inset-0 bg-[linear-gradient(90deg,rgba(4,13,24,0.98)_0%,rgba(5,17,31,0.94)_32%,rgba(7,20,33,0.72)_58%,rgba(7,20,33,0.42)_100%)]" /> <div
<div className="absolute inset-0 bg-[radial-gradient(circle_at_82%_18%,rgba(251,191,36,0.18),transparent_24%)]" /> className={
isDark
? "absolute inset-0 bg-[linear-gradient(90deg,rgba(4,13,24,0.98)_0%,rgba(5,17,31,0.94)_32%,rgba(7,20,33,0.72)_58%,rgba(7,20,33,0.42)_100%)]"
: "absolute inset-0 bg-[linear-gradient(90deg,rgba(255,255,255,0.88)_0%,rgba(248,250,252,0.72)_34%,rgba(15,23,42,0.18)_68%,rgba(15,23,42,0.32)_100%)]"
}
/>
<div
className={
isDark
? "absolute inset-0 bg-[radial-gradient(circle_at_82%_18%,rgba(251,191,36,0.18),transparent_24%)]"
: "absolute inset-0 bg-[radial-gradient(circle_at_82%_18%,rgba(251,191,36,0.16),transparent_28%)]"
}
/>
<div className="relative p-5 lg:p-6"> <div className="relative p-5 lg:p-6">
<div className="flex flex-wrap items-start justify-between gap-4"> <div className="flex flex-wrap items-start justify-between gap-4">
<div> <div>
<h2 className="text-xl font-black tracking-[-0.04em] text-white"> <h2 className={isDark ? "text-xl font-black tracking-[-0.04em] text-white" : "text-xl font-black tracking-[-0.04em] text-[#0F172A]"}>
{location} {location}
</h2> </h2>
<p className="mt-1 text-sm font-medium text-slate-300"> <p className={isDark ? "mt-1 text-sm font-medium text-slate-300" : "mt-1 text-sm font-semibold text-slate-600"}>
{selectedDayIndex === 0 {selectedDayIndex === 0
? "Condições de hoje" ? "Condições de hoje"
: `Previsão para ${heroDateLabel}`} : `Previsão para ${heroDateLabel}`}
@@ -633,7 +645,7 @@ function WeatherHeroPanel({
<button <button
type="button" type="button"
onClick={onOpenWeatherBoard} onClick={onOpenWeatherBoard}
className="inline-flex items-center gap-2 rounded-[5px] border border-sky-400/25 bg-sky-400/10 px-3 py-2 text-sm font-black text-sky-200 transition hover:bg-sky-400/15" className="inline-flex items-center gap-2 rounded-[5px] border border-sky-300/35 bg-sky-300/15 px-3 py-2 text-sm font-black text-sky-100 transition hover:bg-sky-300/25"
> >
<Activity className="h-4 w-4" /> <Activity className="h-4 w-4" />
Abrir quadro meteorológico Abrir quadro meteorológico
@@ -658,13 +670,13 @@ function WeatherHeroPanel({
)} )}
<div> <div>
<div className="text-[48px] font-black leading-none tracking-[-0.07em] text-white"> <div className={isDark ? "text-[48px] font-black leading-none tracking-[-0.07em] text-white" : "text-[48px] font-black leading-none tracking-[-0.07em] text-[#0F172A]"}>
{formatNumber(heroTemperature, 1)}° {formatNumber(heroTemperature, 1)}°
</div> </div>
<p className="mt-2 text-sm font-black text-white"> <p className={isDark ? "mt-2 text-sm font-black text-white" : "mt-2 text-sm font-black text-[#0F172A]"}>
{conditionText} {conditionText}
</p> </p>
<p className="mt-1 text-xs font-semibold text-slate-400"> <p className={isDark ? "mt-1 text-xs font-semibold text-slate-400" : "mt-1 text-xs font-semibold text-slate-500"}>
{heroMinTemperature !== null {heroMinTemperature !== null
? `Mínima ${formatNumber(heroMinTemperature, 0)}°` ? `Mínima ${formatNumber(heroMinTemperature, 0)}°`
: "Sem mínima disponível"} : "Sem mínima disponível"}
@@ -672,8 +684,9 @@ function WeatherHeroPanel({
</div> </div>
</div> </div>
<div className="grid gap-0 divide-y divide-white/10 rounded-[5px] border border-white/0 sm:grid-cols-2 sm:divide-x sm:divide-y-0 lg:grid-cols-5"> <div className={isDark ? "grid gap-0 divide-y divide-white/10 rounded-[5px] border border-white/0 sm:grid-cols-2 sm:divide-x sm:divide-y-0 lg:grid-cols-5" : "grid gap-0 divide-y divide-slate-200 rounded-[5px] border border-slate-200/70 bg-white/55 sm:grid-cols-2 sm:divide-x sm:divide-y-0 lg:grid-cols-5"}>
<HeroMetric <HeroMetric
theme={theme}
title="Chuva" title="Chuva"
value={`${day.dailyRainChance ?? "--"}%`} value={`${day.dailyRainChance ?? "--"}%`}
helper={`${formatNumber(day.totalPrecipitationMm, 1)} mm previstos`} helper={`${formatNumber(day.totalPrecipitationMm, 1)} mm previstos`}
@@ -681,6 +694,7 @@ function WeatherHeroPanel({
/> />
<HeroMetric <HeroMetric
theme={theme}
title="UV Index" title="UV Index"
value={formatNumber(day.uv, 0)} value={formatNumber(day.uv, 0)}
helper={uvLabel(day.uv)} helper={uvLabel(day.uv)}
@@ -688,6 +702,7 @@ function WeatherHeroPanel({
/> />
<HeroMetric <HeroMetric
theme={theme}
title="Vento" title="Vento"
value={`${formatNumber(day.averageWindKph, 1)} km/h`} value={`${formatNumber(day.averageWindKph, 1)} km/h`}
helper={ helper={
@@ -699,6 +714,7 @@ function WeatherHeroPanel({
/> />
<HeroMetric <HeroMetric
theme={theme}
title="Humidade" title="Humidade"
value={`${formatNumber(day.averageHumidity, 0)}%`} value={`${formatNumber(day.averageHumidity, 0)}%`}
helper="Média diária" helper="Média diária"
@@ -706,6 +722,7 @@ function WeatherHeroPanel({
/> />
<HeroMetric <HeroMetric
theme={theme}
title="Visibilidade" title="Visibilidade"
value={`${formatNumber(day.averageVisibilityKm, 1)} km`} value={`${formatNumber(day.averageVisibilityKm, 1)} km`}
helper="Média diária" helper="Média diária"
@@ -743,15 +760,15 @@ function ForecastPanel({
<div className="mb-4 flex flex-wrap items-end justify-between gap-3"> <div className="mb-4 flex flex-wrap items-end justify-between gap-3">
<div> <div>
<h2 className={panelTitleClass(isDark)}>Previsão diária</h2> <h2 className={panelTitleClass(isDark)}>Previsão diária</h2>
<p className="mt-1 text-sm text-slate-400">Próximos 7 dias</p> <p className={isDark ? "mt-1 text-sm text-slate-400" : "mt-1 text-sm text-slate-500"}>Próximos 7 dias</p>
</div> </div>
{selectedDay && ( {selectedDay && (
<div className="hidden text-right lg:block"> <div className="hidden text-right lg:block">
<p className="text-xs font-bold uppercase tracking-[0.18em] text-slate-500"> <p className={isDark ? "text-xs font-bold uppercase tracking-[0.18em] text-slate-500" : "text-xs font-bold uppercase tracking-[0.18em] text-slate-400"}>
Dia selecionado Dia selecionado
</p> </p>
<p className="mt-1 text-sm font-black text-slate-200"> <p className={isDark ? "mt-1 text-sm font-black text-slate-200" : "mt-1 text-sm font-black text-slate-700"}>
{weekday(selectedDay.date)} · {shortDate(selectedDay.date)} {weekday(selectedDay.date)} · {shortDate(selectedDay.date)}
</p> </p>
</div> </div>
@@ -807,6 +824,7 @@ function ForecastDayCard({
className={[ className={[
RADIUS, RADIUS,
"group relative min-h-[110px] overflow-hidden px-3.5 py-3 text-left outline-none transition-all duration-300 focus-visible:ring-1 focus-visible:ring-sky-300/45", "group relative min-h-[110px] overflow-hidden px-3.5 py-3 text-left outline-none transition-all duration-300 focus-visible:ring-1 focus-visible:ring-sky-300/45",
isDark ? "border border-white/[0.035]" : "border border-slate-200",
active active
? isDark ? isDark
? "bg-white/[0.04]" ? "bg-white/[0.04]"
@@ -816,13 +834,22 @@ function ForecastDayCard({
: "bg-slate-100/60 hover:bg-slate-100", : "bg-slate-100/60 hover:bg-slate-100",
].join(" ")} ].join(" ")}
style={{ style={{
backgroundImage: ` backgroundImage: isDark
? `
linear-gradient( linear-gradient(
180deg, 180deg,
rgba(4,13,24,${active ? "0.78" : "0.86"}), rgba(4,13,24,${active ? "0.78" : "0.86"}),
rgba(4,13,24,${active ? "0.95" : "0.985"}) rgba(4,13,24,${active ? "0.95" : "0.985"})
), ),
url(${background}) url(${background})
`
: `
linear-gradient(
180deg,
rgba(255,255,255,${active ? "0.50" : "0.58"}),
rgba(248,250,252,${active ? "0.76" : "0.84"})
),
url(${background})
`, `,
backgroundSize: "cover", backgroundSize: "cover",
backgroundPosition: "center 24%", backgroundPosition: "center 24%",
@@ -862,10 +889,10 @@ function ForecastDayCard({
<span className="relative z-10 flex h-full flex-col justify-between"> <span className="relative z-10 flex h-full flex-col justify-between">
<span className="flex items-start justify-between gap-3"> <span className="flex items-start justify-between gap-3">
<span> <span>
<span className="block text-sm font-black text-white"> <span className={isDark ? "block text-sm font-black text-white" : "block text-sm font-black text-[#0F172A]"}>
{label} {label}
</span> </span>
<span className="mt-1 block text-xs font-semibold text-slate-300"> <span className={isDark ? "mt-1 block text-xs font-semibold text-slate-300" : "mt-1 block text-xs font-semibold text-slate-500"}>
{shortDate(day.date)} {shortDate(day.date)}
</span> </span>
</span> </span>
@@ -888,10 +915,10 @@ function ForecastDayCard({
<span className="flex items-end justify-between gap-3"> <span className="flex items-end justify-between gap-3">
<span className="flex items-end gap-2"> <span className="flex items-end gap-2">
<span className="text-2xl font-black leading-none tracking-[-0.06em] text-white"> <span className={isDark ? "text-2xl font-black leading-none tracking-[-0.06em] text-white" : "text-2xl font-black leading-none tracking-[-0.06em] text-[#0F172A]"}>
{Math.round(day.maxTemperatureC)}° {Math.round(day.maxTemperatureC)}°
</span> </span>
<span className="mb-0.5 text-sm font-black text-slate-400"> <span className={isDark ? "mb-0.5 text-sm font-black text-slate-400" : "mb-0.5 text-sm font-black text-slate-500"}>
{Math.round(day.minTemperatureC)}° {Math.round(day.minTemperatureC)}°
</span> </span>
</span> </span>
@@ -899,9 +926,13 @@ function ForecastDayCard({
<span <span
className={[ className={[
"rounded-full px-2 py-1 text-[10px] font-black uppercase tracking-[0.08em] backdrop-blur-sm transition", "rounded-full px-2 py-1 text-[10px] font-black uppercase tracking-[0.08em] backdrop-blur-sm transition",
active isDark
? active
? "border border-white/10 bg-white/[0.065] text-white" ? "border border-white/10 bg-white/[0.065] text-white"
: "border border-white/10 bg-white/[0.045] text-slate-400 group-hover:text-slate-300", : "border border-white/10 bg-white/[0.045] text-slate-400 group-hover:text-slate-300"
: active
? "border border-sky-200 bg-sky-50 text-sky-700"
: "border border-slate-200 bg-white/70 text-slate-500 group-hover:text-slate-700",
].join(" ")} ].join(" ")}
> >
UV {formatNumber(day.uv, 0)} UV {formatNumber(day.uv, 0)}
@@ -1212,12 +1243,19 @@ function RealtimeChartPanel({
}); });
} }
const hasAnyChartData = chart.variables.some(
(variable) => variable.data.length > 0,
);
return ( return (
<div className="relative flex min-h-0 flex-1 flex-col"> <div className={theme === "dark" ? "relative flex min-h-0 flex-1 flex-col text-slate-100" : "relative flex min-h-0 flex-1 flex-col text-slate-950"}>
<div className="absolute right-3 top-3 z-20"> <div className="absolute right-3 top-3 z-20">
<button <button
type="button" type="button"
className="rounded-[5px] border border-sky-400/20 bg-sky-400/10 px-3 py-2 text-xs font-black text-sky-200 transition hover:bg-sky-400/15" className={
theme === "dark"
? "rounded-[5px] border border-sky-400/20 bg-sky-400/10 px-3 py-2 text-xs font-black text-sky-200 transition hover:bg-sky-400/15"
: "rounded-[5px] border border-sky-300 bg-sky-50 px-3 py-2 text-xs font-black text-sky-700 transition hover:bg-sky-100"
}
onClick={onOpenMeteoCharts} onClick={onOpenMeteoCharts}
> >
Gráficos Personalizados Gráficos Personalizados
@@ -1228,7 +1266,7 @@ function RealtimeChartPanel({
<WorkspaceChart <WorkspaceChart
theme={theme} theme={theme}
chart={chart} chart={chart}
loading={historyLoading} loading={historyLoading && !hasAnyChartData}
configuredVariableCount={series.length} configuredVariableCount={series.length}
onModeChange={setMode} onModeChange={setMode}
onVariableToggle={handleVariableToggle} onVariableToggle={handleVariableToggle}
@@ -1268,24 +1306,32 @@ function CompactMeteoChart({
} }
function HeroMetric({ function HeroMetric({
theme,
title, title,
value, value,
helper, helper,
icon: Icon, icon: Icon,
}: { }: {
theme: "dark" | "light";
title: string; title: string;
value: string; value: string;
helper: string; helper: string;
icon: LucideIcon; icon: LucideIcon;
}) { }) {
const isDark = theme === "dark";
return ( return (
<div className="px-4 py-3"> <div className="px-4 py-3">
<div className="flex items-center gap-2 text-xs font-semibold text-slate-400"> <div className={isDark ? "flex items-center gap-2 text-xs font-semibold text-slate-400" : "flex items-center gap-2 text-xs font-semibold text-slate-500"}>
<Icon className="h-3.5 w-3.5" /> <Icon className="h-3.5 w-3.5" />
{title} {title}
</div> </div>
<p className="mt-3 text-base font-black text-white">{value}</p> <p className={isDark ? "mt-3 text-base font-black text-white" : "mt-3 text-base font-black text-[#0F172A]"}>
<p className="mt-2 text-xs font-medium text-slate-400">{helper}</p> {value}
</p>
<p className={isDark ? "mt-2 text-xs font-medium text-slate-400" : "mt-2 text-xs font-medium text-slate-500"}>
{helper}
</p>
</div> </div>
); );
} }
@@ -1344,7 +1390,7 @@ function SummaryTile({
className={ className={
isDark isDark
? "rounded-[5px] bg-slate-700 px-2 py-1 text-[11px] font-black text-slate-200" ? "rounded-[5px] bg-slate-700 px-2 py-1 text-[11px] font-black text-slate-200"
: "rounded-[5px] bg-white px-2 py-1 text-[11px] font-black text-slate-700" : "rounded-[5px] border border-slate-200 bg-white px-2 py-1 text-[11px] font-black text-slate-700"
} }
> >
{badge} {badge}