Skip to content

Commit fb9d26b

Browse files
committed
hotfix: survey
1 parent 837622a commit fb9d26b

1 file changed

Lines changed: 48 additions & 33 deletions

File tree

src/components/survey/SurveyForm.tsx

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ interface AnswerState {
5757
export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = false, onSuccess, onError }: SurveyFormProps) {
5858
const { colors, radius, typography, spacing } = useAppgramTheme()
5959
const { survey, nodes, isLoading, error } = useSurvey(slug)
60-
const { isSubmitting, submitResponse } = useSurveySubmit({ onSuccess: () => onSuccess?.(), onError })
60+
// Don't pass onSuccess to hook - we'll call it after showing success screen
61+
const { isSubmitting, submitResponse } = useSurveySubmit({ onError })
6162
const [answers, setAnswers] = useState<Map<string, AnswerState>>(new Map())
6263
const [visitedNodes, setVisitedNodes] = useState<string[]>([])
6364
const [submitted, setSubmitted] = useState(false)
@@ -145,6 +146,11 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
145146
return nodes.find(n => n.id === node.next_node_id) || null
146147
}
147148

149+
// If node has result_message, this is an endpoint - survey ends here
150+
if (node.result_message) {
151+
return null
152+
}
153+
148154
// Tree-based routing: find child node (node whose parent_id equals this node's id)
149155
const childNode = nodes.find(n => n.parent_id === node.id)
150156
if (childNode) {
@@ -192,9 +198,9 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
192198
})
193199
}
194200

195-
const handleSubmit = useCallback(async () => {
201+
const submitSurvey = useCallback(async (finalAnswers: Map<string, AnswerState>) => {
196202
if (!survey) return
197-
const answerEntries = Array.from(answers.entries()).map(([nodeId, ans]) => ({
203+
const answerEntries = Array.from(finalAnswers.entries()).map(([nodeId, ans]) => ({
198204
node_id: nodeId,
199205
answer: ans.answer,
200206
answer_text: ans.answer_text,
@@ -203,12 +209,18 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
203209
}))
204210
const result = await submitResponse(survey.id, { fingerprint, answers: answerEntries })
205211
if (result) setSubmitted(true)
206-
}, [survey, answers, submitResponse, fingerprint])
212+
}, [survey, submitResponse, fingerprint])
207213

208-
const goNext = useCallback(() => {
209-
if (!currentNode || !canProceed) return
214+
// Handle answer and navigate - passes answer directly to avoid state timing issues
215+
const handleAnswer = useCallback((answer: AnswerState) => {
216+
if (!currentNode) return
210217

211-
const answer = answers.get(currentNode.id)
218+
// Store answer
219+
const newAnswers = new Map(answers)
220+
newAnswers.set(currentNode.id, answer)
221+
setAnswers(newAnswers)
222+
223+
// Determine next node using the answer directly (not from state)
212224
const nextNode = getNextNode(currentNode, answer)
213225

214226
if (nextNode) {
@@ -217,9 +229,25 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
217229
})
218230
} else {
219231
// No next node — submit the survey
220-
handleSubmit()
232+
submitSurvey(newAnswers)
233+
}
234+
}, [currentNode, answers, getNextNode, submitSurvey])
235+
236+
// For OK button - uses stored answer
237+
const goNext = useCallback(() => {
238+
if (!currentNode || !canProceed) return
239+
const answer = answers.get(currentNode.id)
240+
if (answer) {
241+
const nextNode = getNextNode(currentNode, answer)
242+
if (nextNode) {
243+
animateTransition('next', () => {
244+
setVisitedNodes(prev => [...prev, nextNode.id])
245+
})
246+
} else {
247+
submitSurvey(answers)
248+
}
221249
}
222-
}, [currentNode, canProceed, answers, getNextNode, handleSubmit])
250+
}, [currentNode, canProceed, answers, getNextNode, submitSurvey])
223251

224252
const goPrev = useCallback(() => {
225253
if (visitedNodes.length > 0) {
@@ -284,8 +312,8 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
284312
<TouchableOpacity
285313
key={opt}
286314
onPress={() => {
287-
updateAnswer(node.id, { answer_text: optValue, answer: opt === 'Yes' })
288-
if (autoAdvance) setTimeout(goNext, 300)
315+
// Use handleAnswer to avoid state timing issues
316+
handleAnswer({ answer_text: optValue, answer: opt === 'Yes' })
289317
}}
290318
style={{
291319
flex: 1,
@@ -318,8 +346,8 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
318346
<TouchableOpacity
319347
key={i}
320348
onPress={() => {
321-
updateAnswer(node.id, { answer_options: [opt.value] })
322-
if (autoAdvance) setTimeout(goNext, 300)
349+
// Use handleAnswer to avoid state timing issues
350+
handleAnswer({ answer_options: [opt.value] })
323351
}}
324352
style={{
325353
flexDirection: 'row',
@@ -417,8 +445,8 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
417445
<TouchableOpacity
418446
key={i}
419447
onPress={() => {
420-
updateAnswer(node.id, { answer_rating: i + 1 })
421-
if (autoAdvance) setTimeout(goNext, 300)
448+
// Use handleAnswer to avoid state timing issues
449+
handleAnswer({ answer_rating: i + 1 })
422450
}}
423451
style={{ padding: spacing.xs }}
424452
>
@@ -460,31 +488,18 @@ export function SurveyForm({ slug, fingerprint = 'anonymous', autoAdvance = fals
460488

461489
if (!survey || nodes.length === 0) return null
462490

463-
// Show result message if current node has one (terminal node)
464-
if (currentNode?.result_message) {
465-
return (
466-
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: spacing.xl }}>
467-
<View style={{ width: 80, height: 80, borderRadius: 40, backgroundColor: colors.primary + '20', alignItems: 'center', justifyContent: 'center', marginBottom: spacing.lg }}>
468-
<CheckCircle2 size={40} color={colors.primary} />
469-
</View>
470-
<Text style={{ fontSize: typography['2xl'], fontWeight: '700', color: colors.foreground, marginBottom: spacing.sm, textAlign: 'center' }}>
471-
{currentNode.result_message}
472-
</Text>
473-
</View>
474-
)
475-
}
476-
477491
if (submitted) {
492+
// Show custom result_message from the last answered node, or default message
493+
const lastNodeId = visitedNodes[visitedNodes.length - 1] || currentNodeId
494+
const lastNode = nodes.find(n => n.id === lastNodeId)
495+
const resultMessage = lastNode?.result_message || 'Thank you for your feedback!'
478496
return (
479497
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', padding: spacing.xl }}>
480498
<View style={{ width: 80, height: 80, borderRadius: 40, backgroundColor: colors.primary + '20', alignItems: 'center', justifyContent: 'center', marginBottom: spacing.lg }}>
481499
<CheckCircle2 size={40} color={colors.primary} />
482500
</View>
483501
<Text style={{ fontSize: typography['2xl'], fontWeight: '700', color: colors.foreground, marginBottom: spacing.sm, textAlign: 'center' }}>
484-
Survey Submitted
485-
</Text>
486-
<Text style={{ fontSize: typography.base, color: colors.mutedForeground, textAlign: 'center' }}>
487-
Thank you for your feedback!
502+
{resultMessage}
488503
</Text>
489504
</View>
490505
)

0 commit comments

Comments
 (0)