diff --git a/components/weather/weather-effects.tsx b/components/weather/weather-effects.tsx new file mode 100644 index 0000000..d40cbf5 --- /dev/null +++ b/components/weather/weather-effects.tsx @@ -0,0 +1,75 @@ +"use client"; + +import { motion, useReducedMotion } from "framer-motion"; +import type { SynopStation, WeatherMood } from "@/types/imgw"; + +const rainDrops = Array.from({ length: 32 }, (_, index) => ({ + left: `${(index * 29 + 7) % 100}%`, + delay: (index % 11) * 0.13, + duration: 0.72 + (index % 5) * 0.12, + height: 12 + (index % 4) * 4, +})); + +const windLines = Array.from({ length: 7 }, (_, index) => ({ + top: `${18 + index * 11}%`, + delay: index * 0.22, + width: 70 + (index % 3) * 34, +})); + +const stars = Array.from({ length: 16 }, (_, index) => ({ + left: `${(index * 37 + 11) % 96}%`, + top: `${(index * 23 + 8) % 72}%`, + delay: (index % 6) * 0.35, +})); + +export function WeatherEffects({ station, mood }: { station: SynopStation; mood: WeatherMood }) { + const reduceMotion = useReducedMotion(); + const rainfall = station.rainfall ?? 0; + const isRaining = rainfall >= 0.1; + const visibleDrops = rainfall >= 5 ? rainDrops : rainDrops.slice(0, 18); + const isWindy = (station.windSpeed ?? 0) >= 8; + + return ( +
+ ); +} diff --git a/components/weather/weather-hero.tsx b/components/weather/weather-hero.tsx index 044ae6f..876db2c 100644 --- a/components/weather/weather-hero.tsx +++ b/components/weather/weather-hero.tsx @@ -16,6 +16,7 @@ import { } from "@/lib/weather-utils"; import type { SynopStation } from "@/types/imgw"; import { WeatherIcon } from "@/components/weather/weather-icon"; +import { WeatherEffects } from "@/components/weather/weather-effects"; import { useI18n } from "@/lib/i18n"; export function WeatherHero({ station, locationName, distanceKm }: { station: SynopStation; locationName?: string; distanceKm?: number }) { @@ -36,6 +37,7 @@ export function WeatherHero({ station, locationName, distanceKm }: { station: Sy transition={{ duration: 0.55, ease: "easeOut" }} className={`relative isolate overflow-hidden rounded-[2rem] bg-gradient-to-br ${moodGradient(mood)} px-5 py-6 text-white shadow-[0_24px_75px_rgba(15,23,42,0.24)] sm:px-8 sm:py-8 lg:px-10`} > +{getWeatherDescription(station, language)}
diff --git a/components/weather/weather-icon.tsx b/components/weather/weather-icon.tsx index 9f28a7e..c102a09 100644 --- a/components/weather/weather-icon.tsx +++ b/components/weather/weather-icon.tsx @@ -1,9 +1,9 @@ -import { CloudRain, CloudSun, MoonStar, Snowflake, Sun, Wind } from "lucide-react"; +import { CloudRain, CloudSun, MoonStar, Snowflake, ThermometerSun, Wind } from "lucide-react"; import type { WeatherMood } from "@/types/imgw"; export function WeatherIcon({ mood, className = "" }: { mood: WeatherMood; className?: string }) { const Icon = { - clear: Sun, + warm: ThermometerSun, rain: CloudRain, wind: Wind, cold: Snowflake, diff --git a/lib/weather-utils.ts b/lib/weather-utils.ts index 0a9157f..33f1a7a 100644 --- a/lib/weather-utils.ts +++ b/lib/weather-utils.ts @@ -160,11 +160,11 @@ export function getWindDirection(degrees: number) { export function getWeatherMoodFromData(station: SynopStation, date = new Date()): WeatherMood { const hour = date.getHours(); - if (hour < 6 || hour >= 21) return "night"; if ((station.rainfall ?? 0) >= 0.1) return "rain"; + if (hour < 6 || hour >= 21) return "night"; if ((station.windSpeed ?? 0) >= 8) return "wind"; if ((station.temperature ?? 15) <= 3) return "cold"; - if ((station.temperature ?? 15) >= 20) return "clear"; + if ((station.temperature ?? 15) >= 20) return "warm"; return "mild"; } @@ -178,11 +178,11 @@ export function getWeatherDescription(station: SynopStation, language: Language export function moodGradient(mood: WeatherMood) { return { - clear: "from-sky-500 via-blue-500 to-indigo-700", - rain: "from-slate-500 via-slate-600 to-indigo-900", - wind: "from-cyan-600 via-slate-500 to-blue-900", - cold: "from-cyan-400 via-blue-500 to-indigo-800", + warm: "from-sky-400 via-blue-500 to-indigo-700", + rain: "from-slate-500 via-blue-700 to-slate-950", + wind: "from-cyan-600 via-slate-600 to-blue-950", + cold: "from-cyan-300 via-blue-500 to-indigo-900", night: "from-slate-800 via-indigo-950 to-slate-950", - mild: "from-sky-500 via-cyan-600 to-blue-800", + mild: "from-sky-500 via-cyan-700 to-blue-900", }[mood]; } diff --git a/types/imgw.ts b/types/imgw.ts index 7784deb..acb9e97 100644 --- a/types/imgw.ts +++ b/types/imgw.ts @@ -115,4 +115,4 @@ export interface WeatherWarning { office: string | null; } -export type WeatherMood = "clear" | "rain" | "wind" | "cold" | "night" | "mild"; +export type WeatherMood = "warm" | "rain" | "wind" | "cold" | "night" | "mild";