diff --git a/app/(main)/admin/clues/page.js b/app/(main)/admin/clues/page.js
index fd4384c..a549718 100644
--- a/app/(main)/admin/clues/page.js
+++ b/app/(main)/admin/clues/page.js
@@ -29,6 +29,11 @@ export default function AdminCluesPage() {
qr_code: "", // Add QR code field
});
+ const [isReorderMode, setIsReorderMode] = useState(false);
+ const [reorderingClue, setReorderingClue] = useState(null);
+ const [newPosition, setNewPosition] = useState(1);
+ const [reorderMessage, setReorderMessage] = useState("");
+
// Check if user is admin
useEffect(() => {
if (status === "authenticated") {
@@ -91,17 +96,21 @@ export default function AdminCluesPage() {
try {
setLoading(true);
- // Add timestamp parameter to bust cache
+
+ // Make sure to get all clues with a high limit to avoid pagination issues
const timestamp = Date.now();
- const response = await fetch(`/api/admin/clues?t=${timestamp}`, {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- "Cache-Control": "no-cache, no-store, must-revalidate",
- Pragma: "no-cache",
- },
- credentials: "include",
- });
+ const response = await fetch(
+ `/api/admin/clues?t=${timestamp}&limit=100`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ "Cache-Control": "no-cache, no-store, must-revalidate",
+ Pragma: "no-cache",
+ },
+ credentials: "include",
+ }
+ );
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
@@ -117,8 +126,11 @@ export default function AdminCluesPage() {
throw new Error("Invalid response format from server");
}
- console.log("Fetched clues:", data); // Debug log to see what's coming from API
- setClues(data);
+ // Sort the clues by ID to ensure correct ordering
+ const sortedClues = [...data].sort((a, b) => a.id - b.id);
+
+ console.log("Fetched clues:", sortedClues);
+ setClues(sortedClues);
setError("");
// Update lastRefresh timestamp
setLastRefresh(Date.now());
@@ -311,6 +323,138 @@ export default function AdminCluesPage() {
}
};
+ // Start reordering a clue
+ const handleReorderStart = (clue) => {
+ // Disable auto-refresh when starting to reorder
+ setAutoRefreshEnabled(false);
+ setReorderingClue(clue);
+ setNewPosition(clue.id); // Default to current position
+ setIsReorderMode(true);
+ };
+
+ // Handle position selection change
+ const handlePositionChange = (e) => {
+ setNewPosition(parseInt(e.target.value));
+ };
+
+ // Cancel reordering
+ const handleCancelReorder = () => {
+ setIsReorderMode(false);
+ setReorderingClue(null);
+ // Re-enable auto-refresh
+ setAutoRefreshEnabled(true);
+ };
+
+ // Submit reorder request
+ const handleReorderSubmit = async (e) => {
+ e.preventDefault();
+
+ if (!reorderingClue || newPosition < 1 || newPosition > clues.length) {
+ setError("Invalid position selected");
+ return;
+ }
+
+ try {
+ setLoading(true);
+ setReorderMessage("");
+
+ // Store reordering info for success message
+ const clueTitle = reorderingClue.title;
+ const targetPosition = newPosition;
+
+ const response = await fetch("/api/admin/clues/reorder", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify({
+ clueId: reorderingClue.id,
+ newPosition: newPosition,
+ }),
+ credentials: "include",
+ });
+
+ const data = await response.json();
+
+ if (!response.ok) {
+ throw new Error(
+ data.error || `Failed to reorder clue (Status: ${response.status})`
+ );
+ }
+
+ // Success message
+ setReorderMessage(
+ `Clue "${clueTitle}" moved to position ${targetPosition} successfully`
+ );
+
+ // Reset all state to ensure fresh data
+ setClues([]);
+ setIsReorderMode(false);
+ setReorderingClue(null);
+ setError("");
+
+ // Force a complete refresh with delay to allow database to complete operations
+ setTimeout(async () => {
+ try {
+ await fetchClues();
+ console.log("Clues refreshed after reordering");
+ } catch (refreshError) {
+ console.error("Error refreshing clues after reorder:", refreshError);
+ setError(
+ "Reordering succeeded but failed to refresh the list. Please reload the page."
+ );
+ }
+ }, 800);
+ } catch (err) {
+ console.error("Error reordering clue:", err);
+ setError(err.message);
+ setLoading(false);
+ }
+ };
+
+ // Add a function to force a hard refresh that bypasses cache
+ const forceHardRefresh = async () => {
+ try {
+ setLoading(true);
+ setClues([]);
+
+ // Clear browser cache for this specific request
+ const timestamp = Date.now();
+ const response = await fetch(
+ `/api/admin/clues?t=${timestamp}&forceRefresh=true`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ "Cache-Control": "no-cache, no-store, must-revalidate",
+ Pragma: "no-cache",
+ Expires: "0",
+ },
+ credentials: "include",
+ }
+ );
+
+ if (!response.ok) {
+ throw new Error(`Failed to refresh clues (Status: ${response.status})`);
+ }
+
+ const data = await response.json();
+
+ // Sort the clues by ID to ensure correct ordering
+ const sortedClues = [...data].sort((a, b) => a.id - b.id);
+
+ console.log("Force refreshed clues:", sortedClues);
+ setClues(sortedClues);
+ setLastRefresh(Date.now());
+ setNextRefresh(10);
+ } catch (err) {
+ console.error("Error during hard refresh:", err);
+ setError(`Refresh failed: ${err.message}. Try reloading the page.`);
+ } finally {
+ setLoading(false);
+ }
+ };
+
if (status === "loading" || loading) {
return
Loading...
;
}
@@ -350,199 +494,254 @@ export default function AdminCluesPage() {
{error && {error}
}
{fixMessage && {fixMessage}
}
- {/* Add New Clue Form */}
- {!isEditMode ? (
+ {/* Reordering Modal */}
+ {isReorderMode ? (
- ) : (
-
-
Edit Clue
-
- )}
+ ) : (
+ <>
+ {/* Add New Clue Form */}
+ {!isEditMode ? (
+
+
Add New Clue
+