Remove phone icon and improve horizontal overflow on mobile devices

Refactors Layout and Tasks components, removing the smartphone icon, disabling phone mode logic, and applying global CSS to prevent horizontal overflow across the application, particularly on mobile viewports.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 95e8aab4-f39f-4b48-aa57-a759ec15ba3d
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/95e8aab4-f39f-4b48-aa57-a759ec15ba3d/GEw2Z4s
This commit is contained in:
michaelschal committed 2025-09-11 10:08:31 +00:00
1 parent d7de31ac2a
commit c0a7b06c34
3 files changed
+39 -166

No files matched your search

+11 -56
View File
@@ -3,14 +3,12 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useLocation } from "wouter"; import { useLocation } from "wouter";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { LogOut, Store, Menu, AlertTriangle, Smartphone, Monitor } from "lucide-react"; import { LogOut, Store, Menu, AlertTriangle } from "lucide-react";
import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useAuthUnified } from "@/hooks/useAuthUnified";
import { useIsMobile } from "@/hooks/use-mobile"; import { useIsMobile } from "@/hooks/use-mobile";
import { useScreenSize } from "@/hooks/use-screen-size"; import { useScreenSize } from "@/hooks/use-screen-size";
import { usePhoneMode } from "@/hooks/use-phone-mode";
import { StoreProvider } from "@/contexts/StoreContext"; import { StoreProvider } from "@/contexts/StoreContext";
import Sidebar from "./Sidebar"; import Sidebar from "./Sidebar";
import PhoneBottomNav from "./PhoneBottomNav";
import WeatherWidget from "./WeatherWidget"; import WeatherWidget from "./WeatherWidget";
import DateWidget from "./DateWidget"; import DateWidget from "./DateWidget";
import type { Group } from "@shared/schema"; import type { Group } from "@shared/schema";
@@ -26,7 +24,6 @@ export default function Layout({ children }: LayoutProps) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { screenSize, isMobileOrTablet, isTablet } = useScreenSize(); const { screenSize, isMobileOrTablet, isTablet } = useScreenSize();
const { isPhoneMode, setPhoneMode, canUsePhoneMode } = usePhoneMode();
const [selectedStoreId, setSelectedStoreId] = useState<number | null>(() => { const [selectedStoreId, setSelectedStoreId] = useState<number | null>(() => {
// Restaurer le selectedStoreId depuis localStorage si disponible // Restaurer le selectedStoreId depuis localStorage si disponible
@@ -125,9 +122,9 @@ export default function Layout({ children }: LayoutProps) {
return ( return (
<StoreProvider 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 ${isPhoneMode ? 'phone-mode' : ''}`}> <div className="layout-container flex bg-gray-50">
{/* Mobile overlay for normal mode */} {/* Mobile overlay for normal mode */}
{!isPhoneMode && isMobile && mobileMenuOpen && ( {isMobile && mobileMenuOpen && (
<div <div
className="fixed inset-0 bg-black bg-opacity-50 z-40" className="fixed inset-0 bg-black bg-opacity-50 z-40"
onClick={() => setMobileMenuOpen(false)} onClick={() => setMobileMenuOpen(false)}
@@ -135,25 +132,21 @@ export default function Layout({ children }: LayoutProps) {
)} )}
{/* Sidebar for normal mode */} {/* Sidebar for normal mode */}
{!isPhoneMode && <Sidebar />} <Sidebar />
<main className={`flex-1 flex flex-col h-full ${ <main className={`flex-1 flex flex-col h-full ${
// Ajustement des marges selon le mode // Ajustement des marges selon le mode
isPhoneMode isMobile
? 'ml-0 mb-20' // Mode téléphone : pas de marge gauche, marge bas pour bottom nav
: isMobile
? 'ml-0' ? 'ml-0'
: (isTablet && !sidebarCollapsed) ? 'ml-48' : 'ml-0' : (isTablet && !sidebarCollapsed) ? 'ml-48' : 'ml-0'
}`}> }`}>
{/* Header with mobile menu and store selector */} {/* Header with mobile menu and store selector */}
<header className={`${ <header className={`h-16 bg-white border-b border-gray-200 flex items-center justify-between ${
isPhoneMode ? 'h-12' : 'h-16'
} bg-white border-b border-gray-200 flex items-center justify-between ${
isMobileOrTablet ? 'px-3' : 'px-6' isMobileOrTablet ? 'px-3' : 'px-6'
}`}> }`}>
<div className="flex items-center gap-2 sm:gap-4 min-w-0 flex-1"> <div className="flex items-center gap-2 sm:gap-4 min-w-0 flex-1">
{/* Mobile menu button (only in normal mode) */} {/* Mobile menu button (only in normal mode) */}
{!isPhoneMode && isMobile && ( {isMobile && (
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
@@ -169,47 +162,13 @@ export default function Layout({ children }: LayoutProps) {
<div className={`flex items-center ${ <div className={`flex items-center ${
isMobile ? 'gap-1' : 'gap-3' isMobile ? 'gap-1' : 'gap-3'
} min-w-0`}> } min-w-0`}>
{/* En mode téléphone, affichage simplifié */} <WeatherWidget />
{isPhoneMode ? ( {!isMobile && <DateWidget />}
<div className="flex items-center gap-2">
<WeatherWidget />
{/* Phone mode toggle button */}
<Button
variant="ghost"
size="sm"
onClick={() => setPhoneMode(!isPhoneMode)}
className="min-h-[44px] min-w-[44px] p-2 flex-shrink-0"
data-testid="button-phone-mode-toggle"
title="Basculer vers le mode normal"
>
<Monitor className="h-4 w-4 text-blue-600" />
</Button>
</div>
) : (
<>
<WeatherWidget />
{!isMobile && <DateWidget />}
{/* Phone mode toggle button */}
{canUsePhoneMode && (
<Button
variant="ghost"
size="sm"
onClick={() => setPhoneMode(!isPhoneMode)}
className="min-h-[44px] min-w-[44px] p-2 flex-shrink-0"
data-testid="button-phone-mode-toggle"
title="Basculer vers le mode téléphone"
>
<Smartphone className="h-4 w-4 text-gray-600" />
</Button>
)}
</>
)}
</div> </div>
</div> </div>
{/* Store selector for admin, directeur, and manager - responsive */} {/* Store selector for admin, directeur, and manager - responsive */}
{!isPhoneMode && user && (user.role === 'admin' || user.role === 'directeur' || user.role === 'manager') && stores.length > 0 && ( {user && (user.role === 'admin' || user.role === 'directeur' || user.role === 'manager') && stores.length > 0 && (
<div className="flex items-center gap-1 sm:gap-2 flex-shrink-0"> <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" /> <Store className="h-4 w-4 text-gray-500 hidden sm:block" />
<Select <Select
@@ -299,16 +258,12 @@ export default function Layout({ children }: LayoutProps) {
)} )}
<div className={`flex-1 bg-gray-50 h-full overflow-y-auto ${ <div className={`flex-1 bg-gray-50 h-full overflow-y-auto ${
isPhoneMode isMobileOrTablet ? 'p-3' : 'p-6'
? 'p-2' // Mode téléphone : padding réduit
: isMobileOrTablet ? 'p-3' : 'p-6'
}`}> }`}>
{children} {children}
</div> </div>
</main> </main>
{/* Bottom navigation for phone mode (only when authenticated) */}
{isPhoneMode && user && <PhoneBottomNav user={user} location={location} />}
</div> </div>
</StoreProvider> </StoreProvider>
); );
+14 -1
View File
@@ -64,11 +64,24 @@
@apply font-sans antialiased bg-surface text-foreground; @apply font-sans antialiased bg-surface text-foreground;
max-width: 100vw; max-width: 100vw;
height: 100%; height: 100%;
overflow-x: hidden;
} }
#root { #root {
max-width: 100vw; max-width: 100vw;
height: 100%; min-height: 100%;
overflow-x: hidden;
}
/* Éviter le débordement horizontal sur mobile */
* {
box-sizing: border-box;
}
/* Forcer les conteneurs à ne pas déborder */
.container, .main-content, [data-testid*="task"] {
max-width: 100vw;
overflow-x: hidden;
} }
/* Forcer la cohérence des largeurs de sidebar */ /* Forcer la cohérence des largeurs de sidebar */
+14 -109
View File
@@ -1565,37 +1565,10 @@ export default function Tasks() {
{/* Modal d'édition */} {/* Modal d'édition */}
{showEditModal && selectedTask && ( {showEditModal && selectedTask && (
<div style={{ <div className="fixed inset-0 bg-black bg-opacity-50 z-[1000] flex items-start sm:items-center justify-center p-4">
position: 'fixed', <div className="bg-white dark:bg-gray-800 rounded-lg max-w-full sm:max-w-2xl w-full max-h-[calc(100vh-2rem)] overflow-y-auto shadow-2xl">
top: 0, <div className="p-6 pb-4 border-b border-gray-200 dark:border-gray-700 sticky top-0 bg-white dark:bg-gray-800">
left: 0, <h2 className="text-lg font-semibold m-0 pr-10 dark:text-white">
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 1000,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<div style={{
backgroundColor: 'white',
borderRadius: '0px',
maxWidth: '600px',
width: '90%',
maxHeight: '90vh',
overflow: 'auto',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)'
}}>
<div style={{
padding: '24px 24px 16px',
borderBottom: '1px solid #e5e7eb',
position: 'relative'
}}>
<h2 style={{
fontSize: '18px',
fontWeight: '600',
margin: '0'
}}>
Modifier la tâche Modifier la tâche
</h2> </h2>
<button <button
@@ -1603,21 +1576,7 @@ export default function Tasks() {
setShowEditModal(false); setShowEditModal(false);
setSelectedTask(null); setSelectedTask(null);
}} }}
style={{ className="absolute top-4 right-4 bg-transparent border-none text-xl cursor-pointer p-2 rounded text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
position: 'absolute',
top: '16px',
right: '16px',
background: 'none',
border: 'none',
fontSize: '20px',
cursor: 'pointer',
padding: '4px',
borderRadius: '0px',
color: '#6b7280',
transition: 'color 0.2s'
}}
onMouseEnter={(e) => (e.target as HTMLButtonElement).style.color = '#374151'}
onMouseLeave={(e) => (e.target as HTMLButtonElement).style.color = '#6b7280'}
> >
✕ ✕
</button> </button>
@@ -1637,86 +1596,32 @@ export default function Tasks() {
{/* Modal de confirmation de suppression */} {/* Modal de confirmation de suppression */}
{showDeleteModal && taskToDelete && ( {showDeleteModal && taskToDelete && (
<div style={{ <div className="fixed inset-0 bg-black bg-opacity-50 z-[1000] flex items-center justify-center p-4">
position: 'fixed', <div className="bg-white dark:bg-gray-800 rounded-lg max-w-sm w-full p-6 shadow-2xl mx-4">
top: 0, <h2 className="text-lg font-semibold mb-4 text-red-600 dark:text-red-400 flex items-center gap-2">
left: 0,
right: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 1000,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<div style={{
backgroundColor: 'white',
borderRadius: '0px',
maxWidth: '400px',
width: '90%',
padding: '24px',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25)'
}}>
<h2 style={{
fontSize: '18px',
fontWeight: '600',
margin: '0 0 16px 0',
color: '#dc2626',
display: 'flex',
alignItems: 'center',
gap: '8px'
}}>
⚠️ Confirmer la suppression ⚠️ Confirmer la suppression
</h2> </h2>
<div style={{ marginBottom: '24px' }}> <div className="mb-6">
<p style={{ <p className="text-gray-700 dark:text-gray-300 leading-relaxed mb-2">
color: '#374151',
lineHeight: '1.5',
margin: '0 0 8px 0'
}}>
Êtes-vous sûr de vouloir supprimer la tâche "{taskToDelete.title}" ? Êtes-vous sûr de vouloir supprimer la tâche "{taskToDelete.title}" ?
</p> </p>
<p style={{ <p className="text-sm text-gray-500 dark:text-gray-400">
fontSize: '14px',
color: '#6b7280',
margin: '0'
}}>
Cette action est irréversible. Cette action est irréversible.
</p> </p>
</div> </div>
<div style={{ <div className="flex gap-3 flex-col sm:flex-row">
display: 'flex',
gap: '12px',
justifyContent: 'flex-end'
}}>
<button <button
onClick={() => { onClick={() => {
setShowDeleteModal(false); setShowDeleteModal(false);
setTaskToDelete(null); setTaskToDelete(null);
}} }}
style={{ className="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-600 order-2 sm:order-1"
padding: '8px 16px',
border: '1px solid #d1d5db',
borderRadius: '0px',
backgroundColor: 'white',
cursor: 'pointer'
}}
> >
Annuler Annuler
</button> </button>
<button <button
onClick={handleConfirmDelete} onClick={handleConfirmDelete}
style={{ className="px-4 py-2 border-none rounded-md bg-red-600 text-white cursor-pointer hover:bg-red-700 flex items-center justify-center gap-2 order-1 sm:order-2"
padding: '8px 16px',
border: 'none',
borderRadius: '0px',
backgroundColor: '#dc2626',
color: 'white',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
gap: '8px'
}}
> >
🗑️ Supprimer 🗑️ Supprimer
</button> </button>