17 KiB
GoalsBreakDown - Implementation Plan
1. Project Structure
GoalsBreakDown/
├── app.py # Flask application entry point
├── config.py # Configuration constants
├── database.py # SQLite database operations
├── auth.py # Authentication helpers
├── schema.py # SQLite table creation & migration
├── pyproject.toml # Python dependencies (uv-managed)
├── data/ # SQLite data directory
│ └── db.sqlite # SQLite database file
├── static/
│ ├── css/
│ │ ├── style.css # Global styles
│ │ ├── goals.css # Goal page styles
│ │ └── tasks.css # Task page styles
│ └── js/
│ ├── api.js # API client utilities
│ ├── auth.js # Authentication logic
│ ├── goals.js # Goal page logic
│ └── tasks.js # Task page logic
└── templates/
├── base.html # Base template with navigation
├── login.html # Login page
├── register.html # Registration page
├── goals.html # Goal CRUD page
├── tasks.html # Task CRUD page with scroll view
└── admin.html # Admin user management page
2. Dependencies & Environment Management
2.1 Environment Setup (uv)
# Initialize project with uv
uv init --no-readme
# Add dependencies
uv add flask bcrypt
# Run the application
uv run flask run
2.2 pyproject.toml (managed by uv)
[project]
name = "goalsbreakdown"
version = "0.1.0"
requires-python = ">=3.13"
dependencies = [
"flask>=3.1.3",
"bcrypt>=5.0.0",
]
3. Database Schema (SQLite)
3.1 Tables
users table:
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'user',
max_goals INTEGER NOT NULL DEFAULT 5
);
goals table:
CREATE TABLE goals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
title TEXT NOT NULL,
activated INTEGER NOT NULL DEFAULT 1,
FOREIGN KEY (user_id) REFERENCES users(id)
);
tasks table:
CREATE TABLE tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
goal_id INTEGER NOT NULL,
title TEXT NOT NULL,
desc TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'todo',
start_time TEXT,
finished_time TEXT,
"order" REAL NOT NULL DEFAULT 0.0,
FOREIGN KEY (goal_id) REFERENCES goals(id)
);
3.2 Database Initialization (schema.py)
schema.pydefines SQL table creation andget_connection()helperinit_db()creates tables and seeds admin user on first run- Uses
sqlite3.Rowfor dict-like row access
4. API Endpoints
4.1 Authentication
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/auth/register |
Register new user | No |
| POST | /api/auth/login |
Login user | No |
| POST | /api/auth/logout |
Logout user | Yes |
| GET | /api/auth/me |
Get current user info | Yes |
POST /api/auth/register
- Request:
{ "username": str, "password": str } - Response:
{ "success": bool, "message": str, "user_id": int } - Validation: username unique, password min 6 chars
- Default: role="user", max_goals=5
POST /api/auth/login
- Request:
{ "username": str, "password": str } - Response:
{ "success": bool, "message": str, "user": { user object } }
GET /api/auth/me
- Response:
{ "user_id": int, "username": str, "role": str, "max_goals": int }
4.2 Goals
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/goals |
List all goals for current user | Yes |
| POST | /api/goals |
Create new goal | Yes |
| PUT | /api/goals/<goal_id> |
Update goal | Yes |
| DELETE | /api/goals/<goal_id> |
Delete goal | Yes |
| PATCH | /api/goals/<goal_id>/toggle |
Toggle activated status | Yes |
GET /api/goals
- Response:
[ { goal objects } ] - Note: Returns all goals (activated and deactivated)
POST /api/goals
- Request:
{ "title": str } - Response:
{ "success": bool, "goal_id": int, "message": str } - Validation: Check user's max_goals limit before creation
PUT /api/goals/<goal_id>
- Request:
{ "title": str, "activated": bool } - Response:
{ "success": bool, "message": str } - Validation: Goal must belong to current user
DELETE /api/goals/<goal_id>
- Response:
{ "success": bool, "message": str } - Cascade: Delete all tasks associated with this goal
PATCH /api/goals/<goal_id>/toggle
- Response:
{ "success": bool, "activated": bool }
4.3 Tasks
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/tasks |
List all tasks (optionally filtered by goal) | Yes |
| POST | /api/tasks |
Create new task | Yes |
| PUT | /api/tasks/<task_id> |
Update task | Yes |
| DELETE | /api/tasks/<task_id> |
Delete task | Yes |
| PATCH | /api/tasks/<task_id>/status |
Update task status | Yes |
| PATCH | /api/tasks/<task_id>/order |
Update task order | Yes |
GET /api/tasks
- Query params:
?goal_id=<int>(optional filter) - Response:
[ { task objects } ] - Sorting: Unfinished by
orderASC, finished byfinished_timeDESC
POST /api/tasks
- Request:
{ "goal_id": int, "title": str, "desc": str (optional) } - Response:
{ "success": bool, "task_id": int, "message": str } - Validation: goal_id must belong to current user and be activated
PUT /api/tasks/<task_id>
- Request:
{ "title": str, "desc": str } - Response:
{ "success": bool, "message": str }
DELETE /api/tasks/<task_id>
- Response:
{ "success": bool, "message": str }
PATCH /api/tasks/<task_id>/status
- Request:
{ "status": "todo" | "doing" | "pending" | "done" } - Response:
{ "success": bool, "message": str } - Business logic:
- If status="doing": Check no other "doing" task exists for this goal
- If status="done": Set
finished_timeto current timestamp - If status changed from "done" to other: Set
finished_timeto null
PATCH /api/tasks/<task_id>/order
- Request:
{ "order": float } - Response:
{ "success": bool, "message": str } - Note: Used for drag-and-drop reordering
4.4 Admin
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| GET | /api/admin/users |
List all users | Yes (admin) |
| PUT | /api/admin/users/<user_id> |
Update user settings | Yes (admin) |
GET /api/admin/users
- Response:
[ { user_id, username, role, max_goals } ]
PUT /api/admin/users/<user_id>
- Request:
{ "max_goals": int, "role": str (optional) } - Response:
{ "success": bool, "message": str }
5. Frontend Components
5.1 Page: Login (/login)
Components:
- Username input field
- Password input field
- Login button
- Link to registration page
Flow:
- User enters credentials
- POST to
/api/auth/login - On success: redirect to
/goals - On failure: show error message
5.2 Page: Register (/register)
Components:
- Username input field
- Password input field
- Confirm password input field
- Register button
- Link to login page
Flow:
- User enters credentials
- POST to
/api/auth/register - On success: auto-login and redirect to
/goals - On failure: show error message
5.3 Page: Goals (/goals)
Layout:
+------------------------------------------+
| Navigation: [Goals] [Tasks] [Logout] |
+------------------------------------------+
| [Create Goal Button] |
+------------------------------------------+
| Goal List: |
| +--------------------------------------+ |
| | Goal Title | [Activate/Deactivate] |
| | | [Edit] [Delete] | |
| +--------------------------------------+ |
| | Goal Title | [Activate/Deactivate] |
| | | [Edit] [Delete] | |
| +--------------------------------------+ |
+------------------------------------------+
Components:
- Goal list (table or card layout)
- Create goal modal/form
- Edit goal modal/form
- Activate/Deactivate toggle button
- Delete confirmation dialog
Interactions:
- Click "Create Goal" → opens modal → submit → refresh list
- Click "Edit" → opens modal with pre-filled data → submit → refresh
- Click toggle → PATCH request → update UI
- Click "Delete" → confirmation → DELETE request → refresh
5.4 Page: Tasks (/tasks)
Layout:
+--------------------------------------------------+
| Navigation: [Goals] [Tasks] [Logout] |
+--------------------------------------------------+
| Goal Selector: [Dropdown of activated goals] |
+--------------------------------------------------+
| Task Scroll View (Time Picker Style): |
| |
| +---------------------------+ |
| | Task N-2 (todo) | [faded] |
| +---------------------------+ |
| | Task N-1 (todo) | [dimmed] |
| +---------------------------+ |
| | >>> Task N (doing) <<< | [HIGHLIGHTED] |
| +---------------------------+ |
| | Task N+1 (todo) | [normal] |
| +---------------------------+ |
| | Task N+2 (todo) | [faded] |
| +---------------------------+ |
| |
| [Create Task Button] |
+--------------------------------------------------+
| Side Panel (when task selected): |
| +----------------------------------------------+ |
| | Task Title: [____________] | |
| | Description: [____________] | |
| | Status: [Dropdown: todo/doing/pending/done] | |
| | [Save] [Delete] | |
| +----------------------------------------------+ |
+--------------------------------------------------+
Components:
- Goal selector dropdown (filters tasks by selected goal)
- Scroll view container with centered focus area
- Task items (draggable for unfinished tasks)
- Create task modal/form
- Side panel for task editing
- Status change buttons
Scroll View Implementation:
- Container with
overflow-y: auto - Center item highlighted with CSS
- Scroll to center the "doing" task on load
- Use SortableJS for drag-and-drop reordering
- Only unfinished tasks are draggable
- Finished tasks shown in separate section below (ordered by finished_time)
Drag-and-Drop Flow:
- User drags task item
- SortableJS handles reordering
- On drop: calculate new
ordervalue - PATCH
/api/tasks/<task_id>/order - Update local state
Side Panel Flow:
- User clicks task item
- Side panel slides in from right
- Panel shows editable fields
- User modifies and clicks "Save"
- PUT request to update task
- Panel closes or stays open for further edits
6. Authentication & Session Management
6.1 Session Storage
- Use Flask's built-in session management
- Store
user_idandusernamein session - Session cookie is HTTP-only and secure
6.2 Password Handling
- Hash passwords with bcrypt before storage
- Verify passwords with bcrypt.checkpw()
- Never store plain text passwords
6.3 Middleware
@login_requireddecorator for protected routes@admin_requireddecorator for admin routes- Check user ownership on goal/task operations
7. Business Logic Implementation
7.1 Goal Limit Enforcement
def can_create_goal(user_id):
user = get_user(user_id)
goal_count = count_goals_by_user(user_id)
return goal_count < user.max_goals
7.2 Focus Rule Enforcement
def set_task_to_doing(task_id, goal_id):
# Check if another task is already "doing"
doing_task = find_task(goal_id, status="doing")
if doing_task and doing_task.task_id != task_id:
# Optionally auto-change old doing to todo
update_task_status(doing_task.task_id, "todo")
update_task_status(task_id, "doing")
7.3 Task Ordering
# Unfinished tasks: ordered by 'order' field (ascending)
# Finished tasks: ordered by 'finished_time' (descending)
def get_tasks_for_goal(goal_id):
unfinished = query(status != "done").order_by("order")
finished = query(status == "done").order_by("finished_time", reverse=True)
return unfinished + finished
7.4 Drag-and-Drop Order Calculation
def reorder_task(task_id, new_position, siblings):
# Use real numbers to avoid reordering all tasks
prev_order = siblings[new_position - 1].order if new_position > 0 else 0
next_order = siblings[new_position + 1].order if new_position < len(siblings) - 1 else prev_order + 2
new_order = (prev_order + next_order) / 2
update_task_order(task_id, new_order)
8. Development Phases
Phase 1: Foundation (Setup & Auth)
Setup:
uv init --no-readme
uv add flask tinydb bcrypt
Files to create:
pyproject.toml(auto-generated by uv)uv.lock(auto-generated by uv)config.pyschema.pydatabase.pyauth.pyapp.py(basic setup)templates/login.htmltemplates/register.htmlstatic/css/style.cssstatic/js/api.jsstatic/js/auth.js
Deliverables:
- Flask app running on localhost:5000 (
uv run python app.py) - User registration with validation
- User login/logout with session management
- Password hashing with bcrypt
- Admin user seeded on first run
Phase 2: Goal CRUD
Files to create:
templates/goals.htmlstatic/css/goals.cssstatic/js/goals.js
API endpoints to implement:
- GET/POST/PUT/DELETE
/api/goals - PATCH
/api/goals/<goal_id>/toggle
Deliverables:
- Goal list page with all CRUD operations
- Activate/deactivate toggle
- Goal limit enforcement
- Delete confirmation dialog
Phase 3: Task CRUD (Basic)
Files to create:
templates/tasks.htmlstatic/css/tasks.cssstatic/js/tasks.js
API endpoints to implement:
- GET/POST/PUT/DELETE
/api/tasks - PATCH
/api/tasks/<task_id>/status
Deliverables:
- Task list filtered by goal
- Task creation with goal selection
- Task editing in side panel
- Status change with focus rule enforcement
- Finished time tracking
Phase 4: Task Ordering & Drag-Drop
Files to modify:
static/js/tasks.js(add drag-drop logic)static/css/tasks.css(add scroll view styles)
API endpoints to implement:
- PATCH
/api/tasks/<task_id>/order
Deliverables:
- Scroll view with centered focus
- Highlighted "doing" task
- Drag-and-drop reordering with SortableJS
- Order calculation with real numbers
- Finished tasks section (sorted by finished_time)
Phase 5: Admin Features
Files to create:
- Admin section in goals.html or separate page
static/js/admin.js(if needed)
API endpoints to implement:
- GET
/api/admin/users - PUT
/api/admin/users/<user_id>
Deliverables:
- Admin can view all users
- Admin can modify user's max_goals
- Admin can change user role
Phase 6: Polish & Testing
Tasks:
- Error handling and user feedback
- Loading states and animations
- Responsive design for mobile
- Input validation on frontend
- Edge case handling (empty states, etc.)
- Manual testing of all flows
9. Configuration (config.py)
# Database
DB_PATH = "data/db.sqlite"
# Default admin credentials
DEFAULT_ADMIN_USERNAME = "admin"
DEFAULT_ADMIN_PASSWORD = "admin123"
# Default user settings
DEFAULT_MAX_GOALS = 5
# Flask
SECRET_KEY = "your-secret-key-here" # Change in production
DEBUG = True
HOST = "0.0.0.0"
PORT = 5000
10. Error Handling
API Error Responses
{
"success": false,
"message": "Error description",
"error_code": "VALIDATION_ERROR | NOT_FOUND | UNAUTHORIZED | FORBIDDEN"
}
HTTP Status Codes
- 200: Success
- 201: Created
- 400: Bad Request (validation error)
- 401: Unauthorized (not logged in)
- 403: Forbidden (insufficient permissions)
- 404: Not Found
- 500: Internal Server Error
11. Security Considerations
- Password hashing with bcrypt (cost factor 12)
- Session-based authentication with HTTP-only cookies
- CSRF protection (Flask-WTF or manual token)
- Input sanitization (prevent XSS)
- Parameterized SQL queries (sqlite3 placeholders prevent injection)
- Rate limiting on auth endpoints (optional)
- HTTPS in production
12. Future Enhancements (Out of Scope)
- Task categories/tags
- Task priority levels
- Task search and filtering
- Export/import data
- Email notifications
- Task templates
- Progress tracking per goal
- Mobile app