diff --git a/public/app.js b/public/app.js
index e525968..de1cdc2 100644
--- a/public/app.js
+++ b/public/app.js
@@ -121,9 +121,30 @@ class App {
promoteOption.style.display = 'none';
}
- contextMenu.style.left = e.pageX + 'px';
- contextMenu.style.top = e.pageY + 'px';
+ // Use clientX/clientY for fixed positioning (viewport-relative)
+ let x = e.clientX;
+ let y = e.clientY;
+
+ // Temporarily show offscreen to measure dimensions
+ contextMenu.style.left = '-9999px';
+ contextMenu.style.top = '-9999px';
contextMenu.classList.add('show');
+
+ const menuWidth = contextMenu.offsetWidth;
+ const menuHeight = contextMenu.offsetHeight;
+
+ // Clamp to viewport boundaries
+ if (x + menuWidth > window.innerWidth) {
+ x = window.innerWidth - menuWidth - 5;
+ }
+ if (y + menuHeight > window.innerHeight) {
+ y = window.innerHeight - menuHeight - 5;
+ }
+ if (x < 0) x = 5;
+ if (y < 0) y = 5;
+
+ contextMenu.style.left = x + 'px';
+ contextMenu.style.top = y + 'px';
}
hideContextMenu() {
@@ -546,10 +567,19 @@ class App {
${task.completed ? 'Undo' : 'Complete'}
- ${task.subtasks.length > 0 ? this.renderSubtasks(task) : ''}
-
Drop tasks here to add as subtasks
`;
+ // Append subtasks as DOM nodes to preserve event listeners
+ if (task.subtasks.length > 0) {
+ card.appendChild(this.renderSubtasks(task));
+ }
+
+ // Add drop zone
+ const dropZone = document.createElement('div');
+ dropZone.className = 'drop-zone';
+ dropZone.textContent = 'Drop tasks here to add as subtasks';
+ card.appendChild(dropZone);
+
return card;
}
@@ -623,7 +653,7 @@ class App {
container.appendChild(div);
});
- return container.outerHTML;
+ return container;
}
render() {
diff --git a/readme.me b/readme.me
new file mode 100644
index 0000000..8d17e78
--- /dev/null
+++ b/readme.me
@@ -0,0 +1,95 @@
+# Learning Progress Tracker
+
+A web-based goal and learning progress tracker with subtask management, drag-and-drop reordering, and persistent server-side storage.
+
+## Features
+
+- **Goal Management** — Create, edit, and delete learning goals with titles, descriptions, sizes, and optional rewards.
+- **Subtasks** — Break goals into smaller subtasks. Drag any task onto another to nest it as a subtask, or promote subtasks back to top-level goals.
+- **Progress Tracking** — Automatic progress calculation based on subtask completion, weighted by task size (Small 10%, Medium 25%, Large 50%).
+- **Drag & Drop** — Reorder tasks and subtasks via drag-and-drop. Hold over a task to reveal its drop zone for nesting.
+- **Context Menus** — Right-click any task or subtask to edit, delete, or promote (subtasks only).
+- **Rewards** — Set optional rewards on goals that are revealed only upon completion.
+- **Persistent Storage** — All data is stored in a SQLite database on the server.
+- **Dark Theme** — Clean, modern dark UI.
+
+## Project Structure
+
+```
+├── public/
+│ ├── index.html # Main HTML page
+│ ├── styles.css # Stylesheet (dark theme)
+│ └── app.js # Client-side application logic
+├── server/
+│ └── server.js # Express server with SQLite backend
+├── data/ # SQLite database (auto-created)
+├── package.json
+├── dockerfile
+└── README.md
+```
+
+## Getting Started
+
+### Prerequisites
+
+- [Node.js](https://nodejs.org/) v18 or later
+- npm (comes with Node.js)
+
+### Installation
+
+```bash
+# Clone or download the project
+cd learning-progress-tracker
+
+# Install dependencies
+npm install
+
+# Start the server
+npm start
+```
+
+The app will be available at **http://localhost:3000**.
+
+For development with auto-reload:
+
+```bash
+npm run dev
+```
+
+### Docker
+
+```bash
+# Build the image
+docker build -t learning-tracker .
+
+# Run the container (persists data via volume)
+docker run -d -p 3000:3000 -v tracker-data:/app/data learning-tracker
+```
+
+## API Endpoints
+
+| Method | Endpoint | Description |
+|--------|----------|-------------|
+| `GET` | `/api/tasks` | Fetch all tasks |
+| `POST` | `/api/tasks` | Create a new task |
+| `PUT` | `/api/tasks/:id` | Update a task (including subtasks) |
+| `DELETE` | `/api/tasks/:id` | Delete a task |
+| `POST` | `/api/tasks/reorder` | Reorder tasks (accepts array of task IDs) |
+
+## Usage
+
+- Click **+ New Goal** to create a task.
+- **Right-click** a task or subtask for edit/delete/promote options.
+- **Drag** tasks to reorder them, or hold over another task to nest it as a subtask.
+- Mark tasks complete to reveal rewards and track overall progress.
+
+## Tech Stack
+
+- **Frontend:** Vanilla JavaScript, HTML, CSS
+- **Backend:** Node.js, Express
+- **Database:** SQLite3
+- **Containerization:** Docker
+
+## License
+
+MIT
\ No newline at end of file