|
|
@ -2,7 +2,8 @@ |
|
|
|
|
|
|
|
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
|
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
|
|
import { createPortal } from "react-dom"; |
|
|
import { createPortal } from "react-dom"; |
|
|
import { getLanguageList, LANGUAGES_EN, LANGUAGES_FA } from "@/data/languages"; |
|
|
|
|
|
|
|
|
import { COUNTRIES_EN, COUNTRIES_FA } from "@/data/countries"; |
|
|
|
|
|
import { LANGUAGES_EN, LANGUAGES_FA } from "@/data/languages"; |
|
|
import type { QuestionField } from "@/lib/schema-adapter"; |
|
|
import type { QuestionField } from "@/lib/schema-adapter"; |
|
|
import { useI18n } from "@/translations/provider"; |
|
|
import { useI18n } from "@/translations/provider"; |
|
|
import { Button } from "./button"; |
|
|
import { Button } from "./button"; |
|
|
@ -81,12 +82,26 @@ export function QuestionSheet({ question, disabled }: QuestionSheetProps) { |
|
|
question.title?.includes("زبان") || |
|
|
question.title?.includes("زبان") || |
|
|
question.ui_config?.dataset === "languages"; |
|
|
question.ui_config?.dataset === "languages"; |
|
|
|
|
|
|
|
|
|
|
|
const isCountryQuestion = |
|
|
|
|
|
question.id?.toLowerCase().includes("nationality") || |
|
|
|
|
|
question.id?.toLowerCase().includes("citizenship") || |
|
|
|
|
|
question.id?.toLowerCase().includes("country") || |
|
|
|
|
|
question.id?.toLowerCase().includes("birthplace") || |
|
|
|
|
|
question.id?.toLowerCase().includes("residence") || |
|
|
|
|
|
question.title?.toLowerCase().includes("nationality") || |
|
|
|
|
|
question.title?.toLowerCase().includes("citizenship") || |
|
|
|
|
|
question.title?.toLowerCase().includes("country") || |
|
|
|
|
|
question.title?.includes("ملیت") || |
|
|
|
|
|
question.title?.includes("تابعیت") || |
|
|
|
|
|
question.title?.includes("کشور") || |
|
|
|
|
|
question.title?.includes("سکونت") || |
|
|
|
|
|
question.ui_config?.dataset === "countries" || |
|
|
|
|
|
question.ui_config?.dataset === "nationalities"; |
|
|
|
|
|
|
|
|
const options = useMemo(() => { |
|
|
const options = useMemo(() => { |
|
|
const rawOptions = question.options || []; |
|
|
const rawOptions = question.options || []; |
|
|
if (!isLanguageQuestion) { |
|
|
|
|
|
return rawOptions; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isLanguageQuestion) { |
|
|
const existingByLabel = new Map( |
|
|
const existingByLabel = new Map( |
|
|
rawOptions.map((opt) => [opt.label.toLowerCase().trim(), opt]), |
|
|
rawOptions.map((opt) => [opt.label.toLowerCase().trim(), opt]), |
|
|
); |
|
|
); |
|
|
@ -137,7 +152,63 @@ export function QuestionSheet({ question, disabled }: QuestionSheetProps) { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
return mergedOptions; |
|
|
return mergedOptions; |
|
|
}, [question, isLanguageQuestion, locale, t]); |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (isCountryQuestion) { |
|
|
|
|
|
const existingByLabel = new Map( |
|
|
|
|
|
rawOptions.map((opt) => [opt.label.toLowerCase().trim(), opt]), |
|
|
|
|
|
); |
|
|
|
|
|
const existingByVal = new Map( |
|
|
|
|
|
rawOptions.map((opt) => [String(opt.value).toLowerCase().trim(), opt]), |
|
|
|
|
|
); |
|
|
|
|
|
const existingById = new Map( |
|
|
|
|
|
rawOptions.map((opt) => [opt.id.toLowerCase().trim(), opt]), |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const mergedOptions: typeof rawOptions = []; |
|
|
|
|
|
const seenIds = new Set<string>(); |
|
|
|
|
|
|
|
|
|
|
|
COUNTRIES_EN.forEach((enCountry, idx) => { |
|
|
|
|
|
const localizedLabel = |
|
|
|
|
|
(locale === "fa" || locale === "fa-ir" |
|
|
|
|
|
? COUNTRIES_FA[idx] |
|
|
|
|
|
: (t as any)[enCountry]) || enCountry; |
|
|
|
|
|
const cleanSlug = enCountry |
|
|
|
|
|
.toLowerCase() |
|
|
|
|
|
.replace(/[^a-z0-9]+/g, "_") |
|
|
|
|
|
.replace(/^_+|_+$/g, ""); |
|
|
|
|
|
const generatedId = `${question.id}.${cleanSlug}`; |
|
|
|
|
|
|
|
|
|
|
|
const existing = |
|
|
|
|
|
existingByLabel.get(enCountry.toLowerCase()) || |
|
|
|
|
|
existingByLabel.get(localizedLabel.toLowerCase()) || |
|
|
|
|
|
existingByVal.get(cleanSlug) || |
|
|
|
|
|
existingById.get(generatedId.toLowerCase()); |
|
|
|
|
|
|
|
|
|
|
|
const finalId = existing?.id || generatedId; |
|
|
|
|
|
if (seenIds.has(finalId)) return; |
|
|
|
|
|
seenIds.add(finalId); |
|
|
|
|
|
|
|
|
|
|
|
mergedOptions.push({ |
|
|
|
|
|
id: finalId, |
|
|
|
|
|
value: existing?.value ?? cleanSlug, |
|
|
|
|
|
label: existing?.label ?? localizedLabel, |
|
|
|
|
|
order: existing?.order ?? idx, |
|
|
|
|
|
}); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
rawOptions.forEach((opt) => { |
|
|
|
|
|
if (!seenIds.has(opt.id)) { |
|
|
|
|
|
seenIds.add(opt.id); |
|
|
|
|
|
mergedOptions.push(opt); |
|
|
|
|
|
} |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return mergedOptions; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return rawOptions; |
|
|
|
|
|
}, [question, isLanguageQuestion, isCountryQuestion, locale, t]); |
|
|
|
|
|
|
|
|
const COMPACT_OPTIONS_MAX = 6; |
|
|
const COMPACT_OPTIONS_MAX = 6; |
|
|
|
|
|
|
|
|
@ -166,7 +237,14 @@ export function QuestionSheet({ question, disabled }: QuestionSheetProps) { |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
const getCleanLabel = (optId: string) => { |
|
|
const getCleanLabel = (optId: string) => { |
|
|
const opt = options.find((o) => o.id === optId); |
|
|
|
|
|
|
|
|
const normalized = String(optId || "").toLowerCase().trim(); |
|
|
|
|
|
const opt = options.find( |
|
|
|
|
|
(o) => |
|
|
|
|
|
o.id === optId || |
|
|
|
|
|
o.id.toLowerCase() === normalized || |
|
|
|
|
|
String(o.value).toLowerCase() === normalized || |
|
|
|
|
|
o.id.endsWith(`.${normalized}`), |
|
|
|
|
|
); |
|
|
if (!opt) return optId; |
|
|
if (!opt) return optId; |
|
|
return opt.label.split(" - ")[0]; |
|
|
return opt.label.split(" - ")[0]; |
|
|
}; |
|
|
}; |
|
|
|