diff --git a/components/ColorMenu.tsx b/components/ColorMenu.tsx index 57d7920..defdfe4 100644 --- a/components/ColorMenu.tsx +++ b/components/ColorMenu.tsx @@ -11,6 +11,7 @@ export default function ColorMenu(props: { }) { const [customColor, setCustomColor] = useState(props.currentColor); const [sliderPosition, setSliderPosition] = useState(0); + const [shouldSmoothAnimate, setShouldSmoothAnimate] = useState(false); const gradientRef = useRef(null); const isDraggingRef = useRef(false); @@ -175,6 +176,10 @@ export default function ColorMenu(props: { const x = e.clientX - rect.left; // Immediately update slider position and color + setShouldSmoothAnimate(true); + setTimeout(() => { + setShouldSmoothAnimate(false); + }, 100); setSliderPosition(x); processColorAtPosition(x); @@ -254,7 +259,11 @@ export default function ColorMenu(props: { /> {/* Slider indicator */}
void; + redo: () => void; + event: Event; + eventLocations: Location[]; +}) { + const isMobile = /Mobi|Android/i.test(navigator?.userAgent); + + const { event, eventLocations } = props; + const router = useRouter(); + + return ( + + + + + + + + + + + + + + + + + + + router.push("/home")} + style={{ color: "black" }} + > + + + + + + + ); +} diff --git a/components/EventFlow.tsx b/components/EventFlow.tsx index a3e7376..a977ca3 100644 --- a/components/EventFlow.tsx +++ b/components/EventFlow.tsx @@ -27,7 +27,7 @@ import { ActiveNodeContext, IconNode } from "@components/IconNode"; import { CustomImageNode } from "@components/CustomImageNode"; import Legend from "@components/Legend"; import EventMapSelect from "@components/EventMapSelect"; -import StateButtons from "./stateButtons"; +import ControlButtons from "./ControlButtons"; // Types import { CustomNode } from "@/types/CustomNode"; @@ -451,9 +451,6 @@ function Flow({ return (
-

- {event.name} -

- - + + {/* Hide legend on view only mode */} {isEditable && } {isEditable && ( - )} - +
diff --git a/components/EventMapSelect.tsx b/components/EventMapSelect.tsx index d7f0d21..1384e38 100644 --- a/components/EventMapSelect.tsx +++ b/components/EventMapSelect.tsx @@ -11,64 +11,101 @@ import { Location } from "@prisma/client"; import { Panel } from "@xyflow/react"; import { useParams, useRouter } from "next/navigation"; import { useState } from "react"; -import NavButtons from "./navButtons"; +import { IconButton, Tooltip } from "@mui/material"; +import { ArrowBigLeftDash, ArrowBigRightDash } from "lucide-react"; interface EventMapsSelectProps { + eventName: string; eventId: string; locations: Location[]; } export default function EventMapsSelect({ + eventName, eventId, locations, }: EventMapsSelectProps) { const router = useRouter(); const params = useParams(); - const [isOpen, setIsOpen] = useState(false); + const locationIds = locations.map((l) => l.id.toString()); + + function nextLocation(direction: "forward" | "backward") { + const currId = (params.locationId || locationIds[0]).toString(); + const currIndex = locationIds.indexOf(currId) || 0; + + const offset = direction === "forward" ? 1 : -1; + const newIndex = + (currIndex + offset + locationIds.length) % locationIds.length; + + if (params.mode && params.eventId && locationIds[newIndex]) { + router.push( + `/event/${params.mode}/${params.eventId}/${locationIds[newIndex]}` + ); + } + } + return ( - -
- - - - - - - - Choose a Different Map - - {locations - .filter((v) => v.id === params.locationId?.[0]) - .map((location) => ( -
- - Current - - {location.name} -
- ))} - {locations - .filter((v) => v.id !== params.locationId?.[0]) - .map((location) => ( - - ))} -
-
+ +
+

{eventName}

+
+ + nextLocation("backward")} + style={{ color: "black" }} + > + + + + + + + + + + Choose a Different Map + + {locations + .filter((v) => v.id === params.locationId?.[0]) + .map((location) => ( +
+ + Current + + {location.name} +
+ ))} + {locations + .filter((v) => v.id !== params.locationId?.[0]) + .map((location) => ( + + ))} +
+
+ + nextLocation("forward")} + style={{ color: "black" }} + > + + + +
); diff --git a/components/EventSettings.tsx b/components/EventSettings.tsx index 0be504e..b7afc32 100644 --- a/components/EventSettings.tsx +++ b/components/EventSettings.tsx @@ -32,6 +32,7 @@ import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { z } from "zod"; import LocationAdder from "@/components/LocationCreator"; +import { Tooltip } from "@mui/material"; const formSchema = z.object({ eventName: z.string().min(1, "Event name is required"), @@ -89,139 +90,144 @@ export default function EventSettings({ }, [currentLocations, form, event.isGS]); return ( - <> - - - - - - - Event Settings - -
- - {/* Event Name Input */} - ( -
- - -
- )} - /> - {/* Event Location select */} - ( -
- -
+ +
+ + + + + + + Event Settings + + + + {/* Event Name Input */} + ( +
+ + +
+ )} + /> + {/* Event Location select */} + ( +
+
{ - setLocationAdderOpen(true); - }} + 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" > -
- - Add Location -
-
- {field.value?.map((location, index) => (
{ + setLocationAdderOpen(true); + }} > -

- {currentLocations.find((v) => v.id === location) - ?.name ?? location} -

- { - field.onChange([ - ...(field.value?.slice(0, index) ?? []), - ...(field.value?.slice(index + 1) ?? []), - ]); - }} - /> +
+ + Add Location +
- ))} -
-
- )} - /> - {/* Getting Started weekend switch */} - ( - -
- - Getting Started - - - Is this event related to getting started weekend? - + {field.value?.map((location, index) => ( +
+

+ {currentLocations.find((v) => v.id === location) + ?.name ?? location} +

+ { + field.onChange([ + ...(field.value?.slice(0, index) ?? []), + ...(field.value?.slice(index + 1) ?? []), + ]); + }} + /> +
+ ))} +
- - - - - )} - /> -
- - -
- - - -
- - setCurrentLocations(newLocations) - } - shouldUpdateDB={true} - isOpen={locationAdderOpen} - onClose={() => setLocationAdderOpen(false)} - /> - + )} + /> + {/* Getting Started weekend switch */} + ( + +
+ + Getting Started + + + Is this event related to Getting Started weekend? + +
+ + + +
+ )} + /> +
+ + +
+ + + + + + setCurrentLocations(newLocations) + } + shouldUpdateDB={true} + isOpen={locationAdderOpen} + onClose={() => setLocationAdderOpen(false)} + /> +
+ ); } diff --git a/components/IconNode.tsx b/components/IconNode.tsx index 9ff5cb1..efb25ef 100644 --- a/components/IconNode.tsx +++ b/components/IconNode.tsx @@ -9,13 +9,11 @@ import { import { Textarea } from "@/components/ui/textarea"; import { CustomNode } from "@/types/CustomNode"; import ColorMenu from "@components/ColorMenu"; -import ContentPasteIcon from "@mui/icons-material/ContentPaste"; -import QueueIcon from "@mui/icons-material/Queue"; import { Box, IconButton, Typography, Tooltip } from "@mui/material"; import { createId } from "@paralleldrive/cuid2"; import { NodeProps, useReactFlow } from "@xyflow/react"; import * as Icons from "lucide-react"; -import { Trash2 } from "lucide-react"; +import { Trash, Clipboard, CopyPlus } from "lucide-react"; import { useParams } from "next/navigation"; import { createContext, @@ -52,6 +50,14 @@ export function IconNode({ data, id }: NodeProps) { useEffect(() => { if (isOpen) { setActiveNodeId(id); + + // Prevent auto-focus on form elements by removing focus after a brief delay + setTimeout(() => { + // If an element is focused, blur it + if (document.activeElement instanceof HTMLElement) { + document.activeElement.blur(); + } + }, 0); } }, [isOpen, id, setActiveNodeId]); @@ -233,7 +239,7 @@ export function IconNode({ data, id }: NodeProps) {
{isEditable && (
- +
)}