import { useRef, useState } from "react" import { View, Text, TextInput, TouchableOpacity, StyleSheet } from "react-native" import { Ionicons } from "@expo/vector-icons" import { useTranslation } from "react-i18next" interface QuestionOption { label: string description: string } interface Question { question: string header: string options: QuestionOption[] multiple?: boolean custom?: boolean } interface Props { request: { id: string questions: Question[] } isDark: boolean onReply: (answers: string[][]) => void onReject: () => void } export function QuestionPrompt({ request, isDark, onReply, onReject }: Props) { const { t } = useTranslation() const [answers, setAnswers] = useState(request.questions.map(() => [])) const [custom, setCustom] = useState("") const [showCustom, setShowCustom] = useState(false) const [current, setCurrent] = useState(0) // A question is answered exactly once. Without this guard, a double-tap on a // single-select option schedules two `onReply` timers; the second reply hits // an already-resolved request server-side and surfaces a spurious // "Reply failed" alert even though the answer went through. const replied = useRef(false) const reply = (a: string[][]) => { if (replied.current) return replied.current = true onReply(a) } const reject = () => { if (replied.current) return replied.current = true onReject() } const q = request.questions[current] if (!q) return null const toggleOption = (label: string) => { setAnswers((prev) => { const copy = [...prev] const selected = copy[current] || [] if (q.multiple) { copy[current] = selected.includes(label) ? selected.filter((a) => a !== label) : [...selected, label] } else { copy[current] = [label] if (request.questions.length === 1) { setTimeout(() => reply(copy), 100) } } return copy }) } const submitCustom = () => { if (!custom.trim()) return const copy = [...answers] copy[current] = [custom.trim()] setAnswers(copy) setCustom("") setShowCustom(false) if (request.questions.length === 1) { reply(copy) } } return ( {q.header || t("chat.questionPrompt.headerFallback")} {q.question} {q.options.map((opt) => { const selected = (answers[current] || []).includes(opt.label) return ( toggleOption(opt.label)} > {opt.label} {opt.description ? {opt.description} : null} ) })} {q.custom !== false && (showCustom ? ( ) : ( setShowCustom(true)}> {t("chat.questionPrompt.customAnswerLabel")} ))} {t("chat.questionPrompt.dismiss")} {(request.questions.length > 1 || q.multiple) && ( { if (current < request.questions.length - 1) { setCurrent(current + 1) } else { reply(answers) } }} > {current < request.questions.length - 1 ? t("chat.questionPrompt.next") : t("chat.questionPrompt.submit")} )} ) } const s = StyleSheet.create({ card: { margin: 12, padding: 16, backgroundColor: "#f5f3ff", borderRadius: 12, borderWidth: 1, borderColor: "#ede9fe", }, cardDark: { backgroundColor: "#1a1a2e", borderColor: "#2a2a3e" }, header: { flexDirection: "row", alignItems: "center", gap: 8, marginBottom: 8 }, title: { fontSize: 15, fontWeight: "600", color: "#6d28d9" }, textWhite: { color: "#ffffff" }, question: { fontSize: 14, lineHeight: 20, color: "#0a0a0a", marginBottom: 12 }, metaDark: { color: "#666666" }, options: { gap: 8 }, option: { padding: 12, borderRadius: 8, backgroundColor: "#ffffff", borderWidth: 1, borderColor: "#e5e5e5", }, optionDark: { backgroundColor: "#2a2a2a", borderColor: "#3a3a3a" }, optionSelected: { borderColor: "#8b5cf6", backgroundColor: "#f5f3ff" }, optionSelectedDark: { borderColor: "#8b5cf6", backgroundColor: "#2a1a3e" }, optionLabel: { fontSize: 14, fontWeight: "600", color: "#0a0a0a" }, optionLabelSelected: { color: "#6d28d9" }, optionDesc: { fontSize: 12, color: "#666666", marginTop: 2 }, customRow: { flexDirection: "row", gap: 8 }, customInput: { flex: 1, backgroundColor: "#ffffff", borderRadius: 8, paddingHorizontal: 12, paddingVertical: 10, fontSize: 14, borderWidth: 1, borderColor: "#e5e5e5", color: "#0a0a0a", }, customInputDark: { backgroundColor: "#2a2a2a", borderColor: "#3a3a3a", color: "#ffffff" }, customSubmit: { justifyContent: "center", alignItems: "center", padding: 8 }, footer: { flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginTop: 12 }, dismiss: { fontSize: 14, color: "#999999" }, submitBtn: { backgroundColor: "#8b5cf6", paddingHorizontal: 20, paddingVertical: 10, borderRadius: 8 }, submitBtnDark: { backgroundColor: "#7c3aed" }, submitText: { color: "#ffffff", fontWeight: "600", fontSize: 14 }, })