Compare commits
2 Commits
a4f02d711a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b9de13360 | |||
| 747868867f |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
**Pogoda z danych IMGW. Prosto. Pięknie. Aktualnie.**
|
**Pogoda z danych IMGW. Prosto. Pięknie. Aktualnie.**
|
||||||
|
|
||||||
`wtr.` to nowoczesna pogodowa PWA dla Polski oparta o publiczne dane IMGW i jawnie oznaczoną prognozę modelową łączącą IMGW ALARO z Open-Meteo. Aplikacja prezentuje bieżącą analizę pogody IMGW Hybrid, odczyty synoptyczne, prognozę godzinową i 7-dniową, stacje hydrologiczne oraz ostrzeżenia w spokojnym, mobilnym interfejsie z gradientami, kartami glassmorphism i subtelnymi animacjami. Dashboard pokazuje rozszerzony desktopowy podgląd godzin z podsumowaniem najbliższej doby, a także wykresy temperatury i opadu dla bieżącego dnia. Każdy dzień prognozy można także otworzyć w animowanym widoku szczegółowym z przebiegiem godzinowym oraz wykresami.
|
`wtr.` to nowoczesna pogodowa PWA dla Polski oparta o publiczne dane IMGW i jawnie oznaczoną prognozę modelową łączącą IMGW ALARO z Open-Meteo. Aplikacja prezentuje bieżącą analizę pogody IMGW Hybrid, odczyty synoptyczne, prognozę godzinową i 7-dniową, stacje hydrologiczne oraz ostrzeżenia w spokojnym, mobilnym interfejsie z czytelną typografią, opaque surfaces i subtelnymi animacjami. Dashboard pokazuje rozszerzony desktopowy podgląd godzin z podsumowaniem najbliższej doby, a także wykresy temperatury i opadu dla bieżącego dnia. Każdy dzień prognozy można także otworzyć w animowanym widoku szczegółowym z przebiegiem godzinowym oraz wykresami.
|
||||||
|
|
||||||
Interfejs jest dostępny po polsku i angielsku. Wybrany język jest zapisywany lokalnie w przeglądarce. Oryginalne treści ostrzeżeń oraz nazwy stacji pochodzą bezpośrednio z API IMGW i nie są automatycznie tłumaczone.
|
Interfejs jest dostępny po polsku i angielsku. Wybrany język jest zapisywany lokalnie w przeglądarce. Oryginalne treści ostrzeżeń oraz nazwy stacji pochodzą bezpośrednio z API IMGW i nie są automatycznie tłumaczone.
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ Prognoza godzinowa i dzienna rozpoznaje następujące stany warunków pogodowych
|
|||||||
|
|
||||||
Bieżąca analiza IMGW Hybrid rozpoznaje bezpośrednio opad deszczu, śnieg i burzę. Gdy żadne z tych zjawisk nie występuje, hero może pokazać pomocniczy opis: `Silny wiatr`, `Wilgotne warunki` albo `Spokojne warunki`.
|
Bieżąca analiza IMGW Hybrid rozpoznaje bezpośrednio opad deszczu, śnieg i burzę. Gdy żadne z tych zjawisk nie występuje, hero może pokazać pomocniczy opis: `Silny wiatr`, `Wilgotne warunki` albo `Spokojne warunki`.
|
||||||
|
|
||||||
Gradient hero i część animacji korzystają z uproszczonego nastroju wizualnego:
|
Hero aktualnej pogody korzysta z uproszczonego nastroju wizualnego do wyboru ikony, tekstu i małego akcentu stanu. Nie steruje już pełnoekranowym gradientem.
|
||||||
|
|
||||||
| Mood | Obecna reguła |
|
| Mood | Obecna reguła |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
@@ -103,7 +103,7 @@ Gradient hero i część animacji korzystają z uproszczonego nastroju wizualneg
|
|||||||
| `warm` | temperatura od `20°C` |
|
| `warm` | temperatura od `20°C` |
|
||||||
| `mild` | pozostałe przypadki |
|
| `mild` | pozostałe przypadki |
|
||||||
|
|
||||||
Warstwa efektów wizualnych dodaje miękkie chmury dla `cloudy`, poświatę dla `warm`, gwiazdy nocą, smugi przy silnym wietrze, krople przy lokalnym opadzie, błyski przy burzy oraz chłodną poświatę dla `cold`. Mood hero jest obecnie heurystyką opartą o porę dnia, temperaturę, wilgotność i wiatr. Nie jest jeszcze pełną klasyfikacją sterowaną kodem warunków IMGW Hybrid.
|
Warstwa efektów wizualnych jest ograniczona do subtelnych efektów informacyjnych: kropli przy lokalnym opadzie oraz błysku przy burzy. Mood hero jest obecnie heurystyką opartą o porę dnia, temperaturę, wilgotność i wiatr. Nie jest jeszcze pełną klasyfikacją sterowaną kodem warunków IMGW Hybrid.
|
||||||
|
|
||||||
## Struktura projektu
|
## Struktura projektu
|
||||||
|
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ select {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-overlay {
|
.modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: -1px 0 0;
|
||||||
|
min-height: calc(100dvh + 1px);
|
||||||
background: hsl(var(--foreground) / 0.55);
|
background: hsl(var(--foreground) / 0.55);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useMemo, useRef } from "react";
|
import { useEffect, useMemo, useRef } from "react";
|
||||||
|
import { createPortal } from "react-dom";
|
||||||
import { AnimatePresence, motion } from "framer-motion";
|
import { AnimatePresence, motion } from "framer-motion";
|
||||||
import { CloudSun, Droplets, Sunrise, Sunset, Wind, X } from "lucide-react";
|
import { CloudSun, Droplets, Sunrise, Sunset, Wind, X } from "lucide-react";
|
||||||
import { DayForecastCharts } from "@/components/charts/day-forecast-charts";
|
import { DayForecastCharts } from "@/components/charts/day-forecast-charts";
|
||||||
@@ -55,6 +56,7 @@ export function DayForecastModal({
|
|||||||
}) {
|
}) {
|
||||||
const { language, locale, t } = useI18n();
|
const { language, locale, t } = useI18n();
|
||||||
const closeButtonRef = useRef<HTMLButtonElement>(null);
|
const closeButtonRef = useRef<HTMLButtonElement>(null);
|
||||||
|
const portalRoot = typeof document === "undefined" ? null : document.body;
|
||||||
const maximumWind = useMemo(() => getMaximumWind(hours), [hours]);
|
const maximumWind = useMemo(() => getMaximumWind(hours), [hours]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -80,11 +82,11 @@ export function DayForecastModal({
|
|||||||
? new Intl.DateTimeFormat(locale, { weekday: "long", day: "numeric", month: "long", timeZone: "UTC" }).format(new Date(`${day.date}T12:00:00Z`))
|
? new Intl.DateTimeFormat(locale, { weekday: "long", day: "numeric", month: "long", timeZone: "UTC" }).format(new Date(`${day.date}T12:00:00Z`))
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
return (
|
const modal = (
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{day ? (
|
{day ? (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="modal-overlay fixed inset-0 z-[90] flex items-center justify-center p-0 sm:p-4 lg:p-8"
|
className="modal-overlay z-[90] flex items-center justify-center p-0 sm:p-4 lg:p-8"
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
exit={{ opacity: 0 }}
|
exit={{ opacity: 0 }}
|
||||||
@@ -179,4 +181,6 @@ export function DayForecastModal({
|
|||||||
) : null}
|
) : null}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return portalRoot ? createPortal(modal, portalRoot) : null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user