/* --------------------------------------------------------------------------- * Activity resource — read-only debug feed. * * Activity rows are emitted by side effects elsewhere in the app (voting, * RSVPs, roadmap-ship transitions, pulse opens). The admin view is a tail * of the table for monitoring; no create, no edit, no delete. * ------------------------------------------------------------------------- */ import { getAllActivityForAdmin, type ActivityKind, type ActivityRow, } from '../../lib/db'; import type { Resource } from '../resource-types'; const KIND_LABEL: Record = { voted: 'Voted', rsvped: 'RSVPed', booked_office_hours: 'Booked office hours', roadmap_shipped: 'Roadmap shipped', pulse_opened: 'Pulse opened', }; const KIND_PILL_CLASS: Record = { voted: 'pill-update', rsvped: 'pill-published', booked_office_hours: 'pill-bts', roadmap_shipped: 'pill-shipping', pulse_opened: 'pill-pending', }; const DAY_MS = 24 * 60 * 60 * 1000; export const activityResource: Resource = { key: 'activity', label: 'Activity', pluralLabel: 'Activity', singularLabel: 'Event', groupKey: 'system', description: 'Recent member actions: votes, RSVPs, office-hour bookings, pulse opens, roadmap ships.', list: { queryFn: () => getAllActivityForAdmin(200), columns: [ { key: 'actor_name', label: 'Actor', primary: true, width: '1.5fr', render: (item) => ({ title: item.actor_name, subtitle: item.actor_role, }), }, { key: 'kind', label: 'Kind', kind: 'pill', width: '160px', pillVariants: Object.fromEntries( (Object.keys(KIND_LABEL) as ActivityKind[]).map((k) => [ k, { label: KIND_LABEL[k], class: KIND_PILL_CLASS[k] }, ]), ), }, { key: 'subject', label: 'Subject', width: '1fr', render: (item) => ({ title: `${item.subject_type} #${item.subject_id}`, }), }, { key: 'created_at', label: 'When', kind: 'relative-date', width: '120px', }, ], filters: [ { key: 'all', label: 'All', predicate: () => true, isDefault: true }, { key: 'last_7_days', label: 'Last 7 days', predicate: (i) => Date.now() - new Date(i.created_at).getTime() < 7 * DAY_MS, }, { key: 'last_30_days', label: 'Last 30 days', predicate: (i) => Date.now() - new Date(i.created_at).getTime() < 30 * DAY_MS, }, ], defaultSort: { key: 'created_at', direction: 'desc' }, pageSize: 100, }, // Pure read view — no form, no summary, no ops, no actions. form: null, ops: {}, };