diff --git a/app/(main)/clue/[clueId]/page.js b/app/(main)/clue/[clueId]/page.js index 692e712..c919089 100644 --- a/app/(main)/clue/[clueId]/page.js +++ b/app/(main)/clue/[clueId]/page.js @@ -34,13 +34,17 @@ export default function CluePage({ params }) { const [clueFound, setClueFound] = useState(false); const [allClues, setAllClues] = useState([]); const [nextClueId, setNextClueId] = useState(null); + const [nextClueAvailable, setNextClueAvailable] = useState(false); const [huntActive, setHuntActive] = useState(true); const [previousHuntState, setPreviousHuntState] = useState(true); const [showSuccessNotification, setShowSuccessNotification] = useState(false); + const [showNavErrorNotification, setShowNavErrorNotification] = + useState(false); const [teamData, setTeamData] = useState(null); const router = useRouter(); const { data: session, status } = useSession(); const notificationTimeoutRef = useRef(null); + const navErrorTimeoutRef = useRef(null); // Check if user is admin const isAdmin = session?.user?.role === "admin"; @@ -78,7 +82,10 @@ export default function CluePage({ params }) { // Find next clue for navigation const currentIndex = data.findIndex((c) => c.id === parseInt(clueId)); if (currentIndex !== -1 && currentIndex < data.length - 1) { - setNextClueId(data[currentIndex + 1].id); + const nextClue = data[currentIndex + 1]; + setNextClueId(nextClue.id); + // Set if the next clue is available (already found or is the next unfound clue) + setNextClueAvailable(nextClue.found || nextClue.available); } } return data; @@ -340,19 +347,38 @@ export default function CluePage({ params }) { } }; - // Clear notification timeout on component unmount + // Clear notification timeouts on component unmount useEffect(() => { return () => { if (notificationTimeoutRef.current) { clearTimeout(notificationTimeoutRef.current); } + if (navErrorTimeoutRef.current) { + clearTimeout(navErrorTimeoutRef.current); + } }; }, []); // Navigate to the next clue const handleNextClue = () => { if (nextClueId) { - router.push(`/clue/${nextClueId}`); + // Check if next clue is available before navigating + if (nextClueAvailable || isAdmin) { + router.push(`/clue/${nextClueId}`); + } else { + // Show notification that the next clue is locked + setShowNavErrorNotification(true); + + // Clear previous timeout if it exists + if (navErrorTimeoutRef.current) { + clearTimeout(navErrorTimeoutRef.current); + } + + // Auto-hide the notification after 3 seconds + navErrorTimeoutRef.current = setTimeout(() => { + setShowNavErrorNotification(false); + }, 3000); + } } else { router.push("/map"); } @@ -461,7 +487,31 @@ export default function CluePage({ params }) { )} + {showNavErrorNotification && ( +
+
+
🔒
+
+

Clue Locked

+

+ You need to find this clue first before moving to the next one. +

+
+
+
+ )} +
+ {/* Show a notification when the clue is already found */} + {clueFound && ( +
+
✓
+
+ You've already found this clue! +
+
+ )} + {/* Admin tools section - only visible to admins */} {isAdmin && (
@@ -587,6 +637,66 @@ export default function CluePage({ params }) { margin: 0; } + .nav-error-notification { + position: fixed; + top: 0; + left: 0; + width: 100%; + padding: 20px; + background-color: rgba(0, 0, 0, 0.7); + z-index: 1000; + display: flex; + justify-content: center; + animation: slide-down 0.5s ease-out; + } + + .nav-error-notification-content { + display: flex; + align-items: center; + background-color: #f44336; + color: white; + padding: 15px 25px; + border-radius: 10px; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); + max-width: 400px; + } + + .nav-error-icon { + font-size: 2rem; + margin-right: 15px; + } + + .nav-error-text h3 { + margin: 0 0 5px 0; + font-size: 1.2rem; + } + + .nav-error-text p { + margin: 0; + } + + .clue-found-notification { + display: flex; + align-items: center; + background-color: #e8f5e9; + border-radius: 8px; + padding: 12px 16px; + margin-bottom: 15px; + width: 100%; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + } + + .clue-found-icon { + font-size: 1.5rem; + color: #2e7d32; + margin-right: 12px; + } + + .clue-found-text { + color: #2e7d32; + font-weight: bold; + } + @keyframes slide-down { 0% { transform: translateY(-100%); diff --git a/app/(main)/map/page.js b/app/(main)/map/page.js index a6ee410..a83d252 100644 --- a/app/(main)/map/page.js +++ b/app/(main)/map/page.js @@ -362,7 +362,6 @@ export default function MapPage() { className={styles["map-image"]} /> - {/* Overlay div with the clue button - positioned exactly over the map */}
{/* Hardcoded Clue 1 button */} {firstClue && ( @@ -384,7 +383,6 @@ export default function MapPage() { )} - {/* Add Clue 2 button - positioned 50px more to the right and 30px more down than current position */} {clues.length > 1 && (
diff --git a/clue_hunt.db b/clue_hunt.db index 8f0db0f..3d9f683 100644 Binary files a/clue_hunt.db and b/clue_hunt.db differ