-
-
-
{survey.title}
-
{survey.description}
-
-
-
-
-
- {survey.questions.map((question) => (
-
- setAnswers({ ...answers, [question.id]: value })
- }
- />
- ))}
-
+
diff --git a/app/survey/preview/page.tsx b/app/survey/preview/page.tsx
new file mode 100644
index 0000000..3e2cace
--- /dev/null
+++ b/app/survey/preview/page.tsx
@@ -0,0 +1,74 @@
+"use client";
+
+export const dynamic = 'force-dynamic';
+
+import SurveyDisplay from "@/components/survey/survey-display";
+import { createSurveyValidationSchema } from "@/components/survey/validation";
+import { Button } from "@/components/ui/button";
+import Loading from "@/components/ui/loading";
+import { useFormValidation } from "@/hooks/use-form-validation";
+import { generateShareableLink, getSurveyById, loadDraft, saveDraft, saveSurveyResponse } from "@/lib/survey";
+import { Survey } from "@/types/survey";
+import { useParams, useRouter } from "next/navigation";
+import { useEffect, useState } from "react";
+import { toast } from "sonner";
+import z from "zod";
+
+
+export default function PreviewChanges() {
+ const params = useParams();
+ const [survey, setSurvey] = useState
();
+ const [answers, setAnswers] = useState>({});
+ const router = useRouter();
+ const [surveySchema, setSurveySchema] = useState();
+ const { errors, resetError, validate } = useFormValidation(surveySchema)
+ const [isLoading, setIsLoading] = useState(true);
+
+ useEffect(() => {
+ const survey = loadDraft();
+ if (survey) {
+ setSurvey(survey);
+ const surveySchema = createSurveyValidationSchema(survey.questions);
+ setSurveySchema(surveySchema);
+ }
+ setIsLoading(false);
+ }, [params.id]);
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (!survey) {
+ return Survey not found
;
+ }
+
+
+
+ const handleBackToEdit = () => {
+ saveDraft(survey!);
+ const isSurveySaved = getSurveyById(survey!.id);
+ if (isSurveySaved) {
+ router.push(`/edit/${survey.id}`);
+ } else {
+ router.push("/create");
+ }
+ };
+
+ const handleAnswerChange = (questionId: string, value: any) => {
+ setAnswers((prev) => ({ ...prev, [questionId]: value }));
+ // Clear errors for the field when it's changed for a better UX
+ resetError(questionId);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/survey/dnd.tsx b/components/survey/dnd.tsx
new file mode 100644
index 0000000..65b785d
--- /dev/null
+++ b/components/survey/dnd.tsx
@@ -0,0 +1,5 @@
+import React from "react";
+import { DragDropContext, Droppable, Draggable, DropResult } from "@hello-pangea/dnd";
+
+export { DragDropContext, Droppable, Draggable };
+export type { DropResult };
diff --git a/components/survey/question-builder.tsx b/components/survey/question-builder.tsx
index 0fa7571..4c947af 100644
--- a/components/survey/question-builder.tsx
+++ b/components/survey/question-builder.tsx
@@ -13,9 +13,10 @@ interface QuestionBuilderProps {
question: Question;
onUpdate: (question: Question) => void;
onDelete: (id: string) => void;
+ error: string | undefined;
}
-export function QuestionBuilder({ question, onUpdate, onDelete }: QuestionBuilderProps) {
+export function QuestionBuilder({ question, onUpdate, onDelete, error }: QuestionBuilderProps) {
const questionTypes: { value: QuestionType; label: string }[] = [
{ value: "text", label: "Text Input" },
{ value: "checkbox", label: "Checkbox (Multiple Choice)" },
@@ -25,7 +26,17 @@ export function QuestionBuilder({ question, onUpdate, onDelete }: QuestionBuilde
{ value: "date", label: "Date Picker" },
{ value: "rating", label: "Rating" },
];
-
+ let errorMsg;
+ if (error) {
+ // Find the first property with _errors and display its first error message
+ errorMsg = typeof error === "object" && error !== null
+ ? Object.values(error)
+ .flatMap((v: any) => v?._errors || [])
+ .filter(Boolean)[0]
+ : typeof error === "string"
+ ? error
+ : null
+ }
const showOptions = ["checkbox", "radio", "multiselect", "singleselect"].includes(question.type);
const handleOptionAdd = () => {
@@ -122,6 +133,11 @@ export function QuestionBuilder({ question, onUpdate, onDelete }: QuestionBuilde
)}
+ {errorMsg && (
+
+ {errorMsg}
+
+ )}
);
}
\ No newline at end of file
diff --git a/components/survey/question-display.tsx b/components/survey/question-display.tsx
index 2d198f5..c4a4c02 100644
--- a/components/survey/question-display.tsx
+++ b/components/survey/question-display.tsx
@@ -16,17 +16,17 @@ interface QuestionDisplayProps {
question: Question;
value: any;
onChange: (value: any) => void;
+ error?: string;
}
-export function QuestionDisplay({ question, value, onChange }: QuestionDisplayProps) {
- const isAnswered = value !== undefined && value !== "" && (!Array.isArray(value) || value.length > 0);
- const showError = question.required && !isAnswered;
+export function QuestionDisplay({ question, value, onChange, error }: QuestionDisplayProps) {
+ const showError = !!error;
return (
{question.type === "text" && (
@@ -86,7 +86,7 @@ export function QuestionDisplay({ question, value, onChange }: QuestionDisplayPr
)}
{showError && (
- This question is required
+ {error}
)}
);
diff --git a/components/survey/question-types/checkbox-question.tsx b/components/survey/question-types/checkbox-question.tsx
index 1311483..31f4cb9 100644
--- a/components/survey/question-types/checkbox-question.tsx
+++ b/components/survey/question-types/checkbox-question.tsx
@@ -26,6 +26,7 @@ export function CheckboxQuestion({ question, value = [], onChange }: CheckboxQue
);
}}
required={question.required && value.length === 0}
+ data-question-id={question.id}
/>
diff --git a/components/survey/question-types/date-question.tsx b/components/survey/question-types/date-question.tsx
index a656a0b..1e6c06f 100644
--- a/components/survey/question-types/date-question.tsx
+++ b/components/survey/question-types/date-question.tsx
@@ -34,6 +34,7 @@ export function DateQuestion({ question, value, onChange }: DateQuestionProps) {
"w-full justify-start text-left font-normal",
!date && "text-muted-foreground"
)}
+ data-question-id={question.id}
>
{date ? format(date, "PPP") : "Pick a date"}
diff --git a/components/survey/question-types/multiselect-question.tsx b/components/survey/question-types/multiselect-question.tsx
index 51d3300..09b8c0e 100644
--- a/components/survey/question-types/multiselect-question.tsx
+++ b/components/survey/question-types/multiselect-question.tsx
@@ -59,7 +59,9 @@ export function MultiselectQuestion({