A todo application built to practice OOP fundamentals in a frontend context.
npm install
npm run devOpen the URL from the terminal (usually http://localhost:5173).
| Command | Description |
|---|---|
npm run dev |
Start dev server |
npm run build |
Typecheck + production build |
npm run preview |
Preview production build |
npm run lint |
Run Oxlint |
- Create todos (
standard,work, orlearning) with title, description, and priority - List todos with kind, status, priority, and kind-specific fields (assignee/project or topic)
- Update status:
todo,in_progress,done,blocked - Set priority:
low,medium,high - Filter by status and priority
- Persist in
localStorage; first visit seeds frompublic/todos.json
This project maps OOP principles onto TypeScript modules and types.
- Encapsulation — hide internals behind a small public API. The service owns
nextIdand defaultstatus/completed. Repositories own thelocalStoragekey, JSON parsing, andfetch('/todos.json'). UI callsgetTodos/createTodo/filterTodosBy/updateTodoand does not talk to storage directly. - Inheritance — specialized todos reuse a shared base.
StandardTodo,WorkTodo, andLearningTodoareBaseTodoplus akindand extra fields (assignee/project,topic). - Polymorphism — callers treat every item as
Todo. Kind-specific fields are only read after narrowing onkind. Both repositories exposefetchTodos();getTodosreadslocalStoragefirst and falls back to the JSON file.
Folders follow business domains, not file types. Code that changes together stays in one feature, so a domain can grow or be tested without pulling in the rest of the app.
A feature is a business entity. Today that is todo. Everything else is reusable or shell:
| Folder | Role |
|---|---|
todo |
Domain: types, UI, service, storage |
shared |
Reusable UI with no todo knowledge (Button, Modal) |
core |
App shell on every page (Header, Footer) |
UI (components) → App.tsx → service → repository → storage
| Layer | Where | Responsibility |
|---|---|---|
| UI | todo/components, shared |
Render and collect user input. Call handlers from App. No storage. |
| App | App.tsx |
Own React state (todos, filter, visibleTodos). Call the service. Pass data and handlers down. |
| Service | todo/services |
Business rules: create (ids, defaults), filter, update. Talks to repositories only. |
| Repository | todo/repositories |
Persist and load: localStorage and seed todos.json. Hide keys, JSON, and fetch. |
| Types | todo/types |
Shared shapes (Todo, TodoFilter, …) used across layers. |
src/
App.tsx state + wiring (calls the todo service)
features/
core/ Header, Footer
shared/ Button, Modal
todo/
components/ list, item, filters, create form
types/ Todo, status, priority, create input
services/ create, filter, load, update
repositories/ localStorage, JSON file
const/ status and priority lists
public/
todos.json seed data for first load
- React 19
- TypeScript
- Vite
- Tailwind CSS