Fixes light theme + Topbar strings
This commit is contained in:
@@ -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":
|
||||||
|
|||||||
@@ -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,14 +834,23 @@ 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(
|
? `
|
||||||
180deg,
|
linear-gradient(
|
||||||
rgba(4,13,24,${active ? "0.78" : "0.86"}),
|
180deg,
|
||||||
rgba(4,13,24,${active ? "0.95" : "0.985"})
|
rgba(4,13,24,${active ? "0.78" : "0.86"}),
|
||||||
),
|
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
|
||||||
? "border border-white/10 bg-white/[0.065] text-white"
|
? active
|
||||||
: "border border-white/10 bg-white/[0.045] text-slate-400 group-hover:text-slate-300",
|
? "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(" ")}
|
].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}
|
||||||
|
|||||||
Reference in New Issue
Block a user