diff --git a/src/components/atoms/MoonIcon.tsx b/src/components/atoms/MoonIcon.tsx new file mode 100644 index 0000000..510b489 --- /dev/null +++ b/src/components/atoms/MoonIcon.tsx @@ -0,0 +1,88 @@ +import clsx from "clsx"; +import { useMemo } from "react"; + +interface MoonIconProps { + lat: number; + phase: number; +} + +const ease = (x: number) => 1 - Math.sqrt(1 - Math.pow(x, 2)); + +export const MoonIcon = ({ lat, phase }: MoonIconProps) => { + const isGibbous = useMemo(() => phase >= 0.25 && phase < 0.75, [phase]); + + const scale = useMemo(() => { + const min = 1; + const max = 4; + + if (phase < 0.25) { + return min + (phase / 0.25) * (max - min); + } else if (phase < 0.5) { + return max - ((phase - 0.25) / 0.25) * (max - min); + } else if (phase < 0.75) { + return min + ((phase - 0.5) / 0.25) * (max - min); + } else { + return max - ((phase - 0.75) / 0.25) * (max - min); + } + }, [phase]); + + const translation = useMemo(() => { + if (phase < 0.25) { + const min = 32; + const max = 36; + + return min + (phase / 0.25) * (max - min); + } else if (phase < 0.5) { + const min = 64; + const max = 36; + + return max - ease((phase - 0.25) / 0.25) * (max - min); + } else if (phase < 0.75) { + const min = 64; + const max = 68; + + return min + ((phase - 0.5) / 0.25) * (max - min); + } else { + const min = 96; + const max = 68; + + return max - ease((phase - 0.75) / 0.25) * (max - min); + } + }, [phase]); + + const maskStyles = "w-8 h-8 rounded-full"; + + return ( +
+ {/* Background */} +
+ +
+ {/* Right mask */} +
+ + {/* Center mask */} +
+ + {/* Left mask */} +
+
+ + {/* Shadow overlay */} +
+
+ ); +}; diff --git a/src/components/atoms/WeatherIcon.tsx b/src/components/atoms/WeatherIcon.tsx index df0d178..d0cae7a 100644 --- a/src/components/atoms/WeatherIcon.tsx +++ b/src/components/atoms/WeatherIcon.tsx @@ -18,7 +18,7 @@ export const WeatherIcon = ({ ); const scaleMapStyles = { - 1: "drop-shadow-sm", + 1: "drop-shadow-md", 2: "drop-shadow-xl", 4: "drop-shadow-2xl", }; @@ -26,7 +26,11 @@ export const WeatherIcon = ({ return ( { + const { data } = useWeatherStore(); + + return ( +
  • + Moon phase + +
    +
    +
    + + Moonrise + + + {new Date( + getAdjustedTime(data.timezone_offset, data.daily[0].moonrise) + ).toLocaleTimeString("en-gb", { timeStyle: "short" })} + +
    +
    + + Moonset + + + {new Date( + getAdjustedTime(data.timezone_offset, data.daily[0].moonset) + ).toLocaleTimeString("en-gb", { timeStyle: "short" })} + +
    +
    + + +
      + {data.daily.map((day, index) => ( +
    • + + {getMoonPhase(day.moon_phase)} + + + + + + {getMoonIllumination(day.moon_phase).toFixed()}% + + + +
    • + ))} +
    +
    +
    +
  • + ); +}; diff --git a/src/components/organisms/CurrentConditions.tsx b/src/components/organisms/CurrentConditions.tsx index 3cdd706..056b3cb 100644 --- a/src/components/organisms/CurrentConditions.tsx +++ b/src/components/organisms/CurrentConditions.tsx @@ -1,5 +1,6 @@ import { SkipToContent } from "../atoms/SkipToContent"; import { HumidityCard } from "../molecules/HumidityCard"; +import { MoonPhaseCard } from "../molecules/MoonPhaseCard"; import { PressureCard } from "../molecules/PressureCard"; import { SunriseAndSunsetCard } from "../molecules/SunriseAndSunsetCard"; import { UVCard } from "../molecules/UVCard"; @@ -22,6 +23,7 @@ export const CurrentConditions = () => { + ); diff --git a/src/components/organisms/DailyForecast.tsx b/src/components/organisms/DailyForecast.tsx index 92e2aed..51949dc 100644 --- a/src/components/organisms/DailyForecast.tsx +++ b/src/components/organisms/DailyForecast.tsx @@ -48,7 +48,7 @@ export const DailyForecast = () => { {Math.round(item.pop * 10) * 10 > 0 && ( {Math.round(item.pop * 10) * 10}% diff --git a/src/components/organisms/HourlyForecast.tsx b/src/components/organisms/HourlyForecast.tsx index 3012ab2..fd38af8 100644 --- a/src/components/organisms/HourlyForecast.tsx +++ b/src/components/organisms/HourlyForecast.tsx @@ -26,7 +26,7 @@ export const HourlyForecast = () => { {data.hourly.map((item, index) => (
  • { {Math.round(item.pop * 10) * 10 > 0 ? ( {Math.round(item.pop * 10) * 10}% ) : ( -
    +
    )}
    { />