goalsbreakdown/devdocs/v1/IMPLEMENTATION_PLAN.md

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.py defines SQL table creation and get_connection() helper
  • init_db() creates tables and seeds admin user on first run
  • Uses sqlite3.Row for 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 order ASC, finished by finished_time DESC

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_time to current timestamp
    • If status changed from "done" to other: Set finished_time to 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:

  1. User enters credentials
  2. POST to /api/auth/login
  3. On success: redirect to /goals
  4. 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:

  1. User enters credentials
  2. POST to /api/auth/register
  3. On success: auto-login and redirect to /goals
  4. 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:

  1. User drags task item
  2. SortableJS handles reordering
  3. On drop: calculate new order value
  4. PATCH /api/tasks/<task_id>/order
  5. Update local state

Side Panel Flow:

  1. User clicks task item
  2. Side panel slides in from right
  3. Panel shows editable fields
  4. User modifies and clicks "Save"
  5. PUT request to update task
  6. 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_id and username in 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_required decorator for protected routes
  • @admin_required decorator 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.py
  • schema.py
  • database.py
  • auth.py
  • app.py (basic setup)
  • templates/login.html
  • templates/register.html
  • static/css/style.css
  • static/js/api.js
  • static/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.html
  • static/css/goals.css
  • static/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.html
  • static/css/tasks.css
  • static/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