116 lines
4.1 KiB
TypeScript
Raw Normal View History

2025-03-23 15:24:10 +00:00
"use client";
2025-05-27 13:22:42 +01:00
import { useMemo, useState } from "react";
2025-05-04 16:04:44 +01:00
import useSWR from "swr";
2025-05-12 13:25:57 +01:00
import Map from "@components/Map";
2025-05-04 16:04:44 +01:00
import Sidebar from "@components/Sidebar";
2025-05-27 13:22:42 +01:00
import { createPoster } from "@utils/axiosHelpers";
2025-05-27 13:12:19 +01:00
import { Earthquake } from "@prismaclient";
import { getRelativeDate } from "@utils/formatters";
2025-06-01 14:18:32 +01:00
import GeologicalEvent from "@appTypes/GeologicalEvent";
2025-05-31 23:25:51 +01:00
import EarthquakeSearchModal from "@components/EarthquakeSearchModal";
import EarthquakeLogModal from "@components/EarthquakeLogModal"; // If you use a separate log modal
2025-05-31 21:25:59 +01:00
import { useStoreState } from "@hooks/store";
export default function Earthquakes() {
2025-06-01 14:18:32 +01:00
const [selectedEventId, setSelectedEventId] = useState("");
const [hoveredEventId, setHoveredEventId] = useState("");
const [searchModalOpen, setSearchModalOpen] = useState(false);
const [logModalOpen, setLogModalOpen] = useState(false);
const [noAccessModalOpen, setNoAccessModalOpen] = useState(false);
2025-05-31 21:25:59 +01:00
2025-06-01 14:18:32 +01:00
const user = useStoreState((state) => state.user);
const canLogEarthquake = user?.role === "SCIENTIST" || user?.role === "ADMIN";
2025-05-31 21:25:59 +01:00
2025-06-01 14:18:32 +01:00
const { data, error, isLoading, mutate } = useSWR("/api/earthquakes", createPoster({ rangeDaysPrev: 10 }));
2025-05-31 21:25:59 +01:00
2025-06-01 14:18:32 +01:00
// Shape for Map/Sidebar
const earthquakeEvents = useMemo(
() =>
data && data.earthquakes
? data.earthquakes
.map(
(x: Earthquake): GeologicalEvent => ({
id: x.code,
title: `Earthquake in ${x.location || (x.code && x.code.split("-")[2])}`,
magnitude: x.magnitude,
longitude: x.longitude,
latitude: x.latitude,
text1: "",
text2: getRelativeDate(x.date),
date: x.date,
code: x.code,
})
)
.sort((a: GeologicalEvent, b: GeologicalEvent) => new Date(b.date).getTime() - new Date(a.date).getTime())
: [],
[data]
);
2025-05-31 21:25:59 +01:00
2025-06-01 14:18:32 +01:00
// Handler for log
const handleLogClick = () => {
if (canLogEarthquake) {
setLogModalOpen(true);
} else {
setNoAccessModalOpen(true);
}
};
2025-05-31 21:25:59 +01:00
function NoAccessModal({ open, onClose }: { open: typeof noAccessModalOpen; onClose: () => void }) {
if (!open) return null;
return (
<div className="fixed z-50 inset-0 bg-black/40 flex items-center justify-center">
<div className="bg-white rounded-lg shadow-lg p-8 max-w-xs w-full text-center relative">
<button onClick={onClose} className="absolute right-4 top-4 text-gray-500 hover:text-black text-lg" aria-label="Close">
&times;
</button>
<h2 className="font-bold text-xl mb-4">Access Denied</h2>
<p className="text-gray-600 mb-3">
Sorry, you do not have access rights to Log an Earthquake. Please Log in here, or contact an Admin if you believe this
is a mistake
</p>
<button onClick={onClose} className="bg-blue-600 text-white px-6 py-2 rounded hover:bg-blue-700 mt-2">
OK
</button>
</div>
</div>
);
}
2025-06-01 14:18:32 +01:00
return (
<div className="flex h-[calc(100vh-3.5rem)] w-full overflow-hidden">
<div className="flex-grow h-full">
<Map
events={earthquakeEvents}
selectedEventId={selectedEventId}
setSelectedEventId={setSelectedEventId}
hoveredEventId={hoveredEventId}
setHoveredEventId={setHoveredEventId}
mapType="Earthquakes"
/>
</div>
<Sidebar
logTitle="Log an Earthquake"
logSubtitle="Record new earthquakes - time/date, location, magnitude, observatory and scientists"
recentsTitle="Recent Earthquakes"
events={earthquakeEvents}
selectedEventId={selectedEventId}
setSelectedEventId={setSelectedEventId}
hoveredEventId={hoveredEventId}
setHoveredEventId={setHoveredEventId}
button1Name="Log an Earthquake"
button2Name="Search Earthquakes"
onButton1Click={handleLogClick}
onButton2Click={() => setSearchModalOpen(true)}
button1Disabled={!canLogEarthquake}
/>
<EarthquakeSearchModal
open={searchModalOpen}
onClose={() => setSearchModalOpen(false)}
onSelect={(eq) => setSelectedEventId(eq.code)}
/>
<EarthquakeLogModal open={logModalOpen} onClose={() => setLogModalOpen(false)} onSuccess={() => mutate()} />
<NoAccessModal open={noAccessModalOpen} onClose={() => setNoAccessModalOpen(false)} />
</div>
);
}