A modern task management system built with Next.js 13, featuring a drag-and-drop Kanban board interface, dark mode, and real-time status updates.
- 📋 Drag-and-drop Kanban board
- 🌓 Dark/Light mode toggle
- 🔍 Search and filter tasks
- 🏷️ Priority levels (Low, Medium, High)
- 📅 Due date tracking
- 🔄 Real-time status updates
- 📱 Responsive design
- 🎯 Task categorization
- ⚡ Server-side rendering
- 🔄 Optimistic updates
- Framework: Next.js 13 (App Router)
- Database: PostgreSQL
- ORM: Prisma
- Styling: Tailwind CSS
- State Management: React Hooks
- Drag and Drop: dnd-kit
- Icons: Lucide React
- Date Handling: date-fns
- Notifications: react-toastify
- Node.js 16.8 or later
- PostgreSQL database
- npm or yarn
task-management/
├── prisma/
│ ├── schema.prisma
│ └── migrations/
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ └── tasks/
│ │ │ └── route.ts
│ │ ├── page.tsx
│ │ └── layout.tsx
│ ├── components/
│ │ └── ui/
│ └── lib/
│ └── prisma.ts
├── public/
└── package.json
model Task {
id String @id @default(cuid())
title String
description String?
status Status @default(PENDING)
priority Priority @default(MEDIUM)
dueDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum Status {
PENDING
IN_PROGRESS
COMPLETED
}
enum Priority {
LOW
MEDIUM
HIGH
}
GET /api/tasks
- Fetch all tasksPOST /api/tasks
- Create new taskPATCH /api/tasks
- Update task statusDELETE /api/tasks
- Delete task
The Kanban board uses @dnd-kit/core
and @dnd-kit/sortable
for smooth drag-and-drop functionality between columns:
<DndContext
sensors={sensors}
collisionDetection={closestCorners}
onDragStart={handleDragStart}
onDragEnd={handleDragEnd}
>
{/* Columns and Tasks */}
</DndContext>
Implemented using React state and Tailwind CSS classes:
const [darkMode, setDarkMode] = useState(false);
// Usage in className
`${darkMode ? 'bg-gray-900' : 'bg-gray-50'}`
Real-time filtering based on search terms and priority:
const filteredTasks = tasks.filter(task =>
task.title.toLowerCase().includes(searchTerm.toLowerCase()) &&
(priorityFilter === 'ALL' || task.priority === priorityFilter)
);