mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-22 14:38:19 +02:00
Make daily order and delivery cards larger and more readable
Expand the size and improve the visual clarity of order and delivery cards in the calendar view, and update the delivery order modal to eliminate scrollbars for better usability. Replit-Commit-Author: Agent Replit-Commit-Session-Id: cc2d271b-82f0-4d6a-9302-a0b067ffb429 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/cc2d271b-82f0-4d6a-9302-a0b067ffb429/o69iJI6
This commit is contained in:
1 parent
07fc38e5f0
commit
5e55b08740
1 file changed
+94
-53
@@ -38,20 +38,20 @@ function CalendarItem({ item, type, onItemClick }: { item: any, type: 'order' |
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`text-xs px-1 py-1 cursor-pointer hover:opacity-90 transition-opacity ${getOrderStyle()}`}
|
className={`text-xs px-2 py-2 cursor-pointer hover:opacity-90 transition-opacity ${getOrderStyle()} rounded-sm`}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onItemClick(item, 'order');
|
onItemClick(item, 'order');
|
||||||
}}
|
}}
|
||||||
style={{marginBottom: '2px', display: 'block', width: '100%'}}
|
style={{marginBottom: '3px', display: 'block', width: '100%', minHeight: '24px'}}
|
||||||
>
|
>
|
||||||
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%'}}>
|
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%'}}>
|
||||||
<span className="truncate font-semibold" style={{fontSize: '10px'}}>
|
<span className="truncate font-semibold" style={{fontSize: '11px', lineHeight: '1.2'}}>
|
||||||
{item.supplier?.name || 'Commande'}
|
{item.supplier?.name || 'Commande'}
|
||||||
</span>
|
</span>
|
||||||
<div style={{display: 'flex', alignItems: 'center'}}>
|
<div style={{display: 'flex', alignItems: 'center', marginLeft: '4px'}}>
|
||||||
{item.status === 'planned' && (
|
{item.status === 'planned' && (
|
||||||
<div className="w-1.5 h-1.5 bg-yellow-600" title="Planifié" />
|
<div className="w-2 h-2 bg-yellow-600 rounded-full" title="Planifié" />
|
||||||
)}
|
)}
|
||||||
{item.status === 'delivered' && (
|
{item.status === 'delivered' && (
|
||||||
<Check className="w-3 h-3" />
|
<Check className="w-3 h-3" />
|
||||||
@@ -76,20 +76,20 @@ function CalendarItem({ item, type, onItemClick }: { item: any, type: 'order' |
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`text-xs px-1 py-1 cursor-pointer hover:opacity-90 transition-opacity ${getDeliveryStyle()}`}
|
className={`text-xs px-2 py-2 cursor-pointer hover:opacity-90 transition-opacity ${getDeliveryStyle()} rounded-sm`}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onItemClick(item, 'delivery');
|
onItemClick(item, 'delivery');
|
||||||
}}
|
}}
|
||||||
style={{marginBottom: '2px', display: 'block', width: '100%'}}
|
style={{marginBottom: '3px', display: 'block', width: '100%', minHeight: '24px'}}
|
||||||
>
|
>
|
||||||
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%'}}>
|
<div style={{display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%'}}>
|
||||||
<span className="truncate font-semibold" style={{fontSize: '10px'}}>
|
<span className="truncate font-semibold" style={{fontSize: '11px', lineHeight: '1.2'}}>
|
||||||
{item.supplier?.name || 'Livraison'} - {formatQuantity(item.quantity, item.unit)}
|
{item.supplier?.name || 'Livraison'} - {formatQuantity(item.quantity, item.unit)}
|
||||||
</span>
|
</span>
|
||||||
<div style={{display: 'flex', alignItems: 'center'}}>
|
<div style={{display: 'flex', alignItems: 'center', marginLeft: '4px'}}>
|
||||||
{item.status === 'pending' && (
|
{item.status === 'pending' && (
|
||||||
<div className="w-1.5 h-1.5 bg-green-600" title="En attente" />
|
<div className="w-2 h-2 bg-green-600 rounded-full" title="En attente" />
|
||||||
)}
|
)}
|
||||||
{item.status === 'delivered' && (
|
{item.status === 'delivered' && (
|
||||||
<Check className="w-3 h-3" />
|
<Check className="w-3 h-3" />
|
||||||
@@ -118,7 +118,7 @@ function DayItemsContainer({ dayOrders, dayDeliveries, onItemClick }: { dayOrder
|
|||||||
const hiddenCount = Math.max(0, totalItems - MAX_VISIBLE_ITEMS);
|
const hiddenCount = Math.max(0, totalItems - MAX_VISIBLE_ITEMS);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1 relative" style={{minHeight: '60px'}} data-modal-trigger="container">
|
<div className="space-y-1 relative" style={{minHeight: '70px'}} data-modal-trigger="container">
|
||||||
{/* Éléments visibles - IDENTIQUE DEV/PROD */}
|
{/* Éléments visibles - IDENTIQUE DEV/PROD */}
|
||||||
{visibleItems.map((item, index) => (
|
{visibleItems.map((item, index) => (
|
||||||
<CalendarItem
|
<CalendarItem
|
||||||
@@ -138,7 +138,7 @@ function DayItemsContainer({ dayOrders, dayDeliveries, onItemClick }: { dayOrder
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
data-modal-trigger="button"
|
data-modal-trigger="button"
|
||||||
className="w-full h-5 text-xs bg-white hover:bg-gray-50 border-gray-400 text-gray-700 font-semibold shadow-sm transition-all duration-150 border"
|
className="w-full h-6 text-xs bg-white hover:bg-gray-50 border-gray-400 text-gray-700 font-semibold shadow-sm transition-all duration-150 border rounded-sm"
|
||||||
style={{display: 'block !important', position: 'relative', zIndex: 50}}
|
style={{display: 'block !important', position: 'relative', zIndex: 50}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -150,51 +150,92 @@ function DayItemsContainer({ dayOrders, dayDeliveries, onItemClick }: { dayOrder
|
|||||||
+{hiddenCount} autres
|
+{hiddenCount} autres
|
||||||
</Button>
|
</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-lg max-h-[70vh] overflow-hidden fixed z-[9999]" style={{zIndex: 9999}}>
|
<DialogContent className="max-w-2xl w-full max-h-[85vh] fixed z-[9999] p-0" style={{zIndex: 9999}}>
|
||||||
<DialogHeader>
|
<DialogHeader className="px-6 py-4 border-b border-gray-200 bg-gray-50">
|
||||||
<DialogTitle className="text-base font-semibold text-gray-800 flex items-center gap-2">
|
<DialogTitle className="text-lg font-bold text-gray-900 flex items-center gap-3">
|
||||||
<Package className="w-4 h-4" />
|
<Package className="w-5 h-5 text-blue-600" />
|
||||||
Éléments du jour ({totalItems})
|
Éléments du jour - {totalItems} élément{totalItems > 1 ? 's' : ''}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="mt-3">
|
|
||||||
<div className="space-y-2 max-h-[50vh] overflow-y-auto">
|
<div className="p-6">
|
||||||
{allItems.map((item, index) => (
|
<div className="grid gap-4" style={{maxHeight: '60vh'}}>
|
||||||
<div
|
{allItems.map((item, index) => {
|
||||||
key={`modal-${item.itemType}-${item.id}-${index}`}
|
const isOrder = item.itemType === 'order';
|
||||||
className="border border-gray-200 hover:bg-gray-50 transition-colors p-2 rounded cursor-pointer"
|
const statusColor = item.status === 'delivered'
|
||||||
onClick={(e) => {
|
? 'bg-gray-100 border-gray-300'
|
||||||
e.preventDefault();
|
: item.status === 'planned'
|
||||||
e.stopPropagation();
|
? 'bg-yellow-50 border-yellow-300'
|
||||||
onItemClick(item, item.itemType);
|
: isOrder
|
||||||
setIsOpen(false);
|
? 'bg-blue-50 border-blue-300'
|
||||||
}}
|
: 'bg-green-50 border-green-300';
|
||||||
>
|
|
||||||
<div className={`text-sm px-2 py-2 ${
|
const statusText = item.status === 'delivered' ? 'Livré' :
|
||||||
item.itemType === 'order'
|
item.status === 'planned' ? 'Planifié' : 'En attente';
|
||||||
? item.status === 'delivered'
|
|
||||||
? 'bg-gray-400 text-white'
|
const statusIcon = item.status === 'delivered'
|
||||||
: item.status === 'planned'
|
? <Check className="w-4 h-4 text-gray-600" />
|
||||||
? 'bg-yellow-300 text-gray-800'
|
: item.status === 'planned'
|
||||||
: 'bg-blue-300 text-gray-800'
|
? <div className="w-3 h-3 bg-yellow-500 rounded-full" />
|
||||||
: item.status === 'delivered'
|
: isOrder
|
||||||
? 'bg-gray-400 text-white'
|
? <div className="w-3 h-3 bg-blue-500 rounded-full" />
|
||||||
: 'bg-green-300 text-gray-800'
|
: <div className="w-3 h-3 bg-green-500 rounded-full" />;
|
||||||
}`}>
|
|
||||||
<div className="font-semibold">
|
return (
|
||||||
{item.supplier?.name || (item.itemType === 'order' ? 'Commande' : 'Livraison')}
|
<div
|
||||||
</div>
|
key={`modal-${item.itemType}-${item.id}-${index}`}
|
||||||
{item.itemType === 'delivery' && (
|
className={`${statusColor} border-2 rounded-lg p-4 cursor-pointer hover:shadow-md transition-all duration-200 transform hover:scale-[1.02]`}
|
||||||
<div className="text-xs mt-1">
|
onClick={(e) => {
|
||||||
Quantité: {item.quantity}{item.unit === 'palettes' ? 'P' : 'C'}
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
onItemClick(item, item.itemType);
|
||||||
|
setIsOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className="flex-1">
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
{statusIcon}
|
||||||
|
<span className="text-xs font-medium text-gray-600 uppercase tracking-wide">
|
||||||
|
{isOrder ? 'Commande' : 'Livraison'}
|
||||||
|
</span>
|
||||||
|
<span className={`text-xs px-2 py-1 rounded-full font-medium ${
|
||||||
|
item.status === 'delivered' ? 'bg-gray-200 text-gray-700' :
|
||||||
|
item.status === 'planned' ? 'bg-yellow-200 text-yellow-800' :
|
||||||
|
isOrder ? 'bg-blue-200 text-blue-800' : 'bg-green-200 text-green-800'
|
||||||
|
}`}>
|
||||||
|
{statusText}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-bold text-lg text-gray-900 mb-1">
|
||||||
|
{item.supplier?.name || (isOrder ? 'Commande sans fournisseur' : 'Livraison sans fournisseur')}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
{!isOrder && (
|
||||||
|
<div className="text-sm text-gray-700 mb-1">
|
||||||
|
<span className="font-medium">Quantité:</span> {item.quantity} {item.unit === 'palettes' ? 'palette(s)' : 'colis'}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="text-sm text-gray-600">
|
||||||
|
<span className="font-medium">Date:</span> {
|
||||||
|
item.scheduledDate ? new Date(item.scheduledDate).toLocaleDateString('fr-FR') :
|
||||||
|
item.deliveredDate ? new Date(item.deliveredDate).toLocaleDateString('fr-FR') :
|
||||||
|
new Date(item.createdAt).toLocaleDateString('fr-FR')
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{item.notes && (
|
||||||
|
<div className="text-sm text-gray-600 mt-2">
|
||||||
|
<span className="font-medium">Notes:</span> {item.notes}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
<div className="text-xs mt-1 opacity-75">
|
|
||||||
Statut: {item.status === 'delivered' ? 'Livré' : item.status === 'planned' ? 'Planifié' : 'En attente'}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@@ -474,7 +515,7 @@ export default function CalendarGrid({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Orders and Deliveries - DEV = PRODUCTION */}
|
{/* Orders and Deliveries - DEV = PRODUCTION */}
|
||||||
<div className="flex-1 relative" style={{minHeight: '80px', overflow: 'visible'}}>
|
<div className="flex-1 relative" style={{minHeight: '90px', overflow: 'visible'}}>
|
||||||
<DayItemsContainer
|
<DayItemsContainer
|
||||||
dayOrders={dayOrders}
|
dayOrders={dayOrders}
|
||||||
dayDeliveries={dayDeliveries}
|
dayDeliveries={dayDeliveries}
|
||||||
|
|||||||
Reference in new issue
Block a user