Add project docs and cleanup uv-generated files
This commit is contained in:
parent
f3bffa40cd
commit
79fde447e9
1
.python-version
Normal file
1
.python-version
Normal file
@ -0,0 +1 @@
|
||||
3.13
|
||||
575
devdocs/v1/IMPLEMENTATION_PLAN.md
Normal file
575
devdocs/v1/IMPLEMENTATION_PLAN.md
Normal file
@ -0,0 +1,575 @@
|
||||
# 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/<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
|
||||
```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/<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)
|
||||
|
||||
```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
|
||||
99
devdocs/v1/PRD.md
Normal file
99
devdocs/v1/PRD.md
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Task Table:
|
||||
|
||||
- task_id: primary key
|
||||
- title: str (required, non-empty)
|
||||
- desc: str (optional, can be empty)
|
||||
- status: enum{todo, doing, pending, done}
|
||||
- goal_id: foreign key to goal table (required, each task belongs to exactly one goal)
|
||||
- start_time: timestamp or None
|
||||
- finished_time: timestamp or None
|
||||
- order: float (for ordering unfinished tasks)
|
||||
|
||||
Goal Table:
|
||||
|
||||
- goal_id: primary key
|
||||
- title: str (required, non-empty)
|
||||
- activated: bool (deactivated goals and their tasks are hidden from Task Page GUI)
|
||||
|
||||
User Table:
|
||||
|
||||
- user_id: primary key
|
||||
- username: str (unique, required)
|
||||
- password_hash: str (required)
|
||||
- role: enum{user, admin} (admin can configure goal limits)
|
||||
- max_goals: int (maximum goals this user can create, configurable by admin)
|
||||
|
||||
|
||||
GUI:
|
||||
|
||||
Page 1. Goal CRUD
|
||||
- List all goals with activate/deactivate toggle
|
||||
- Create, edit, delete goals
|
||||
- Shows goal title and activation status
|
||||
|
||||
Page 2. Task CRUD
|
||||
- Tasks are grouped by their parent goal
|
||||
- Only activated goals and their tasks are visible
|
||||
- Focus Rule: Each goal highlights its single "doing" task prominently
|
||||
- Scroll View: Tasks displayed in a scrollable selector (like time picker widget)
|
||||
- Center/focus area shows current task
|
||||
- Unfinished tasks ordered by `order` field
|
||||
- Finished tasks ordered by `finished_time` (most recent first)
|
||||
- Drag-and-drop reordering for unfinished tasks
|
||||
- Side Panel: Clicking a task opens a side panel for editing task details
|
||||
- Task status transitions:
|
||||
- User manually switches task to "doing" (only one per goal)
|
||||
- When "doing" task is completed, status becomes "done" (no auto-promotion)
|
||||
- User must manually set next task to "doing"
|
||||
|
||||
|
||||
Constraints:
|
||||
|
||||
1. **Focus Rule**: Under each goal, there should be only one "doing" task. The GUI must visually emphasize the "doing" task for each goal.
|
||||
|
||||
2. **Ordering Rule**:
|
||||
- Finished tasks are ordered by `finished_time` (descending)
|
||||
- Unfinished tasks are ordered by `order` field (ascending)
|
||||
- Users can reorder unfinished tasks via drag-and-drop
|
||||
|
||||
3. **Scroll View**: Tasks are displayed in a linear scroll view selector (similar to HH:mm time picker). The current task is centered/focused. Users can drag-and-drop to reorder future tasks.
|
||||
|
||||
4. **Task-Good Relationship**: Tasks cannot exist without a goal. Each task belongs to exactly one goal.
|
||||
|
||||
5. **Goal Limit**: Each user can only create up to their `max_goals` limit. Admin can modify this limit per user.
|
||||
|
||||
6. **Visibility**: Deactivated goals and all their tasks are hidden from the Task Page.
|
||||
|
||||
|
||||
Business Rules:
|
||||
|
||||
- Task title is required and cannot be empty
|
||||
- Goal title is required and cannot be empty
|
||||
- Tasks can be deleted (order values don't need to be continuous)
|
||||
- Goals can be activated/deactivated (only affects GUI visibility)
|
||||
- Only one "doing" task per goal at any time
|
||||
- Users must manually set a task to "doing" status
|
||||
- Simple user registration with username/password
|
||||
|
||||
|
||||
Tech Stack:
|
||||
|
||||
- Backend: Python + Flask (lightweight, good for small apps)
|
||||
- Frontend: Vanilla JS + HTML/CSS (simple, no build step needed)
|
||||
- Database: TinyDB (single JSON file, perfect for this scale)
|
||||
- Authentication: Session-based with password hashing (bcrypt)
|
||||
- Drag-and-drop: HTML5 Drag and Drop API or SortableJS
|
||||
|
||||
|
||||
Multi-User Features:
|
||||
|
||||
- User registration and login
|
||||
- Each user has isolated goals and tasks
|
||||
- Admin user can:
|
||||
- Configure `max_goals_per_user` limit
|
||||
- View all users (optional)
|
||||
- Regular users can only see/manage their own data
|
||||
Loading…
x
Reference in New Issue
Block a user