import React, { useState, useMemo, useTransition, useEffect, useCallback } from 'react'; interface Task { id: string; title: string; assignee: string; associatedWith: string; associationType: 'contact' | 'deal' | 'company'; dueDate: string; priority: 'low' | 'medium' | 'high'; status: 'pending' | 'in-progress' | 'completed'; } const mockTasks: Task[] = [ { id: '1', title: 'Follow up call', assignee: 'Sarah Johnson', associatedWith: 'John Doe', associationType: 'contact', dueDate: '2024-02-14', priority: 'high', status: 'pending' }, { id: '2', title: 'Send proposal', assignee: 'Mike Chen', associatedWith: 'Acme Corp Deal', associationType: 'deal', dueDate: '2024-02-15', priority: 'high', status: 'in-progress' }, { id: '3', title: 'Schedule demo', assignee: 'Tom Brown', associatedWith: 'TechCo', associationType: 'company', dueDate: '2024-02-16', priority: 'medium', status: 'pending' }, { id: '4', title: 'Review contract', assignee: 'Sarah Johnson', associatedWith: 'Enterprise Deal', associationType: 'deal', dueDate: '2024-02-13', priority: 'high', status: 'in-progress' }, { id: '5', title: 'Quarterly check-in', assignee: 'Mike Chen', associatedWith: 'Jane Smith', associationType: 'contact', dueDate: '2024-02-20', priority: 'low', status: 'pending' }, ]; const useDebounce = (value: T, delay: number): T => { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { const handler = setTimeout(() => setDebouncedValue(value), delay); return () => clearTimeout(handler); }, [value, delay]); return debouncedValue; }; interface Toast { id: number; message: string; type: 'success' | 'error' | 'info'; } const useToast = () => { const [toasts, setToasts] = useState([]); const addToast = useCallback((message: string, type: Toast['type'] = 'info') => { const id = Date.now(); setToasts(prev => [...prev, { id, message, type }]); setTimeout(() => setToasts(prev => prev.filter(t => t.id !== id)), 3000); }, []); return { toasts, addToast }; }; const App = () => { const [searchTerm, setSearchTerm] = useState(''); const [selectedTask, setSelectedTask] = useState(null); const [isPending, startTransition] = useTransition(); const { toasts, addToast } = useToast(); const debouncedSearch = useDebounce(searchTerm, 300); const filteredTasks = useMemo(() => { if (!debouncedSearch) return mockTasks; const term = debouncedSearch.toLowerCase(); return mockTasks.filter(t => t.title.toLowerCase().includes(term) || t.assignee.toLowerCase().includes(term) || t.associatedWith.toLowerCase().includes(term) ); }, [debouncedSearch]); const stats = useMemo(() => ({ total: mockTasks.length, pending: mockTasks.filter(t => t.status === 'pending').length, inProgress: mockTasks.filter(t => t.status === 'in-progress').length, high: mockTasks.filter(t => t.priority === 'high').length, }), []); const handleSearch = (e: React.ChangeEvent) => { startTransition(() => { setSearchTerm(e.target.value); }); }; const handleSelectTask = (task: Task) => { setSelectedTask(task); addToast(`Viewing task: ${task.title}`, 'info'); }; return (

Task Manager

Tasks across deals/contacts, due dates, assignments

Total Tasks
{stats.total}
Pending
{stats.pending}
In Progress
{stats.inProgress}
High Priority
{stats.high}
{isPending && Searching...}
{filteredTasks.length === 0 ? (

No tasks found

Try adjusting your search criteria

) : (
{filteredTasks.map(task => ( handleSelectTask(task)} className={selectedTask?.id === task.id ? 'selected' : ''} > ))}
Title Assignee Associated With Type Due Date Priority Status
{task.title} {task.assignee} {task.associatedWith} {task.associationType} {task.dueDate} {task.priority} {task.status}
)} {selectedTask && (

Task Details

Title: {selectedTask.title}
Assignee: {selectedTask.assignee}
Associated With: {selectedTask.associatedWith}
Type: {selectedTask.associationType}
Due Date: {selectedTask.dueDate}
Priority: {selectedTask.priority}
Status: {selectedTask.status}
)}
{toasts.map(toast => (
{toast.message}
))}
); }; export default App;