diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..782ae74 --- /dev/null +++ b/.babelrc @@ -0,0 +1,8 @@ +{ + "presets": ["next/babel"], + "env": { + "development": { + "plugins": ["./src/plugins/add-data-locator.js"] + } + } +} diff --git a/AGENTS.md b/AGENTS.md index 8bd0e39..faaeb18 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,4 +2,4 @@ # This is NOT the Next.js you know This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. - + \ No newline at end of file diff --git a/public/assets/images/Group 1.svg b/public/assets/images/Group 1.svg new file mode 100644 index 0000000..6840505 --- /dev/null +++ b/public/assets/images/Group 1.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/assets/images/Intro-Quran.png b/public/assets/images/Intro-Quran.png new file mode 100644 index 0000000..5558222 Binary files /dev/null and b/public/assets/images/Intro-Quran.png differ diff --git a/public/assets/images/Intro-location.png b/public/assets/images/Intro-location.png new file mode 100644 index 0000000..fcbc3a5 Binary files /dev/null and b/public/assets/images/Intro-location.png differ diff --git a/public/assets/images/Rectangle 3077.png b/public/assets/images/Rectangle 3077.png new file mode 100644 index 0000000..67fac5b Binary files /dev/null and b/public/assets/images/Rectangle 3077.png differ diff --git a/src/app/details/[section]/detail-section-client.tsx b/src/app/details/[section]/detail-section-client.tsx new file mode 100644 index 0000000..e49b0c1 --- /dev/null +++ b/src/app/details/[section]/detail-section-client.tsx @@ -0,0 +1,244 @@ +"use client"; + +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { useEffect, useMemo, useState } from "react"; +import { + countCompletedDetailedAnswers, + detailedSections, + type DetailedSection, + getDetailedQuestionCount, + getDetailedSectionProgress, + getDetailedSectionStorageKey, +} from "@/lib/detailed-questions"; + +function BackIcon() { + return ( + + ); +} + +export default function DetailSectionClient({ + section, +}: { + section: DetailedSection; +}) { + const [answers, setAnswers] = useState>({}); + const [isHydrated, setIsHydrated] = useState(false); + const router = useRouter(); + + useEffect(() => { + const savedAnswers = window.localStorage.getItem( + getDetailedSectionStorageKey(section.id), + ); + + setAnswers( + savedAnswers ? (JSON.parse(savedAnswers) as Record) : {}, + ); + setIsHydrated(true); + }, [section.id]); + + useEffect(() => { + if (!isHydrated) { + return; + } + + window.localStorage.setItem( + getDetailedSectionStorageKey(section.id), + JSON.stringify(answers), + ); + + const completedTotal = detailedSections.reduce((total, currentSection) => { + const sectionAnswers = + currentSection.id === section.id + ? answers + : ((JSON.parse( + window.localStorage.getItem( + getDetailedSectionStorageKey(currentSection.id), + ) ?? "{}", + ) as Record) ?? {}); + + return ( + total + countCompletedDetailedAnswers(currentSection, sectionAnswers) + ); + }, 0); + + if (completedTotal === getDetailedQuestionCount()) { + router.replace("/details/complete"); + } + }, [answers, isHydrated, router, section, section.id]); + + const completedCount = useMemo( + () => countCompletedDetailedAnswers(section, answers), + [answers, section], + ); + const progress = useMemo( + () => getDetailedSectionProgress(section, answers), + [answers, section], + ); + + const handleChange = (questionId: string, value: string) => { + setAnswers((currentAnswers) => ({ + ...currentAnswers, + [questionId]: value, + })); + }; + + return ( +
+
+
+ +
+
+ 9:41 +
+ + +
+
+ +
+ + + + +

+ {section.title} +

+ + + {progress}% + +
+ +
+

+ Section Progress +

+

+ {section.title} +

+

+ {section.description} +

+ +
+
+
+ +

+ {completedCount} of {section.questions.length} questions answered +

+
+ +
+ {section.questions.map((question) => { + const value = answers[question.id] ?? ""; + + return ( +
+

+ {question.label} +

+

+ {question.description} +

+ +
+ {question.type === "textarea" ? ( +