Bỏ qua đến nội dung

Usecase: Xây App Todo Nâng Cao Từ Đầu

Một người mới bắt đầu với Superpowers có thể xây dựng một ứng dụng Todo hoàn chỉnh -- từ brainstorm đến chạy thử -- chỉ trong một phiên làm việc duy nhất. Đây là usecase nhập môn lý tưởng để trải nghiệm toàn bộ quy trình.


Bối Cảnh

Bạn muốn xây một ứng dụng Todo làm prototype/demo -- đủ ấn tượng để trình bày, nhưng xây bằng quy trình Superpowers từ đầu đến cuối.

Yêu cầu:

  • CRUD: Thêm, sửa, xóa, đánh dấu hoàn thành
  • Lọc/tìm kiếm theo trạng thái, priority, category
  • Phân loại (Work / Personal / Study) và mức ưu tiên (High / Medium / Low)
  • Drag & drop sắp xếp thứ tự
  • Due date cho từng todo
  • Dark mode (toggle + theo system preference)
  • Dữ liệu lưu trên localStorage (không cần backend)

Tech stack:

  • Vite + React 18 + TypeScript
  • shadcn/ui + Tailwind CSS
  • @dnd-kit (drag & drop)
  • date-fns (xử lý ngày tháng)
  • Vitest + React Testing Library

Bạn Sẽ Học Được Gì

Trong bài hướng dẫn này, bạn sẽ áp dụng bốn kỹ năng cốt lõi của Superpowers:

  1. Brainstorming & Design -- Khám phá yêu cầu qua Q&A, so sánh approach, chọn layout với visual companion
  2. Writing Plans -- Chia nhỏ thành 11 task có verification rõ ràng
  3. TDD -- Viết test trước cho hook và component
  4. Debugging & Verification -- Xử lý lỗi tương thích thực tế và xác minh mọi thứ hoạt động

Mục tiêu cuối cùng: một ứng dụng Todo hoạt động hoàn chỉnh với 12 test case pass, build production thành công, được xây dựng theo quy trình có kỷ luật.


Từng Bước Thực Hành

Bước 1: Brainstorm Thiết Kế Todo App

Bạn mở chat với AI và nói:

"Tôi muốn xây một ứng dụng Todo đơn giản bằng React + TypeScript. Hãy brainstorm trước khi viết code."

AI vào chế độ brainstorm, bật visual companion (hiện mockup trên trình duyệt), và bắt đầu hỏi từng câu:

Câu hỏi 1: "Mục đích chính của ứng dụng Todo này là gì?"

  • A) Dự án học tập/portfolio
  • B) Ứng dụng cá nhân dùng hàng ngày
  • C) Prototype/demo để trình bày

Bạn chọn: C) Prototype/demo -- cần ấn tượng khi trình bày.

Câu hỏi 2: "Ứng dụng cần những tính năng nào?"

  • A) Cơ bản -- Thêm, sửa, xóa, đánh dấu hoàn thành
  • B) Trung bình -- Như A + lọc/tìm kiếm, categories, priority
  • C) Nâng cao -- Như B + drag & drop, due date, dark mode, localStorage persist

Bạn chọn: C) Nâng cao -- đầy đủ tính năng cho demo.

Câu hỏi 3: "Dữ liệu lưu trữ ở đâu?"

  • A) LocalStorage only
  • B) Mock API (json-server hoặc MSW)
  • C) Real backend (Firebase/Supabase)

Bạn chọn: A) LocalStorage -- đơn giản, không cần backend.

Câu hỏi 4: "UI/styling dùng approach nào?"

  • A) Tailwind CSS
  • B) shadcn/ui + Tailwind
  • C) CSS Modules / Styled Components
  • D) Ant Design / MUI

Bạn chọn: B) shadcn/ui + Tailwind -- component đẹp, chuyên nghiệp, dễ customize.

Câu hỏi 5: "Tooling/build dùng gì?"

  • A) Vite
  • B) Next.js
  • C) Create React App

Bạn chọn: A) Vite -- nhanh, nhẹ, phổ biến nhất.

Sau khi thu thập đủ thông tin, AI trình bày 3 cách tiếp cận:

## Approach A: Single Page — All-in-One (Khuyên dùng)
Toàn bộ app nằm trong 1 trang. Sidebar chứa filter/categories, main area chứa todo list.
- Pros: Đơn giản, không cần routing, UX mượt
- Cons: Mọi thứ dồn vào 1 view

## Approach B: Multi-Page với React Router
Chia thành nhiều trang: Dashboard, Todo List, Settings.
- Pros: Cấu trúc rõ ràng, dễ mở rộng
- Cons: Overkill cho todo app, thêm dependency

## Approach C: Kanban Board Style
Todo hiển thị dạng cột (To Do / In Progress / Done), drag & drop giữa các cột.
- Pros: Visual ấn tượng khi demo
- Cons: Phức tạp hơn nhiều, khó filter/sort

Bạn ban đầu chọn Kanban (C), nhưng sau khi xem mockup trên visual companion, bạn đổi ý sang Approach A: Single Page -- cân bằng tốt nhất giữa tính năng và độ phức tạp.

AI tiếp tục hỏi về layout:

  • A) Sidebar + Main Content (giống Todoist)
  • B) Top Filter Bar + Centered List (minimalist)

Bạn chọn: B) Top Filter Bar + Centered List -- gọn gàng và minimalist.

AI viết design spec chi tiết gồm 3 section:

DESIGN SPEC: Todo App

=== Section 1: Architecture & Data Model ===

Data Model:
  interface Todo {
    id: string
    title: string
    completed: boolean
    priority: 'high' | 'medium' | 'low'
    category: 'Work' | 'Personal' | 'Study'
    dueDate: string | null
    order: number
    createdAt: string
  }

State Management:
  - useReducer cho todo state (add, edit, delete, toggle, reorder)
  - Custom hook useTodos() — xử lý logic + localStorage sync
  - Custom hook useTheme() — dark/light mode toggle

Component Structure:
  App
  ├── Header (title, stats, dark mode toggle)
  ├── FilterBar (status pills, priority pills, category pills, search)
  ├── TodoInput (add new todo form — expand khi click)
  ├── TodoList (DnD container)
  │   └── TodoItem[] (checkbox, title, priority badge, category, due date, actions)
  └── EditTodoDialog (shadcn dialog)

=== Section 2: UI Components & Interactions ===

FilterBar:
  - Pill buttons nằm ngang: Status (All|Active|Done) | Priority | Category
  - Kết hợp bằng AND (Active + High + Work → chỉ hiện todo thỏa tất cả)
  - Search input bên phải

TodoItem:
  - Checkbox | Title | Priority badge (màu) | Category tag | Due date | Menu (⋮)
  - Hover → hiện drag handle bên trái
  - Completed → mờ + gạch ngang
  - Overdue → due date hiện màu đỏ

Drag & Drop:
  - @dnd-kit/sortable để kéo thả sắp xếp
  - Khi drag trong filtered view, chỉ cập nhật order tương đối;
    các item bị ẩn bởi filter giữ nguyên order

=== Section 3: Dark Mode & Persistence ===

Dark Mode: Tailwind dark: class + system preference mặc định
localStorage: Debounce 300ms khi write, fallback mảng rỗng nếu invalid data
Testing: Vitest + RTL cho useTodos hook, TodoInput, TodoItem

AI dispatch spec reviewer để kiểm tra chất lượng spec. Reviewer approve với 3 recommendations nhỏ (đã được cập nhật vào spec).

Bạn phê duyệt. Chuyển sang giai đoạn tiếp theo.

Lưu ý Superpowers: Design spec được lưu vào docs/superpowers/specs/, spec reviewer tự động kiểm tra trước khi chuyển sang viết plan. Xem thêm Brainstorming.


Bước 2: Superpowers Viết Plan Chi Tiết

Dựa trên design spec, AI chia công việc thành 11 task (nhiều hơn đáng kể so với app đơn giản):

## Plan: Todo App

### Task 1: Project Scaffold
- Vite + React + TS, Tailwind, shadcn/ui, @dnd-kit, date-fns
- Vitest + React Testing Library
- Verification: npm run build thành công

### Task 2: Types & Storage Utilities
- src/types/todo.ts — interface Todo, Filters, constants
- src/lib/storage.ts — localStorage helpers
- Verification: TypeScript compile OK

### Task 3: useTodos Hook (TDD)
- Test trước: src/hooks/use-todos.test.ts
- Code: src/hooks/use-todos.ts
- Verification: 6/6 tests pass

### Task 4: Filter Logic & useTheme Hook
- src/lib/filters.ts — applyFilters() function
- src/hooks/use-theme.ts — dark mode toggle

### Task 5: Header & FilterBar Components
- src/components/header.tsx
- src/components/filter-bar.tsx

### Task 6: TodoInput Component (TDD)
- Test trước: src/components/todo-input.test.tsx
- Code: src/components/todo-input.tsx
- Verification: 3/3 tests pass

### Task 7: TodoItem Component (TDD)
- Test trước: src/components/todo-item.test.tsx (với DndContext wrapper)
- Code: src/components/todo-item.tsx
- Verification: 3/3 tests pass

### Task 8: TodoList + Drag & Drop
- src/components/todo-list.tsx

### Task 9: EditTodoDialog
- src/components/edit-todo-dialog.tsx

### Task 10: Assemble App + Toast
- Kết nối tất cả components vào App.tsx
- Verification: npm run build thành công

### Task 11: Final Polish & All Tests
- Verification: 12/12 tests pass, tsc --noEmit OK, build OK

AI dispatch plan reviewer kiểm tra. Reviewer phát hiện 2 vấn đề:

  1. TodoItem test thiếu DndContext wrapper -- useSortable cần DndContext provider, test sẽ fail
  2. Sonner chưa được cài ở Task 1 -- sẽ gây lỗi ở Task 10

AI fix cả 2 trước khi bắt đầu implement.

Lưu ý Superpowers: Plan được lưu vào docs/superpowers/plans/ và review tự động trước khi thực thi. Xem thêm Writing Plans.

Bạn xác nhận: "OK, bắt đầu implement."


Bước 3: Implement Theo Plan (TDD: RED → GREEN → REFACTOR)

AI thực thi từng task theo plan. Các task có test đều tuân theo chu kỳ TDD.

Task 1: Project Scaffold

Scaffold Vite + React + TS, cài đặt tất cả dependencies. Gặp vấn đề thực tế:

  • Vite 8 chưa tương thích với @tailwindcss/vite → dùng --legacy-peer-deps
  • shadcn/ui init fail do thiếu import alias → cấu hình @/ alias trong tsconfig + vite.config
  • Vite 8 conflict với shadcn → downgrade về Vite 7

Bài học thực tế: Scaffold không phải lúc nào cũng suôn sẻ. Compatibility issues giữa các library là chuyện thường. Quan trọng là biết cách debug và workaround.

Task 2: Types & Storage Utilities

FileMô tả
src/types/todo.tsInterface Todo, Filters, type aliases, constants (PRIORITIES, CATEGORIES)
src/lib/storage.tsloadTodos(), saveTodos(), loadTheme(), saveTheme() với error handling

Task 3: useTodos Hook (TDD)

FileMô tả
Testsrc/hooks/use-todos.test.ts6 test cases: starts empty, add todo, toggle todo, delete todo, edit todo, reorder todos
Codesrc/hooks/use-todos.tsuseReducer + localStorage sync, expose: addTodo, toggleTodo, deleteTodo, editTodo, reorderTodos

RED → npx vitest run → FAIL (file chưa tồn tại) → GREEN → Implement hook → 6/6 PASS

Task 4: Filter Logic & useTheme

FileMô tả
src/lib/filters.tsapplyFilters() -- filter kết hợp AND cho status, priority, category, search
src/hooks/use-theme.tsToggle dark/light, sync với localStorage + system preference

Task 5: Header & FilterBar

FileMô tả
src/components/header.tsxTên app, stats counter, dark mode toggle (Sun/Moon icon)
src/components/filter-bar.tsxPill buttons cho status/priority/category + search input

Task 6: TodoInput (TDD)

FileMô tả
Testsrc/components/todo-input.test.tsx3 test cases: render placeholder, call onAdd on submit, clear input after submit
Codesrc/components/todo-input.tsxInput expand thành form: title, priority dropdown, category dropdown, date picker

RED → FAIL → GREEN → 3/3 PASS

Task 7: TodoItem (TDD)

FileMô tả
Testsrc/components/todo-item.test.tsx3 test cases: render title + priority, toggle checkbox, line-through khi completed. Lưu ý: Test cần DndContext + SortableContext wrapper
Codesrc/components/todo-item.tsxSortable item với drag handle, checkbox, priority badge, category tag, due date, dropdown menu

RED → FAIL → GREEN → 3/3 PASS

Task 8-9: TodoList + EditTodoDialog

FileMô tả
src/components/todo-list.tsxDnD container với @dnd-kit/core + @dnd-kit/sortable, empty state
src/components/edit-todo-dialog.tsxshadcn Dialog với form chỉnh sửa: title, priority, category, date picker

Task 10: Assemble App

Kết nối tất cả vào App.tsx: useTodos + useTheme + applyFilters + Toaster. Build production thành công.

Task 11: Final Polish

Chạy tsc --noEmit pass OK, nhưng npm run build phát hiện lỗi TypeScript với asChild prop -- shadcn v2 dùng base-ui thay vì radix, cần đổi sang render prop. Fix xong → build OK, 12/12 tests pass.

Quy trình TDD ở mỗi task: AI viết test trước → chạy test xác nhận FAIL → implement code tối thiểu → chạy test xác nhận PASS → refactor nếu cần → commit. Xem thêm TDD.


Bước 4: Verification -- Xác Minh Toàn Bộ

Tất cả 11 task đã hoàn thành. Chạy verification cuối cùng.

Chạy toàn bộ test suite

npx vitest run
✓ src/hooks/use-todos.test.ts (6 tests)
  ✓ useTodos > starts with empty todos
  ✓ useTodos > adds a todo
  ✓ useTodos > toggles a todo
  ✓ useTodos > deletes a todo
  ✓ useTodos > edits a todo
  ✓ useTodos > reorders todos

✓ src/components/todo-input.test.tsx (3 tests)
  ✓ TodoInput > renders placeholder input
  ✓ TodoInput > calls onAdd with todo data on submit
  ✓ TodoInput > clears input after submit

✓ src/components/todo-item.test.tsx (3 tests)
  ✓ TodoItem > renders todo title and priority
  ✓ TodoItem > calls onToggle when checkbox clicked
  ✓ TodoItem > shows line-through when completed

Test Files  3 passed (3)
     Tests  12 passed (12)

Type check & Build

npx tsc --noEmit    # No errors
npm run build       # Build thành công

Tuyên bố

Todo App hoàn chỉnh. 12/12 test pass. Build production OK. No TypeScript errors. 10 commits sạch sẽ theo từng feature.


Kết Quả

Sau khi hoàn thành toàn bộ quy trình, bạn có:

Tính năng hoàn chỉnh:

  • CRUD todos (thêm, sửa, xóa, toggle hoàn thành)
  • Filter kết hợp AND theo status, priority, category + search
  • Drag & drop sắp xếp thứ tự
  • Due date với cảnh báo overdue (màu đỏ)
  • Dark mode (toggle + theo system preference)
  • localStorage persist (debounce 300ms)
  • Responsive, minimalist UI với shadcn/ui
  • Hiển thị stats (tổng task, active, done)

12 test cases pass 100% bao phủ:

  • Custom hook useTodos: add, toggle, delete, edit, reorder, empty state
  • Component TodoInput: render, submit, clear
  • Component TodoItem: render, toggle, completed style

Cấu trúc file:

src/
  App.tsx
  index.css
  test-setup.ts
  types/
    todo.ts
  lib/
    storage.ts
    filters.ts
    utils.ts
  hooks/
    use-todos.ts
    use-todos.test.ts
    use-theme.ts
  components/
    header.tsx
    filter-bar.tsx
    todo-input.tsx
    todo-input.test.tsx
    todo-item.tsx
    todo-item.test.tsx
    todo-list.tsx
    edit-todo-dialog.tsx
    ui/  (shadcn components)

Vấn Đề Thực Tế Gặp Phải

Không giống các tutorial lý tưởng, session thực tế gặp nhiều vấn đề cần xử lý:

1. Vite 8 chưa tương thích với Tailwind plugin

@tailwindcss/vite chưa support Vite 8 → dùng --legacy-peer-deps để cài, sau đó downgrade về Vite 7 khi shadcn cũng conflict.

2. shadcn/ui init fail do thiếu import alias

shadcn yêu cầu @/ import alias → phải cấu hình baseUrl + paths trong tsconfig và resolve.alias trong vite.config.

3. shadcn v2 dùng base-ui thay vì radix

Prop asChild không còn hoạt động → phải đổi sang render prop cho PopoverTrigger và DropdownMenuTrigger. Lỗi này chỉ xuất hiện khi chạy npm run build (vite build có type check riêng), tsc --noEmit lại pass OK, và dev mode cũng không báo.

4. TodoItem test cần DnD wrapper

useSortable hook yêu cầu DndContext + SortableContext provider. Test sẽ crash nếu không wrap. Plan reviewer đã phát hiện và fix trước khi implement.

Bài học: Đây là lý do verification quan trọng. Nhiều lỗi chỉ xuất hiện khi build production hoặc chạy type check nghiêm ngặt, không thấy trong dev mode.


Key Takeaways

1. Brainstorm giúp bạn đổi ý đúng lúc

Bạn ban đầu chọn Kanban Board, nhưng khi xem mockup trên visual companion, bạn nhận ra Single Page phù hợp hơn. Thay đổi ở giai đoạn brainstorm tốn 0 dòng code. Thay đổi sau khi implement tốn hàng giờ refactor.

2. Plan reviewer bắt bug trước khi code

Reviewer phát hiện 2 vấn đề trong plan (thiếu DndContext wrapper trong test, thiếu sonner dependency). Nếu không review, các bug này sẽ xuất hiện giữa chừng implement và làm mất thời gian debug.

3. Compatibility issues là chuyện thường

3 trong 11 task gặp vấn đề tương thích (Vite 8, shadcn alias, asChild prop). Đây không phải bug của bạn -- đây là thực tế của hệ sinh thái JavaScript. Quy trình giúp bạn phát hiện và fix nhanh thay vì lúng túng.

4. useReducer + Custom Hook + TDD là combo mạnh

useTodos hook đóng gói toàn bộ logic (CRUD, reorder, localStorage sync) và có 6 test cases bảo vệ. Khi UI phức tạp (drag & drop, filter, edit dialog), logic vẫn ổn định vì đã được test độc lập.

5. 11 task nhưng mỗi task nhỏ và rõ ràng

"Xây Todo app nâng cao" nghe đáng sợ. Nhưng khi chia thành 11 task, mỗi task chỉ tạo 1-2 file và có verification riêng. Bạn không bao giờ phải giữ toàn bộ app trong đầu -- chỉ cần tập trung vào task hiện tại.

6. Đây là bước đệm cho project thực tế

Todo app "nâng cao" này đã bao gồm: custom hooks, drag & drop, dark mode, shadcn/ui, localStorage persistence, TDD, automated review. Đây là những pattern bạn sẽ dùng lại trong mọi project React.


Thực tế không hoàn hảo như tutorial. Bạn sẽ gặp compatibility issues, library changes, và unexpected errors. Quy trình Superpowers không loại bỏ những vấn đề này -- nó giúp bạn phát hiện sớm và xử lý có hệ thống thay vì loay hoay không biết bắt đầu từ đâu.