From 155c3385c1b7b78381ad9b548d55b774ee0e8544 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 12:44:11 +0000 Subject: [PATCH] Refonte UI : design system, logo, shell responsive et pages simples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Nouveaux tokens (indigo/corail, statuts, plateformes) et mode sombre - Logo et favicon Social Flow redessinés - AppShell partagé : sidebar groupée (desktop) + barre de navigation basse (mobile) - Suppression des pages mobiles dupliquées et des composants morts - Tableau de bord, connexion, 404, calendrier, médiathèque, IA, statistiques Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017ADkrVcVFTT14hbB148HYS --- client/index.html | 16 +- client/public/favicon.svg | 26 +- client/src/App.tsx | 194 ++--- client/src/components/ai-chat.tsx | 171 ++-- client/src/components/brand/logo.tsx | 56 ++ client/src/components/camera-recorder.tsx | 303 ------- client/src/components/empty-state.tsx | 32 + client/src/components/layout/app-shell.tsx | 49 ++ client/src/components/layout/mobile-nav.tsx | 189 +++++ client/src/components/layout/nav-config.ts | 107 +++ client/src/components/layout/page-header.tsx | 52 ++ client/src/components/managed-pages.tsx | 153 ++-- client/src/components/ongoing-reels.tsx | 31 +- client/src/components/platform-icon.tsx | 35 + client/src/components/quick-actions.tsx | 124 --- client/src/components/recent-publications.tsx | 184 ++-- client/src/components/responsive-route.tsx | 49 -- client/src/components/sidebar.tsx | 429 ++++------ client/src/components/stats-cards.tsx | 117 +-- client/src/components/theme-provider.tsx | 51 ++ client/src/components/topbar.tsx | 52 -- client/src/components/ui/badge.tsx | 7 +- client/src/components/ui/button.tsx | 16 +- client/src/components/ui/card.tsx | 10 +- client/src/components/ui/input.tsx | 2 +- client/src/components/ui/select.tsx | 2 +- client/src/components/ui/tabs.tsx | 4 +- client/src/components/ui/textarea.tsx | 2 +- client/src/hooks/use-session.ts | 36 + client/src/hooks/useIsMobile.ts | 72 -- client/src/index.css | 317 +++---- client/src/pages/AnalyticsPage.tsx | 38 - client/src/pages/ai.tsx | 46 +- client/src/pages/analytics.tsx | 17 + client/src/pages/calendar.tsx | 55 +- client/src/pages/dashboard.tsx | 75 +- client/src/pages/login.tsx | 105 ++- client/src/pages/media.tsx | 46 +- client/src/pages/mobile/ai.tsx | 42 - client/src/pages/mobile/analytics.tsx | 38 - client/src/pages/mobile/audio-admin.tsx | 2 - client/src/pages/mobile/calendar.tsx | 42 - client/src/pages/mobile/dashboard.tsx | 119 --- client/src/pages/mobile/history.tsx | 160 ---- client/src/pages/mobile/image-editor.tsx | 645 -------------- client/src/pages/mobile/media.tsx | 42 - client/src/pages/mobile/new-post.tsx | 800 ------------------ client/src/pages/mobile/new-reel.tsx | 657 -------------- client/src/pages/mobile/pages.tsx | 533 ------------ client/src/pages/mobile/settings.tsx | 585 ------------- client/src/pages/mobile/sql.tsx | 240 ------ client/src/pages/mobile/users-admin.tsx | 589 ------------- client/src/pages/not-found.tsx | 32 +- client/src/pages/test-camera.tsx | 40 - tailwind.config.ts | 86 +- 55 files changed, 1591 insertions(+), 6331 deletions(-) create mode 100644 client/src/components/brand/logo.tsx delete mode 100644 client/src/components/camera-recorder.tsx create mode 100644 client/src/components/empty-state.tsx create mode 100644 client/src/components/layout/app-shell.tsx create mode 100644 client/src/components/layout/mobile-nav.tsx create mode 100644 client/src/components/layout/nav-config.ts create mode 100644 client/src/components/layout/page-header.tsx create mode 100644 client/src/components/platform-icon.tsx delete mode 100644 client/src/components/quick-actions.tsx delete mode 100644 client/src/components/responsive-route.tsx create mode 100644 client/src/components/theme-provider.tsx delete mode 100644 client/src/components/topbar.tsx create mode 100644 client/src/hooks/use-session.ts delete mode 100644 client/src/hooks/useIsMobile.ts delete mode 100644 client/src/pages/AnalyticsPage.tsx create mode 100644 client/src/pages/analytics.tsx delete mode 100644 client/src/pages/mobile/ai.tsx delete mode 100644 client/src/pages/mobile/analytics.tsx delete mode 100644 client/src/pages/mobile/audio-admin.tsx delete mode 100644 client/src/pages/mobile/calendar.tsx delete mode 100644 client/src/pages/mobile/dashboard.tsx delete mode 100644 client/src/pages/mobile/history.tsx delete mode 100644 client/src/pages/mobile/image-editor.tsx delete mode 100644 client/src/pages/mobile/media.tsx delete mode 100644 client/src/pages/mobile/new-post.tsx delete mode 100644 client/src/pages/mobile/new-reel.tsx delete mode 100644 client/src/pages/mobile/pages.tsx delete mode 100644 client/src/pages/mobile/settings.tsx delete mode 100644 client/src/pages/mobile/sql.tsx delete mode 100644 client/src/pages/mobile/users-admin.tsx delete mode 100644 client/src/pages/test-camera.tsx diff --git a/client/index.html b/client/index.html index 8c3ef08..3775657 100644 --- a/client/index.html +++ b/client/index.html @@ -4,11 +4,23 @@ Social Flow - Automatisation des réseaux sociaux - + + + - +
diff --git a/client/public/favicon.svg b/client/public/favicon.svg index ff1ab3e..a9d39eb 100644 --- a/client/public/favicon.svg +++ b/client/public/favicon.svg @@ -1,21 +1,13 @@ - + - - - + + + + - - - - - - - - - - - - - + + + + diff --git a/client/src/App.tsx b/client/src/App.tsx index e2c1323..0319f13 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,99 +1,58 @@ -import { Switch, Route, Redirect, useLocation } from "wouter"; -import { useEffect } from "react"; +import { Switch, Route, useLocation, Link } from "wouter"; +import { lazy, Suspense, useEffect, type ComponentType } from "react"; import { queryClient } from "./lib/queryClient"; -import { QueryClientProvider, useQuery } from "@tanstack/react-query"; +import { QueryClientProvider } from "@tanstack/react-query"; +import { ShieldAlert } from "lucide-react"; import { Toaster } from "@/components/ui/toaster"; import { TooltipProvider } from "@/components/ui/tooltip"; -import { createResponsiveRoute } from "@/components/responsive-route"; +import { Button } from "@/components/ui/button"; +import { ThemeProvider } from "@/components/theme-provider"; +import { AppShell, Page } from "@/components/layout/app-shell"; +import { EmptyState } from "@/components/empty-state"; +import { LogoMark } from "@/components/brand/logo"; +import { useSession } from "@/hooks/use-session"; import NotFound from "@/pages/not-found"; import Login from "@/pages/login"; -import TestCamera from "@/pages/test-camera"; +// Pages chargées à la demande : une seule version responsive par écran. +const Dashboard = lazy(() => import("@/pages/dashboard")); +const NewPost = lazy(() => import("@/pages/new-post")); +const NewReel = lazy(() => import("@/pages/new-reel")); +const ScheduleReel = lazy(() => import("@/pages/schedule-reel")); +const Calendar = lazy(() => import("@/pages/calendar")); +const Media = lazy(() => import("@/pages/media")); +const ImageEditor = lazy(() => import("@/pages/image-editor")); +const PagesManagement = lazy(() => import("@/pages/pages")); +const AI = lazy(() => import("@/pages/ai")); +const History = lazy(() => import("@/pages/history")); +const Settings = lazy(() => import("@/pages/settings")); +const SqlAdmin = lazy(() => import("@/pages/sql")); +const AudioAdmin = lazy(() => import("@/pages/audio-admin")); +const UsersAdmin = lazy(() => import("@/pages/users-admin")); +const Analytics = lazy(() => import("@/pages/analytics")); -// Create responsive routes with lazy loading for optimal performance -const History = createResponsiveRoute( - () => import("@/pages/history"), - () => import("@/pages/mobile/history") -); -const Dashboard = createResponsiveRoute( - () => import("@/pages/dashboard"), - () => import("@/pages/mobile/dashboard") -); +function FullScreenLoader() { + return ( +
+
+ +

Chargement…

+
+
+ ); +} -const NewPost = createResponsiveRoute( - () => import("@/pages/new-post"), - () => import("@/pages/mobile/new-post") -); +function PageLoader() { + return ( +
+
+
+ ); +} -const Calendar = createResponsiveRoute( - () => import("@/pages/calendar"), - () => import("@/pages/mobile/calendar") -); - -const Media = createResponsiveRoute( - () => import("@/pages/media"), - () => import("@/pages/mobile/media") -); - -const ImageEditor = createResponsiveRoute( - () => import("@/pages/image-editor"), - () => import("@/pages/mobile/image-editor") -); - -const PagesManagement = createResponsiveRoute( - () => import("@/pages/pages"), - () => import("@/pages/mobile/pages") -); - -const AI = createResponsiveRoute( - () => import("@/pages/ai"), - () => import("@/pages/mobile/ai") -); - -const Settings = createResponsiveRoute( - () => import("@/pages/settings"), - () => import("@/pages/mobile/settings") -); - -const SqlAdmin = createResponsiveRoute( - () => import("@/pages/sql"), - () => import("@/pages/mobile/sql") -); - -const AudioAdmin = createResponsiveRoute( - () => import("@/pages/audio-admin"), - () => import("@/pages/mobile/audio-admin") -); - -const UsersAdmin = createResponsiveRoute( - () => import("@/pages/users-admin"), - () => import("@/pages/mobile/users-admin") -); - -const Analytics = createResponsiveRoute( - () => import("@/pages/AnalyticsPage"), - () => import("@/pages/mobile/analytics") -); - -// NewReel uses desktop version for now (mobile can be added later) -const NewReel = createResponsiveRoute( - () => import("@/pages/new-reel"), - () => import("@/pages/mobile/new-reel") // Uses same component for now -); - -// Reel déjà monté : même page responsive sur mobile et desktop -const ScheduleReel = createResponsiveRoute( - () => import("@/pages/schedule-reel"), - () => import("@/pages/schedule-reel") -); - -function ProtectedRoute({ component: Component, adminOnly = false }: { component: React.ComponentType; adminOnly?: boolean }) { +function ProtectedRoute({ component: Component, adminOnly = false }: { component: ComponentType; adminOnly?: boolean }) { const [, setLocation] = useLocation(); - - const { data: session, isLoading } = useQuery({ - queryKey: ["/api/auth/session"], - retry: false, - }); + const { session, isAdmin, isLoading } = useSession(); useEffect(() => { if (!isLoading && !session) { @@ -101,33 +60,31 @@ function ProtectedRoute({ component: Component, adminOnly = false }: { component } }, [isLoading, session, setLocation]); - if (isLoading) { - return ( -
-
-
-

Chargement...

-
-
- ); - } + if (isLoading) return ; + if (!session) return null; - if (!session) { - return null; - } - - if (adminOnly && (session as any).role !== "admin") { - return ( -
-
-

Accès refusé

-

Cette page est réservée aux administrateurs.

-
-
- ); - } - - return ; + return ( + + {adminOnly && !isAdmin ? ( + + + Retour au tableau de bord + + } + /> + + ) : ( + }> + + + )} + + ); } function Router() { @@ -149,7 +106,6 @@ function Router() { {() => } {() => } {() => } - ); @@ -157,14 +113,14 @@ function Router() { function App() { return ( - - -
+ + + -
-
-
+ + + ); } diff --git a/client/src/components/ai-chat.tsx b/client/src/components/ai-chat.tsx index 33aec8e..5355722 100644 --- a/client/src/components/ai-chat.tsx +++ b/client/src/components/ai-chat.tsx @@ -4,7 +4,8 @@ import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { useMutation, useQuery } from "@tanstack/react-query"; import { apiRequest, queryClient } from "@/lib/queryClient"; -import { Bot, User, Lightbulb, History, Zap, Sparkles, Loader2 } from "lucide-react"; +import { Bot, User, Sparkles, Loader2, Copy, RotateCcw } from "lucide-react"; +import { Badge } from "@/components/ui/badge"; import { useToast } from "@/hooks/use-toast"; import { ModelCombobox } from "@/components/model-combobox"; @@ -90,33 +91,20 @@ export default function AiChat() { setInput(""); }; + const copyVariant = async (text: string) => { + try { + await navigator.clipboard.writeText(text); + toast({ title: "Texte copié", description: "Collez-le dans votre publication." }); + } catch { + toast({ title: "Copie impossible", description: "Sélectionnez le texte manuellement.", variant: "destructive" }); + } + }; + return ( -
-
-
-
-
- -
-
-

Assistant IA

-

Génération de contenu intelligent

-
-
- -
- -
- +
+
+
+ Modèle
+
-
+
{messages.map((message, index) => ( -
+
{message.role === "assistant" && ( -
- +
+
)} - -
-
+
-

{message.content}

- + > +

{message.content}

+ {message.variants && ( -
+
{message.variants.map((variant, vIndex) => ( -
copyVariant(variant.text)} + className="group block w-full rounded-lg border bg-muted/40 p-4 text-left transition-colors hover:border-primary/40 hover:bg-accent" data-testid={`variant-${vIndex}`} > -
- - {variant.variant} +
+ {variant.variant} + + {variant.characterCount} caractères + - {variant.characterCount} caractères
-

{variant.text}

-
+

{variant.text}

+ ))} +

Cliquez sur une proposition pour la copier.

)}
- - {message.role === "user" ? "Maintenant" : "Il y a quelques secondes"} -
{message.role === "user" && ( -
- +
+
)}
))} + {generateMutation.isPending && ( +
+
+ +
+ L'IA rédige vos propositions… +
+ )}
-
-
+
+