117 lines
4.1 KiB
TypeScript
117 lines
4.1 KiB
TypeScript
"use client";
|
|
import { useState, useMemo } from "react";
|
|
import useSWR from "swr";
|
|
import Sidebar from "@/components/Sidebar";
|
|
import Map from "@components/Map";
|
|
import LogObservatoryModal from "@/components/LogObservatoryModal"; // Adjust if your path is different
|
|
import { fetcher } from "@utils/axiosHelpers";
|
|
import { Observatory } from "@prismaclient";
|
|
import { getRelativeDate } from "@utils/formatters";
|
|
import GeologicalEvent from "@appTypes/Event";
|
|
import { useStoreState } from "@hooks/store";
|
|
|
|
function NoAccessModal({ open, onClose }) {
|
|
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"
|
|
>×</button>
|
|
<h2 className="font-bold text-xl mb-4">No Access</h2>
|
|
<p className="text-gray-600 mb-3">Sorry, You do not have access rights, please log in or contact an Admin.</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>
|
|
);
|
|
}
|
|
|
|
export default function Observatories() {
|
|
const [selectedEventId, setSelectedEventId] = useState("");
|
|
const [hoveredEventId, setHoveredEventId] = useState("");
|
|
const [logModalOpen, setLogModalOpen] = useState(false);
|
|
const [noAccessModalOpen, setNoAccessModalOpen] = useState(false);
|
|
|
|
const user = useStoreState((state) => state.user);
|
|
const role: "GUEST" | "SCIENTIST" | "ADMIN" = user?.role ?? "GUEST";
|
|
const canLogObservatory = role === "SCIENTIST" || role === "ADMIN";
|
|
|
|
const { data, error, isLoading, mutate } = useSWR(
|
|
"/api/observatories",
|
|
fetcher
|
|
);
|
|
|
|
const observatoryEvents = useMemo(
|
|
() =>
|
|
data && data.observatories
|
|
? data.observatories
|
|
.map((x: Observatory): GeologicalEvent & { isFunctional: boolean } => ({
|
|
id: x.id.toString(),
|
|
title: ` ${x.name}`,
|
|
longitude: x.longitude,
|
|
latitude: x.latitude,
|
|
isFunctional: x.isFunctional, // <-- include this!
|
|
text1: "",
|
|
text2: getRelativeDate(x.dateEstablished),
|
|
date: x.dateEstablished,
|
|
}))
|
|
.sort(
|
|
(a: GeologicalEvent, b: GeologicalEvent) =>
|
|
new Date(b.date).getTime() - new Date(a.date).getTime()
|
|
)
|
|
: [],
|
|
[data]
|
|
);
|
|
|
|
const handleLogClick = () => {
|
|
if (canLogObservatory) {
|
|
setLogModalOpen(true);
|
|
} else {
|
|
setNoAccessModalOpen(true);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex h-[calc(100vh-3.5rem)] w-full overflow-hidden">
|
|
<div className="flex-grow h-full">
|
|
<Map
|
|
events={observatoryEvents}
|
|
selectedEventId={selectedEventId}
|
|
setSelectedEventId={setSelectedEventId}
|
|
hoveredEventId={hoveredEventId}
|
|
setHoveredEventId={setHoveredEventId}
|
|
mapType="observatories"
|
|
/>
|
|
</div>
|
|
<Sidebar
|
|
logTitle="Observatory Mapping"
|
|
logSubtitle="Record and search observatories - time/date set-up, location, scientists and recent earthquakes"
|
|
recentsTitle="New Observatories"
|
|
events={observatoryEvents}
|
|
selectedEventId={selectedEventId}
|
|
setSelectedEventId={setSelectedEventId}
|
|
hoveredEventId={hoveredEventId}
|
|
setHoveredEventId={setHoveredEventId}
|
|
button1Name="Log a New Observatory"
|
|
button2Name="Search Observatories"
|
|
onButton1Click={handleLogClick}
|
|
button1Disabled={!canLogObservatory}
|
|
/>
|
|
<LogObservatoryModal
|
|
open={logModalOpen}
|
|
onClose={() => setLogModalOpen(false)}
|
|
onSuccess={() => mutate()}
|
|
/>
|
|
<NoAccessModal
|
|
open={noAccessModalOpen}
|
|
onClose={() => setNoAccessModalOpen(false)}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|