From c0142d167e55edcb2173a3eec13a3755163d26cb Mon Sep 17 00:00:00 2001 From: odentas Date: Wed, 10 Dec 2025 16:16:32 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Ajouter=20possibilit=C3=A9=20de=20renom?= =?UTF-8?q?mer=20les=20p=C3=A9riodes=20dans=20documents=20comptables=20(st?= =?UTF-8?q?aff)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(app)/staff/documents/page.tsx | 132 +++++++++++++++--- .../staff/documents/update-period/route.ts | 66 +++++++++ 2 files changed, 178 insertions(+), 20 deletions(-) create mode 100644 app/api/staff/documents/update-period/route.ts diff --git a/app/(app)/staff/documents/page.tsx b/app/(app)/staff/documents/page.tsx index 42499ec..cd644a1 100644 --- a/app/(app)/staff/documents/page.tsx +++ b/app/(app)/staff/documents/page.tsx @@ -415,6 +415,8 @@ export default function StaffDocumentsPage() { const [expandedPeriods, setExpandedPeriods] = React.useState>(new Set()) const [viewDocument, setViewDocument] = React.useState<{ name: string; downloadUrl: string; size?: number } | null>(null) const [deleteConfirm, setDeleteConfirm] = React.useState<{ type: 'general' | 'comptable'; data: any } | null>(null) + const [editingPeriod, setEditingPeriod] = React.useState(null) + const [newPeriodName, setNewPeriodName] = React.useState('') const queryClient = useQueryClient() @@ -515,6 +517,49 @@ export default function StaffDocumentsPage() { onError: () => toast.error('Erreur lors de la suppression') }) + // Renommer une période + const renamePeriod = useMutation({ + mutationFn: async ({ oldName, newName }: { oldName: string; newName: string }) => { + const response = await fetch('/api/staff/documents/update-period', { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + org_id: selectedOrgId, + old_period_label: oldName, + new_period_label: newName + }) + }) + if (!response.ok) throw new Error('Erreur mise à jour') + return response.json() + }, + onSuccess: (data) => { + toast.success(`${data.updated_count} document(s) mis à jour`) + queryClient.invalidateQueries({ queryKey: ['documents', 'comptables'] }) + setEditingPeriod(null) + setNewPeriodName('') + }, + onError: () => toast.error('Erreur lors de la mise à jour') + }) + + const handleStartEditPeriod = (period: string) => { + setEditingPeriod(period) + setNewPeriodName(period) + } + + const handleSavePeriod = (oldName: string) => { + if (newPeriodName.trim() && newPeriodName !== oldName) { + renamePeriod.mutate({ oldName, newName: newPeriodName.trim() }) + } else { + setEditingPeriod(null) + setNewPeriodName('') + } + } + + const handleCancelEditPeriod = () => { + setEditingPeriod(null) + setNewPeriodName('') + } + return (
@@ -739,31 +784,78 @@ export default function StaffDocumentsPage() {
{Array.from(documentsByPeriod.entries()).map(([period, docs]) => { const isExpanded = expandedPeriods.has(period) + const isEditing = editingPeriod === period + return ( -
- + + {isEditing ? ( +
e.stopPropagation()}> + setNewPeriodName(e.target.value)} + className="max-w-sm" + autoFocus + onKeyDown={(e) => { + if (e.key === 'Enter') handleSavePeriod(period) + if (e.key === 'Escape') handleCancelEditPeriod() + }} + /> + + +
+ ) : ( +
+

{period}

+

+ {docs.length} document{docs.length > 1 ? 's' : ''} +

+
+ )} + + + {!isEditing && ( + + )} +
{isExpanded && (
diff --git a/app/api/staff/documents/update-period/route.ts b/app/api/staff/documents/update-period/route.ts new file mode 100644 index 0000000..c034c05 --- /dev/null +++ b/app/api/staff/documents/update-period/route.ts @@ -0,0 +1,66 @@ +import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs' +import { cookies } from 'next/headers' +import { NextResponse } from 'next/server' + +export const dynamic = 'force-dynamic' + +export async function PUT(request: Request) { + try { + const supabase = createRouteHandlerClient({ cookies }) + + // Vérifier l'authentification et les droits staff + const { data: { session } } = await supabase.auth.getSession() + if (!session) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + } + + const { data: staffUser } = await supabase + .from('staff_users') + .select('is_staff') + .eq('user_id', session.user.id) + .maybeSingle() + + if (!staffUser?.is_staff) { + return NextResponse.json({ error: 'Forbidden' }, { status: 403 }) + } + + const body = await request.json() + const { org_id, old_period_label, new_period_label } = body + + if (!org_id || !old_period_label || !new_period_label) { + return NextResponse.json( + { error: 'Missing required fields' }, + { status: 400 } + ) + } + + console.log('📝 Update Period - Org:', org_id, 'Old:', old_period_label, 'New:', new_period_label) + + // Mettre à jour tous les documents de cette période + const { error, count } = await supabase + .from('documents') + .update({ period_label: new_period_label }) + .eq('org_id', org_id) + .eq('period_label', old_period_label) + .eq('category', 'docs_comptables') + + if (error) { + console.error('❌ Error updating period:', error) + return NextResponse.json({ error: error.message }, { status: 500 }) + } + + console.log('✅ Updated', count, 'documents') + + return NextResponse.json({ + success: true, + updated_count: count + }) + + } catch (error: any) { + console.error('❌ Update period error:', error) + return NextResponse.json( + { error: error.message || 'Internal server error' }, + { status: 500 } + ) + } +}