import { isQuestionVisibleForProfile, type QuestionListItem, } from "@/data/question-data"; import type { MarriageFieldValue, MarriageGender, } from "@/hooks/marriage/types"; import { hasQuestionAnswerValue } from "./question-answer-storage"; export function getStoredAge(): number | null { try { if (typeof window === "undefined") return null; const rawValue = window.localStorage.getItem( "marriage:sections:personal_info:answers", ); if (!rawValue) return null; const storedAnswers = JSON.parse(rawValue); const ageField = storedAnswers.fields?.find( (f: Record) => f.type === "number" || f.label === "Age" || f.label === "سن" || (typeof f.key === "string" && (f.key.endsWith("_age") || f.key.endsWith("_sn"))), ); if (ageField && ageField.value !== undefined && ageField.value !== null) { const num = Number(ageField.value); if (Number.isFinite(num)) return num; } const dobField = storedAnswers.fields?.find( (f: Record) => f.type === "date" || f.label === "Date of Birth" || f.label === "تاریخ تولد" || (typeof f.key === "string" && (f.key.endsWith("_date_of_birth") || f.key.endsWith("_tarykh_twld"))), ); if (dobField?.value) { const dob = new Date(String(dobField.value)); if (!Number.isNaN(dob.getTime())) { const today = new Date(); let age = today.getFullYear() - dob.getFullYear(); const m = today.getMonth() - dob.getMonth(); if (m < 0 || (m === 0 && today.getDate() < dob.getDate())) { age--; } return age >= 0 ? age : null; } } } catch (_e) {} return null; } function isFieldAnswered( q: Record, field: Record | undefined, ): boolean { if (!field || !hasQuestionAnswerValue(field.value as MarriageFieldValue)) { return false; } if (q.type === "birthplace") { const strVal = String(field.value); const parts = strVal.split(",").map((p) => p.trim()); return parts.length >= 2 && parts[0].length > 0 && parts[1].length > 0; } return true; } function hashString(value: string) { let hash = 0; for (let index = 0; index < value.length; index += 1) { hash = (hash * 31 + value.charCodeAt(index)) >>> 0; } return hash.toString(36); } function slugifyTitle(title: string) { const slug = title .normalize("NFKD") .replace(/[\u0300-\u036f]/g, "") .toLowerCase() .replace(/[^a-z0-9]+/g, "_") .replace(/^_+|_+$/g, ""); return slug || `field_${hashString(title)}`; } export function getLocalSectionProgress( item: QuestionListItem, profile: { gender?: MarriageGender | null } | null | undefined, age: number | null, ): number | null { try { if (typeof window === "undefined") return null; const fields: Record[] = []; let hasFoundStorage = false; const mainKey = `marriage:sections:${item.slug}:answers`; const mainRaw = window.localStorage.getItem(mainKey); if (mainRaw) { try { const parsed = JSON.parse(mainRaw); if ( parsed && Array.isArray(parsed.fields) && parsed.fields.length > 0 ) { fields.push(...parsed.fields); hasFoundStorage = true; } } catch {} } if (item.slug === "family_marital_history") { const fbRaw = window.localStorage.getItem( "marriage:sections:family_background:answers", ); if (fbRaw) { try { const parsed = JSON.parse(fbRaw); if (parsed && Array.isArray(parsed.fields)) { fields.push(...parsed.fields); hasFoundStorage = true; } } catch {} } const mhRaw = window.localStorage.getItem( "marriage:sections:marital_history_children:answers", ); if (mhRaw) { try { const parsed = JSON.parse(mhRaw); if (parsed && Array.isArray(parsed.fields)) { fields.push(...parsed.fields); hasFoundStorage = true; } } catch {} } } if (!hasFoundStorage || fields.length === 0) { return null; } const profileContext = { age, gender: profile?.gender, }; const hasDobQuestion = item.questions.some( (q) => q.title === "Date of Birth" || q.title === "تاریخ تولد", ); const profileVisible = item.questions.filter((question) => { if ( hasDobQuestion && (question.title === "Age" || question.title === "سن") ) { return false; } return isQuestionVisibleForProfile(question, profileContext); }); const findAnswer = ( questionTitle: string, questionIndex: number, originalIndex?: number, ) => { const indexToUse = originalIndex !== undefined ? originalIndex : questionIndex; const key = `q${indexToUse + 1}_${slugifyTitle(questionTitle)}`; const field = fields.find( (f) => f && (f.key === key || f.label === questionTitle), ); return field?.value; }; const activeQuestions = profileVisible.filter((question, _idx) => { if (question.logic?.dependsOn) { const { title, values } = question.logic.dependsOn; const depIndex = profileVisible.findIndex((q) => q.title === title); const depQuestion = depIndex !== -1 ? profileVisible[depIndex] : null; const depAnswer = depQuestion ? findAnswer(depQuestion.title, depIndex, depQuestion.originalIndex) : undefined; if (depAnswer === undefined || depAnswer === null) { return false; } const ansList = Array.isArray(depAnswer) ? depAnswer.map(String) : [String(depAnswer)]; const isMatch = values.some((val) => ansList.some((a) => a === val || a.includes(val) || val.includes(a)), ); if (!isMatch) { return false; } } return true; }); if (activeQuestions.length === 0) { return 100; } const answeredCount = activeQuestions.filter((q, idx) => { const indexToUse = q.originalIndex !== undefined ? q.originalIndex : idx; const key = `q${indexToUse + 1}_${slugifyTitle(q.title)}`; const field = fields.find( (f) => f && (f.key === key || f.label === q.title), ); return isFieldAnswered(q, field); }).length; return Math.max( 0, Math.min(100, Math.round((answeredCount / activeQuestions.length) * 100)), ); } catch (_e) { return null; } }