Merge pull request #432 from R0m1k3/1.1

Refactor store context and improve responsiveness across the application
This commit is contained in:
LogiFlow authored and GitHub committed 2025-09-11 08:22:47 +02:00
commit 3976f151e2
29 files changed
+957 -254

No files matched your search

+4
View File
@@ -15,6 +15,10 @@ run = ["npm", "run", "start"]
localPort = 5000
externalPort = 80
[[ports]]
localPort = 45105
externalPort = 3000
[workflows]
runButton = "Project"
+1 -1
View File
@@ -39,7 +39,7 @@ import {
Sparkles
} from "lucide-react";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { safeFormat, safeDate } from "@/lib/dateUtils";
import {
insertAnnouncementSchema,
+1 -1
View File
@@ -23,7 +23,7 @@ import {
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { insertCustomerOrderFrontendSchema, type CustomerOrderWithRelations, type Group, type Supplier } from "@shared/schema";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
const customerOrderFormSchema = z.object({
orderTaker: z.string().min(1, "Qui a pris la commande est requis"),
+39 -36
View File
@@ -1,35 +1,17 @@
import { ReactNode, useState, createContext, useContext, useEffect } from "react";
import { ReactNode, useState, useEffect } 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, Menu, AlertTriangle } from "lucide-react";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useIsMobile } from "@/hooks/use-mobile";
import { useScreenSize } from "@/hooks/use-screen-size";
import { StoreProvider } from "@/contexts/StoreContext";
import Sidebar from "./Sidebar";
import WeatherWidget from "./WeatherWidget";
import DateWidget from "./DateWidget";
import type { Group } from "@shared/schema";
interface StoreContextType {
selectedStoreId: number | null;
setSelectedStoreId: (storeId: number | null) => void;
stores: Group[];
sidebarCollapsed: boolean;
setSidebarCollapsed: (collapsed: boolean) => void;
mobileMenuOpen: boolean;
setMobileMenuOpen: (open: boolean) => void;
storeInitialized: boolean;
}
const StoreContext = createContext<StoreContextType | undefined>(undefined);
export const useStore = () => {
const context = useContext(StoreContext);
if (!context) {
throw new Error("useStore must be used within a StoreProvider");
}
return context;
};
interface LayoutProps {
children: ReactNode;
@@ -39,6 +21,7 @@ export default function Layout({ children }: LayoutProps) {
const { user } = useAuthUnified();
const queryClient = useQueryClient();
const isMobile = useIsMobile();
const { screenSize, isMobileOrTablet, isTablet } = useScreenSize();
const [selectedStoreId, setSelectedStoreId] = useState<number | null>(() => {
// Restaurer le selectedStoreId depuis localStorage si disponible
@@ -136,7 +119,7 @@ export default function Layout({ children }: LayoutProps) {
};
return (
<StoreContext.Provider value={{ selectedStoreId, setSelectedStoreId, stores, sidebarCollapsed, setSidebarCollapsed, mobileMenuOpen, setMobileMenuOpen, storeInitialized }}>
<StoreProvider value={{ selectedStoreId, setSelectedStoreId, stores, sidebarCollapsed, setSidebarCollapsed, mobileMenuOpen, setMobileMenuOpen, storeInitialized }}>
<div className="layout-container flex bg-gray-50">
{/* Mobile overlay */}
{isMobile && mobileMenuOpen && (
@@ -148,32 +131,42 @@ export default function Layout({ children }: LayoutProps) {
<Sidebar />
<main className="flex-1 flex flex-col h-full">
<main className={`flex-1 flex flex-col h-full ${
// Ajuster la marge gauche selon la taille de l'écran et l'état de la sidebar
isMobile ? 'ml-0' :
isTablet ? (sidebarCollapsed ? 'ml-16' : 'ml-48') :
(sidebarCollapsed ? 'ml-16' : 'ml-64')
}`}>
{/* Header with mobile menu and store selector */}
<header className="h-16 bg-white border-b border-gray-200 flex items-center justify-between px-4 sm:px-6">
<div className="flex items-center gap-4">
<header className={`h-16 bg-white border-b border-gray-200 flex items-center justify-between ${
isMobileOrTablet ? 'px-3' : 'px-6'
}`}>
<div className="flex items-center gap-2 sm:gap-4 min-w-0 flex-1">
{/* Mobile menu button */}
{isMobile && (
<Button
variant="ghost"
size="sm"
onClick={() => setMobileMenuOpen(true)}
className="h-8 w-8 p-0"
className="min-h-[44px] min-w-[44px] p-0 flex-shrink-0"
data-testid="button-mobile-menu"
>
<Menu className="h-5 w-5" />
</Button>
)}
{/* Weather and Date widgets */}
<div className="flex items-center gap-3">
{/* Weather and Date widgets - responsive */}
<div className={`flex items-center ${
isMobile ? 'gap-1' : 'gap-3'
} min-w-0`}>
<WeatherWidget />
<DateWidget />
{!isMobile && <DateWidget />}
</div>
</div>
{/* Store selector for admin, directeur, and manager - responsive */}
{user && (user.role === 'admin' || user.role === 'directeur' || user.role === 'manager') && stores.length > 0 && (
<div className="flex items-center gap-2">
<div className="flex items-center gap-1 sm:gap-2 flex-shrink-0">
<Store className="h-4 w-4 text-gray-500 hidden sm:block" />
<Select
value={selectedStoreId?.toString() || (user.role === 'admin' ? "all" : "")}
@@ -206,8 +199,12 @@ export default function Layout({ children }: LayoutProps) {
setSelectedStoreId(newStoreId);
}}
>
<SelectTrigger className="w-32 sm:w-64 border border-gray-300">
<SelectValue placeholder="Sélectionnez un magasin" />
<SelectTrigger className={`border border-gray-300 min-h-[44px] ${
isMobile ? 'w-28 text-xs' :
isTablet ? 'w-40 text-sm' :
'w-64 text-sm'
}`} data-testid="select-store">
<SelectValue placeholder="Magasin" />
</SelectTrigger>
<SelectContent>
{/* Only show "Tous les magasins" option for admin */}
@@ -215,7 +212,9 @@ export default function Layout({ children }: LayoutProps) {
<SelectItem value="all">
<div className="flex items-center gap-2">
<div className="w-3 h-3 bg-gray-400"></div>
<span>Tous les magasins</span>
<span className={isMobile ? 'text-xs' : 'text-sm'}>
{isMobile ? 'Tous' : 'Tous les magasins'}
</span>
</div>
</SelectItem>
)}
@@ -226,7 +225,9 @@ export default function Layout({ children }: LayoutProps) {
className="w-3 h-3"
style={{ backgroundColor: store.color || '#gray-400' }}
/>
<span>{store.name}</span>
<span className={`${isMobile ? 'text-xs' : 'text-sm'} truncate max-w-[120px]`}>
{store.name}
</span>
</div>
</SelectItem>
))}
@@ -253,11 +254,13 @@ export default function Layout({ children }: LayoutProps) {
</div>
)}
<div className="flex-1 bg-gray-50 p-6 h-full overflow-y-auto">
<div className={`flex-1 bg-gray-50 h-full overflow-y-auto ${
isMobileOrTablet ? 'p-3' : 'p-6'
}`}>
{children}
</div>
</main>
</div>
</StoreContext.Provider>
</StoreProvider>
);
}
+77 -19
View File
@@ -1,8 +1,9 @@
import { Link, useLocation } from "wouter";
import { useAuthSimple } from "@/hooks/useAuthSimple";
import { Button } from "@/components/ui/button";
import { useStore } from "./Layout";
import { useStore } from "@/contexts/StoreContext";
import { useIsMobile } from "@/hooks/use-mobile";
import { useScreenSize } from "@/hooks/use-screen-size";
import { useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
@@ -41,6 +42,7 @@ export default function Sidebar() {
const [location] = useLocation();
const { sidebarCollapsed, setSidebarCollapsed, mobileMenuOpen, setMobileMenuOpen } = useStore();
const isMobile = useIsMobile();
const { screenSize, isMobileOrTablet, isTablet } = useScreenSize();
const [showBapModal, setShowBapModal] = useState(false);
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [selectedRecipient, setSelectedRecipient] = useState<string>('');
@@ -338,12 +340,24 @@ export default function Sidebar() {
// Classes responsives pour la sidebar avec classes CSS forcées pour cohérence
const sidebarClasses = isMobile
? `fixed inset-y-0 left-0 z-50 w-64 bg-white border-r border-gray-200 shadow-lg transform transition-transform duration-300 ease-in-out ${
// Classes responsives adaptées avec support tablette
const getSidebarClasses = () => {
if (isMobile) {
return `fixed inset-y-0 left-0 z-50 w-64 bg-white border-r border-gray-200 shadow-lg transform transition-transform duration-300 ease-in-out ${
mobileMenuOpen ? 'translate-x-0' : '-translate-x-full'
}`
: `${sidebarCollapsed ? 'sidebar-collapsed' : 'sidebar-expanded'} bg-white border-r border-gray-200 flex flex-col shadow-lg transition-all duration-300 ease-in-out`;
}`;
}
// Mode tablette : semi-collapsed par défaut ou collapsed si forcé
if (isTablet) {
return `${sidebarCollapsed ? 'sidebar-collapsed' : 'sidebar-tablet'} bg-white border-r border-gray-200 flex flex-col shadow-lg transition-all duration-300 ease-in-out`;
}
// Mode desktop standard
return `${sidebarCollapsed ? 'sidebar-collapsed' : 'sidebar-expanded'} bg-white border-r border-gray-200 flex flex-col shadow-lg transition-all duration-300 ease-in-out`;
};
const sidebarClasses = getSidebarClasses();
// Debug log pour vérifier l'état de la sidebar
console.log('🔧 Sidebar Debug:', {
@@ -542,16 +556,32 @@ export default function Sidebar() {
return (
<Link key={item.path} href={item.path}>
<div
className={`flex items-center ${sidebarCollapsed && !isMobile ? 'px-3 py-3 justify-center' : 'px-3 py-2'} text-sm font-medium transition-colors hover:bg-gray-100 ${
className={`flex items-center transition-colors hover:bg-gray-100 ${
// Espacement adaptatif selon l'écran et l'état
sidebarCollapsed && !isMobile
? 'px-3 py-3 justify-center min-h-[44px]'
: isMobileOrTablet
? 'px-4 py-3 min-h-[48px]'
: 'px-3 py-2 min-h-[40px]'
} text-sm font-medium ${
active
? 'bg-gray-100 text-gray-900 border-r-2 border-gray-700'
? 'bg-gray-100 text-gray-900 border-r-2 border-blue-600'
: 'text-gray-700'
}`}
title={sidebarCollapsed && !isMobile ? item.label : undefined}
onClick={handleMenuClick}
>
<Icon className={`h-4 w-4 ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && item.label}
<Icon className={`${
// Tailles d'icônes adaptatives
isMobile ? 'h-5 w-5' :
isTablet ? 'h-6 w-6' :
'h-5 w-5'
} ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && (
<span className={`${isMobileOrTablet ? 'text-base' : 'text-sm'} font-medium`}>
{item.label}
</span>
)}
</div>
</Link>
);
@@ -582,15 +612,29 @@ export default function Sidebar() {
return (
<div key={item.path}>
<div
className={`flex items-center cursor-pointer ${sidebarCollapsed ? 'px-3 py-3 justify-center' : 'px-3 py-2'} text-sm font-medium transition-colors hover:bg-gray-100 text-gray-700`}
title={sidebarCollapsed ? item.label : undefined}
className={`flex items-center cursor-pointer transition-colors hover:bg-gray-100 text-gray-700 ${
sidebarCollapsed && !isMobile
? 'px-3 py-3 justify-center min-h-[44px]'
: isMobileOrTablet
? 'px-4 py-3 min-h-[48px]'
: 'px-3 py-2 min-h-[40px]'
} text-sm font-medium`}
title={sidebarCollapsed && !isMobile ? item.label : undefined}
onClick={() => {
setShowBapModal(true);
if (isMobile) setMobileMenuOpen(false);
}}
>
<Icon className={`h-4 w-4 ${sidebarCollapsed ? '' : 'mr-3'}`} />
{!sidebarCollapsed && item.label}
<Icon className={`${
isMobile ? 'h-5 w-5' :
isTablet ? 'h-6 w-6' :
'h-5 w-5'
} ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && (
<span className={`${isMobileOrTablet ? 'text-base' : 'text-sm'} font-medium`}>
{item.label}
</span>
)}
</div>
</div>
);
@@ -599,16 +643,30 @@ export default function Sidebar() {
return (
<Link key={item.path} href={item.path}>
<div
className={`flex items-center ${sidebarCollapsed ? 'px-3 py-3 justify-center' : 'px-3 py-2'} text-sm font-medium transition-colors hover:bg-gray-100 ${
className={`flex items-center transition-colors hover:bg-gray-100 ${
sidebarCollapsed && !isMobile
? 'px-3 py-3 justify-center min-h-[44px]'
: isMobileOrTablet
? 'px-4 py-3 min-h-[48px]'
: 'px-3 py-2 min-h-[40px]'
} text-sm font-medium ${
active
? 'bg-gray-100 text-gray-900 border-r-2 border-gray-700'
? 'bg-gray-100 text-gray-900 border-r-2 border-blue-600'
: 'text-gray-700'
}`}
title={sidebarCollapsed ? item.label : undefined}
title={sidebarCollapsed && !isMobile ? item.label : undefined}
onClick={() => console.log(`Navigating to admin: ${item.path}`)}
>
<Icon className={`h-4 w-4 ${sidebarCollapsed ? '' : 'mr-3'}`} />
{!sidebarCollapsed && item.label}
<Icon className={`${
isMobile ? 'h-5 w-5' :
isTablet ? 'h-6 w-6' :
'h-5 w-5'
} ${sidebarCollapsed && !isMobile ? '' : 'mr-3'}`} />
{(!sidebarCollapsed || isMobile) && (
<span className={`${isMobileOrTablet ? 'text-base' : 'text-sm'} font-medium`}>
{item.label}
</span>
)}
</div>
</Link>
);
+1 -1
View File
@@ -1,7 +1,7 @@
import { useQuery } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { TrendingUp, Package, Truck, Clock } from "lucide-react";
import { useStore } from "./Layout";
import { useStore } from "@/contexts/StoreContext";
import { useAuthUnified } from "@/hooks/useAuthUnified";
interface StatsPanelProps {
@@ -7,7 +7,7 @@ import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { isUnauthorizedError } from "@/lib/authUtils";
@@ -7,7 +7,7 @@ import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { isUnauthorizedError } from "@/lib/authUtils";
+1 -1
View File
@@ -3,7 +3,7 @@ import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -13,7 +13,7 @@ import {
import { format, addDays, isAfter, isBefore } from "date-fns";
import { fr } from "date-fns/locale";
import { useLocation } from "wouter";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { Task } from "@shared/schema";
type TaskWithRelations = Task & {
@@ -3,7 +3,7 @@ import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
@@ -3,7 +3,7 @@ import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
+32
View File
@@ -0,0 +1,32 @@
import { ReactNode, createContext, useContext } from "react";
import type { Group } from "@shared/schema";
interface StoreContextType {
selectedStoreId: number | null;
setSelectedStoreId: (storeId: number | null) => void;
stores: Group[];
sidebarCollapsed: boolean;
setSidebarCollapsed: (collapsed: boolean) => void;
mobileMenuOpen: boolean;
setMobileMenuOpen: (open: boolean) => void;
storeInitialized: boolean;
}
const StoreContext = createContext<StoreContextType | undefined>(undefined);
export const useStore = () => {
const context = useContext(StoreContext);
if (!context) {
throw new Error("useStore must be used within a StoreProvider");
}
return context;
};
interface StoreProviderProps {
children: ReactNode;
value: StoreContextType;
}
export function StoreProvider({ children, value }: StoreProviderProps) {
return <StoreContext.Provider value={value}>{children}</StoreContext.Provider>;
}
+58
View File
@@ -0,0 +1,58 @@
import { useState, useEffect } from 'react'
export type ScreenSize = 'mobile' | 'tablet' | 'desktop'
export interface ScreenBreakpoints {
mobile: number
tablet: number
desktop: number
}
const defaultBreakpoints: ScreenBreakpoints = {
mobile: 768,
tablet: 1024,
desktop: 1280
}
export function useScreenSize(breakpoints: ScreenBreakpoints = defaultBreakpoints) {
const [screenSize, setScreenSize] = useState<ScreenSize>('desktop')
const [dimensions, setDimensions] = useState({
width: typeof window !== 'undefined' ? window.innerWidth : 1200,
height: typeof window !== 'undefined' ? window.innerHeight : 800
})
useEffect(() => {
const getScreenSize = (width: number): ScreenSize => {
if (width < breakpoints.mobile) return 'mobile'
if (width <= breakpoints.tablet) return 'tablet' // Inclut 1024px comme tablette
return 'desktop'
}
const updateScreenSize = () => {
const width = window.innerWidth
const height = window.innerHeight
setDimensions({ width, height })
setScreenSize(getScreenSize(width))
}
// Set initial values
updateScreenSize()
// Add event listener
window.addEventListener('resize', updateScreenSize)
// Cleanup
return () => window.removeEventListener('resize', updateScreenSize)
}, [breakpoints])
return {
screenSize,
dimensions,
isMobile: screenSize === 'mobile',
isTablet: screenSize === 'tablet',
isDesktop: screenSize === 'desktop',
isMobileOrTablet: screenSize === 'mobile' || screenSize === 'tablet',
isTabletOrDesktop: screenSize === 'tablet' || screenSize === 'desktop'
}
}
+11
View File
@@ -80,6 +80,17 @@
max-width: 4rem !important;
}
.sidebar-tablet {
width: 12rem !important;
min-width: 12rem !important;
max-width: 12rem !important;
position: fixed;
left: 0;
top: 0;
bottom: 0;
z-index: 30;
}
.sidebar-expanded {
width: 16rem !important;
min-width: 16rem !important;
+1 -1
View File
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { Plus, Search, FileText, CheckCircle, AlertCircle, Clock, Edit, Trash2, UserCheck, Send, Upload, XCircle, MessageSquare, Settings } from "lucide-react";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+1 -1
View File
@@ -8,7 +8,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { usePermissions } from "@shared/permissions";
import { Pagination, usePagination } from "@/components/ui/pagination";
+1 -1
View File
@@ -3,7 +3,7 @@ import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { safeFormat } from "@/lib/dateUtils";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { usePermissions } from "@shared/permissions";
import { Search, Edit, FileText, Settings, Eye, AlertTriangle, X, Check, Trash2, Ban, ChevronLeft, ChevronRight } from "lucide-react";
+1 -1
View File
@@ -9,7 +9,7 @@ import CreateOrderModal from "@/components/modals/CreateOrderModal";
import CreateDeliveryModal from "@/components/modals/CreateDeliveryModal";
import StatsPanel from "@/components/StatsPanel";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { apiRequest } from "@/lib/queryClient";
import { useToast } from "@/hooks/use-toast";
import { format, startOfMonth, endOfMonth } from "date-fns";
+1 -1
View File
@@ -39,7 +39,7 @@ import type { CustomerOrderWithRelations, Group } from "@shared/schema";
import { CustomerOrderForm } from "@/components/CustomerOrderForm";
import { CustomerOrderDetails } from "@/components/CustomerOrderDetails";
import { ConfirmationModal } from "@/components/ConfirmationModal";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { usePermissions } from "@shared/permissions";
export default function CustomerOrders() {
+1 -1
View File
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { useQuery } from "@tanstack/react-query";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
+1 -1
View File
@@ -6,7 +6,7 @@ import { Badge } from "@/components/ui/badge";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Pagination, usePagination } from "@/components/ui/pagination";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { isUnauthorizedError } from "@/lib/authUtils";
+1 -1
View File
@@ -21,7 +21,7 @@ import { format } from "date-fns";
import { fr } from "date-fns/locale";
import { useToast } from "@/hooks/use-toast";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { apiRequest } from "@/lib/queryClient";
import type { DlcProductWithRelations, InsertDlcProduct } from "@shared/schema";
+1 -1
View File
@@ -6,7 +6,7 @@ import { Badge } from "@/components/ui/badge";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Pagination, usePagination } from "@/components/ui/pagination";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { isUnauthorizedError } from "@/lib/authUtils";
+1 -1
View File
@@ -8,7 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
import { useToast } from "@/hooks/use-toast";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { format, startOfMonth, endOfMonth, eachWeekOfInterval, eachDayOfInterval, startOfWeek, endOfWeek, isSameMonth, isWithinInterval, startOfYear, endOfYear, getWeek, getMonth } from "date-fns";
import { fr } from "date-fns/locale";
import { safeFormat, safeDate, safeCompareDate } from "@/lib/dateUtils";
+1 -1
View File
@@ -11,7 +11,7 @@ import { Textarea } from "@/components/ui/textarea";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import {
Plus,
Search,
+1 -1
View File
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
+1 -1
View File
@@ -1,7 +1,7 @@
import { useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useStore } from "@/components/Layout";
import { useStore } from "@/contexts/StoreContext";
import { useToast } from "@/hooks/use-toast";
import { apiRequest } from "@/lib/queryClient";
import { Button } from "@/components/ui/button";