Merge pull request #37 from R0m1k3/dev

Dev
This commit is contained in:
LogiFlow authored and GitHub committed 2025-10-08 21:02:21 +02:00
commit 6045ad29af
14 files changed
+82 -51

No files matched your search

+8
View File
@@ -22,6 +22,10 @@ externalPort = 3003
localPort = 35357
externalPort = 3002
[[ports]]
localPort = 37431
externalPort = 5000
[[ports]]
localPort = 37659
externalPort = 4200
@@ -34,6 +38,10 @@ externalPort = 3000
localPort = 43245
externalPort = 3001
[[ports]]
localPort = 46681
externalPort = 5173
[env]
PORT = "5000"
+43 -21
View File
@@ -7,7 +7,11 @@ import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { useState, useEffect } from "react";
export default function Sidebar() {
interface SidebarProps {
onLinkClick?: () => void;
}
export default function Sidebar({ onLinkClick }: SidebarProps = {}) {
const [location] = useLocation();
const [, setLocation] = useLocation();
const { toast } = useToast();
@@ -27,6 +31,18 @@ export default function Sidebar() {
const isAdmin = session?.role === "admin";
const handleLinkClick = (href: string, e: React.MouseEvent) => {
e.preventDefault();
// Always close sidebar on mobile first
if (onLinkClick) {
onLinkClick();
}
// Navigate after a small delay to ensure state update completes
setTimeout(() => {
setLocation(href);
}, 10);
};
const logoutMutation = useMutation({
mutationFn: async () => {
const res = await apiRequest("POST", "/api/auth/logout", {});
@@ -82,10 +98,11 @@ export default function Sidebar() {
return (
<li key={item.href} className="relative group">
<Link
<a
href={item.href}
onClick={(e) => handleLinkClick(item.href, e)}
className={`
flex items-center gap-3 px-4 py-3 rounded-xl font-medium transition-all relative
flex items-center gap-3 px-4 py-3 rounded-xl font-medium transition-all relative cursor-pointer
${isActive
? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm'
: 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground'
@@ -108,7 +125,7 @@ export default function Sidebar() {
)}
</>
)}
</Link>
</a>
{isCollapsed && (
<div className="absolute left-full ml-2 px-3 py-2 bg-popover text-popover-foreground text-sm rounded-lg shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all whitespace-nowrap z-50">
{item.label}
@@ -131,10 +148,11 @@ export default function Sidebar() {
return (
<li key={item.href} className="relative group">
<Link
<a
href={item.href}
onClick={(e) => handleLinkClick(item.href, e)}
className={`
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative cursor-pointer
${isActive
? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm'
: 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground'
@@ -148,7 +166,7 @@ export default function Sidebar() {
)}
<Icon className={`w-5 h-5 ${isActive ? 'text-primary' : ''}`} />
{!isCollapsed && <span>{item.label}</span>}
</Link>
</a>
{isCollapsed && (
<div className="absolute left-full ml-2 px-3 py-2 bg-popover text-popover-foreground text-sm rounded-lg shadow-lg opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all whitespace-nowrap z-50">
{item.label}
@@ -170,10 +188,11 @@ export default function Sidebar() {
<p className="text-xs font-semibold text-muted-foreground mb-2 px-4 uppercase tracking-wider">Administration</p>
</div>
)}
<Link
<a
href="/pages"
onClick={(e) => handleLinkClick("/pages", e)}
className={`
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group cursor-pointer
${location === "/pages"
? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm'
: 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground'
@@ -192,11 +211,12 @@ export default function Sidebar() {
Pages gérées
</div>
)}
</Link>
<Link
</a>
<a
href="/users"
onClick={(e) => handleLinkClick("/users", e)}
className={`
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group cursor-pointer
${location === "/users"
? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm'
: 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground'
@@ -215,11 +235,12 @@ export default function Sidebar() {
Utilisateurs
</div>
)}
</Link>
<Link
</a>
<a
href="/sql"
onClick={(e) => handleLinkClick("/sql", e)}
className={`
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group cursor-pointer
${location === "/sql"
? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm'
: 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground'
@@ -238,11 +259,12 @@ export default function Sidebar() {
SQL
</div>
)}
</Link>
<Link
</a>
<a
href="/settings"
onClick={(e) => handleLinkClick("/settings", e)}
className={`
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group
flex items-center gap-3 px-4 py-3 rounded-xl transition-all relative group cursor-pointer
${location === "/settings"
? 'bg-gradient-to-r from-primary/10 to-secondary/10 text-primary shadow-sm'
: 'text-muted-foreground hover:bg-sidebar-accent hover:text-foreground'
@@ -261,7 +283,7 @@ export default function Sidebar() {
Paramètres
</div>
)}
</Link>
</a>
</>
)}
@@ -302,10 +324,10 @@ export default function Sidebar() {
</div>
)}
{/* Toggle Button */}
{/* Toggle Button (Desktop only) */}
<button
onClick={() => setIsCollapsed(!isCollapsed)}
className="mt-2 w-full flex items-center justify-center p-2 text-muted-foreground hover:text-primary hover:bg-sidebar-accent rounded-xl transition-all"
className="mt-2 w-full hidden lg:flex items-center justify-center p-2 text-muted-foreground hover:text-primary hover:bg-primary/10 border-2 border-border hover:border-primary/50 rounded-xl transition-all"
data-testid="button-toggle-sidebar"
>
{isCollapsed ? <ChevronRight className="w-5 h-5" /> : <ChevronLeft className="w-5 h-5" />}
+4 -3
View File
@@ -8,12 +8,13 @@ interface TopBarProps {
export default function TopBar({ onMenuClick }: TopBarProps) {
return (
<header className="bg-card/50 backdrop-blur-xl border-b border-border/50 sticky top-0 z-10">
<div className="flex items-center justify-between px-6 lg:px-8 py-5">
<div className="flex items-center gap-6 flex-1">
<div className="flex items-center justify-between px-4 sm:px-6 lg:px-8 py-4 sm:py-5">
<div className="flex items-center gap-3 sm:gap-6 flex-1">
<button
className="lg:hidden text-foreground hover:text-primary transition-colors"
className="lg:hidden text-foreground hover:text-primary transition-all hover:scale-110 active:scale-95 p-2 hover:bg-primary/10 rounded-xl"
onClick={onMenuClick}
data-testid="button-menu"
aria-label="Toggle menu"
>
<Menu className="w-6 h-6" />
</button>
+4 -4
View File
@@ -20,10 +20,10 @@ const buttonVariants = cva(
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
default: "h-11 px-4 py-2",
sm: "h-11 rounded-md px-3",
lg: "h-12 rounded-md px-8",
icon: "h-11 w-11",
},
},
defaultVariants: {
+2 -2
View File
@@ -19,13 +19,13 @@ export default function AI() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-5xl mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-5xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground">Assistant IA</h1>
<p className="text-muted-foreground mt-2">
+2 -2
View File
@@ -19,13 +19,13 @@ export default function Calendar() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-[1600px] mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-[1600px] mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground">Calendrier</h1>
<p className="text-muted-foreground mt-2">
+2 -2
View File
@@ -21,13 +21,13 @@ export default function Dashboard() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 space-y-8 max-w-[1600px] mx-auto">
<div className="p-4 sm:p-6 lg:p-8 space-y-6 sm:space-y-8 max-w-[1600px] mx-auto">
<StatsCards />
<RecentPublications />
+2 -2
View File
@@ -31,13 +31,13 @@ export default function History() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-5xl mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-5xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground">Historique</h1>
<p className="text-muted-foreground mt-2">
+2 -2
View File
@@ -19,13 +19,13 @@ export default function Media() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-[1600px] mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-[1600px] mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground">Médiathèque</h1>
<p className="text-muted-foreground mt-2">
+3 -3
View File
@@ -202,13 +202,13 @@ export default function NewPost() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-6xl mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-6xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground">Nouvelle publication</h1>
<p className="text-muted-foreground mt-2">
@@ -216,7 +216,7 @@ export default function NewPost() {
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
<div className="space-y-8">
<Card className="rounded-2xl border-border/50 shadow-lg">
<CardHeader className="p-6">
+2 -2
View File
@@ -55,13 +55,13 @@ export default function PagesManagement() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-[1600px] mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-[1600px] mx-auto">
<div className="flex justify-between items-center mb-8">
<div>
<h1 className="text-3xl font-bold text-foreground">Pages gérées</h1>
+2 -2
View File
@@ -132,13 +132,13 @@ export default function Settings() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-4xl mx-auto">
<div className="p-4 sm:p-6 lg:p-8 max-w-4xl mx-auto">
<div className="mb-8">
<h1 className="text-3xl font-bold text-foreground">Paramètres</h1>
<p className="text-muted-foreground mt-2">
+3 -3
View File
@@ -87,13 +87,13 @@ export default function SqlAdmin() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-[1600px] mx-auto space-y-8">
<div className="p-4 sm:p-6 lg:p-8 max-w-[1600px] mx-auto space-y-6 sm:space-y-8">
<div>
<h1 className="text-3xl font-bold flex items-center gap-2">
<Database className="w-8 h-8" />
@@ -104,7 +104,7 @@ export default function SqlAdmin() {
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-4 gap-8">
<div className="grid grid-cols-1 lg:grid-cols-4 gap-4 sm:gap-6 lg:gap-8">
{/* Liste des tables */}
<Card className="rounded-2xl border-border/50 shadow-lg">
<CardHeader className="p-6">
+3 -3
View File
@@ -290,13 +290,13 @@ export default function UsersAdmin() {
fixed lg:static inset-y-0 left-0 z-50 transform transition-transform duration-300 ease-in-out
${sidebarOpen ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}
`}>
<Sidebar />
<Sidebar onLinkClick={() => setSidebarOpen(false)} />
</div>
<main className="flex-1 overflow-y-auto">
<TopBar onMenuClick={() => setSidebarOpen(!sidebarOpen)} />
<div className="p-8 max-w-[1600px] mx-auto space-y-8">
<div className="p-4 sm:p-6 lg:p-8 max-w-[1600px] mx-auto space-y-6 sm:space-y-8">
<div>
<h1 className="text-3xl font-bold flex items-center gap-2">
<Users className="w-8 h-8" />
@@ -307,7 +307,7 @@ export default function UsersAdmin() {
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4 sm:gap-6 lg:gap-8">
{/* Liste des utilisateurs */}
<div className="lg:col-span-2">
<Card className="rounded-2xl border-border/50 shadow-lg">