Files
towercontrol/components/ui/Header.tsx
Julien Froidefond 9193305550 feat: implement drag & drop functionality using @dnd-kit
- Added drag & drop capabilities to the Kanban board with @dnd-kit for task status updates.
- Integrated DndContext in `KanbanBoard` and utilized `useDroppable` in `KanbanColumn` for drop zones.
- Enhanced `TaskCard` with draggable features and visual feedback during dragging.
- Updated `TODO.md` to reflect the completion of drag & drop tasks and optimistically update task statuses.
- Introduced optimistic updates in `useTasks` for smoother user experience during drag & drop operations.
2025-09-14 09:08:06 +02:00

101 lines
3.0 KiB
TypeScript

import { Card, CardContent } from '@/components/ui/Card';
interface HeaderProps {
title: string;
subtitle: string;
stats: {
total: number;
completed: number;
inProgress: number;
todo: number;
completionRate: number;
};
syncing?: boolean;
}
export function Header({ title, subtitle, stats, syncing = false }: HeaderProps) {
return (
<header className="bg-slate-900/80 backdrop-blur-sm border-b border-slate-700/50 shadow-lg shadow-slate-900/20">
<div className="container mx-auto px-6 py-4">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-6">
{/* Titre tech avec glow */}
<div className="flex items-center gap-4">
<div className={`w-3 h-3 rounded-full shadow-lg ${
syncing
? 'bg-yellow-400 animate-spin shadow-yellow-400/50'
: 'bg-cyan-400 animate-pulse shadow-cyan-400/50'
}`}></div>
<div>
<h1 className="text-2xl font-mono font-bold text-slate-100 tracking-wider">
{title}
</h1>
<p className="text-slate-400 mt-1 font-mono text-sm">
{subtitle} {syncing && '• Synchronisation...'}
</p>
</div>
</div>
{/* Stats tech dashboard */}
<div className="flex flex-wrap gap-3">
<StatCard
label="TOTAL"
value={String(stats.total).padStart(2, '0')}
color="blue"
/>
<StatCard
label="DONE"
value={String(stats.completed).padStart(2, '0')}
color="green"
/>
<StatCard
label="ACTIVE"
value={String(stats.inProgress).padStart(2, '0')}
color="yellow"
/>
<StatCard
label="QUEUE"
value={String(stats.todo).padStart(2, '0')}
color="gray"
/>
<StatCard
label="RATE"
value={`${stats.completionRate}%`}
color="purple"
/>
</div>
</div>
</div>
</header>
);
}
interface StatCardProps {
label: string;
value: number | string;
color: 'blue' | 'green' | 'yellow' | 'gray' | 'purple';
}
function StatCard({ label, value, color }: StatCardProps) {
const textColors = {
blue: 'text-cyan-300',
green: 'text-emerald-300',
yellow: 'text-yellow-300',
gray: 'text-slate-300',
purple: 'text-purple-300'
};
return (
<Card variant="elevated" className="px-3 py-2 hover:border-opacity-75 transition-all duration-300">
<CardContent className="p-0">
<div className={`text-xs font-mono font-bold ${textColors[color]} opacity-75 uppercase tracking-wider`}>
{label}
</div>
<div className={`text-lg font-mono font-bold ${textColors[color]}`}>
{value}
</div>
</CardContent>
</Card>
);
}