feat: add compact view feature to Kanban components
- Introduced `compactView` prop in `KanbanBoard`, `KanbanColumn`, and `TaskCard` for a streamlined task display. - Updated `KanbanFilters` to include a toggle for compact view, enhancing user experience. - Adjusted rendering logic in `TaskCard` to conditionally display task details based on the compact view state.
This commit is contained in:
@@ -13,9 +13,10 @@ interface TaskCardProps {
|
||||
onDelete?: (taskId: string) => Promise<void>;
|
||||
onEdit?: (task: Task) => void;
|
||||
onUpdateTitle?: (taskId: string, newTitle: string) => Promise<void>;
|
||||
compactView?: boolean;
|
||||
}
|
||||
|
||||
export function TaskCard({ task, onDelete, onEdit, onUpdateTitle }: TaskCardProps) {
|
||||
export function TaskCard({ task, onDelete, onEdit, onUpdateTitle, compactView = false }: TaskCardProps) {
|
||||
const [isEditingTitle, setIsEditingTitle] = useState(false);
|
||||
const [editTitle, setEditTitle] = useState(task.title);
|
||||
const { tags: availableTags } = useTasksContext();
|
||||
@@ -92,6 +93,84 @@ export function TaskCard({ task, onDelete, onEdit, onUpdateTitle }: TaskCardProp
|
||||
const titleWithoutEmojis = task.title.replace(emojiRegex, '').trim();
|
||||
|
||||
|
||||
// Vue compacte : seulement le titre
|
||||
if (compactView) {
|
||||
return (
|
||||
<Card
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
className={`p-2 hover:border-cyan-500/30 hover:shadow-lg hover:shadow-cyan-500/10 transition-all duration-300 cursor-pointer group ${
|
||||
isDragging ? 'opacity-50 rotate-3 scale-105' : ''
|
||||
}`}
|
||||
{...attributes}
|
||||
{...(isEditingTitle ? {} : listeners)}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{emojis.length > 0 && (
|
||||
<div className="flex gap-1 flex-shrink-0">
|
||||
{emojis.slice(0, 1).map((emoji, index) => (
|
||||
<span key={index} className="text-sm opacity-80">
|
||||
{emoji}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isEditingTitle ? (
|
||||
<input
|
||||
type="text"
|
||||
value={editTitle}
|
||||
onChange={(e) => setEditTitle(e.target.value)}
|
||||
onKeyDown={handleTitleKeyPress}
|
||||
onBlur={handleTitleSave}
|
||||
autoFocus
|
||||
className="flex-1 bg-transparent border-none outline-none text-slate-100 font-mono text-sm font-medium leading-tight"
|
||||
/>
|
||||
) : (
|
||||
<h4
|
||||
className="font-mono text-sm font-medium text-slate-100 leading-tight line-clamp-1 flex-1 cursor-pointer hover:text-cyan-300 transition-colors"
|
||||
onClick={handleTitleClick}
|
||||
title={onUpdateTitle ? "Cliquer pour éditer" : undefined}
|
||||
>
|
||||
{titleWithoutEmojis}
|
||||
</h4>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-1 flex-shrink-0">
|
||||
{/* Boutons d'action compacts */}
|
||||
{onEdit && (
|
||||
<button
|
||||
onClick={handleEdit}
|
||||
className="opacity-0 group-hover:opacity-100 w-3 h-3 rounded-full bg-blue-900/50 hover:bg-blue-800/80 border border-blue-500/30 hover:border-blue-400/50 flex items-center justify-center transition-all duration-200 text-blue-400 hover:text-blue-300 text-xs"
|
||||
title="Modifier la tâche"
|
||||
>
|
||||
✎
|
||||
</button>
|
||||
)}
|
||||
|
||||
{onDelete && (
|
||||
<button
|
||||
onClick={handleDelete}
|
||||
className="opacity-0 group-hover:opacity-100 w-3 h-3 rounded-full bg-red-900/50 hover:bg-red-800/80 border border-red-500/30 hover:border-red-400/50 flex items-center justify-center transition-all duration-200 text-red-400 hover:text-red-300 text-xs"
|
||||
title="Supprimer la tâche"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Indicateur de priorité compact */}
|
||||
<div className={`w-1.5 h-1.5 rounded-full ${
|
||||
task.priority === 'high' ? 'bg-red-400' :
|
||||
task.priority === 'medium' ? 'bg-yellow-400' :
|
||||
'bg-slate-500'
|
||||
}`} />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// Vue détaillée : version complète
|
||||
return (
|
||||
<Card
|
||||
ref={setNodeRef}
|
||||
|
||||
Reference in New Issue
Block a user