mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-11-02 02:19:43 +00:00
fix(admin): support typed question responses
Render database-backed text, audio, photo, and choice responses across admin activity and user detail views. Add support for the both_answered match state while retaining legacy swipe behavior.
This commit is contained in:
1 parent
01bb8225ae
commit
6df9442cd0
6 files changed
+175
-42
No files matched your search
@@ -0,0 +1,67 @@
|
||||
import type { AnswerType, QuestionType } from '@sauci/shared';
|
||||
|
||||
export type AdminResponseData =
|
||||
| { type: 'text_answer'; text: string }
|
||||
| { type: 'audio'; media_path: string; duration_seconds: number }
|
||||
| { type: 'photo'; media_path: string }
|
||||
| { type: 'who_likely'; chosen_user_id: string }
|
||||
| Record<string, unknown>
|
||||
| null;
|
||||
|
||||
export const QUESTION_TYPE_LABELS: Record<QuestionType, string> = {
|
||||
swipe: 'Swipe',
|
||||
text_answer: 'Text answer',
|
||||
audio: 'Audio',
|
||||
photo: 'Photo',
|
||||
who_likely: 'Who is more likely',
|
||||
};
|
||||
|
||||
export const MATCH_TYPE_LABELS = {
|
||||
yes_yes: 'Both Yes!',
|
||||
yes_maybe: 'Yes + Maybe',
|
||||
maybe_maybe: 'Both Maybe',
|
||||
both_answered: 'Both Answered',
|
||||
} as const;
|
||||
|
||||
export function resolveQuestionType(questionType?: QuestionType | null): QuestionType {
|
||||
return questionType ?? 'swipe';
|
||||
}
|
||||
|
||||
export function formatAdminResponse(
|
||||
questionType: QuestionType | null | undefined,
|
||||
answer: AnswerType,
|
||||
responseData: AdminResponseData,
|
||||
): { label: string; detail: string | null } {
|
||||
const resolvedType = resolveQuestionType(questionType);
|
||||
|
||||
if (resolvedType === 'swipe') {
|
||||
return {
|
||||
label: answer.charAt(0).toUpperCase() + answer.slice(1),
|
||||
detail: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (resolvedType === 'text_answer') {
|
||||
const text = responseData && 'text' in responseData && typeof responseData.text === 'string'
|
||||
? responseData.text.trim()
|
||||
: '';
|
||||
return { label: 'Text submitted', detail: text || null };
|
||||
}
|
||||
|
||||
if (resolvedType === 'audio') {
|
||||
const duration = responseData && 'duration_seconds' in responseData
|
||||
&& typeof responseData.duration_seconds === 'number'
|
||||
? Math.max(0, Math.round(responseData.duration_seconds))
|
||||
: null;
|
||||
return {
|
||||
label: 'Audio submitted',
|
||||
detail: duration === null ? null : `${duration}s recording`,
|
||||
};
|
||||
}
|
||||
|
||||
if (resolvedType === 'photo') {
|
||||
return { label: 'Photo submitted', detail: null };
|
||||
}
|
||||
|
||||
return { label: 'Choice submitted', detail: null };
|
||||
}
|
||||
Reference in new issue
Block a user