diff --git a/src/components/survey/section.tsx b/src/components/survey/section.tsx index 69759cb4..636d55cf 100644 --- a/src/components/survey/section.tsx +++ b/src/components/survey/section.tsx @@ -7,6 +7,7 @@ type SectionProps = { section: SurveyQuestionsYamlFile; next: () => void; setProgress: (n: number) => void; + questions: SurveyQuestionsYamlFile[]; }; export const ERRORS = { @@ -41,110 +42,132 @@ const normalizeAnswers = ( return convertedAnswers; }; -export default React.memo(({ section, next, setProgress }: SectionProps) => { - const [loading, setLoading] = useState(false); - const [error, setError] = useState(ERRORS.none); - const { register, getValues } = useForm(); - const [QIndex, setQIndex] = useState(0); - const isLastQuestion = section.questions.length === QIndex + 1; - const isRequired = !!section.questions[QIndex].required; - - const nextQuestion = async () => { - setError(ERRORS.none); - const name = `${section.label}-q-${QIndex}`; - const value = getValues(name); - // value === null default value for simple questions and false for multiple ones - if (isRequired && (value === null || value === false)) { - setError(ERRORS.required); - return; - } +export default React.memo( + ({ section, next, setProgress, questions }: SectionProps) => { + const [loading, setLoading] = useState(false); + const [error, setError] = useState(ERRORS.none); + const savedAnswars = + localStorage.getItem("answars") || JSON.stringify(questions); + const { register, getValues } = useForm({ + defaultValues: JSON.parse(savedAnswars) + }); + const savedQIndex = parseInt(localStorage.getItem("savedQIndex") || "0"); + const [QIndex, setQIndex] = useState(savedQIndex); + const isLastQuestion = section.questions.length === QIndex + 1; + const isRequired = !!section.questions[QIndex].required; - if (isLastQuestion) { - await submitData(); - setProgress(1); - } else { - setQIndex((QIndex) => QIndex + 1); - setProgress(1); - } - scrollToSection("#steps"); - }; - const backToPreviousQ = () => { - if (QIndex > 0) { - setQIndex((QIndex) => QIndex - 1); - setProgress(-1); - } - }; + useEffect(() => { + const _savedAnswars = JSON.parse(localStorage.getItem("answars") || "{}"); + const keys = Object.keys(_savedAnswars); + const currentSectionLenght = keys.filter((key) => + key.startsWith(section.label) + ).length; + const progress = keys.length - (currentSectionLenght - QIndex); - const submitData = useCallback(async () => { - const answers = normalizeAnswers(getValues()); - setLoading(true); - const { error } = await submitAnswers({ - answers - }); - if (error) { - setError(ERRORS.submission); - setLoading(false); - } else { - next(); - setLoading(false); - } - }, []); + setProgress(progress); + }, []); - // Add useEffect to clear error after 3 seconds - useEffect(() => { - if (error) { - const timer = setTimeout(() => { - setError(ERRORS.none); - }, 2000); + const nextQuestion = async () => { + localStorage.setItem("answars", JSON.stringify(getValues())); + localStorage.setItem("savedQIndex", QIndex.toString()); + setError(ERRORS.none); + const name = `${section.label}-q-${QIndex}`; + const value = getValues(name); + // value === null default value for simple questions and false for multiple ones + if (isRequired && (value === null || value === false)) { + setError(ERRORS.required); + return; + } - return () => clearTimeout(timer); - } - }, [error]); + if (isLastQuestion) { + await submitData(); + setProgress(1); + } else { + setQIndex((QIndex) => QIndex + 1); + setProgress(1); + } + scrollToSection("#steps"); + }; + const backToPreviousQ = () => { + if (QIndex > 0) { + localStorage.setItem("answars", JSON.stringify(getValues())); + localStorage.setItem("savedQIndex", QIndex.toString()); + setQIndex((QIndex) => QIndex - 1); + setProgress(-1); + } + }; - return ( -
-
- {section.questions.map((q, i) => ( - - ))} -
-
-
- {QIndex > 0 && backToPreviousQ()} />} + const submitData = useCallback(async () => { + const answers = normalizeAnswers(getValues()); + setLoading(true); + const { error } = await submitAnswers({ + answers + }); + if (error) { + setError(ERRORS.submission); + setLoading(false); + } else { + next(); + setLoading(false); + } + }, []); + + // Add useEffect to clear error after 3 seconds + useEffect(() => { + if (error) { + const timer = setTimeout(() => { + setError(ERRORS.none); + }, 2000); + + return () => clearTimeout(timer); + } + }, [error]); + + return ( +
+
+ {section.questions.map((q, i) => ( + + ))}
-
- {isRequired ? null : ( +
+
+ {QIndex > 0 && backToPreviousQ()} />} +
+
+ {isRequired ? null : ( + + )} - )} - +
-
- ); -}); + ); + } +); const ErrorMessage = ({ error }: { error: string }) => { if (!error) return null; diff --git a/src/components/survey/survey-form.tsx b/src/components/survey/survey-form.tsx index 650eb707..89525775 100644 --- a/src/components/survey/survey-form.tsx +++ b/src/components/survey/survey-form.tsx @@ -1,4 +1,4 @@ -import { useState, useMemo, useCallback } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import LoadingBar from "react-top-loading-bar"; import { Steps } from "./steps"; import Section from "./section"; @@ -9,9 +9,20 @@ type Props = { }; export const SurveyForm = ({ questions }: Props) => { - const [selectedSectionIndex, setSelectedSectionIndex] = useState(0); + const savedSectionIndex = parseInt( + localStorage.getItem("savedSelectedSectionIndex") || "0" + ); + const [selectedSectionIndex, setSelectedSectionIndex] = + useState(savedSectionIndex); const [progress, setPr] = useState(0); + useEffect(() => { + localStorage.setItem( + "savedSelectedSectionIndex", + selectedSectionIndex.toString() + ); + }, [selectedSectionIndex]); + const section = useMemo( () => questions[selectedSectionIndex], [questions, selectedSectionIndex] @@ -42,6 +53,7 @@ export const SurveyForm = ({ questions }: Props) => { const next = useCallback(() => { if (selectedSectionIndex + 1 < questions.length) { setSelectedSectionIndex((prv) => prv + 1); + localStorage.setItem("savedQIndex", "0"); } else { goToThanksPage(); } @@ -57,6 +69,7 @@ export const SurveyForm = ({ questions }: Props) => { next={next} key={section.label} setProgress={setProgress} + questions={questions} />