94 lines
2.2 KiB
TypeScript
94 lines
2.2 KiB
TypeScript
import { useState } from 'react';
|
||
import { useSortable } from '@dnd-kit/sortable';
|
||
import { CSS } from '@dnd-kit/utilities';
|
||
import type { Task } from '../types';
|
||
|
||
interface TaskCardProps {
|
||
task: Task;
|
||
isDragging?: boolean;
|
||
onDelete?: () => void;
|
||
onUpdate?: (updates: Partial<Task>) => void;
|
||
}
|
||
|
||
export function TaskCard({ task, isDragging, onDelete, onUpdate }: TaskCardProps) {
|
||
const [isEditing, setIsEditing] = useState(false);
|
||
const [editTitle, setEditTitle] = useState(task.title);
|
||
|
||
const {
|
||
attributes,
|
||
listeners,
|
||
setNodeRef,
|
||
transform,
|
||
transition,
|
||
isDragging: isSortableDragging,
|
||
} = useSortable({ id: task.id });
|
||
|
||
const style = {
|
||
transform: CSS.Transform.toString(transform),
|
||
transition,
|
||
opacity: isSortableDragging ? 0.5 : 1,
|
||
};
|
||
|
||
const handleSave = () => {
|
||
if (editTitle.trim() && onUpdate) {
|
||
onUpdate({ title: editTitle.trim() });
|
||
}
|
||
setIsEditing(false);
|
||
};
|
||
|
||
if (isDragging) {
|
||
return (
|
||
<div className="task-card task-card-overlay">
|
||
<p>{task.title}</p>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div
|
||
ref={setNodeRef}
|
||
style={style}
|
||
className="task-card"
|
||
{...attributes}
|
||
{...listeners}
|
||
>
|
||
{isEditing ? (
|
||
<div className="task-edit" onClick={(e) => e.stopPropagation()}>
|
||
<input
|
||
type="text"
|
||
value={editTitle}
|
||
onChange={(e) => setEditTitle(e.target.value)}
|
||
onKeyDown={(e) => e.key === 'Enter' && handleSave()}
|
||
autoFocus
|
||
/>
|
||
<button onClick={handleSave}>Save</button>
|
||
</div>
|
||
) : (
|
||
<>
|
||
<p>{task.title}</p>
|
||
<div className="task-actions">
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
setIsEditing(true);
|
||
}}
|
||
title="Edit"
|
||
>
|
||
✏️
|
||
</button>
|
||
<button
|
||
onClick={(e) => {
|
||
e.stopPropagation();
|
||
onDelete?.();
|
||
}}
|
||
title="Delete"
|
||
>
|
||
🗑️
|
||
</button>
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|