From 84c34bdc21f9694f87415b58b77efa39fc8ef417 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 13 Aug 2026 12:26:46 +0200 Subject: [PATCH] fix ui update --- apps/frontend/DESIGN_SYSTEM.md | 18 + apps/frontend/app/[locale]/about/page.tsx | 32 +- .../frontend/app/[locale]/admin/blog/page.tsx | 252 +-- .../app/[locale]/admin/bookings/page.tsx | 176 +- .../app/[locale]/admin/csv-rates/page.tsx | 14 +- .../app/[locale]/admin/documents/page.tsx | 124 +- apps/frontend/app/[locale]/admin/layout.tsx | 218 +-- .../frontend/app/[locale]/admin/logs/page.tsx | 108 +- .../app/[locale]/admin/organizations/page.tsx | 100 +- .../app/[locale]/admin/users/page.tsx | 100 +- .../[locale]/blog/[slug]/BlogPostContent.tsx | 42 +- apps/frontend/app/[locale]/blog/page.tsx | 34 +- .../[locale]/booking/confirm/[token]/page.tsx | 102 +- apps/frontend/app/[locale]/booking/layout.tsx | 5 + .../[locale]/booking/reject/[token]/page.tsx | 94 +- apps/frontend/app/[locale]/careers/page.tsx | 50 +- .../[locale]/carrier/accept/[token]/page.tsx | 20 +- .../carrier/documents/[token]/page.tsx | 96 +- apps/frontend/app/[locale]/carrier/layout.tsx | 5 + .../[locale]/carrier/reject/[token]/page.tsx | 20 +- .../frontend/app/[locale]/compliance/page.tsx | 28 +- apps/frontend/app/[locale]/contact/page.tsx | 68 +- apps/frontend/app/[locale]/cookies/page.tsx | 32 +- .../dashboard/booking/[id]/pay/page.tsx | 130 +- .../booking/[id]/payment-success/page.tsx | 38 +- .../[locale]/dashboard/booking/new/page.tsx | 170 +- .../[locale]/dashboard/bookings/[id]/page.tsx | 427 +++-- .../[locale]/dashboard/bookings/new/page.tsx | 871 ---------- .../app/[locale]/dashboard/bookings/page.tsx | 1223 +++++--------- .../app/[locale]/dashboard/documents/page.tsx | 1464 +++++------------ .../app/[locale]/dashboard/layout.tsx | 290 +--- .../[locale]/dashboard/notifications/page.tsx | 89 +- apps/frontend/app/[locale]/dashboard/page.tsx | 548 +++--- .../app/[locale]/dashboard/profile/page.tsx | 64 +- .../dashboard/search-advanced/page.tsx | 198 +-- .../search-advanced/results/page.tsx | 110 +- .../app/[locale]/dashboard/search/page.tsx | 614 ------- .../dashboard/settings/api-keys/page.tsx | 102 +- .../dashboard/settings/organization/page.tsx | 71 +- .../dashboard/settings/subscription/page.tsx | 4 +- .../dashboard/settings/users/page.tsx | 204 ++- .../[locale]/dashboard/track-trace/page.tsx | 790 ++++----- .../dashboard/wiki/assurance/page.tsx | 51 +- .../dashboard/wiki/calcul-fret/page.tsx | 51 +- .../dashboard/wiki/conteneurs/page.tsx | 59 +- .../wiki/documents-transport/page.tsx | 51 +- .../[locale]/dashboard/wiki/douanes/page.tsx | 49 +- .../app/[locale]/dashboard/wiki/imdg/page.tsx | 57 +- .../dashboard/wiki/incoterms/page.tsx | 55 +- .../app/[locale]/dashboard/wiki/layout.tsx | 13 + .../dashboard/wiki/lcl-vs-fcl/page.tsx | 61 +- .../dashboard/wiki/lettre-credit/page.tsx | 65 +- .../app/[locale]/dashboard/wiki/page.tsx | 20 +- .../dashboard/wiki/ports-routes/page.tsx | 73 +- .../dashboard/wiki/transit-time/page.tsx | 101 +- .../app/[locale]/dashboard/wiki/vgm/page.tsx | 75 +- .../frontend/app/[locale]/demo-carte/page.tsx | 72 - apps/frontend/app/[locale]/page.tsx | 72 +- apps/frontend/app/[locale]/press/page.tsx | 56 +- apps/frontend/app/[locale]/pricing/page.tsx | 44 +- apps/frontend/app/[locale]/privacy/page.tsx | 4 +- apps/frontend/app/[locale]/security/page.tsx | 18 +- apps/frontend/app/[locale]/terms/page.tsx | 4 +- .../frontend/app/[locale]/test-image/page.tsx | 49 - .../app/[locale]/verify-email/page.tsx | 26 +- apps/frontend/app/globals.css | 60 +- apps/frontend/messages/en.json | 149 +- apps/frontend/messages/fr.json | 141 +- apps/frontend/package-lock.json | 1046 +++++++++++- apps/frontend/package.json | 4 + .../__tests__/components/data-table.test.tsx | 134 ++ .../__tests__/components/nav-config.test.ts | 106 ++ .../src/app/rates/csv-search/page.tsx | 213 --- .../frontend/src/components/CookieConsent.tsx | 48 +- apps/frontend/src/components/DebugUser.tsx | 2 +- apps/frontend/src/components/ExportButton.tsx | 28 +- .../src/components/LanguageSwitcher.tsx | 6 +- .../src/components/NotificationDropdown.tsx | 32 +- .../src/components/NotificationPanel.tsx | 64 +- .../src/components/admin/CarrierForm.tsx | 40 +- .../src/components/admin/CsvUpload.tsx | 4 +- .../src/components/blog/RichTextEditor.tsx | 18 +- .../bookings/BookingDetailDialog.tsx | 161 ++ .../components/bookings/BookingFilters.tsx | 62 +- .../bookings/BookingStatusBadge.tsx | 41 + .../src/components/bookings/BookingsTable.tsx | 28 +- .../src/components/bookings/BulkActions.tsx | 24 +- .../src/components/data/data-table.tsx | 377 +++++ .../src/components/data/description-list.tsx | 47 + .../src/components/data/filter-bar.tsx | 122 ++ apps/frontend/src/components/data/index.ts | 10 + .../src/components/data/search-input.tsx | 78 + .../src/components/data/stat-card.tsx | 80 + .../src/components/docs/CodeBlock.tsx | 12 +- .../src/components/docs/DocsPageContent.tsx | 180 +- .../documents/AddDocumentsDialog.tsx | 120 ++ .../documents/ReplaceDocumentDialog.tsx | 93 ++ .../components/documents/document-icon.tsx | 46 + .../src/components/forms/file-dropzone.tsx | 142 ++ .../src/components/layout/LandingHeader.tsx | 6 +- .../components/organization/LicensesTab.tsx | 112 +- .../organization/SubscriptionTab.tsx | 58 +- apps/frontend/src/components/providers.tsx | 13 +- .../rate-search/RateResultsTable.tsx | 10 +- .../rate-search/VolumeWeightInput.tsx | 6 +- .../src/components/shell/app-shell.tsx | 252 +++ .../src/components/shell/bottom-nav.tsx | 81 + .../src/components/shell/breadcrumb.tsx | 124 ++ .../src/components/shell/command-menu.tsx | 199 +++ .../src/components/shell/nav-config.ts | 206 +++ .../src/components/shell/portal-shell.tsx | 43 + .../src/components/shell/settings-nav.tsx | 56 + .../src/components/shell/sidebar-nav.tsx | 114 ++ apps/frontend/src/components/shell/topbar.tsx | 97 ++ .../src/components/shell/user-menu.tsx | 126 ++ .../src/components/ui/FeatureGate.tsx | 8 +- .../frontend/src/components/ui/PageHeader.tsx | 40 +- apps/frontend/src/components/ui/avatar.tsx | 38 + apps/frontend/src/components/ui/badge.tsx | 59 +- apps/frontend/src/components/ui/button.tsx | 113 +- apps/frontend/src/components/ui/callout.tsx | 60 + apps/frontend/src/components/ui/card.tsx | 51 +- apps/frontend/src/components/ui/checkbox.tsx | 36 + .../src/components/ui/confirm-dialog.tsx | 79 + apps/frontend/src/components/ui/dialog.tsx | 164 +- .../src/components/ui/dropdown-menu.tsx | 172 ++ .../frontend/src/components/ui/form-field.tsx | 77 + apps/frontend/src/components/ui/index.ts | 98 ++ apps/frontend/src/components/ui/input.tsx | 62 +- apps/frontend/src/components/ui/label.tsx | 35 +- .../frontend/src/components/ui/pagination.tsx | 146 ++ apps/frontend/src/components/ui/popover.tsx | 75 +- apps/frontend/src/components/ui/select.tsx | 206 ++- apps/frontend/src/components/ui/separator.tsx | 23 + apps/frontend/src/components/ui/sheet.tsx | 65 + apps/frontend/src/components/ui/states.tsx | 189 +++ apps/frontend/src/components/ui/tabs.tsx | 65 + apps/frontend/src/components/ui/textarea.tsx | 30 + apps/frontend/src/components/ui/toast.tsx | 196 +++ apps/frontend/src/components/ui/tooltip.tsx | 32 + .../src/components/ui/use-confirm.tsx | 73 + .../src/components/wiki/WikiBackLink.tsx | 24 + apps/frontend/src/hooks/use-sidebar.ts | 40 + apps/frontend/src/hooks/use-url-state.ts | 94 ++ .../src/legacy-pages/BookingsManagement.tsx | 124 -- .../src/legacy-pages/CarrierManagement.tsx | 254 --- .../src/legacy-pages/CarrierMonitoring.tsx | 308 ---- apps/frontend/src/lib/chart-colors.ts | 54 + docs/design-system-audit.md | 711 ++++++++ docs/ui-architecture.md | 695 ++++++++ docs/ui-audit.md | 419 +++++ 151 files changed, 12074 insertions(+), 8333 deletions(-) create mode 100644 apps/frontend/app/[locale]/booking/layout.tsx create mode 100644 apps/frontend/app/[locale]/carrier/layout.tsx delete mode 100644 apps/frontend/app/[locale]/dashboard/bookings/new/page.tsx delete mode 100644 apps/frontend/app/[locale]/dashboard/search/page.tsx create mode 100644 apps/frontend/app/[locale]/dashboard/wiki/layout.tsx delete mode 100644 apps/frontend/app/[locale]/demo-carte/page.tsx delete mode 100644 apps/frontend/app/[locale]/test-image/page.tsx create mode 100644 apps/frontend/src/__tests__/components/data-table.test.tsx create mode 100644 apps/frontend/src/__tests__/components/nav-config.test.ts delete mode 100644 apps/frontend/src/app/rates/csv-search/page.tsx create mode 100644 apps/frontend/src/components/bookings/BookingDetailDialog.tsx create mode 100644 apps/frontend/src/components/bookings/BookingStatusBadge.tsx create mode 100644 apps/frontend/src/components/data/data-table.tsx create mode 100644 apps/frontend/src/components/data/description-list.tsx create mode 100644 apps/frontend/src/components/data/filter-bar.tsx create mode 100644 apps/frontend/src/components/data/index.ts create mode 100644 apps/frontend/src/components/data/search-input.tsx create mode 100644 apps/frontend/src/components/data/stat-card.tsx create mode 100644 apps/frontend/src/components/documents/AddDocumentsDialog.tsx create mode 100644 apps/frontend/src/components/documents/ReplaceDocumentDialog.tsx create mode 100644 apps/frontend/src/components/documents/document-icon.tsx create mode 100644 apps/frontend/src/components/forms/file-dropzone.tsx create mode 100644 apps/frontend/src/components/shell/app-shell.tsx create mode 100644 apps/frontend/src/components/shell/bottom-nav.tsx create mode 100644 apps/frontend/src/components/shell/breadcrumb.tsx create mode 100644 apps/frontend/src/components/shell/command-menu.tsx create mode 100644 apps/frontend/src/components/shell/nav-config.ts create mode 100644 apps/frontend/src/components/shell/portal-shell.tsx create mode 100644 apps/frontend/src/components/shell/settings-nav.tsx create mode 100644 apps/frontend/src/components/shell/sidebar-nav.tsx create mode 100644 apps/frontend/src/components/shell/topbar.tsx create mode 100644 apps/frontend/src/components/shell/user-menu.tsx create mode 100644 apps/frontend/src/components/ui/avatar.tsx create mode 100644 apps/frontend/src/components/ui/callout.tsx create mode 100644 apps/frontend/src/components/ui/checkbox.tsx create mode 100644 apps/frontend/src/components/ui/confirm-dialog.tsx create mode 100644 apps/frontend/src/components/ui/dropdown-menu.tsx create mode 100644 apps/frontend/src/components/ui/form-field.tsx create mode 100644 apps/frontend/src/components/ui/index.ts create mode 100644 apps/frontend/src/components/ui/pagination.tsx create mode 100644 apps/frontend/src/components/ui/separator.tsx create mode 100644 apps/frontend/src/components/ui/sheet.tsx create mode 100644 apps/frontend/src/components/ui/states.tsx create mode 100644 apps/frontend/src/components/ui/tabs.tsx create mode 100644 apps/frontend/src/components/ui/textarea.tsx create mode 100644 apps/frontend/src/components/ui/toast.tsx create mode 100644 apps/frontend/src/components/ui/tooltip.tsx create mode 100644 apps/frontend/src/components/ui/use-confirm.tsx create mode 100644 apps/frontend/src/components/wiki/WikiBackLink.tsx create mode 100644 apps/frontend/src/hooks/use-sidebar.ts create mode 100644 apps/frontend/src/hooks/use-url-state.ts delete mode 100644 apps/frontend/src/legacy-pages/BookingsManagement.tsx delete mode 100644 apps/frontend/src/legacy-pages/CarrierManagement.tsx delete mode 100644 apps/frontend/src/legacy-pages/CarrierMonitoring.tsx create mode 100644 apps/frontend/src/lib/chart-colors.ts create mode 100644 docs/design-system-audit.md create mode 100644 docs/ui-architecture.md create mode 100644 docs/ui-audit.md diff --git a/apps/frontend/DESIGN_SYSTEM.md b/apps/frontend/DESIGN_SYSTEM.md index d4675d6..69f00e1 100644 --- a/apps/frontend/DESIGN_SYSTEM.md +++ b/apps/frontend/DESIGN_SYSTEM.md @@ -1,5 +1,23 @@ # Xpeditis Design System +> ## ⚠️ Ce document n'est pas la source de vérité +> +> La source de vérité du design system est **`apps/frontend/tailwind.config.ts`**, complétée par les variables CSS de `apps/frontend/app/globals.css`. +> +> Pour travailler sur l'UI, référez-vous à : +> +> | Document | Contenu | +> |---|---| +> | [`docs/design-system-audit.md`](../../docs/design-system-audit.md) | **Charte verrouillée** — valeurs réelles relevées dans le code, 24 sections | +> | [`docs/ui-audit.md`](../../docs/ui-audit.md) | Cartographie des pages, problèmes identifiés, duplications | +> | [`docs/ui-architecture.md`](../../docs/ui-architecture.md) | Architecture UI cible, plan de refonte, indicateurs, règles de contraste | +> +> Le présent fichier est conservé pour sa description narrative de l'identité de marque. **Les valeurs ci-dessous sont exactes**, mais les exemples d'usage qu'il contient précèdent la refonte UI et ne reflètent plus les composants en place. +> +> Deux points en particulier ont évolué depuis sa rédaction — voir `docs/ui-architecture.md` §17 : +> - Le turquoise `#34CCCD` **ne doit pas porter de texte sur fond clair** (2,05:1, échec AA). Il est réservé aux fonds, bordures et anneaux de focus. +> - Sur un aplat turquoise, le texte est **navy** (8,49:1, AAA) et non blanc. + ## 📐 Charte Graphique Ce document définit la charte graphique officielle de Xpeditis pour assurer la cohérence visuelle de l'application. diff --git a/apps/frontend/app/[locale]/about/page.tsx b/apps/frontend/app/[locale]/about/page.tsx index a49585e..d50ae0d 100644 --- a/apps/frontend/app/[locale]/about/page.tsx +++ b/apps/frontend/app/[locale]/about/page.tsx @@ -24,7 +24,7 @@ type TimelineKey = '2023' | '2024' | '2025' | '2026'; type StatKey = 'clients' | 'carriers' | 'countries' | 'bookings'; const VALUES: { key: ValueKey; icon: LucideIcon; color: string }[] = [ - { key: 'excellence', icon: Target, color: 'from-blue-500 to-cyan-500' }, + { key: 'excellence', icon: Target, color: 'from-brand-turquoise to-cyan-500' }, { key: 'transparency', icon: Heart, color: 'from-pink-500 to-rose-500' }, { key: 'collaboration', icon: Users, color: 'from-purple-500 to-indigo-500' }, { key: 'innovation', icon: TrendingUp, color: 'from-orange-500 to-amber-500' }, @@ -158,7 +158,7 @@ export default function AboutPage() {

{t('mission.title')}

-

{t('mission.body')}

+

{t('mission.body')}

{t('vision.title')}

-

{t('vision.body')}

+

{t('vision.body')}

{/* Stats Section */} -
+
{stat.value} -
{t(`stats.${stat.key}`)}
+
{t(`stats.${stat.key}`)}
))} @@ -213,7 +213,7 @@ export default function AboutPage() {

{t('valuesTitle')}

-

{t('valuesSubtitle')}

+

{t('valuesSubtitle')}

{t(`values.${value.key}.title`)} -

{t(`values.${value.key}.description`)}

+

{t(`values.${value.key}.description`)}

); })} @@ -248,7 +248,7 @@ export default function AboutPage() {
{/* Timeline Section */} -
+
{t('timelineTitle')} -

{t('timelineSubtitle')}

+

{t('timelineSubtitle')}

@@ -286,7 +286,7 @@ export default function AboutPage() {
-
+
@@ -296,7 +296,7 @@ export default function AboutPage() {

{t(`timeline.${year}.title`)}

-

{t(`timeline.${year}.description`)}

+

{t(`timeline.${year}.description`)}

@@ -336,7 +336,7 @@ export default function AboutPage() {

{t('teamTitle')}

-

{t('teamSubtitle')}

+

{t('teamSubtitle')}

@@ -370,7 +370,7 @@ export default function AboutPage() {

{t(`team.${member.key}.role`)}

-

{t(`team.${member.key}.bio`)}

+

{t(`team.${member.key}.bio`)}

))} @@ -399,7 +399,7 @@ export default function AboutPage() { {t('cta.viewCareers')} diff --git a/apps/frontend/app/[locale]/admin/blog/page.tsx b/apps/frontend/app/[locale]/admin/blog/page.tsx index 7973ffc..912eeb0 100644 --- a/apps/frontend/app/[locale]/admin/blog/page.tsx +++ b/apps/frontend/app/[locale]/admin/blog/page.tsx @@ -38,6 +38,7 @@ import { Sparkles, } from 'lucide-react'; import { Link } from '@/i18n/navigation'; +import { useToast } from '@/components/ui/toast'; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000'; @@ -67,9 +68,9 @@ const STATUS_LABELS: Record = { const STATUS_COLORS: Record = { draft: 'bg-yellow-100 text-yellow-800', - scheduled: 'bg-blue-100 text-blue-800', + scheduled: 'bg-brand-turquoise/10 text-brand-navy', published: 'bg-green-100 text-green-800', - archived: 'bg-gray-100 text-gray-600', + archived: 'bg-neutral-100 text-neutral-600', }; interface FormData extends CreateBlogPostRequest { @@ -134,18 +135,19 @@ function SeoPreview({ const displayDesc = metaDescription || "Description de l'article..."; const displayUrl = `xpeditis.com/blog/${slug || 'votre-slug'}`; return ( -
-

+

+

Aperçu Google

-

{displayTitle}

+

{displayTitle}

{displayUrl}

-

{displayDesc}

+

{displayDesc}

); } export default function AdminBlogPage() { + const { toast } = useToast(); const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -254,7 +256,7 @@ export default function AdminBlogPage() { await fetchPosts(); closeModal(); } catch (err: any) { - alert(err.message || 'Erreur lors de la création'); + toast.error(err.message || 'Erreur lors de la création'); } finally { setSaving(false); } @@ -272,7 +274,7 @@ export default function AdminBlogPage() { await fetchPosts(); closeModal(); } catch (err: any) { - alert(err.message || 'Erreur lors de la mise à jour'); + toast.error(err.message || 'Erreur lors de la mise à jour'); } finally { setSaving(false); } @@ -286,7 +288,7 @@ export default function AdminBlogPage() { setShowDeleteConfirm(false); setSelectedPost(null); } catch (err: any) { - alert(err.message || 'Erreur lors de la suppression'); + toast.error(err.message || 'Erreur lors de la suppression'); } }; @@ -296,7 +298,7 @@ export default function AdminBlogPage() { await updateBlogPost(post.id, { status: nextStatus }); await fetchPosts(); } catch (err: any) { - alert(err.message || 'Erreur lors du changement de statut'); + toast.error(err.message || 'Erreur lors du changement de statut'); } }; @@ -305,17 +307,17 @@ export default function AdminBlogPage() { await updateBlogPost(post.id, { isFeatured: !post.isFeatured }); await fetchPosts(); } catch (err: any) { - alert(err.message || 'Erreur lors du changement'); + toast.error(err.message || 'Erreur lors du changement'); } }; const uploadCoverFile = async (file: File) => { if (!file.type.startsWith('image/')) { - alert('Veuillez sélectionner une image'); + toast.error('Veuillez sélectionner une image'); return; } if (file.size > 5 * 1024 * 1024) { - alert('Image trop volumineuse (max 5 Mo)'); + toast.error('Image trop volumineuse (max 5 Mo)'); return; } @@ -331,7 +333,7 @@ export default function AdminBlogPage() { const coverUrl = result.url.startsWith('http') ? result.url : `${API_BASE_URL}${result.url}`; setFormData(prev => ({ ...prev, coverImageUrl: coverUrl })); } catch (err: any) { - alert(err.message || "Erreur lors de l'upload"); + toast.error(err.message || "Erreur lors de l'upload"); } finally { setUploadingCover(false); if (coverInputRef.current) coverInputRef.current.value = ''; @@ -375,7 +377,7 @@ export default function AdminBlogPage() { await duplicateBlogPost(post.id); await fetchPosts(); } catch (err: any) { - alert(err.message || 'Erreur lors de la duplication'); + toast.error(err.message || 'Erreur lors de la duplication'); } finally { setActioningId(null); } @@ -387,7 +389,7 @@ export default function AdminBlogPage() { await restoreBlogPost(post.id); await fetchPosts(); } catch (err: any) { - alert(err.message || 'Erreur lors de la restauration'); + toast.error(err.message || 'Erreur lors de la restauration'); } finally { setActioningId(null); } @@ -401,7 +403,7 @@ export default function AdminBlogPage() { setShowDeleteConfirm(false); setSelectedPost(null); } catch (err: any) { - alert(err.message || 'Erreur lors de la suppression définitive'); + toast.error(err.message || 'Erreur lors de la suppression définitive'); } }; @@ -502,13 +504,13 @@ export default function AdminBlogPage() { const metaDescLen = formData.metaDescription.length; const metaTitleColor = metaTitleLen === 0 - ? 'text-gray-400' + ? 'text-neutral-400' : metaTitleLen <= 60 ? 'text-green-600' : 'text-red-500'; const metaDescColor = metaDescLen === 0 - ? 'text-gray-400' + ? 'text-neutral-400' : metaDescLen <= 160 ? 'text-green-600' : 'text-red-500'; @@ -524,7 +526,7 @@ export default function AdminBlogPage() { actions={
{loading ? ( -
Chargement des articles...
+
Chargement des articles...
) : ( -
- - +
+
+ - - - - - - - + {visiblePosts.length === 0 ? ( - ) : ( visiblePosts.map(post => ( - + - - - +
+ Article + Catégorie + Statut + Auteur + Date + Actions
+ {viewFilter === 'trash' ? 'La corbeille est vide.' : 'Aucun article. Créez votre premier article !'} @@ -602,7 +604,7 @@ export default function AdminBlogPage() {
{post.coverImageUrl && ( @@ -617,15 +619,15 @@ export default function AdminBlogPage() { {post.isFeatured && ( )} - + {post.title}
-
{post.slug}
+
{post.slug}
+ {CATEGORIES.find(c => c.value === post.category)?.label ?? post.category} @@ -636,7 +638,7 @@ export default function AdminBlogPage() { {STATUS_LABELS[post.status]} {post.status === 'scheduled' && post.publishedAt && ( - + {new Date(post.publishedAt).toLocaleString('fr-FR', { day: '2-digit', @@ -649,8 +651,8 @@ export default function AdminBlogPage() { )} {post.authorName} + {post.authorName} {post.publishedAt ? new Date(post.publishedAt).toLocaleDateString('fr-FR') : new Date(post.createdAt).toLocaleDateString('fr-FR')} @@ -662,7 +664,7 @@ export default function AdminBlogPage() { -

+

{showCreateModal ? 'Nouvel article' : `Modifier — ${selectedPost?.title}`}

@@ -780,7 +782,7 @@ export default function AdminBlogPage() {