import { useState } from 'react'; import type { Task, User, Status, Priority } from './data'; import { STATUS_LABELS, getUserById } from './data'; import { Avatar, Tag, ProgressBar } from './Shared'; interface DrawerProps { task: Task; currentUser: User; onClose: () => void; onUpdate: (updated: Task) => void; onAddDependency: (taskId: string, dep: { dependsOnUserId: string; description: string }) => void; onToggleDependency: (taskId: string, depId: string, resolved: boolean) => void; onRemoveDependency: (taskId: string, depId: string) => void; users: User[]; } export function TaskDrawer({ task, currentUser, onClose, onUpdate, onAddDependency, onToggleDependency, onRemoveDependency, users }: DrawerProps) { const [commentText, setCommentText] = useState(''); const [subtaskText, setSubtaskText] = useState(''); const [depUser, setDepUser] = useState(''); const [depDesc, setDepDesc] = useState(''); const updateField = (field: string, value: any) => { const now = new Date().toISOString(); const updated = { ...task, [field]: value, activity: [...task.activity, { id: `a${Date.now()}`, text: `๐Ÿ”„ ${currentUser.name} changed ${field} to ${value}`, timestamp: now }] }; onUpdate(updated); }; const toggleSubtask = (sid: string) => { const now = new Date().toISOString(); const subtasks = task.subtasks.map(s => s.id === sid ? { ...s, done: !s.done } : s); const st = subtasks.find(s => s.id === sid)!; onUpdate({ ...task, subtasks, activity: [...task.activity, { id: `a${Date.now()}`, text: `${st.done ? 'โœ…' : 'โ†ฉ๏ธ'} ${currentUser.name} ${st.done ? 'completed' : 'unchecked'} subtask "${st.title}"`, timestamp: now }] }); }; const addSubtask = () => { if (!subtaskText.trim()) return; onUpdate({ ...task, subtasks: [...task.subtasks, { id: `s${Date.now()}`, title: subtaskText, done: false }] }); setSubtaskText(''); }; const addComment = () => { if (!commentText.trim()) return; const now = new Date().toISOString(); onUpdate({ ...task, comments: [...task.comments, { id: `c${Date.now()}`, userId: currentUser.id, text: commentText, timestamp: now }], activity: [...task.activity, { id: `a${Date.now()}`, text: `๐Ÿ’ฌ ${currentUser.name} added a comment`, timestamp: now }] }); setCommentText(''); }; const handleAddDep = () => { if (!depDesc.trim()) return; onAddDependency(task.id, { dependsOnUserId: depUser, description: depDesc }); setDepDesc(''); setDepUser(''); }; const reporter = getUserById(users, task.reporter); const doneCount = task.subtasks.filter(s => s.done).length; const unresolvedDeps = (task.dependencies || []).filter(d => !d.resolved).length; return ( <>
Task Detail

{task.title}

{task.description}

Assignee
Reporter
{reporter?.name}
Status
Priority
Due Date
updateField('dueDate', e.target.value)} />
Tags
{task.tags.map(t => )}
{/* Dependencies Section */}
๐Ÿ”— Dependencies {unresolvedDeps > 0 && {unresolvedDeps} blocking}
{(task.dependencies || []).length === 0 && (
No dependencies yet
)} {(task.dependencies || []).map(dep => { const depUser = getUserById(users, dep.dependsOnUserId); return (
{depUser && ( {depUser.name} )} {dep.description}
); })}
setDepDesc(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleAddDep()} />
Subtasks {doneCount} of {task.subtasks.length} complete
{task.subtasks.length > 0 && } {task.subtasks.map(s => (
toggleSubtask(s.id)}> {s.title}
))}
setSubtaskText(e.target.value)} onKeyDown={e => e.key === 'Enter' && addSubtask()} />
Comments
{task.comments.map(c => { const cu = getUserById(users, c.userId); return (
{cu?.name} {new Date(c.timestamp).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}
{c.text}
); })}
setCommentText(e.target.value)} onKeyDown={e => e.key === 'Enter' && addComment()} />
Activity
{task.activity.map(a => (
{a.text} ยท {new Date(a.timestamp).toLocaleString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}
))}
); } interface ModalProps { onClose: () => void; onAdd: (task: Task) => void; defaultDate?: string; defaultStatus?: Status; users: User[]; currentUser: User; } interface PendingDep { id: string; dependsOnUserId: string; description: string; } export function AddTaskModal({ onClose, onAdd, defaultDate, defaultStatus, users, currentUser }: ModalProps) { const [title, setTitle] = useState(''); const [desc, setDesc] = useState(''); const [assignee, setAssignee] = useState(currentUser.id); const [priority, setPriority] = useState('medium'); const [status, setStatus] = useState(defaultStatus || 'todo'); const [dueDate, setDueDate] = useState(defaultDate || new Date().toISOString().split('T')[0]); const [tags, setTags] = useState(''); const [error, setError] = useState(false); // Dependencies state const [deps, setDeps] = useState([]); const [depUser, setDepUser] = useState(''); const [depDesc, setDepDesc] = useState(''); const addDep = () => { if (!depDesc.trim()) return; setDeps(prev => [...prev, { id: `pd${Date.now()}`, dependsOnUserId: depUser, description: depDesc }]); setDepDesc(''); setDepUser(''); }; const removeDep = (id: string) => { setDeps(prev => prev.filter(d => d.id !== id)); }; const submit = () => { if (!title.trim()) { setError(true); return; } const task: Task = { id: `t${Date.now()}`, title, description: desc, status, priority, assignee, reporter: currentUser.id, dueDate, tags: tags ? tags.split(',').map(t => t.trim()).filter(Boolean) : [], subtasks: [], comments: [], activity: [{ id: `a${Date.now()}`, text: `๐Ÿ“ Task created`, timestamp: new Date().toISOString() }], dependencies: deps.map(d => ({ id: d.id, dependsOnUserId: d.dependsOnUserId, description: d.description, resolved: false })), }; onAdd(task); onClose(); }; return (
e.stopPropagation()}>

New Task

{ setTitle(e.target.value); setError(false); }} />