# GoalsBreakDown - Implementation Plan ## 1. Project Structure ``` GoalsBreakDown/ ├── app.py # Flask application entry point ├── config.py # Configuration constants ├── database.py # TinyDB initialization and operations ├── auth.py # Authentication helpers ├── requirements.txt # Python dependencies ├── data/ # TinyDB data directory │ └── db.json # TinyDB 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 │ └── sortable.min.js # Drag-and-drop library └── 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 ``` ## 2. Dependencies & Environment Management ### 2.1 Environment Setup (uv) ```bash # Initialize project with uv uv init --no-readme # Add dependencies uv add flask tinydb bcrypt # Run the application uv run python app.py ``` ### 2.2 requirements.txt (managed by uv) ``` flask==3.0.0 tinydb==4.8.0 bcrypt==4.1.2 ``` ### 2.3 pyproject.toml (auto-generated by uv) ```toml [project] name = "goalsbreakdown" version = "0.1.0" requires-python = ">=3.10" dependencies = [ "flask>=3.0.0", "tinydb>=4.8.0", "bcrypt>=4.1.2", ] ``` ## 3. Database Schema (TinyDB) ### 3.1 Collections (TinyDB Tables) **users** table: ```json { "user_id": 1, "username": "admin", "password_hash": "$2b$12$...", "role": "admin", "max_goals": 10 } ``` **goals** table: ```json { "goal_id": 1, "user_id": 1, "title": "Learn Python", "activated": true } ``` **tasks** table: ```json { "task_id": 1, "goal_id": 1, "title": "Complete basics", "desc": "Learn variables, loops, functions", "status": "doing", "start_time": "2026-05-08T10:00:00", "finished_time": null, "order": 1.0 } ``` ### 3.2 Database Initialization ```python # database.py responsibilities: # - Initialize TinyDB with data/db.json # - Create tables: users, goals, tasks # - Seed admin user on first run (username: admin, password: admin123) # - Provide CRUD helper functions for each table ``` ## 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/` | Update goal | Yes | | DELETE | `/api/goals/` | Delete goal | Yes | | PATCH | `/api/goals//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/** - Request: `{ "title": str, "activated": bool }` - Response: `{ "success": bool, "message": str }` - Validation: Goal must belong to current user **DELETE /api/goals/** - Response: `{ "success": bool, "message": str }` - Cascade: Delete all tasks associated with this goal **PATCH /api/goals//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/` | Update task | Yes | | DELETE | `/api/tasks/` | Delete task | Yes | | PATCH | `/api/tasks//status` | Update task status | Yes | | PATCH | `/api/tasks//order` | Update task order | Yes | **GET /api/tasks** - Query params: `?goal_id=` (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/** - Request: `{ "title": str, "desc": str }` - Response: `{ "success": bool, "message": str }` **DELETE /api/tasks/** - Response: `{ "success": bool, "message": str }` **PATCH /api/tasks//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//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/` | Update user settings | Yes (admin) | **GET /api/admin/users** - Response: `[ { user_id, username, role, max_goals } ]` **PUT /api/admin/users/** - 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//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 ```python 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 ```python 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 ```python # 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 ```python 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:** ```bash 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` - `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//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//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//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/` **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) ```python # Database DB_PATH = "data/db.json" # 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 ```json { "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) - SQL injection not applicable (TinyDB), but validate all inputs - 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