mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-21 22:18:17 +02:00
- Routes en React.lazy (sauf connexion et accueil) avec un Suspense dans la zone de contenu ; recharts n'est plus préchargé. JS initial : 1,72 Mo -> 625 Ko (183 Ko gzip). Rechargement automatique unique si un ancien fichier JS a disparu après un déploiement, et ErrorBoundary par page pour garder le menu affiché en cas d'erreur. - Authentification unifiée sur le cache React Query ['/api/user'] : un seul GET /api/user pour toute l'application (au lieu de 4 à 5 par page), plus de rechargement complet après la connexion. - Pas de nouvel essai sur les erreurs 4xx ; fournisseurs et magasins en cache 5 minutes ; valeur du StoreContext mémoïsée et redimensionnement qui ne re-rend que lorsque le palier d'écran change. - Pages : requêtes inutilisées ou en double supprimées, appels lancés seulement une fois l'utilisateur connu, invalidations ciblées au lieu de rechargements complets, filtres et tris mémoïsés, anciennes données gardées (et estompées) pendant un changement de filtre ou de mois, recherche DLC mobile temporisée, vérifications de factures à concurrence bornée, navigation interne sans rechargement de la page. - index.html : script de bannière Replit retiré, lang="fr". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MsDJjQrAggcJwbbBtKhgyb
64 lines
2.0 KiB
TypeScript
64 lines
2.0 KiB
TypeScript
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
|
|
}
|
|
|
|
const getScreenSize = (width: number, breakpoints: ScreenBreakpoints): ScreenSize => {
|
|
if (width < breakpoints.mobile) return 'mobile'
|
|
if (width <= breakpoints.tablet) return 'tablet' // Inclut 1024px comme tablette
|
|
return 'desktop'
|
|
}
|
|
|
|
export function useScreenSize(breakpoints: ScreenBreakpoints = defaultBreakpoints) {
|
|
// Palier calculé dès le premier rendu (pas de passage transitoire par 'desktop')
|
|
const [screenSize, setScreenSize] = useState<ScreenSize>(() =>
|
|
typeof window !== 'undefined' ? getScreenSize(window.innerWidth, breakpoints) : 'desktop'
|
|
)
|
|
|
|
useEffect(() => {
|
|
// Seul le palier est stocké : setScreenSize avec la même valeur ne provoque
|
|
// pas de re-rendu, donc l'arbre n'est re-rendu que lorsque le palier change
|
|
// et non à chaque pixel de redimensionnement
|
|
const updateScreenSize = () => {
|
|
setScreenSize(getScreenSize(window.innerWidth, breakpoints))
|
|
}
|
|
|
|
// Set initial values
|
|
updateScreenSize()
|
|
|
|
// Add event listener
|
|
window.addEventListener('resize', updateScreenSize)
|
|
|
|
// Cleanup
|
|
return () => window.removeEventListener('resize', updateScreenSize)
|
|
}, [breakpoints])
|
|
|
|
// Dimensions lues au moment du rendu (non stockées dans l'état pour ne pas
|
|
// re-rendre à chaque redimensionnement)
|
|
const dimensions = {
|
|
width: typeof window !== 'undefined' ? window.innerWidth : 1200,
|
|
height: typeof window !== 'undefined' ? window.innerHeight : 800
|
|
}
|
|
|
|
return {
|
|
screenSize,
|
|
dimensions,
|
|
isMobile: screenSize === 'mobile',
|
|
isTablet: screenSize === 'tablet',
|
|
isDesktop: screenSize === 'desktop',
|
|
isMobileOrTablet: screenSize === 'mobile' || screenSize === 'tablet',
|
|
isTabletOrDesktop: screenSize === 'tablet' || screenSize === 'desktop'
|
|
}
|
|
}
|