feat: admin survey responses page with expandable detail and CSV export
- Backend: GET /admin/survey-responses (list with stats, invite join) - Backend: GET /admin/survey-responses/export (CSV download) - Frontend: SurveyResponsesPage with expandable row detail - Two-column Q&A grid with typed answer rendering (chips, ranked lists, quote blocks) - Stats cards (total responses, this week) - CSV export button with blob download - Sidebar nav + route wiring - Also: updated Q14 from product domain ranking to diagnostic prioritization Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,21 @@ export interface SurveyInviteResponse {
|
||||
survey_url: string
|
||||
}
|
||||
|
||||
export interface SurveyResponseDetail {
|
||||
id: string
|
||||
respondent_name: string | null
|
||||
responses: Record<string, string | string[]>
|
||||
source: 'invite' | 'direct'
|
||||
invite_name: string | null
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface SurveyResponseListResponse {
|
||||
responses: SurveyResponseDetail[]
|
||||
total: number
|
||||
this_week: number
|
||||
}
|
||||
|
||||
export const adminApi = {
|
||||
// Dashboard
|
||||
getDashboardMetrics: () =>
|
||||
@@ -158,6 +173,12 @@ export const adminApi = {
|
||||
api.get<SurveyInviteResponse[]>('/admin/survey-invites').then(r => r.data),
|
||||
createSurveyInvite: (data: { recipient_name: string; recipient_email?: string; send_email?: boolean }) =>
|
||||
api.post<SurveyInviteResponse>('/admin/survey-invites', data).then(r => r.data),
|
||||
|
||||
// Survey Responses
|
||||
listSurveyResponses: () =>
|
||||
api.get<SurveyResponseListResponse>('/admin/survey-responses').then(r => r.data),
|
||||
exportSurveyResponsesCsv: () =>
|
||||
api.get('/admin/survey-responses/export', { responseType: 'blob' }).then(r => r.data),
|
||||
}
|
||||
|
||||
export default adminApi
|
||||
|
||||
Reference in New Issue
Block a user