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";
case "meteo":
return "Previsões";
return "Previsões Meteorológicas";
case "meteoCharts":
return "Gráficos";
return "Gráficos Meteorológicos";
case "synoptic":
return "Sinótico";
@@ -315,11 +315,13 @@ function pageTitle(page: AppPage | null) {
// ALL CLIMATE PAGES
case "climate":
case "climateCharts":
case "climateLighting":
case "climateVentilation":
return "Clima";
case "climateCharts":
return "Gráficos Climáticos";
// ALL IRRIGATION / REGA PAGES
case "irrigation":
case "irrigationCharts":
+83 -37
View File
@@ -202,7 +202,7 @@ export function MeteoPage({ theme, onOpenMeteoCharts }: MeteoPageProps) {
);
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
theme={theme}
forecast={forecast}
@@ -477,7 +477,7 @@ function formatAccumulatedValue(value: number | null, unit?: string) {
if (unit === "Wh/m²") {
return {
value: value.toFixed(1),
value: (value / 1000).toFixed(2),
unit: "kWh/m²",
};
}
@@ -611,19 +611,31 @@ function WeatherHeroPanel({
<img
src={heroBackground}
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%" }}
/>
<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 className="absolute inset-0 bg-[radial-gradient(circle_at_82%_18%,rgba(251,191,36,0.18),transparent_24%)]" />
<div
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="flex flex-wrap items-start justify-between gap-4">
<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}
</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
? "Condições de hoje"
: `Previsão para ${heroDateLabel}`}
@@ -633,7 +645,7 @@ function WeatherHeroPanel({
<button
type="button"
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" />
Abrir quadro meteorológico
@@ -658,13 +670,13 @@ function WeatherHeroPanel({
)}
<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)}°
</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}
</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
? `Mínima ${formatNumber(heroMinTemperature, 0)}°`
: "Sem mínima disponível"}
@@ -672,8 +684,9 @@ function WeatherHeroPanel({
</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
theme={theme}
title="Chuva"
value={`${day.dailyRainChance ?? "--"}%`}
helper={`${formatNumber(day.totalPrecipitationMm, 1)} mm previstos`}
@@ -681,6 +694,7 @@ function WeatherHeroPanel({
/>
<HeroMetric
theme={theme}
title="UV Index"
value={formatNumber(day.uv, 0)}
helper={uvLabel(day.uv)}
@@ -688,6 +702,7 @@ function WeatherHeroPanel({
/>
<HeroMetric
theme={theme}
title="Vento"
value={`${formatNumber(day.averageWindKph, 1)} km/h`}
helper={
@@ -699,6 +714,7 @@ function WeatherHeroPanel({
/>
<HeroMetric
theme={theme}
title="Humidade"
value={`${formatNumber(day.averageHumidity, 0)}%`}
helper="Média diária"
@@ -706,6 +722,7 @@ function WeatherHeroPanel({
/>
<HeroMetric
theme={theme}
title="Visibilidade"
value={`${formatNumber(day.averageVisibilityKm, 1)} km`}
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>
<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>
{selectedDay && (
<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
</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)}
</p>
</div>
@@ -807,6 +824,7 @@ function ForecastDayCard({
className={[
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",
isDark ? "border border-white/[0.035]" : "border border-slate-200",
active
? isDark
? "bg-white/[0.04]"
@@ -816,14 +834,23 @@ function ForecastDayCard({
: "bg-slate-100/60 hover:bg-slate-100",
].join(" ")}
style={{
backgroundImage: `
linear-gradient(
180deg,
rgba(4,13,24,${active ? "0.78" : "0.86"}),
rgba(4,13,24,${active ? "0.95" : "0.985"})
),
url(${background})
`,
backgroundImage: isDark
? `
linear-gradient(
180deg,
rgba(4,13,24,${active ? "0.78" : "0.86"}),
rgba(4,13,24,${active ? "0.95" : "0.985"})
),
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",
backgroundPosition: "center 24%",
}}
@@ -862,10 +889,10 @@ function ForecastDayCard({
<span className="relative z-10 flex h-full flex-col justify-between">
<span className="flex items-start justify-between gap-3">
<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}
</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)}
</span>
</span>
@@ -888,10 +915,10 @@ function ForecastDayCard({
<span className="flex items-end justify-between gap-3">
<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)}°
</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)}°
</span>
</span>
@@ -899,9 +926,13 @@ function ForecastDayCard({
<span
className={[
"rounded-full px-2 py-1 text-[10px] font-black uppercase tracking-[0.08em] backdrop-blur-sm transition",
active
? "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",
isDark
? active
? "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"
: 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(" ")}
>
UV {formatNumber(day.uv, 0)}
@@ -1212,12 +1243,19 @@ function RealtimeChartPanel({
});
}
const hasAnyChartData = chart.variables.some(
(variable) => variable.data.length > 0,
);
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">
<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}
>
Gráficos Personalizados
@@ -1228,7 +1266,7 @@ function RealtimeChartPanel({
<WorkspaceChart
theme={theme}
chart={chart}
loading={historyLoading}
loading={historyLoading && !hasAnyChartData}
configuredVariableCount={series.length}
onModeChange={setMode}
onVariableToggle={handleVariableToggle}
@@ -1268,24 +1306,32 @@ function CompactMeteoChart({
}
function HeroMetric({
theme,
title,
value,
helper,
icon: Icon,
}: {
theme: "dark" | "light";
title: string;
value: string;
helper: string;
icon: LucideIcon;
}) {
const isDark = theme === "dark";
return (
<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" />
{title}
</div>
<p className="mt-3 text-base font-black text-white">{value}</p>
<p className="mt-2 text-xs font-medium text-slate-400">{helper}</p>
<p className={isDark ? "mt-3 text-base font-black text-white" : "mt-3 text-base font-black text-[#0F172A]"}>
{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>
);
}
@@ -1344,7 +1390,7 @@ function SummaryTile({
className={
isDark
? "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}