debats/app/s/[slug]/modifier/page.tsx
Jalil Arfaoui eed063c657 feat: add related subjects (symmetric links) with tabbed edit page and improved subject detail layout
Related subjects: migration with CHECK(id1 < id2) for uniqueness, repository with dual-query (no string interpolation), link/unlink use cases with 8 tests.
Edit page: Radix Tabs (Contenu / Classification), themes extracted as immediate-save SubjectThemes component, related subjects with chip+remove UI and Combobox search.
Subject detail: themes and related subjects displayed in header metadata area, 'Voir aussi' links inline.
Also extracts mapRowToEntity from subject repo for reuse, removes themes from SubjectForm (now independent).
2026-04-05 01:51:14 +02:00

76 lines
2.6 KiB
TypeScript

import { Metadata } from 'next'
import { redirect, notFound } from 'next/navigation'
import { Effect } from 'effect'
import { createAdminSupabaseClient } from '../../../../infra/supabase/admin'
import { createSubjectRepository } from '../../../../infra/database/subject-repository-supabase'
import { createThemeRepository } from '../../../../infra/database/theme-repository-supabase'
import { createRelatedSubjectsRepository } from '../../../../infra/database/related-subjects-repository-supabase'
import { getAuthenticatedContributor } from '../../../actions/get-authenticated-contributor'
import { canPerform } from '../../../../domain/reputation/permissions'
import ContentWithSidebar from '../../../../components/layout/ContentWithSidebar'
import FormPageHeader from '../../../../components/layout/FormPageHeader'
import EditSubjectTabs from './EditSubjectTabs'
interface PageProps {
params: Promise<{ slug: string }>
}
export const metadata: Metadata = {
title: 'Modifier un sujet',
description: 'Modifier un sujet de débat sur Débats.co.',
}
export default async function EditSubjectPage({ params }: PageProps) {
const { slug } = await params
const contributor = await getAuthenticatedContributor()
if (!contributor || !canPerform(contributor.reputation, 'edit_subject')) {
redirect('/s')
}
const supabase = createAdminSupabaseClient()
const subjectRepo = createSubjectRepository(supabase)
const themeRepo = createThemeRepository(supabase)
const relatedRepo = createRelatedSubjectsRepository(supabase)
const [subject, allThemes] = await Promise.all([
Effect.runPromise(subjectRepo.findBySlug(slug)),
Effect.runPromise(themeRepo.findAll()),
])
if (!subject) notFound()
const [subjectThemes, relatedSubjects] = await Promise.all([
Effect.runPromise(themeRepo.findBySubjectId(subject.id)),
Effect.runPromise(relatedRepo.findRelated(subject.id)),
])
return (
<ContentWithSidebar topMargin>
<FormPageHeader
backHref={`/s/${slug}`}
backLabel="Retour au sujet"
title="Modifier le sujet"
subtitle={subject.title}
/>
<EditSubjectTabs
subjectId={subject.id}
subjectSlug={subject.slug}
subject={{
title: subject.title,
presentation: subject.presentation,
problem: subject.problem,
}}
availableThemes={allThemes.map((t) => ({ id: t.id, name: t.name }))}
selectedThemeIds={subjectThemes.map((t) => t.id)}
relatedSubjects={relatedSubjects.map((s) => ({
id: s.id,
title: s.title,
slug: s.slug,
}))}
/>
</ContentWithSidebar>
)
}