You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

117 lines
4.0 KiB

"use client";
import { ExplanationUiFont } from "./explanation-ui-font";
import type { QuestionField } from "@/lib/schema-adapter";
import { useQuestionAnswers } from "./question-answer-storage";
import QuestionTitle from "./question-title";
type QuestionRadioProps = {
question: QuestionField;
disabled?: boolean;
};
export function QuestionRadio({
question,
disabled,
}: QuestionRadioProps) {
const options = question.options || [];
const { getAnswerValue, setAnswerValue } = useQuestionAnswers();
const value = getAnswerValue(question);
if (options.length === 0) {
return null;
}
// Render horizontally only for 2-option binary choices (e.g. Yes/No, Male/Female)
const isShortOptions =
options.length <= 2 &&
options.every((opt) => String(opt.label || opt.value || "").length <= 10);
return (
<div
className={[
"flex w-full flex-col gap-3.5 transition-opacity duration-200",
disabled ? "pointer-events-none opacity-30" : "",
].join(" ")}
>
<QuestionTitle question={question} />
<div
className={
isShortOptions
? "flex flex-row flex-wrap items-center gap-3 pt-1"
: "flex flex-col gap-3.5 pt-1"
}
>
{options.map((option) => {
const optionId = `question-${question.id}-${option.id}`;
const isSelected = String(value) === option.id;
return (
<label
key={option.id}
htmlFor={optionId}
className={[
"cursor-pointer rounded-[16px] font-semibold text-[15px] transition-all duration-200 active:scale-[0.99] flex items-center gap-3",
isShortOptions
? "flex-1 min-w-[90px] px-5 py-3.5 text-center justify-center"
: "w-full px-5 py-4 text-start leading-snug",
isSelected
? "bg-[#F0445B] text-white shadow-[0_8px_20px_rgba(240,68,91,0.25)]"
: "bg-[#FAFAFA] text-[#181818] hover:bg-white shadow-[0_2px_6px_rgba(0,0,0,0.03)] border border-[#F0EDED]",
].join(" ")}
>
<input
type="radio"
id={optionId}
name={`question-${question.id}`}
value={option.id}
checked={isSelected}
disabled={disabled}
onChange={() => setAnswerValue(question, option.id)}
className="sr-only"
/>
{!isShortOptions && (
<div
className={[
"size-[18px] shrink-0 rounded-full border-[2px] transition-all flex items-center justify-center",
isSelected
? "border-white bg-white text-[#F0445B]"
: "border-[#D0D5DD] bg-white text-transparent",
].join(" ")}
>
{isSelected && (
<div className="size-[8px] rounded-full bg-current" />
)}
</div>
)}
{(option.label || "").includes(" - ") ? (
(() => {
const parts = (option.label || "").split(" - ");
const title = parts[0];
const description = parts.slice(1).join(" - ");
return (
<span className="flex flex-col gap-1 text-start flex-1">
<span className="font-bold">{title}</span>
<ExplanationUiFont
textColor={
isSelected ? "text-white/85" : "text-[#667085]"
}
>
{description}
</ExplanationUiFont>
</span>
);
})()
) : (
<span className="flex-1">{option.label || option.value || ""}</span>
)}
</label>
);
})}
</div>
</div>
);
}
export default QuestionRadio;