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).
76 lines
2.6 KiB
TypeScript
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>
|
|
)
|
|
}
|