mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-21 05:58:23 +02:00
Adapt layout and sidebar for responsive mobile experience
Introduce a `useResponsive` hook, implement mobile-first sidebar behavior with a toggleable menu, and adjust layout for various screen sizes, along with minor type and deposit value handling in `CustomerOrderForm`. Replit-Commit-Author: Agent Replit-Commit-Session-Id: cc8ba926-557c-4bf1-a2ea-ceabbcf38824 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/cc8ba926-557c-4bf1-a2ea-ceabbcf38824/f2TM8xQ
This commit is contained in:
1 parent
479577c4ff
commit
f1d6f27e3d
5 files changed
+241
-73
No files matched your search
@@ -2,8 +2,9 @@ import { ReactNode, useState, createContext, useContext } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { LogOut, Store } from "lucide-react";
|
||||
import { LogOut, Store, Menu, X } from "lucide-react";
|
||||
import { useAuthUnified } from "@/hooks/useAuthUnified";
|
||||
import { useResponsive } from "@/hooks/useResponsive";
|
||||
import Sidebar from "./Sidebar";
|
||||
import type { Group } from "@shared/schema";
|
||||
|
||||
@@ -13,6 +14,8 @@ interface StoreContextType {
|
||||
stores: Group[];
|
||||
sidebarCollapsed: boolean;
|
||||
setSidebarCollapsed: (collapsed: boolean) => void;
|
||||
mobileMenuOpen: boolean;
|
||||
setMobileMenuOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const StoreContext = createContext<StoreContextType | undefined>(undefined);
|
||||
@@ -32,6 +35,8 @@ interface LayoutProps {
|
||||
export default function Layout({ children }: LayoutProps) {
|
||||
const { user } = useAuthUnified();
|
||||
const queryClient = useQueryClient();
|
||||
const { isMobile, isTablet, isDesktop } = useResponsive();
|
||||
|
||||
const [selectedStoreId, setSelectedStoreId] = useState<number | null>(() => {
|
||||
// Restaurer le selectedStoreId depuis localStorage si disponible
|
||||
const saved = localStorage.getItem('selectedStoreId');
|
||||
@@ -43,9 +48,12 @@ export default function Layout({ children }: LayoutProps) {
|
||||
const [sidebarCollapsed, setSidebarCollapsed] = useState<boolean>(() => {
|
||||
// Restaurer l'état de la sidebar depuis localStorage
|
||||
const saved = localStorage.getItem('sidebarCollapsed');
|
||||
return saved ? JSON.parse(saved) : false;
|
||||
// Sur mobile, toujours collapsé par défaut
|
||||
return saved ? JSON.parse(saved) : isMobile;
|
||||
});
|
||||
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState<boolean>(false);
|
||||
|
||||
const { data: stores = [] } = useQuery<Group[]>({
|
||||
queryKey: ['/api/groups'],
|
||||
enabled: !!user,
|
||||
@@ -56,20 +64,56 @@ export default function Layout({ children }: LayoutProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<StoreContext.Provider value={{ selectedStoreId, setSelectedStoreId, stores, sidebarCollapsed, setSidebarCollapsed }}>
|
||||
<div className="flex h-screen overflow-hidden bg-gray-50">
|
||||
<Sidebar />
|
||||
<main className="flex-1 flex flex-col overflow-hidden">
|
||||
<StoreContext.Provider value={{
|
||||
selectedStoreId,
|
||||
setSelectedStoreId,
|
||||
stores,
|
||||
sidebarCollapsed,
|
||||
setSidebarCollapsed,
|
||||
mobileMenuOpen,
|
||||
setMobileMenuOpen
|
||||
}}>
|
||||
<div className="flex h-screen overflow-hidden bg-gray-50 dark:bg-gray-900">
|
||||
{/* Mobile Sidebar Overlay */}
|
||||
{isMobile && mobileMenuOpen && (
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 bg-black/50 z-40"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
/>
|
||||
<div className="fixed inset-y-0 left-0 z-50 w-64 bg-white dark:bg-gray-800">
|
||||
<Sidebar />
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Desktop Sidebar */}
|
||||
{!isMobile && <Sidebar />}
|
||||
|
||||
<main className={`flex-1 flex flex-col overflow-hidden ${
|
||||
isMobile ? 'ml-0' : sidebarCollapsed ? 'ml-16' : 'ml-64'
|
||||
}`}>
|
||||
{/* Header with store selector for admin */}
|
||||
<header className="h-16 bg-white border-b border-gray-200 flex items-center justify-between px-6">
|
||||
<header className="h-16 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between px-4 sm:px-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<h1 className="text-lg font-medium text-gray-800">LogiFlow</h1>
|
||||
{/* Mobile menu button */}
|
||||
{isMobile && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
{mobileMenuOpen ? <X className="h-5 w-5" /> : <Menu className="h-5 w-5" />}
|
||||
</Button>
|
||||
)}
|
||||
<h1 className="text-lg font-medium text-gray-800 dark:text-gray-200">LogiFlow</h1>
|
||||
</div>
|
||||
|
||||
{/* Store selector for admin - moved to top right */}
|
||||
{user?.role === 'admin' && stores.length > 0 && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Store className="h-4 w-4 text-gray-500" />
|
||||
<Store className="h-4 w-4 text-gray-500 dark:text-gray-400" />
|
||||
<Select
|
||||
value={selectedStoreId?.toString() || "all"}
|
||||
onValueChange={(value) => {
|
||||
@@ -123,10 +167,21 @@ export default function Layout({ children }: LayoutProps) {
|
||||
)}
|
||||
</header>
|
||||
|
||||
<div className="flex-1 overflow-auto bg-gray-50 p-6">
|
||||
{children}
|
||||
{/* Main content area */}
|
||||
<div className="flex-1 overflow-auto bg-gray-50 dark:bg-gray-900 p-4 sm:p-6">
|
||||
<div className="container-responsive">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{/* Mobile menu close overlay */}
|
||||
{isMobile && mobileMenuOpen && (
|
||||
<div
|
||||
className="fixed inset-0 bg-black/20 z-30"
|
||||
onClick={() => setMobileMenuOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</StoreContext.Provider>
|
||||
);
|
||||
|
||||
Reference in new issue
Block a user