Fixes light theme + Topbar strings
This commit is contained in:
@@ -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":
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user