import Link from 'next/link' import { redirect, notFound } from 'next/navigation' import { createClient } from '@/lib/supabase/server' import type { Policy } from '@/lib/types' import { PolicyActions } from './policy-actions' import { MarkdownBody } from '@/components/markdown' import { CommentThread } from '@/components/comments/comment-thread' import { loadComments } from '@/components/comments/load-comments' export const dynamic = 'force-dynamic' export default async function PolicyDetailPage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params const supabase = await createClient() const { data: { user } } = await supabase.auth.getUser() if (!user) redirect('/login') const { data: member } = await supabase .from('space_members') .select('space_id, role') .eq('user_id', user.id) .in('status', ['current', 'unverified', 'late']) .maybeSingle() if (!member?.space_id) redirect('/signup') const { data: versionsRaw } = await supabase .from('policies') .select('*') .eq('space_id', member.space_id) .eq('slug', slug) .order('version', { ascending: false }) const versions = (versionsRaw ?? []) as unknown as Policy[] if (versions.length === 0) notFound() // Pick the currently-active version, or the latest version, for the primary view. const current = versions.find(p => p.status === 'active') ?? versions[0] const isAdminOrBoard = member.role === 'admin' || member.role === 'board' // Find the member's own id (needed for the discussion thread). const { data: self } = await supabase .from('space_members') .select('id') .eq('user_id', user.id) .eq('space_id', member.space_id) .maybeSingle() // Comments are attached to the policy slug across all versions, so we anchor // on the slug-stable version id of the current row (v1 baseline). const baseId = versions[versions.length - 1].id const comments = await loadComments(supabase, 'policy', baseId) return (
← Policies

{current.title}

{current.slug} {current.section_ref ? ` · §${current.section_ref}` : ''} {' · v'}{current.version} {' · '} {current.status} {current.effective_at ? ` · effective ${new Date(current.effective_at).toLocaleDateString()}` : ''}

{current.body_plain && (

Plain language

)}

Formal text

{isAdminOrBoard && ( )}

Version history ({versions.length})

    {versions.map(v => (
  • v{v.version} · {v.status}

    created {new Date(v.created_at).toLocaleDateString()} {v.effective_at ? ` · effective ${new Date(v.effective_at).toLocaleDateString()}` : ''} {v.adopted_by_proposal_id ? ( <> {' · '} adopted by proposal ) : ''}

  • ))}
) }