46 Commits

Author SHA1 Message Date
Yuyao Huang
3f0fccd218 feat: disable Save button when content unchanged
- Save button starts disabled and only enables when title or description
  differs from the original task values
- updateSaveButton() compares current input values against task data
- input event listeners on title and desc fields call updateSaveButton
- Add global button:disabled style (opacity 0.5, cursor not-allowed)
2026-05-09 16:26:41 +08:00
Yuyao Huang
ea21b0c78c feat: status buttons as one-row group, wider side panel
- Status buttons now form a seamless button group (no gaps, shared borders,
  rounded ends) with flex-wrap: nowrap to keep them in one row
- Side panel width increased from 350px to 400px for more content space
2026-05-09 16:21:36 +08:00
Yuyao Huang
9c1d45506a feat: replace status dropdown with one-click toggle buttons
Replace <select> in side panel with 4 toggle buttons (To Do / Doing /
Pending / Done). Clicking a button immediately sends the PATCH status
API call. Active button is highlighted with status-specific colors and
shadow. saveTask now only handles title/description changes.
2026-05-09 16:16:58 +08:00
Yuyao Huang
43ca6b8462 fix: correct task sort order per status
DONE: finished_time ASC, PENDING: start_time ASC, TODO: order ASC
2026-05-09 16:13:05 +08:00
Yuyao Huang
01ae9c964a fix: add position: relative to scroll-view for correct offsetTop
Without position: relative, .task-item offsetParent is the body element,
causing offsetTop to be measured from document root rather than the
scroll container. This makes scrollToTask calculate wrong scrollTop.
2026-05-09 16:06:06 +08:00
Yuyao Huang
5294446407 fix: use requestAnimationFrame to defer in-focus and handler binding
requestAnimationFrame waits until after the browser has rendered the
current frame, which includes processing the async scroll event queued
by scrollToTask. This ensures in-focus is set after the scroll event
fires, not overwritten by it.
2026-05-09 16:04:08 +08:00
Yuyao Huang
ab000bcd41 fix: delay scroll handler binding to skip queued scroll event
scrollTop assignment triggers an async scroll event. When all tasks
fit in the viewport, handleScrollFocus recalculates center-aligned
task and picks the last one instead of the saved one. Using setTimeout(0)
defers handler binding to after the queued event fires.
2026-05-09 15:59:13 +08:00
Yuyao Huang
2229fdd0ef fix: directly set in-focus on scrolled task instead of recalculating geometry
Previously handleScrollFocus() recalculated the centered task during
init, which could select a different task than the one scrollToTask()
targeted due to scroll container clamping or DOM layout timing.

Now the scrolled task directly receives the in-focus class, and
handleScrollFocus is only used during user-initiated scroll events.
Also removes the isInitializing flag as it's no longer needed.
2026-05-09 15:52:24 +08:00
Yuyao Huang
1a23558cad fix: restore center alignment in scrollToTask to match handleScrollFocus
Both scrollToTask and handleScrollFocus now use center-of-viewport
calculation, ensuring consistent behavior between scrolling and
in-focus detection.
2026-05-09 15:44:47 +08:00
Yuyao Huang
84181e1ec2 fix: use scrollTop instead of viewport center for in-focus detection
handleScrollFocus now finds the task closest to scrollTop (offset)
instead of closest to the vertical center of the viewport. This
ensures that the saved task matches the user's scroll target.
2026-05-09 15:37:34 +08:00
Yuyao Huang
eca0cf4193 fix: call handleScrollFocus before binding scroll event handlers
Call handleScrollFocus before adding scroll event listeners to prevent
handleScrollSave from triggering during initial setup.
2026-05-09 15:33:40 +08:00
Yuyao Huang
14ebbda585 fix: skip save during initial handleScrollFocus call
Wrap the initial handleScrollFocus call with isInitializing flag
to prevent handleScrollSave from incorrectly updating selected_task_id
2026-05-09 15:29:01 +08:00
Yuyao Huang
fd92c6fe96 fix: save the in-focus task instead of recalculating top task
handleScrollSave now saves the task with in-focus class (determined by
handleScrollFocus as the centered task) rather than recalculating which
task is closest to the top. This ensures consistency between what's
highlighted and what's saved.
2026-05-09 15:21:13 +08:00
Yuyao Huang
12610d26c0 Add debugging logs to trace scroll save behavior 2026-05-09 15:14:11 +08:00
Yuyao Huang
1df90490e6 fix: restore scroll position and in-focus highlighting correctly
- Set selectedTaskId when loading saved task
- Call handleScrollFocus initially to set in-focus class
- Skip saving during initialization unless task matches saved
2026-05-09 14:51:41 +08:00
Yuyao Huang
ca7bd7e24e fix: align task to top instead of center in scroll view 2026-05-09 14:47:03 +08:00
Yuyao Huang
025195be27 Add detailed scroll position diagnostics 2026-05-09 14:43:29 +08:00
Yuyao Huang
0f1fa712a9 Add delayed scrollTop checks to catch post-load changes 2026-05-09 14:39:00 +08:00
Yuyao Huang
df74f1b8a7 Add end-of-loadTasks scrollTop debug log 2026-05-09 14:35:28 +08:00
Yuyao Huang
295fde8a75 Add debug logging for goals data 2026-05-09 14:26:57 +08:00
Yuyao Huang
1f4efcd7b3 Add debug logging for scroll position restoration 2026-05-09 14:16:15 +08:00
Yuyao Huang
643ba56768 fix: skip initial handleScrollFocus call to prevent position override
Remove immediate handleScrollFocus() call in initScrollFocus().
Only actual user scroll events will trigger position saving now.
2026-05-09 14:08:22 +08:00
Yuyao Huang
27f85cd913 fix: prevent scroll position override during page initialization
Add isInitializing flag to block persistSelectedTask during loadTasks,
preventing handleScrollFocus from overwriting the saved scroll position
2026-05-09 14:05:11 +08:00
Yuyao Huang
f021395773 fix: ensure scroll position is restored before initializing scroll focus
Move initScrollFocus() after scrollToTask() to prevent handleScrollFocus()
from incorrectly updating selected_task_id before the saved position is restored
2026-05-09 13:59:57 +08:00
Yuyao Huang
b69065e487 feat: add favicon to browser tab 2026-05-09 13:47:30 +08:00
Yuyao Huang
0d148b694f fix: change DOING takeover behavior to PENDING and enforce status sort order
- When setting a new task to DOING, the previous DOING task now switches to PENDING instead of TODO
- Task display order now prioritizes by status: DONE < DOING < PENDING < TODO, with order field respected within each status group
2026-05-09 13:43:57 +08:00
Yuyao Huang
427f62acca fix: handle foreign key constraint when deleting tasks with selected_task_id refs
Goals table has selected_task_id referencing tasks(id) without
ON DELETE SET NULL. When deleting a task, first clear any
selected_task_id references in goals to prevent FK violation.

Also update schema for future databases.
2026-05-09 13:05:53 +08:00
Yuyao Huang
6a2e0537ea fix: remove duplicate submit handler that caused double task creation
The Save button already has type=submit which naturally triggers
form submission. The additional click handler dispatching submit
event caused handleTaskSubmit to run twice.
2026-05-09 13:03:03 +08:00
Yuyao Huang
8ede63adcd fix: quote column names in UPDATE statements to handle reserved keywords
'order' is a reserved keyword in SQLite. Quote all column names
in update_user, update_goal, and update_task to prevent syntax
errors when updating columns with reserved names.
2026-05-09 12:57:18 +08:00
Yuyao Huang
be4d11a60e fix: mobile task creation button reliability
- Add novalidate to task-form to prevent browser validation quirks
- Add explicit click handler for Save button that triggers
  form submission via dispatched event for mobile compatibility
2026-05-09 12:55:05 +08:00
Yuyao Huang
f7afdf5c96 fix: stack modal buttons vertically on mobile for touch-friendly layout
On small screens (<=640px), modal action buttons now stack
vertically with full width instead of wrapping unpredictably.
This applies to all modals: note, task, goal.
2026-05-09 11:02:37 +08:00
Yuyao Huang
2345724535 fix: constrain goal selector width on mobile in tasks page
On small screens (<=480px), the goal selector dropdown could
overflow due to long option text. Match notes page behavior:
set select to width:100% with max-width:100%.
2026-05-09 11:00:51 +08:00
Yuyao Huang
bc590eb40a handle long titles with text-overflow ellipsis
- goals.css: goal-title truncates with ellipsis, goal-info
  gets min-width:0 (prevents flex overflow), mobile allows
  word-break wrap
- tasks.css: task-title truncates with ellipsis
- notes.css: note-card-title truncates with ellipsis
2026-05-09 10:57:09 +08:00
Yuyao Huang
91169f117b responsive layout fixes for mobile and desktop
- style.css: shrink nav-link padding, wrap nav-links on mobile,
  reduce container margin, responsive modal
- goals.css: stack goal cards vertically on small screens
- tasks.css: fix scroll-view height for mobile (50-55vh),
  side-panel width uses percentage (85%), add small-screen
  breakpoint at 480px
- notes.css: stack filters vertically on mobile, remove
  min-width constraints
2026-05-09 10:51:09 +08:00
Yuyao Huang
3dbe7f9c17 disable browser autocomplete on all input fields 2026-05-09 10:38:00 +08:00
Yuyao Huang
0fc62f2d16 add gunicorn as project dependency, remove leftover tinydb 2026-05-09 10:22:10 +08:00
Yuyao Huang
2a3482c2c0 fix: prevent UNIQUE constraint race with gunicorn multi-worker
Use INSERT OR IGNORE instead of SELECT-then-INSERT for
default admin user creation, avoiding the race condition
when multiple gunicorn workers initialize simultaneously.
2026-05-09 10:19:58 +08:00
Yuyao Huang
2629e8f2cd feat: move config.py to config.example.py, exclude config.py from git tracking
- Copy config.py to config.example.py as template (tracked in git)
- Add config.py to .gitignore (local config per developer)
- Update README.md with configuration setup instructions
- Fix outdated references (TinyDB -> SQLite, add missing files)
- Persist goal selection across task and note pages
2026-05-09 10:12:37 +08:00
Yuyao Huang
3c325bdb0f feat(notes): add notes feature with CRUD operations and UI
- Implement notes database schema and API endpoints
- Add notes page with filtering, search, and markdown support
- Persist selected goal and task preferences for better UX
- Include responsive design and mobile-friendly layout
2026-05-08 17:42:42 +08:00
Yuyao Huang
594bf65715 Update devdocs: TinyDB→SQLite, project structure, deps, and commands 2026-05-08 16:29:40 +08:00
Yuyao Huang
a5c5f5b077 Remove db.json migration logic 2026-05-08 16:23:00 +08:00
Yuyao Huang
a8fe6ed7b3 Migrate from TinyDB to SQLite
- Replace TinyDB (JSON file) with sqlite3 for data persistence
- Add schema.py: table creation + data migration from db.json
- Rewrite database.py: all CRUD operations use sqlite3 directly
- All data retains original IDs via migration script
- Remove tinydb dependency from pyproject.toml
2026-05-08 16:18:26 +08:00
Yuyao Huang
b060ba6bf8 Fix layout: move create button to header, increase description area height
- Move '+ Create Task' button into tasks-header to avoid breaking scroll/edit height alignment
- Increase edit-task description textarea from rows=3 to rows=6
- Remove unused .create-task-container and #create-task-btn CSS rules
2026-05-08 16:04:12 +08:00
Yuyao Huang
6b05ba3e2c Improve tasks UI: scroll-to-focus picker, landscape layout, height alignment
- Complete tasks now displayed in scroll view alongside unfinished tasks
- Priority order: completed tasks first (by finished_time desc), then unfinished (by order asc)
- Time picker-style scroll: wheel scroll snaps per task, center item gets visual focus
- Landscape mode (>=1024px): scroll view + edit panel side by side, panel always visible
- Portrait mode: edit panel slides in from right on tap
- Fixed flex layout so scroll view and edit panel align perfectly in height
2026-05-08 15:47:25 +08:00
Yuyao Huang
79fde447e9 Add project docs and cleanup uv-generated files 2026-05-08 12:42:50 +08:00
Yuyao Huang
f3bffa40cd Initial commit: GoalsBreakDown web app
- Flask backend with TinyDB database
- Multi-user auth with bcrypt password hashing
- Goal CRUD with activation/deactivation and per-user limits
- Task CRUD with status tracking (todo/doing/pending/done)
- Focus rule: one doing task per goal
- Time picker-style scroll view with drag-and-drop reordering
- Admin panel for user management
- uv environment management
2026-05-08 12:41:19 +08:00