diff --git a/app/form/admin/client.tsx b/app/form/admin/client.tsx
index 364e7e9..82f9d5f 100644
--- a/app/form/admin/client.tsx
+++ b/app/form/admin/client.tsx
@@ -20,6 +20,7 @@ import {
} from "@/app/actions/questions";
import { uploadImage } from "@/app/actions/upload";
import { Plus, Trash, ArrowUp, ArrowDown, Loader2, Save, Image as ImageIcon, X } from "lucide-react";
+import Image from 'next/image';
interface Question {
id: string;
@@ -297,7 +298,8 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
{q.imageUrl ? (
-

;
}
+interface ContextMenuState {
+ visible: boolean;
+ x: number;
+ y: number;
+ questionId: string | null;
+}
+
export default function SubmissionDetailClient({
submission,
questions,
answers,
}: SubmissionDetailClientProps) {
const [copiedId, setCopiedId] = useState
(null);
+ const [contextMenu, setContextMenu] = useState({
+ visible: false,
+ x: 0,
+ y: 0,
+ questionId: null,
+ });
+ const menuRef = useRef(null);
const handleCopy = (text: string, id: string) => {
if (!text) return;
@@ -41,12 +56,48 @@ export default function SubmissionDetailClient({
setTimeout(() => setCopiedId(null), 2000);
};
+ const handleContextMenu = (e: React.MouseEvent, questionId: string) => {
+ e.preventDefault();
+ setContextMenu({ visible: true, x: e.clientX, y: e.clientY, questionId });
+ };
+
+ const closeMenu = () => {
+ setContextMenu((prev) => ({ ...prev, visible: false, questionId: null }));
+ };
+
+ // Close menu on click outside or scroll
+ useEffect(() => {
+ const handleClick = (e: MouseEvent) => {
+ if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
+ closeMenu();
+ }
+ };
+ document.addEventListener("mousedown", handleClick);
+ document.addEventListener("scroll", closeMenu, true);
+ return () => {
+ document.removeEventListener("mousedown", handleClick);
+ document.removeEventListener("scroll", closeMenu, true);
+ };
+ }, []);
+
const userLabel = submission.userName
? `${submission.userName} (${submission.userDiscordId || "N/A"})`
: submission.userDiscordId || "Anonymous";
const editHistory = Array.isArray(submission.editHistory) ? submission.editHistory : [];
+ // Build context menu data for the right-clicked question
+ const ctxQuestion = questions.find((q) => q.id === contextMenu.questionId);
+ const ctxAnswerHistory: { editedAt: string; answer: string }[] = [];
+ if (contextMenu.questionId) {
+ for (const edit of editHistory) {
+ ctxAnswerHistory.push({
+ editedAt: edit.editedAt,
+ answer: edit.oldAnswers[contextMenu.questionId] ?? "",
+ });
+ }
+ }
+
return (
{/* Submission Metadata Card */}
@@ -83,41 +134,32 @@ export default function SubmissionDetailClient({
{questions.map((q) => {
const ansValue = answers[q.id] || "";
-
- // Check if this specific question was edited by comparing current answer with old ones
- let wasEdited = false;
- let oldAnswerForQ = "";
- let lastEditedTime = "";
- if (editHistory.length > 0) {
- // Find the most recent edit where the answer was different
- for (let i = editHistory.length - 1; i >= 0; i--) {
- const oldAns = editHistory[i].oldAnswers[q.id] || "";
- if (oldAns !== ansValue) {
- wasEdited = true;
- oldAnswerForQ = oldAns;
- lastEditedTime = new Date(editHistory[i].editedAt).toLocaleString();
- break;
- }
- }
- }
+ const wasEdited = editHistory.some(
+ (edit) => (edit.oldAnswers[q.id] ?? "") !== ansValue
+ );
return (
-
+ handleContextMenu(e, q.id)}
+ className={wasEdited ? "cursor-context-menu" : ""}
+ >
{wasEdited && (
-
- This section has been edited (last edit: {lastEditedTime})
+
+ edited
)}
{q.imageUrl && (
-
- {/* Current Answer */}
{ansValue ? (
- {wasEdited &&
Current Answer:}
+ {wasEdited && (
+
+ Current Answer:
+
+ )}
{ansValue}
@@ -153,23 +198,84 @@ export default function SubmissionDetailClient({
No response provided
)}
-
- {/* Previous Answer if edited */}
- {wasEdited && (
-
-
- Previous Answer:
-
- {oldAnswerForQ || No previous response}
-
-
-
- )}
);
})}
+
+ {/* Context Menu */}
+ {contextMenu.visible && ctxQuestion && (
+
+ {/* Header */}
+
+
+ History
+
+
+ {ctxQuestion.label}
+
+
+
+ {/* Edit History timestamps */}
+ {editHistory.length > 0 && (
+
+
+ Edit History:
+
+
+ {editHistory.map((edit, idx) => (
+ -
+
+ {new Date(edit.editedAt).toLocaleString()}
+
+ ))}
+
+
+ )}
+
+ {/* All Previous Answers */}
+
+
+ Previous Answers:
+
+ {ctxAnswerHistory.length === 0 ? (
+
No edit history for this question.
+ ) : (
+
+ {ctxAnswerHistory.map((entry, idx) => (
+
+
+
+ {new Date(entry.editedAt).toLocaleString()}
+
+
+ {entry.answer || No response}
+
+
+ ))}
+
+ )}
+
+
+ {/* Footer */}
+
+
+
+
+ )}
);
}
diff --git a/components/delete-form-button.tsx b/components/delete-form-button.tsx
index 56a271b..6cdcdb1 100644
--- a/components/delete-form-button.tsx
+++ b/components/delete-form-button.tsx
@@ -39,7 +39,7 @@ export default function DeleteFormButton({ formId }: DeleteFormButtonProps) {
return (