From 26d727ba067fdfc99e3456e26610934b9b420962 Mon Sep 17 00:00:00 2001
From: Dobromir Yordanov <32433021+dobromiryor@users.noreply.github.com>
Date: Sun, 21 Jul 2024 15:34:58 +0300
Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20implemented=20moon=20phase?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/components/atoms/MoonIcon.tsx | 88 ++++++++++++++++++
src/components/atoms/WeatherIcon.tsx | 8 +-
src/components/molecules/MoonPhaseCard.tsx | 89 +++++++++++++++++++
.../organisms/CurrentConditions.tsx | 2 +
src/components/organisms/DailyForecast.tsx | 2 +-
src/components/organisms/HourlyForecast.tsx | 8 +-
src/utils/getMoonIllumination.ts | 11 +++
src/utils/getMoonPhase.ts | 18 ++++
tailwind.config.ts | 3 +
9 files changed, 222 insertions(+), 7 deletions(-)
create mode 100644 src/components/atoms/MoonIcon.tsx
create mode 100644 src/components/molecules/MoonPhaseCard.tsx
create mode 100644 src/utils/getMoonIllumination.ts
create mode 100644 src/utils/getMoonPhase.ts
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}%
) : (
-
+
)}
{
/>