feat(forms): per-member 'Forms submitted' view on the members page
listMemberSubmissions (forms.manage, RLS-honoring, metadata only) + a FORMS column/button -> MemberFormsDialog listing the member's submissions (title, kind, version, date) with a link to the audited forms results surface. Gated by forms.manage (matches existing submission-read RLS; no new exposure).
This commit is contained in:
@@ -19,6 +19,7 @@ import {
|
||||
formIdSchema,
|
||||
submitFormSchema,
|
||||
linkSubmissionsSchema,
|
||||
memberSubmissionsSchema,
|
||||
getPublicFormSchema,
|
||||
} from '@/lib/validations'
|
||||
import { parseFormSchema, validateAnswers } from '@/lib/forms-schema'
|
||||
@@ -538,3 +539,41 @@ export async function linkSubmissionsForMember(input: unknown) {
|
||||
)
|
||||
return { data: { linked: linked?.length ?? 0 } }
|
||||
}
|
||||
|
||||
/**
|
||||
* The forms a given member has submitted (for the per-member panel on the
|
||||
* members page). forms.manage gated; the gate's client honors the
|
||||
* form_submissions/forms RLS (forms.manage), so no service-client bypass.
|
||||
* Metadata only -- answers stay in the audited results surface.
|
||||
*/
|
||||
export async function listMemberSubmissions(input: unknown) {
|
||||
const gate = await requireFormsManager()
|
||||
if (!gate.ok) return { error: gate.error }
|
||||
const { supabase, member } = gate
|
||||
|
||||
const v = parseInput(memberSubmissionsSchema, input)
|
||||
if (!v.ok) return { error: v.error }
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('form_submissions')
|
||||
.select('id, form_id, form_version, created_at, forms(title, kind, slug)')
|
||||
.eq('space_id', member.space_id)
|
||||
.eq('member_id', v.data.memberId)
|
||||
.order('created_at', { ascending: false })
|
||||
if (error) return { error: error.message }
|
||||
|
||||
return {
|
||||
data: (data ?? []).map(s => {
|
||||
const f = s.forms as { title: string; kind: string; slug: string } | { title: string; kind: string; slug: string }[] | null
|
||||
const form = Array.isArray(f) ? f[0] : f
|
||||
return {
|
||||
id: s.id as string,
|
||||
formId: s.form_id as string,
|
||||
title: form?.title ?? 'Form',
|
||||
kind: form?.kind ?? 'form',
|
||||
version: s.form_version as number,
|
||||
submittedAt: s.created_at as string,
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user