Skip to content

Commit a69675e

Browse files
authored
Merge pull request #1 from Chris0Jeky/claude/create-feature-f-01QrRAsJ4S14advmNnQhp2La
Claude/create feature f 01 qr r as j4 s14advm nn qhp2 la
2 parents 2aa113b + 652e723 commit a69675e

File tree

114 files changed

+9899
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+9899
-1
lines changed

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Backend
2+
backend/src/*/bin/
3+
backend/src/*/obj/
4+
backend/tests/*/bin/
5+
backend/tests/*/obj/
6+
*.db
7+
*.db-shm
8+
*.db-wal
9+
10+
# Frontend
11+
frontend/*/node_modules/
12+
frontend/*/dist/
13+
frontend/*/.env.local
14+
frontend/*/.env.*.local
15+
16+
# IDEs
17+
.vs/
18+
.vscode/
19+
.idea/
20+
*.swp
21+
*.swo
22+
*~
23+
24+
# OS
25+
.DS_Store
26+
Thumbs.db

README.md

Lines changed: 272 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,273 @@
11
# Taskdeck
2-
Personal Kanban and to-do system for developers – keyboard-friendly, offline-first, and extensible.
2+
3+
**Taskdeck** is a personal Kanban and to-do manager designed for developers, featuring a keyboard-friendly interface, offline-first architecture, and clean design principles.
4+
5+
## 🎯 Features
6+
7+
- **Kanban Boards**: Visual management with boards → columns → cards
8+
- **WIP Limits**: Enforce work-in-progress limits per column to maintain focus
9+
- **Labels & Due Dates**: Organize cards with color-coded labels and track deadlines
10+
- **Blocked Cards**: Mark cards as blocked with reasons to track impediments
11+
- **Clean Architecture**: Backend built with Domain-Driven Design principles
12+
- **Modern Stack**: Vue 3 + TypeScript frontend, .NET 8 + EF Core backend
13+
- **Offline-First**: Local SQLite database, no cloud dependency required
14+
15+
## 📋 Tech Stack
16+
17+
### Backend
18+
- **.NET 8** - Modern C# runtime
19+
- **ASP.NET Core** - Web API framework
20+
- **Entity Framework Core** - ORM with SQLite
21+
- **Clean Architecture** - Domain, Application, Infrastructure, API layers
22+
- **xUnit + FluentAssertions** - Testing framework
23+
24+
### Frontend
25+
- **Vue 3** - Progressive JavaScript framework
26+
- **Vite** - Fast build tool
27+
- **TypeScript** - Type-safe JavaScript
28+
- **Pinia** - State management
29+
- **Vue Router** - Client-side routing
30+
- **TailwindCSS** - Utility-first CSS framework
31+
- **Axios** - HTTP client
32+
33+
## 🚀 Getting Started
34+
35+
### Prerequisites
36+
37+
- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)
38+
- [Node.js 20+](https://nodejs.org/) and npm
39+
40+
### Backend Setup
41+
42+
1. Navigate to the backend directory:
43+
```bash
44+
cd backend
45+
```
46+
47+
2. Restore dependencies:
48+
```bash
49+
dotnet restore
50+
```
51+
52+
3. Create the database and run migrations:
53+
```bash
54+
dotnet ef database update -p src/Taskdeck.Infrastructure/Taskdeck.Infrastructure.csproj -s src/Taskdeck.Api/Taskdeck.Api.csproj
55+
```
56+
57+
4. Run the API:
58+
```bash
59+
dotnet run --project src/Taskdeck.Api/Taskdeck.Api.csproj
60+
```
61+
62+
The API will be available at `http://localhost:5000` (or the port specified in your configuration).
63+
64+
### Frontend Setup
65+
66+
1. Navigate to the frontend directory:
67+
```bash
68+
cd frontend/taskdeck-web
69+
```
70+
71+
2. Install dependencies:
72+
```bash
73+
npm install
74+
```
75+
76+
3. Start the development server:
77+
```bash
78+
npm run dev
79+
```
80+
81+
The frontend will be available at `http://localhost:5173`.
82+
83+
## 🧪 Running Tests
84+
85+
### Backend Tests
86+
87+
Run domain and application tests:
88+
```bash
89+
cd backend
90+
dotnet test
91+
```
92+
93+
Run tests with coverage:
94+
```bash
95+
dotnet test /p:CollectCoverage=true
96+
```
97+
98+
## 📐 Architecture
99+
100+
Taskdeck follows **Clean Architecture** principles with clear separation of concerns:
101+
102+
```
103+
backend/
104+
├── src/
105+
│ ├── Taskdeck.Domain/ # Domain entities and business rules
106+
│ │ ├── Entities/ # Board, Column, Card, Label
107+
│ │ ├── Common/ # Base entity, Result pattern
108+
│ │ └── Exceptions/ # Domain exceptions
109+
│ │
110+
│ ├── Taskdeck.Application/ # Use cases and business logic
111+
│ │ ├── Services/ # BoardService, ColumnService, etc.
112+
│ │ ├── DTOs/ # Data transfer objects
113+
│ │ └── Interfaces/ # Repository interfaces
114+
│ │
115+
│ ├── Taskdeck.Infrastructure/ # Data access and external concerns
116+
│ │ ├── Persistence/ # EF Core DbContext
117+
│ │ └── Repositories/ # Repository implementations
118+
│ │
119+
│ └── Taskdeck.Api/ # REST API layer
120+
│ └── Controllers/ # API endpoints
121+
122+
└── tests/
123+
├── Taskdeck.Domain.Tests/
124+
└── Taskdeck.Application.Tests/
125+
```
126+
127+
```
128+
frontend/
129+
└── taskdeck-web/
130+
└── src/
131+
├── api/ # HTTP client and API calls
132+
├── components/ # Vue components
133+
├── router/ # Vue Router configuration
134+
├── store/ # Pinia state management
135+
├── types/ # TypeScript type definitions
136+
└── views/ # Page-level components
137+
```
138+
139+
## 🎨 Domain Model
140+
141+
### Core Entities
142+
143+
**Board**
144+
- Name, description
145+
- Contains columns and cards
146+
- Archive functionality
147+
148+
**Column**
149+
- Name, position
150+
- Optional WIP limit
151+
- Belongs to a board
152+
153+
**Card**
154+
- Title, description
155+
- Due date (optional)
156+
- Position within column
157+
- Blocked status with reason
158+
- Multiple labels
159+
160+
**Label**
161+
- Name, color (hex)
162+
- Board-scoped
163+
- Many-to-many with cards
164+
165+
### Business Rules
166+
167+
1. **WIP Limit Enforcement**: Cards cannot be moved to a column that has reached its WIP limit
168+
2. **Position Management**: Cards and columns maintain ordered positions
169+
3. **Validation**: All entities enforce validation rules (e.g., non-empty names, valid hex colors)
170+
4. **Board Integrity**: Cards must belong to exactly one board and one column
171+
172+
## 🔌 API Endpoints
173+
174+
### Boards
175+
- `GET /api/boards` - List all boards
176+
- `GET /api/boards/{id}` - Get board with columns
177+
- `POST /api/boards` - Create a new board
178+
- `PUT /api/boards/{id}` - Update board
179+
- `DELETE /api/boards/{id}` - Archive board
180+
181+
### Columns
182+
- `GET /api/boards/{boardId}/columns` - List columns for a board
183+
- `POST /api/boards/{boardId}/columns` - Create a column
184+
- `PATCH /api/boards/{boardId}/columns/{columnId}` - Update column
185+
- `DELETE /api/boards/{boardId}/columns/{columnId}` - Delete column
186+
187+
### Cards
188+
- `GET /api/boards/{boardId}/cards` - List/search cards
189+
- `POST /api/boards/{boardId}/cards` - Create a card
190+
- `PATCH /api/boards/{boardId}/cards/{cardId}` - Update card
191+
- `POST /api/boards/{boardId}/cards/{cardId}/move` - Move card
192+
- `DELETE /api/boards/{boardId}/cards/{cardId}` - Delete card
193+
194+
### Labels
195+
- `GET /api/boards/{boardId}/labels` - List labels for a board
196+
- `POST /api/boards/{boardId}/labels` - Create a label
197+
- `PATCH /api/boards/{boardId}/labels/{labelId}` - Update label
198+
- `DELETE /api/boards/{boardId}/labels/{labelId}` - Delete label
199+
200+
API documentation is available via Swagger at `http://localhost:5000/swagger` when running in development mode.
201+
202+
## 🗂️ Database
203+
204+
Taskdeck uses **SQLite** for local, file-based storage. The database file (`taskdeck.db`) is created in the API project directory on first run.
205+
206+
### Running Migrations
207+
208+
Create a new migration after model changes:
209+
```bash
210+
dotnet ef migrations add MigrationName -p src/Taskdeck.Infrastructure/Taskdeck.Infrastructure.csproj -s src/Taskdeck.Api/Taskdeck.Api.csproj
211+
```
212+
213+
Apply migrations:
214+
```bash
215+
dotnet ef database update -p src/Taskdeck.Infrastructure/Taskdeck.Infrastructure.csproj -s src/Taskdeck.Api/Taskdeck.Api.csproj
216+
```
217+
218+
## 🛠️ Development
219+
220+
### Code Style
221+
222+
- **Backend**: Follow standard C# conventions, use `PascalCase` for public members, `camelCase` for private fields
223+
- **Frontend**: Use TypeScript strict mode, follow Vue 3 Composition API patterns
224+
225+
### Key Design Patterns
226+
227+
- **Repository Pattern**: Abstracts data access
228+
- **Unit of Work**: Manages transactions
229+
- **Result Pattern**: Type-safe error handling
230+
- **Service Layer**: Encapsulates business logic
231+
- **DTO Pattern**: Separates API contracts from domain models
232+
233+
## 📈 Roadmap
234+
235+
### Phase 1 (Complete)
236+
- ✅ Core domain model
237+
- ✅ CRUD operations for all entities
238+
- ✅ WIP limit enforcement
239+
- ✅ Basic Vue 3 frontend
240+
- ✅ API integration
241+
242+
### Phase 2 (Planned)
243+
- [ ] Drag-and-drop for cards and columns
244+
- [ ] Card modal for detailed editing
245+
- [ ] Time tracking per card
246+
- [ ] Keyboard shortcuts
247+
- [ ] Search and filtering UI
248+
249+
### Phase 3 (Future)
250+
- [ ] CLI client
251+
- [ ] Recurring tasks
252+
- [ ] Analytics dashboard
253+
- [ ] Dark mode
254+
- [ ] Multi-user support (optional)
255+
- [ ] Sync to remote server (optional)
256+
257+
## 🤝 Contributing
258+
259+
This is primarily a personal learning project, but feedback and suggestions are welcome!
260+
261+
## 📄 License
262+
263+
MIT License - feel free to use this project as a reference or starting point for your own Kanban tool.
264+
265+
## 🙏 Acknowledgments
266+
267+
- Inspired by Trello, Jira, and other Kanban tools
268+
- Built following Clean Architecture principles by Robert C. Martin
269+
- Uses modern best practices for .NET and Vue.js development
270+
271+
---
272+
273+
**Happy task tracking!** 🎯

backend/Taskdeck.sln

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8A7E8B9C-1D2E-4F3A-9B5C-6D7E8F9A0B1C}"
7+
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{9B8F9CAD-2E3F-5G4B-AC6D-7E8F9GA1C2D}"
9+
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Taskdeck.Domain", "src\Taskdeck.Domain\Taskdeck.Domain.csproj", "{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}"
11+
EndProject
12+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Taskdeck.Application", "src\Taskdeck.Application\Taskdeck.Application.csproj", "{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}"
13+
EndProject
14+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Taskdeck.Infrastructure", "src\Taskdeck.Infrastructure\Taskdeck.Infrastructure.csproj", "{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}"
15+
EndProject
16+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Taskdeck.Api", "src\Taskdeck.Api\Taskdeck.Api.csproj", "{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}"
17+
EndProject
18+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Taskdeck.Domain.Tests", "tests\Taskdeck.Domain.Tests\Taskdeck.Domain.Tests.csproj", "{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}"
19+
EndProject
20+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Taskdeck.Application.Tests", "tests\Taskdeck.Application.Tests\Taskdeck.Application.Tests.csproj", "{F6A7B8C9-D0E1-9FA0-3B4C-5D6E7F8A9B0C}"
21+
EndProject
22+
Global
23+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
24+
Debug|Any CPU = Debug|Any CPU
25+
Release|Any CPU = Release|Any CPU
26+
EndGlobalSection
27+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
28+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
30+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
31+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
34+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E}.Release|Any CPU.Build.0 = Release|Any CPU
36+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
38+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
39+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F}.Release|Any CPU.Build.0 = Release|Any CPU
40+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
42+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
43+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A}.Release|Any CPU.Build.0 = Release|Any CPU
44+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
46+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
47+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B}.Release|Any CPU.Build.0 = Release|Any CPU
48+
{F6A7B8C9-D0E1-9FA0-3B4C-5D6E7F8A9B0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49+
{F6A7B8C9-D0E1-9FA0-3B4C-5D6E7F8A9B0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
50+
{F6A7B8C9-D0E1-9FA0-3B4C-5D6E7F8A9B0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
51+
{F6A7B8C9-D0E1-9FA0-3B4C-5D6E7F8A9B0C}.Release|Any CPU.Build.0 = Release|Any CPU
52+
EndGlobalSection
53+
GlobalSection(NestedProjects) = preSolution
54+
{A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D} = {8A7E8B9C-1D2E-4F3A-9B5C-6D7E8F9A0B1C}
55+
{B2C3D4E5-F6A7-5B6C-9D0E-1F2A3B4C5D6E} = {8A7E8B9C-1D2E-4F3A-9B5C-6D7E8F9A0B1C}
56+
{C3D4E5F6-A7B8-6C7D-0E1F-2A3B4C5D6E7F} = {8A7E8B9C-1D2E-4F3A-9B5C-6D7E8F9A0B1C}
57+
{D4E5F6A7-B8C9-7D8E-1F2A-3B4C5D6E7F8A} = {8A7E8B9C-1D2E-4F3A-9B5C-6D7E8F9A0B1C}
58+
{E5F6A7B8-C9D0-8E9F-2A3B-4C5D6E7F8A9B} = {9B8F9CAD-2E3F-5G4B-AC6D-7E8F9GA1C2D}
59+
{F6A7B8C9-D0E1-9FA0-3B4C-5D6E7F8A9B0C} = {9B8F9CAD-2E3F-5G4B-AC6D-7E8F9GA1C2D}
60+
EndGlobalSection
61+
EndGlobal

0 commit comments

Comments
 (0)