Skip to content

Commit d06c5bc

Browse files
committed
️🏆🎢 ↝ [SSG-179 SSC-112 SSM-171]: Starting to put events together with a global fetch function across terrariums/locations
1 parent 38b1f0d commit d06c5bc

File tree

4 files changed

+210
-2
lines changed

4 files changed

+210
-2
lines changed

app/tests/page.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
"use client";
22

33
import { PlanetGenerator } from "@/components/Data/Generator/Astronomers/PlanetHunters/PlanetGenerator";
4+
import WeatherEventsOverview from "@/components/Data/Generator/Weather/EventsAcrossMyLocations";
45
import WeatherEventStatus from "@/components/Data/Generator/Weather/EventsCounter";
56
import AlertComponent from "@/components/Structures/Missions/Milestones/Alerts/Alerts";
67
import MilestoneTotalCompleted from "@/components/Structures/Missions/Milestones/Completed";
78
import TotalPoints from "@/components/Structures/Missions/Stardust/Total";
9+
import MyLocationIds from "@/content/Classifications/UserLocationPK";
810
import MySettlementsLocations from "@/content/Classifications/UserLocations";
11+
import { useSession, useSupabaseClient } from "@supabase/auth-helpers-react";
12+
import { useEffect, useState } from "react";
913

1014
export default function TestPage() {
15+
const supabase = useSupabaseClient();
16+
const session = useSession();
17+
const [locationIds, setLocationIds] = useState<number[]>([]);
18+
const [loading, setLoading] = useState<boolean>(true);
19+
20+
useEffect(() => {
21+
async function fetchLocationIds() {
22+
if (!session) return;
23+
const { data, error } = await supabase
24+
.from("classifications")
25+
.select("id")
26+
.eq("author", session.user.id)
27+
.in("classificationtype", ["planet", "telescope-minorPlanet"]);
28+
29+
if (!error && data) {
30+
setLocationIds(data.map((item) => item.id));
31+
}
32+
setLoading(false);
33+
}
34+
35+
fetchLocationIds();
36+
}, [session]);
37+
1138
return (
1239
<div className="min-h-screen bg-black text-white p-4 space-y-8">
1340
{/* <AlertComponent /> */}
@@ -20,6 +47,8 @@ export default function TestPage() {
2047
biomass={0.01}
2148
density={3.5}
2249
/>
50+
<MyLocationIds />
51+
{/* <WeatherEventsOverview classificationInfo={locationIds} /> */}
2352
</div>
2453
);
2554
};
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
'use client';
2+
3+
import { useEffect, useState } from "react";
4+
import { useSupabaseClient } from "@supabase/auth-helpers-react";
5+
import { startOfWeek } from "date-fns";
6+
import { toZonedTime } from "date-fns-tz";
7+
8+
const TIMEZONE = 'Australia/Melbourne';
9+
10+
const biomeToStormMap: Record<string, string> = {
11+
"RockyHighlands": "Dust Storm",
12+
"Barren (Pending)": "Dust Storm",
13+
"Barren Wasteland": "Radiation Storm",
14+
"Arid Dunes": "Sandstorm",
15+
"Frigid Expanse": "Snowstorm",
16+
"Volcanic Terrain": "Ashfall",
17+
"Basalt Plains": "Windstorm",
18+
"Sediment Flats": "Flash Flood",
19+
"Cratered Terrain": "Seismic Shock",
20+
"Tundra Basin": "Ice Storm",
21+
"Temperate Highlands": "Thunderstorm",
22+
"Oceanic World": "Cyclone",
23+
"Tropical Jungle": "Monsoon",
24+
"Flood Basin": "Deluge",
25+
"Coral Reefs": "Supercell",
26+
"Dune Fields": "Heatwave",
27+
};
28+
29+
function getPlanetType(density: number): "terrestrial" | "gaseous" | "ocean" {
30+
if (density >= 3.5) return "terrestrial";
31+
if (density < 1.5) return "gaseous";
32+
return "ocean";
33+
};
34+
35+
interface EventData {
36+
classificationId: number;
37+
eventCount: number;
38+
redeemed: boolean;
39+
nextEventType: string | null;
40+
}
41+
42+
export default function WeatherEventsOverview({
43+
classificationInfo,
44+
}: {
45+
classificationInfo: { id: number; biome: string; biomass: number; density: number }[];
46+
}) {
47+
const supabase = useSupabaseClient();
48+
const [eventsData, setEventsData] = useState<EventData[]>([]);
49+
50+
useEffect(() => {
51+
const fetchEvents = async () => {
52+
if (!classificationInfo || classificationInfo.length === 0) return;
53+
54+
const startOfWeekMelbourne = startOfWeek(toZonedTime(new Date(), TIMEZONE), { weekStartsOn: 1 });
55+
startOfWeekMelbourne.setHours(0, 1, 0, 0);
56+
57+
const classificationIds = classificationInfo.map(c => c.id);
58+
59+
const { data: events, error } = await supabase
60+
.from("events")
61+
.select("*")
62+
.in("classification_location", classificationIds)
63+
.gte("time", startOfWeekMelbourne.toISOString());
64+
65+
if (error) {
66+
console.error("Error fetching events:", error);
67+
return;
68+
}
69+
70+
const grouped: Record<number, { count: number; redeemed: boolean; nextEventType: string | null }> = {};
71+
72+
for (const info of classificationInfo) {
73+
const { id, biome, biomass, density } = info;
74+
const planetType = getPlanetType(density);
75+
76+
grouped[id] = { count: 0, redeemed: false, nextEventType: null };
77+
78+
const eventsForLocation = events.filter(e => e.classification_location === id);
79+
80+
for (const event of eventsForLocation) {
81+
grouped[id].count += 1;
82+
if (event.status === "redeemed") {
83+
grouped[id].redeemed = true;
84+
}
85+
}
86+
87+
if (!grouped[id].redeemed) {
88+
const lightningEventExists = eventsForLocation.some(e =>
89+
e.type?.toLowerCase().includes("lightning")
90+
);
91+
92+
let newEventType: string | null = null;
93+
94+
if (
95+
planetType === "terrestrial" &&
96+
biomass >= 0.000001 &&
97+
biomass <= 0.02 &&
98+
!lightningEventExists
99+
) {
100+
newEventType = "lightning-kickoff";
101+
} else {
102+
newEventType = biomeToStormMap[biome] || "rain-general";
103+
}
104+
105+
grouped[id].nextEventType = newEventType;
106+
}
107+
}
108+
109+
const newData: EventData[] = classificationInfo.map(info => ({
110+
classificationId: info.id,
111+
eventCount: grouped[info.id]?.count || 0,
112+
redeemed: grouped[info.id]?.redeemed || false,
113+
nextEventType: grouped[info.id]?.nextEventType || null,
114+
}));
115+
116+
setEventsData(newData);
117+
};
118+
119+
fetchEvents();
120+
}, [classificationInfo]);
121+
122+
if (eventsData.length === 0) return null;
123+
124+
return (
125+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
126+
{eventsData.map(event => (
127+
<div
128+
key={event.classificationId}
129+
className="bg-black/60 text-white p-4 rounded-lg shadow-md flex flex-col items-center"
130+
>
131+
<div className="text-lg font-semibold">Location ID: {event.classificationId}</div>
132+
<div className="text-sm">Events this week: {event.eventCount}</div>
133+
<div className={`text-sm ${event.redeemed ? 'text-green-400' : 'text-red-400'}`}>
134+
{event.redeemed ? 'Redeemed' : 'Not redeemed'}
135+
</div>
136+
{!event.redeemed && event.nextEventType && (
137+
<div className="text-yellow-400 text-sm mt-2">
138+
Next event: {event.nextEventType}
139+
</div>
140+
)}
141+
</div>
142+
))}
143+
</div>
144+
);
145+
};

components/Data/Generator/Weather/EventsCounter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ export default function WeatherEventStatus({
6565

6666
if (eventsError) {
6767
console.error("Error fetching weather events:", eventsError);
68-
return;
69-
}
68+
return;
69+
};
7070

7171
const hasEvent = events.length > 0;
7272
setHasEventThisWeek(hasEvent);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"use client";
2+
3+
import { useSession, useSupabaseClient } from "@supabase/auth-helpers-react";
4+
import { useEffect, useState } from "react";
5+
6+
export default function MyLocationIds() {
7+
const supabase = useSupabaseClient();
8+
const session = useSession();
9+
const [locationIds, setLocationIds] = useState<number[]>([]);
10+
const [loading, setLoading] = useState<boolean>(true);
11+
12+
useEffect(() => {
13+
async function fetchLocationIds() {
14+
if (!session) return;
15+
const { data, error } = await supabase
16+
.from("classifications")
17+
.select("id")
18+
.eq("author", session.user.id)
19+
.in("classificationtype", ["planet", "telescope-minorPlanet"]);
20+
21+
if (!error && data) {
22+
setLocationIds(data.map((item) => item.id));
23+
}
24+
setLoading(false);
25+
}
26+
27+
fetchLocationIds();
28+
}, [session]);
29+
30+
if (loading) return <p>Loading IDs...</p>;
31+
if (locationIds.length === 0) return <p>No locations found.</p>;
32+
33+
return <p>{locationIds.join(", ")}</p>;
34+
};

0 commit comments

Comments
 (0)