Project: Task Management Dashboard
Overview
Build a complete task management application with projects, tasks, filtering, and local storage persistence.
Learning Objectives
- Apply all fundamental React concepts
- Component composition and reusability
- Form handling and validation
- List rendering and keys
- State management
- Local storage integration
- Conditional rendering
- Event handling
Project Requirements
Core Features
1. Project Management
- Create, edit, delete projects
- Each project has: name, color, description
- Default "Inbox" project (cannot be deleted)
- Active project selection
2. Task Management
- Create, edit, delete tasks
- Task properties:
- Title (required)
- Description (optional)
- Due date
- Priority (low, medium, high)
- Status (todo, in-progress, done)
- Project assignment
- Drag to reorder tasks (bonus)
3. Filtering & Sorting
- Filter by project
- Filter by status
- Filter by priority
- Search tasks by title/description
- Sort by: due date, priority, creation date, alphabetically
4. Views
- Today: Tasks due today
- Upcoming: Tasks due in next 7 days
- All tasks
- Completed tasks
- Project-specific view
5. Data Persistence
- Save to localStorage
- Load on app start
- Auto-save on changes
Bonus Features
- Task tags/labels
- Task notes/comments
- Recurring tasks
- Task time tracking
- Statistics dashboard
- Dark mode toggle
- Export/import data
- Keyboard shortcuts
- Mobile responsive design
Technical Requirements
Tech Stack
- React 18+ with TypeScript
- Vite for build tooling
- CSS Modules or Styled Components
- Date handling: date-fns or dayjs
- Icons: react-icons or heroicons
Project Structure
task-manager/
├── src/
│ ├── components/
│ │ ├── Layout/
│ │ │ ├── Header.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ └── MainContent.tsx
│ │ ├── Project/
│ │ │ ├── ProjectList.tsx
│ │ │ ├── ProjectItem.tsx
│ │ │ └── ProjectForm.tsx
│ │ ├── Task/
│ │ │ ├── TaskList.tsx
│ │ │ ├── TaskItem.tsx
│ │ │ ├── TaskForm.tsx
│ │ │ └── TaskDetail.tsx
│ │ ├── Filters/
│ │ │ ├── SearchBar.tsx
│ │ │ ├── FilterPanel.tsx
│ │ │ └── SortDropdown.tsx
│ │ └── common/
│ │ ├── Button.tsx
│ │ ├── Modal.tsx
│ │ ├── Input.tsx
│ │ └── Select.tsx
│ ├── hooks/
│ │ ├── useLocalStorage.ts
│ │ ├── useTasks.ts
│ │ └── useProjects.ts
│ ├── types/
│ │ └── index.ts
│ ├── utils/
│ │ ├── localStorage.ts
│ │ ├── dateUtils.ts
│ │ └── taskFilters.ts
│ ├── App.tsx
│ ├── App.module.css
│ └── main.tsx
├── package.json
├── tsconfig.json
└── vite.config.ts
Data Models
TypeScript Interfaces
// types/index.ts
export type Priority = 'low' | 'medium' | 'high';
export type TaskStatus = 'todo' | 'in-progress' | 'done';
export interface Project {
id: string;
name: string;
color: string;
description?: string;
createdAt: Date;
isDefault?: boolean;
}
export interface Task {
id: string;
title: string;
description?: string;
projectId: string;
priority: Priority;
status: TaskStatus;
dueDate?: Date;
createdAt: Date;
completedAt?: Date;
tags?: string[];
}
export interface FilterState {
searchTerm: string;
projectId: string | null;
status: TaskStatus | null;
priority: Priority | null;
}
export type SortOption =
| 'dueDate-asc'
| 'dueDate-desc'
| 'priority-asc'
| 'priority-desc'
| 'createdAt-asc'
| 'createdAt-desc'
| 'title-asc'
| 'title-desc';
Implementation Guide
Step 1: Project Setup (30 min)
# Create Vite project
npm create vite@latest task-manager -- --template react-ts
cd task-manager
npm install
# Install dependencies
npm install date-fns react-icons
# Start dev server
npm run dev
Step 2: Basic Layout (1 hour)
Create the app shell:
- Header with app title and actions
- Sidebar for project navigation
- Main content area for tasks
Step 3: Project Management (2 hours)
- Create project list in sidebar
- Add project form (modal or inline)
- Edit/delete project functionality
- Project selection
Step 4: Task Management (3 hours)
- Task list component
- Task item component with all fields
- Add/edit task form
- Delete task with confirmation
- Mark task as complete
Step 5: Filtering & Sorting (2 hours)
- Search bar for tasks
- Filter panel (status, priority, project)
- Sort dropdown
- Implement filter/sort logic with useMemo
Step 6: Special Views (1 hour)
- Today view
- Upcoming view
- Completed view
- All tasks view
Step 7: Local Storage (1 hour)
- Custom useLocalStorage hook
- Save projects and tasks
- Load on mount
- Auto-save on changes
Step 8: Styling & Polish (2 hours)
- Make it beautiful
- Add transitions/animations
- Responsive design
- Dark mode (bonus)
Sample Code
useLocalStorage Hook
import { useState, useEffect } from 'react';
export function useLocalStorage\<T\>(key: string, initialValue: T) {
const [value, setValue] = useState\<T\>(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
console.error(error);
return initialValue;
}
});
useEffect(() => {
try {
window.localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error(error);
}
}, [key, value]);
return [value, setValue] as const;
}
Task Filtering Logic
export function filterTasks(tasks: Task[], filters: FilterState): Task[] {
return tasks.filter(task => {
// Search term
if (filters.searchTerm) {
const term = filters.searchTerm.toLowerCase();
if (
!task.title.toLowerCase().includes(term) &&
!task.description?.toLowerCase().includes(term)
) {
return false;
}
}
// Project filter
if (filters.projectId && task.projectId !== filters.projectId) {
return false;
}
// Status filter
if (filters.status && task.status !== filters.status) {
return false;
}
// Priority filter
if (filters.priority && task.priority !== filters.priority) {
return false;
}
return true;
});
}
export function sortTasks(tasks: Task[], sortBy: SortOption): Task[] {
const sorted = [...tasks];
switch (sortBy) {
case 'dueDate-asc':
return sorted.sort(
(a, b) => (a.dueDate?.getTime() || 0) - (b.dueDate?.getTime() || 0)
);
case 'priority-asc':
const priorityMap = { low: 0, medium: 1, high: 2 };
return sorted.sort(
(a, b) => priorityMap[a.priority] - priorityMap[b.priority]
);
// Add more sort cases...
default:
return sorted;
}
}
Task Form Component
interface TaskFormProps {
task?: Task;
projectId?: string;
onSave: (task: Omit<Task, 'id' | 'createdAt'>) => void;
onCancel: () => void;
}
export function TaskForm({ task, projectId, onSave, onCancel }: TaskFormProps) {
const [title, setTitle] = useState(task?.title || '');
const [description, setDescription] = useState(task?.description || '');
const [priority, setPriority] = useState<Priority>(
task?.priority || 'medium'
);
const [dueDate, setDueDate] = useState(task?.dueDate || '');
const [selectedProject, setSelectedProject] = useState(
task?.projectId || projectId || ''
);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!title.trim()) {
alert('Title is required');
return;
}
onSave({
title: title.trim(),
description: description.trim(),
projectId: selectedProject,
priority,
status: task?.status || 'todo',
dueDate: dueDate ? new Date(dueDate) : undefined,
});
};
return <form onSubmit={handleSubmit}>{/* Form fields... */}</form>;
}
Evaluation Criteria
Functionality (40%)
- All core features work correctly
- No bugs or errors
- Smooth user experience
- Data persists correctly
Code Quality (30%)
- Clean, readable code
- Proper component structure
- Reusable components
- Appropriate use of hooks
- TypeScript types used correctly
UI/UX (20%)
- Intuitive interface
- Good visual design
- Responsive layout
- Loading states
- Error handling
Best Practices (10%)
- Proper key usage in lists
- Optimized re-renders
- Accessibility considerations
- Performance optimizations
Submission
Create a GitHub repository with:
- Complete source code
- README with setup instructions
- Screenshots or demo GIF
- List of implemented features
- Known issues (if any)
Time Estimate
12-15 hours over 3-5 days
Resources
Next Steps
After completing this project:
- Get code review from peers or mentor
- Deploy to Netlify/Vercel
- Add additional features from bonus list
- Move to Module 02: Hooks & State