|
|
@ -1,5 +1,6 @@ |
|
|
"use client"; |
|
|
"use client"; |
|
|
|
|
|
|
|
|
|
|
|
import { useEffect, useRef, useState } from "react"; |
|
|
import type { QuestionField } from "@/data/question-data"; |
|
|
import type { QuestionField } from "@/data/question-data"; |
|
|
import { useI18n } from "@/translations/provider"; |
|
|
import { useI18n } from "@/translations/provider"; |
|
|
import { useQuestionAnswers } from "./question-answer-storage"; |
|
|
import { useQuestionAnswers } from "./question-answer-storage"; |
|
|
@ -13,6 +14,12 @@ type QuestionTextProps = { |
|
|
heightClassName?: string; |
|
|
heightClassName?: string; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function toEnglishDigits(str: string): string { |
|
|
|
|
|
return str |
|
|
|
|
|
.replace(/[٠-٩]/g, (d) => String(d.charCodeAt(0) - 1632)) |
|
|
|
|
|
.replace(/[۰-۹]/g, (d) => String(d.charCodeAt(0) - 1776)); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
export default function QuestionText({ |
|
|
export default function QuestionText({ |
|
|
question, |
|
|
question, |
|
|
questionIndex, |
|
|
questionIndex, |
|
|
@ -25,7 +32,44 @@ export default function QuestionText({ |
|
|
const value = getAnswerValue(question, questionIndex); |
|
|
const value = getAnswerValue(question, questionIndex); |
|
|
|
|
|
|
|
|
const isMuted = value === "-"; |
|
|
const isMuted = value === "-"; |
|
|
const stringValue = String(value ?? "").trim(); |
|
|
|
|
|
|
|
|
const [localValue, setLocalValue] = useState( |
|
|
|
|
|
isMuted ? "" : String(value ?? ""), |
|
|
|
|
|
); |
|
|
|
|
|
const debounceTimerRef = useRef<NodeJS.Timeout | null>(null); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
setLocalValue(isMuted ? "" : String(value ?? "")); |
|
|
|
|
|
}, [value, isMuted]); |
|
|
|
|
|
|
|
|
|
|
|
const enTitleLower = (question.englishTitle || question.title).toLowerCase(); |
|
|
|
|
|
const isNumericQuestion = |
|
|
|
|
|
question.type === "number" || enTitleLower.includes("duration"); |
|
|
|
|
|
|
|
|
|
|
|
const handleChange = (val: string) => { |
|
|
|
|
|
let nextVal = val; |
|
|
|
|
|
if (isNumericQuestion) { |
|
|
|
|
|
nextVal = toEnglishDigits(nextVal).replace(/[^\d]/g, ""); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
setLocalValue(nextVal); |
|
|
|
|
|
|
|
|
|
|
|
if (debounceTimerRef.current) { |
|
|
|
|
|
clearTimeout(debounceTimerRef.current); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
debounceTimerRef.current = setTimeout(() => { |
|
|
|
|
|
setAnswerValue(question, questionIndex, nextVal); |
|
|
|
|
|
}, 300); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleBlur = () => { |
|
|
|
|
|
if (debounceTimerRef.current) { |
|
|
|
|
|
clearTimeout(debounceTimerRef.current); |
|
|
|
|
|
} |
|
|
|
|
|
setAnswerValue(question, questionIndex, localValue); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const stringValue = localValue.trim(); |
|
|
const isEmailQuestion = (question.englishTitle || question.title) |
|
|
const isEmailQuestion = (question.englishTitle || question.title) |
|
|
.toLowerCase() |
|
|
.toLowerCase() |
|
|
.includes("email"); |
|
|
.includes("email"); |
|
|
@ -65,10 +109,9 @@ export default function QuestionText({ |
|
|
> |
|
|
> |
|
|
<input |
|
|
<input |
|
|
type="text" |
|
|
type="text" |
|
|
value={isMuted ? "" : String(value ?? "")} |
|
|
|
|
|
onChange={(e) => |
|
|
|
|
|
setAnswerValue(question, questionIndex, e.target.value) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
value={localValue} |
|
|
|
|
|
onChange={(e) => handleChange(e.target.value)} |
|
|
|
|
|
onBlur={handleBlur} |
|
|
placeholder={question.extras.placeHolder} |
|
|
placeholder={question.extras.placeHolder} |
|
|
disabled={disabled || isMuted} |
|
|
disabled={disabled || isMuted} |
|
|
className="h-full w-full border-0 bg-transparent px-4.5 text-[15px] font-medium text-[#181818] outline-none placeholder:text-[#98A2B3] disabled:opacity-50 disabled:cursor-not-allowed" |
|
|
className="h-full w-full border-0 bg-transparent px-4.5 text-[15px] font-medium text-[#181818] outline-none placeholder:text-[#98A2B3] disabled:opacity-50 disabled:cursor-not-allowed" |
|
|
@ -101,11 +144,12 @@ export default function QuestionText({ |
|
|
> |
|
|
> |
|
|
<QuestionTitle question={question} /> |
|
|
<QuestionTitle question={question} /> |
|
|
<input |
|
|
<input |
|
|
type="text" |
|
|
|
|
|
value={isMuted ? "" : String(value ?? "")} |
|
|
|
|
|
onChange={(e) => |
|
|
|
|
|
setAnswerValue(question, questionIndex, e.target.value) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
type={isNumericQuestion ? "tel" : "text"} |
|
|
|
|
|
inputMode={isNumericQuestion ? "numeric" : undefined} |
|
|
|
|
|
pattern={isNumericQuestion ? "[0-9]*" : undefined} |
|
|
|
|
|
value={localValue} |
|
|
|
|
|
onChange={(e) => handleChange(e.target.value)} |
|
|
|
|
|
onBlur={handleBlur} |
|
|
placeholder={question.extras.placeHolder} |
|
|
placeholder={question.extras.placeHolder} |
|
|
disabled={disabled || isMuted} |
|
|
disabled={disabled || isMuted} |
|
|
className={[ |
|
|
className={[ |
|
|
@ -124,6 +168,9 @@ export default function QuestionText({ |
|
|
type="checkbox" |
|
|
type="checkbox" |
|
|
checked={isMuted} |
|
|
checked={isMuted} |
|
|
onChange={(e) => { |
|
|
onChange={(e) => { |
|
|
|
|
|
if (debounceTimerRef.current) { |
|
|
|
|
|
clearTimeout(debounceTimerRef.current); |
|
|
|
|
|
} |
|
|
if (e.target.checked) { |
|
|
if (e.target.checked) { |
|
|
setAnswerValue(question, questionIndex, "-"); |
|
|
setAnswerValue(question, questionIndex, "-"); |
|
|
} else { |
|
|
} else { |
|
|
|