mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-12 09:47:54 +02:00
2 files changed
+19
-125
No files matched your search
+18
-124
@@ -553,134 +553,30 @@ export default function Tasks() {
|
||||
{/* Contenu selon la vue sélectionnée */}
|
||||
<Tabs value={viewMode} onValueChange={setViewMode} className="h-full">
|
||||
<TabsContent value="kanban" className="mt-0">
|
||||
{/* Vue Kanban avec 10 colonnes - Workflow complet */}
|
||||
{/* Vue Kanban simple - 2 colonnes */}
|
||||
<div className="p-6">
|
||||
<div className="grid grid-cols-10 gap-1 h-full text-xs overflow-x-auto">
|
||||
{/* Colonne Backlog */}
|
||||
<div className="bg-gray-50 rounded-lg p-3">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<Circle className="w-4 h-4 text-gray-400" />
|
||||
Backlog ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'backlog').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'backlog').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-6 h-full">
|
||||
{/* Colonne À faire */}
|
||||
<div className="bg-blue-50 rounded-lg p-3">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<Circle className="w-4 h-4 text-blue-500" />
|
||||
À faire ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'todo').length})
|
||||
<div className="bg-blue-50 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-gray-900 mb-4 flex items-center gap-2">
|
||||
<Circle className="w-5 h-5 text-blue-500" />
|
||||
À faire ({filteredTasks.filter((task: TaskWithRelations) => task.status !== 'done' && task.status !== 'archived').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'todo').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne En cours */}
|
||||
<div className="bg-yellow-50 rounded-lg p-3">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<Clock className="w-4 h-4 text-yellow-500" />
|
||||
En cours ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'in_progress').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'in_progress').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Révision */}
|
||||
<div className="bg-purple-50 rounded-lg p-3">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<Edit className="w-4 h-4 text-purple-500" />
|
||||
Révision ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'review').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'review').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Test */}
|
||||
<div className="bg-orange-50 rounded-lg p-2">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<AlertTriangle className="w-4 h-4 text-orange-500" />
|
||||
Test ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'testing').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'testing').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Bloqué */}
|
||||
<div className="bg-red-50 rounded-lg p-2">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<Circle className="w-4 h-4 text-red-500" />
|
||||
Bloqué ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'blocked').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'blocked').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Prêt Déploiement */}
|
||||
<div className="bg-indigo-50 rounded-lg p-2">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<CheckCircle className="w-4 h-4 text-indigo-500" />
|
||||
Prêt Déploiement ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'ready_to_deploy').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'ready_to_deploy').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Déployé */}
|
||||
<div className="bg-cyan-50 rounded-lg p-2">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<CheckCircle className="w-4 h-4 text-cyan-500" />
|
||||
Déployé ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'deployed').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'deployed').map((task: TaskWithRelations) => {
|
||||
<div className="space-y-3 max-h-[600px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status !== 'done' && task.status !== 'archived').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Terminé */}
|
||||
<div className="bg-green-50 rounded-lg p-2">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<CheckCircle className="w-4 h-4 text-green-500" />
|
||||
Terminé ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'done').length})
|
||||
<div className="bg-green-50 rounded-lg p-4">
|
||||
<h3 className="font-semibold text-gray-900 mb-4 flex items-center gap-2">
|
||||
<CheckCircle className="w-5 h-5 text-green-500" />
|
||||
Terminé ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'done' || task.status === 'archived').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'done').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks, true);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne Archivé */}
|
||||
<div className="bg-gray-100 rounded-lg p-2">
|
||||
<h3 className="font-semibold text-gray-900 mb-3 flex items-center gap-2 text-xs">
|
||||
<Circle className="w-4 h-4 text-gray-400" />
|
||||
Archivé ({filteredTasks.filter((task: TaskWithRelations) => task.status === 'archived').length})
|
||||
</h3>
|
||||
<div className="space-y-2 max-h-[500px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'archived').map((task: TaskWithRelations) => {
|
||||
<div className="space-y-3 max-h-[600px] overflow-y-auto">
|
||||
{filteredTasks.filter((task: TaskWithRelations) => task.status === 'done' || task.status === 'archived').map((task: TaskWithRelations) => {
|
||||
return renderKanbanCard(task, canEditTasks, true);
|
||||
})}
|
||||
</div>
|
||||
@@ -704,15 +600,15 @@ export default function Tasks() {
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{/* Tâches actives (non terminées/archivées) */}
|
||||
{paginatedTasks.filter(task => !['done', 'archived'].includes(task.status)).length > 0 && (
|
||||
{/* Tâches À faire en premier */}
|
||||
{paginatedTasks.filter(task => ['todo', 'backlog', 'in_progress', 'review', 'testing', 'blocked', 'ready_to_deploy', 'deployed'].includes(task.status)).length > 0 && (
|
||||
<div>
|
||||
<h4 className="text-lg font-semibold text-gray-900 mb-3">
|
||||
Tâches actives ({paginatedTasks.filter(task => !['done', 'archived'].includes(task.status)).length})
|
||||
Tâches à faire ({paginatedTasks.filter(task => ['todo', 'backlog', 'in_progress', 'review', 'testing', 'blocked', 'ready_to_deploy', 'deployed'].includes(task.status)).length})
|
||||
</h4>
|
||||
<div className="space-y-3">
|
||||
{paginatedTasks
|
||||
.filter(task => !['done', 'archived'].includes(task.status))
|
||||
.filter(task => ['todo', 'backlog', 'in_progress', 'review', 'testing', 'blocked', 'ready_to_deploy', 'deployed'].includes(task.status))
|
||||
.map((task) => {
|
||||
const priorityConfig = getPriorityConfig(task.priority);
|
||||
const PriorityIcon = priorityConfig.icon;
|
||||
@@ -912,8 +808,6 @@ export default function Tasks() {
|
||||
)}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,7 @@ The platform is built with a clear separation of concerns, utilizing a modern fu
|
||||
- **Reconciliation:** Functionality for reconciling Bills of Lading (BL) and invoices with immediate UI updates.
|
||||
- **Invoice Verification Cache:** Robust caching system for invoice verification results with automatic expiration and conflict resolution. Enhanced with unique constraint handling and graceful error management for production stability (August 2025). Fixed production SSL certificate errors and fetch timeout loops with enhanced error handling, network timeout protection, and error result caching to prevent infinite retry loops (August 2025).
|
||||
- **UI Scrollbar Optimization:** Eliminated redundant vertical scrollbar on the right side of the screen while preserving necessary internal page scrolling. Implemented global CSS rules with `overflow: hidden` on html/body/root and Layout height management to prevent vertical overflow issues in production (August 2025).
|
||||
- **Task Management:** Système complet de gestion des tâches avec workflow Kanban 7 colonnes - Backlog, À faire, En cours, Révision, Test, Terminé, Archivé. Fonctionnalités temporelles avancées avec tri intelligent par statut/priorité/date, dates d'échéance avec sélecteur calendrier, indicateurs visuels pour tâches en retard/urgentes, filtres par échéance et statut complets. Interface optimisée avec cartes compactes pour vue Kanban étendue et vue liste détaillée (Août 2025).
|
||||
- **Task Management:** Système simple de gestion des tâches avec workflow Kanban 2 colonnes - À faire et Terminé. Préférence utilisateur pour un workflow simplifié. Fonctionnalités temporelles avancées avec tri intelligent par statut/priorité/date, dates d'échéance avec sélecteur calendrier, indicateurs visuels pour tâches en retard/urgentes, filtres par échéance et statut complets. Interface optimisée avec vue Kanban simple 2 colonnes et vue liste détaillée (Août 2025).
|
||||
- **User and Permission Management:** Granular access controls ensuring that users (e.g., employees) have appropriate permissions for tasks like creating customer orders.
|
||||
- **Reporting:** Statistical reporting, including monthly summaries of deliveries based on `deliveredDate`.
|
||||
|
||||
|
||||
Reference in new issue
Block a user