From 817b976392532437b175e3fb1f4808b579467663 Mon Sep 17 00:00:00 2001
From: Isaac Lloyd <57055268+theisaaclloyd@users.noreply.github.com>
Date: Fri, 18 Apr 2025 23:29:17 -0500
Subject: [PATCH 1/3] added map loading screen
---
.../[eventId]/[[...locationId]]/loading.tsx | 76 +++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx
diff --git a/app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx b/app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx
new file mode 100644
index 0000000..71ca779
--- /dev/null
+++ b/app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx
@@ -0,0 +1,76 @@
+"use client";
+
+import Heading from "@components/Heading";
+import { useEffect, useState } from "react";
+
+const PinpointLoader = () => {
+ const [progress, setProgress] = useState(0);
+ const [loadingText, setLoadingText] = useState("Initializing maps");
+
+ useEffect(() => {
+ // Loading phrases...
+ const loadingPhrases = [
+ "Initializing maps",
+ "Loading terrain data",
+ "Preparing navigation",
+ "Calculating routes",
+ "Syncing location data",
+ "Rendering map tiles",
+ // "Phoning Brian..."
+ // "Checking Teams"
+ // "Waiting for my carmelo"
+ ];
+
+ // fake loading progress
+ const interval = setInterval(() => {
+ setProgress((prev) => {
+ if (prev >= 100) {
+ clearInterval(interval);
+ return 100;
+ }
+ return prev + 1;
+ });
+
+ // Change loading text every now and then
+ if (progress % 16 === 0) {
+ const nextPhrase =
+ loadingPhrases[Math.floor((progress / 16) % loadingPhrases.length)];
+ setLoadingText(nextPhrase);
+ }
+ }, 80);
+
+ return () => clearInterval(interval);
+ }, [progress]);
+
+ return (
+
+
+ {/* Logo */}
+
+
+
+
+ {/* Loading progress */}
+
+
+
+ {loadingText}
+
+
+ {progress}%
+
+
+
+
+
+
+
+ );
+};
+
+export default PinpointLoader;
From 3b9842bb33145ca26e7c852d10ab3080fdd95d55 Mon Sep 17 00:00:00 2001
From: Isaac Lloyd <57055268+theisaaclloyd@users.noreply.github.com>
Date: Fri, 18 Apr 2025 23:34:53 -0500
Subject: [PATCH 2/3] locations loading spinner
---
components/EventSelectForm.tsx | 80 +++++++++++++++++++---------------
1 file changed, 46 insertions(+), 34 deletions(-)
diff --git a/components/EventSelectForm.tsx b/components/EventSelectForm.tsx
index 0dbaa4e..34bdce3 100644
--- a/components/EventSelectForm.tsx
+++ b/components/EventSelectForm.tsx
@@ -10,6 +10,7 @@ import {
Select,
SelectChangeEvent,
Typography,
+ CircularProgress,
} from "@mui/material";
import { Label } from "./ui/label";
import { Plus, Trash } from "lucide-react";
@@ -51,6 +52,7 @@ export default function EventSelectForm({
Location[]
>([]);
const [locationAdderOpen, setLocationAdderOpen] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [entityToDelete, setEntityToDelete] = useState<{
@@ -89,6 +91,7 @@ export default function EventSelectForm({
const handleChange = async (e: SelectChangeEvent) => {
setEventSelected(true);
+ setIsLoading(true);
const selectedEventId = e.target.value;
setEventId(selectedEventId);
@@ -111,6 +114,7 @@ export default function EventSelectForm({
setSelectedEventLocations(updatedLocations ?? []);
}
+ setIsLoading(false);
};
const { data: session } = useSession();
@@ -203,43 +207,51 @@ export default function EventSelectForm({
id="eventLocations"
className="space-y-2 rounded-md border-gray-200 border-2 p-2 pt-0 transition-all duration-300 max-h-[45vh] overflow-y-auto"
>
- {
- setLocationAdderOpen(true);
- }}
- >
-
-
- Add Location
+ {isLoading ? (
+
+
-
- {selectedEventLocations.map((location) => (
-
{
- // Prevent the click event from triggering when clicking the trash button
- if ((e.target as HTMLElement).closest(".trash-button"))
- return;
- router.push(`/event/edit/${eventId}/${location.id}`);
- }}
- >
-
- {location.name}{" "}
+ ) : (
+ <>
+
{
+ setLocationAdderOpen(true);
+ }}
+ >
+
- {canEdit && (
-
(
+ {
- e.stopPropagation();
- setDeleteDialogOpen(true);
- setEntityToDelete({ entity: location, type: "location" });
+ // Prevent the click event from triggering when clicking the trash button
+ if ((e.target as HTMLElement).closest(".trash-button"))
+ return;
+ router.push(`/event/edit/${eventId}/${location.id}`);
}}
- />
- )}
-
- ))}
+ >
+
+ {location.name}{" "}
+
+ {canEdit && (
+ {
+ e.stopPropagation();
+ setDeleteDialogOpen(true);
+ setEntityToDelete({ entity: location, type: "location" });
+ }}
+ />
+ )}
+
+ ))}
+ >
+ )}
)}
@@ -329,4 +341,4 @@ export default function EventSelectForm({
/>
);
-}
+}
\ No newline at end of file
From fad7d740aaf49753f93a2774a1ab454b61537fda Mon Sep 17 00:00:00 2001
From: Ashlyn DeVries
Date: Wed, 23 Apr 2025 14:17:23 -0400
Subject: [PATCH 3/3] minor ui thangs
---
components/EventSelectForm.tsx | 41 ++++++++++++-------
.../PinpointLoader.tsx | 34 +++++++--------
2 files changed, 44 insertions(+), 31 deletions(-)
rename app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx => components/PinpointLoader.tsx (69%)
diff --git a/components/EventSelectForm.tsx b/components/EventSelectForm.tsx
index 34bdce3..3ae526f 100644
--- a/components/EventSelectForm.tsx
+++ b/components/EventSelectForm.tsx
@@ -15,11 +15,11 @@ import {
import { Label } from "./ui/label";
import { Plus, Trash } from "lucide-react";
import { Event, Location } from "@prisma/client";
-import LocationAdder from "./LocationCreator";
-
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
-import { useState } from "react";
+import { useState, startTransition } from "react";
+import LocationAdder from "./LocationCreator";
+import PinpointLoader from "./PinpointLoader";
import {
AlertDialog,
@@ -46,24 +46,23 @@ export default function EventSelectForm({
events: Array;
}) {
const router = useRouter();
+
const [eventSelected, setEventSelected] = useState(false);
const [eventId, setEventId] = useState("");
- const [selectedEventLocations, setSelectedEventLocations] = useState<
- Location[]
- >([]);
const [locationAdderOpen, setLocationAdderOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
-
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
+ const [insertDialogOpen, setInsertDialogOpen] = useState(false);
+ const [eventToCreate, setEventToCreate] = useState("");
+ const [dropdownEvents, setDropdownEvents] = useState(events);
+ const [isNavigating, setIsNavigating] = useState(false);
const [entityToDelete, setEntityToDelete] = useState<{
entity: Event | Location;
type: "event" | "location";
}>();
-
- const [insertDialogOpen, setInsertDialogOpen] = useState(false);
- const [eventToCreate, setEventToCreate] = useState("");
-
- const [dropdownEvents, setDropdownEvents] = useState(events);
+ const [selectedEventLocations, setSelectedEventLocations] = useState<
+ Location[]
+ >([]);
function deleteEvent(id: string) {
DeleteEntity("event", id);
@@ -232,7 +231,14 @@ export default function EventSelectForm({
// Prevent the click event from triggering when clicking the trash button
if ((e.target as HTMLElement).closest(".trash-button"))
return;
- router.push(`/event/edit/${eventId}/${location.id}`);
+
+ // Show loading immediately
+ setIsNavigating(true);
+
+ // Use startTransition for the navigation to indicate it's a UI update
+ startTransition(() => {
+ router.push(`/event/edit/${eventId}/${location.id}`);
+ });
}}
>
@@ -244,7 +250,10 @@ export default function EventSelectForm({
onClick={(e) => {
e.stopPropagation();
setDeleteDialogOpen(true);
- setEntityToDelete({ entity: location, type: "location" });
+ setEntityToDelete({
+ entity: location,
+ type: "location",
+ });
}}
/>
)}
@@ -339,6 +348,8 @@ export default function EventSelectForm({
setSelectedEventLocations((prev) => [...prev, location]);
}}
/>
+
+ {isNavigating &&
}
);
-}
\ No newline at end of file
+}
diff --git a/app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx b/components/PinpointLoader.tsx
similarity index 69%
rename from app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx
rename to components/PinpointLoader.tsx
index 71ca779..1c1aa3c 100644
--- a/app/event/[mode]/[eventId]/[[...locationId]]/loading.tsx
+++ b/components/PinpointLoader.tsx
@@ -5,7 +5,7 @@ import { useEffect, useState } from "react";
const PinpointLoader = () => {
const [progress, setProgress] = useState(0);
- const [loadingText, setLoadingText] = useState("Initializing maps");
+ const [loadingText, setLoadingText] = useState("Initializing maps...");
useEffect(() => {
// Loading phrases...
@@ -16,12 +16,9 @@ const PinpointLoader = () => {
"Calculating routes",
"Syncing location data",
"Rendering map tiles",
- // "Phoning Brian..."
- // "Checking Teams"
- // "Waiting for my carmelo"
];
- // fake loading progress
+ // Fake loading progress
const interval = setInterval(() => {
setProgress((prev) => {
if (prev >= 100) {
@@ -33,8 +30,9 @@ const PinpointLoader = () => {
// Change loading text every now and then
if (progress % 16 === 0) {
- const nextPhrase =
- loadingPhrases[Math.floor((progress / 16) % loadingPhrases.length)];
+ const nextPhrase = `${
+ loadingPhrases[Math.floor((progress / 16) % loadingPhrases.length)]
+ }...`;
setLoadingText(nextPhrase);
}
}, 80);
@@ -43,7 +41,12 @@ const PinpointLoader = () => {
}, [progress]);
return (
-
+
{/* Logo */}
@@ -53,18 +56,17 @@ const PinpointLoader = () => {
{/* Loading progress */}
-
- {loadingText}
-
-
- {progress}%
-
+
{loadingText}
+
{progress}%