diff --git a/.github/alias.txt b/.github/alias.txt
new file mode 100644
index 0000000..468b5e9
--- /dev/null
+++ b/.github/alias.txt
@@ -0,0 +1,19 @@
+
+**Powershell
+git config --global alias.save-wip "!f() { git add . ; if (git log -1 --format=%s -eq 'wip') { git commit --amend --no-edit } else { git commit -m 'wip' }; git push origin `$(git branch --show-current):wip-sync --force-with-lease; }; f"
+git config --global alias.load-wip "!f() { if (git diff-index --quiet HEAD --) { git fetch origin wip-sync; git merge origin/wip-sync; if (git log -1 --format=%s -eq 'wip') { git reset --soft HEAD~1; echo 'WIP Loaded and unwrapped.' } else { echo 'No WIP found. Merge complete.' } } else { echo 'Error: Uncommitted changes detected.'; exit 1 }; }; f"
+git config --global alias.abort-wip "git reset --hard HEAD"
+
+**Git Bash
+git config --global alias.save-wip '!f() { git add . ; if [ "$(git log -1 --format=%s)" = "wip" ]; then git commit --amend --no-edit; else git commit -m "wip"; fi; git push origin $(git branch --show-current):wip-sync --force-with-lease; }; f'
+git config --global alias.load-wip '!f() { if ! git diff-index --quiet HEAD --; then echo "Error: Uncommitted changes detected."; exit 1; fi; git fetch origin wip-sync && git merge origin/wip-sync && if [ "$(git log -1 --format=%s)" = "wip" ]; then git reset --soft HEAD~1; echo "WIP Loaded and unwrapped."; else echo "No WIP found. Merge complete."; fi; }; f'
+git config --global alias.abort-wip 'git reset --hard HEAD'
+
+
+**Mac
+git config --global alias.save-wip '!f() { git add . ; if [ "$(git log -1 --format=%s)" = "wip" ]; then git commit --amend --no-edit; else git commit -m "wip"; fi; git push origin $(git branch --show-current):wip-sync --force-with-lease; }; f'
+git config --global alias.load-wip '!f() { if ! git diff-index --quiet HEAD --; then echo "Error: Uncommitted changes detected."; exit 1; fi; git fetch origin wip-sync && git merge origin/wip-sync && if [ "$(git log -1 --format=%s)" = "wip" ]; then git reset --soft HEAD~1; echo "WIP Loaded and unwrapped."; else echo "No WIP found. Merge complete."; fi; }; f'
+git config --global alias.abort-wip 'git reset --hard HEAD'
+
+***Reset wip-sync
+git push origin --delete wip-sync
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.agent.xml b/.idea/copilot.data.migration.agent.xml
new file mode 100644
index 0000000..4ea72a9
--- /dev/null
+++ b/.idea/copilot.data.migration.agent.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.edit.xml b/.idea/copilot.data.migration.edit.xml
new file mode 100644
index 0000000..8648f94
--- /dev/null
+++ b/.idea/copilot.data.migration.edit.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 3bb6c6a..a7dbdf2 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -2,8 +2,8 @@
"version": "0.2.0",
"configurations": [
{
- "name": "Python: Flask",
- "type": "debugpy",
+ "name": "Python: Flask (mac)",
+ "type": "python",
"request": "launch",
"module": "flask",
"python": "${command:python.interpreterPath}",
@@ -17,7 +17,9 @@
"--port=5000",
"--no-debugger",
"--no-reload"
- ]
+ ],
+ "cwd": "${workspaceFolder}/backend",
+ "console": "integratedTerminal"
},
{
"name": "Vue: Dev Server",
@@ -32,17 +34,17 @@
"console": "integratedTerminal"
},
{
- "name": "Chrome: Attach to Vue App",
- "type": "chrome",
+ "name": "Chrome: Launch (Vue App)",
+ "type": "pwa-chrome",
"request": "launch",
- "url": "https://localhost:5173", // or your Vite dev server port
+ "url": "http://localhost:5173",
"webRoot": "${workspaceFolder}/frontend/vue-app"
},
{
"name": "Python: Backend Tests",
"type": "python",
"request": "launch",
- "program": "${workspaceFolder}/backend/.venv/Scripts/pytest.exe",
+ "module": "pytest",
"args": [
"tests/"
],
@@ -68,9 +70,9 @@
{
"name": "Full Stack (Backend + Frontend)",
"configurations": [
- "Python: Flask",
+ "Python: Flask (mac)",
"Vue: Dev Server",
- "Chrome: Attach to Vue App"
+ "Chrome: Launch (Vue App)"
]
}
]
diff --git a/.vscode/launch.json.bak b/.vscode/launch.json.bak
new file mode 100644
index 0000000..3bb6c6a
--- /dev/null
+++ b/.vscode/launch.json.bak
@@ -0,0 +1,77 @@
+{
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": "Python: Flask",
+ "type": "debugpy",
+ "request": "launch",
+ "module": "flask",
+ "python": "${command:python.interpreterPath}",
+ "env": {
+ "FLASK_APP": "backend/main.py",
+ "FLASK_DEBUG": "1"
+ },
+ "args": [
+ "run",
+ "--host=0.0.0.0",
+ "--port=5000",
+ "--no-debugger",
+ "--no-reload"
+ ]
+ },
+ {
+ "name": "Vue: Dev Server",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npm",
+ "runtimeArgs": [
+ "run",
+ "dev"
+ ],
+ "cwd": "${workspaceFolder}/frontend/vue-app",
+ "console": "integratedTerminal"
+ },
+ {
+ "name": "Chrome: Attach to Vue App",
+ "type": "chrome",
+ "request": "launch",
+ "url": "https://localhost:5173", // or your Vite dev server port
+ "webRoot": "${workspaceFolder}/frontend/vue-app"
+ },
+ {
+ "name": "Python: Backend Tests",
+ "type": "python",
+ "request": "launch",
+ "program": "${workspaceFolder}/backend/.venv/Scripts/pytest.exe",
+ "args": [
+ "tests/"
+ ],
+ "cwd": "${workspaceFolder}/backend",
+ "console": "integratedTerminal",
+ "env": {
+ "PYTHONPATH": "${workspaceFolder}/backend"
+ }
+ },
+ {
+ "name": "Vue: Frontend Tests",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "npx",
+ "runtimeArgs": [
+ "vitest"
+ ],
+ "cwd": "${workspaceFolder}/frontend/vue-app",
+ "console": "integratedTerminal"
+ }
+ ],
+ "compounds": [
+ {
+ "name": "Full Stack (Backend + Frontend)",
+ "configurations": [
+ "Python: Flask",
+ "Vue: Dev Server",
+ "Chrome: Attach to Vue App"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index dfac589..69d1ef4 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,31 +1,45 @@
{
- "version": "2.0.0",
- "tasks": [
- {
- "label": "Save Work In Progress",
- "type": "shell",
- "command": "git",
- "args": ["savewip"],
- "group": "build",
- "presentation": {
- "echo": true,
- "reveal": "silent",
- "focus": false,
- "panel": "shared"
- }
- },
- {
- "label": "Load Work In Progress",
- "type": "shell",
- "command": "git",
- "args": ["loadwip"],
- "group": "build",
- "presentation": {
- "echo": true,
- "reveal": "silent",
- "focus": false,
- "panel": "shared"
- }
- }
- ]
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "Git: Save WIP",
+ "type": "shell",
+ "command": "git save-wip",
+ "group": "build",
+ "presentation": {
+ "reveal": "always",
+ "panel": "shared"
+ }
+ },
+ {
+ "label": "Git: Load WIP",
+ "type": "shell",
+ "command": "git load-wip",
+ "group": "build",
+ "presentation": {
+ "reveal": "always",
+ "panel": "shared"
+ }
+ },
+ {
+ "label": "Git: Reset Cloud WIP",
+ "type": "shell",
+ "command": "git push origin --delete wip-sync",
+ "presentation": {
+ "reveal": "always",
+ "panel": "shared"
+ }
+ },
+ {
+ "label": "Git: Abort WIP (Reset Local)",
+ "type": "shell",
+ "command": "git abort-wip",
+ "group": "none",
+ "presentation": {
+ "reveal": "always",
+ "panel": "shared",
+ "echo": true
+ }
+ }
+ ]
}
\ No newline at end of file
diff --git a/backend/test_data/db/child_overrides.json b/backend/test_data/db/child_overrides.json
index 560ef4d..8d16e13 100644
--- a/backend/test_data/db/child_overrides.json
+++ b/backend/test_data/db/child_overrides.json
@@ -1,94 +1,3 @@
{
- "_default": {
- "1": {
- "id": "0a380d32-881a-4886-9cd8-a8a84b4e1239",
- "created_at": 1771031906.3919146,
- "updated_at": 1771031906.3919146,
- "child_id": "child1",
- "entity_id": "task1",
- "entity_type": "task",
- "custom_value": 20
- },
- "2": {
- "id": "c3672d1a-3cef-4d11-a492-369aa657014d",
- "created_at": 1771031906.4299235,
- "updated_at": 1771031906.4299235,
- "child_id": "child2",
- "entity_id": "task2",
- "entity_type": "task",
- "custom_value": 25
- },
- "3": {
- "id": "641d7614-8c92-4c93-a157-bca97640d0a8",
- "created_at": 1771031906.4359252,
- "updated_at": 1771031906.4359252,
- "child_id": "child3",
- "entity_id": "task1",
- "entity_type": "task",
- "custom_value": 10
- },
- "4": {
- "id": "ee56c0e9-a468-4e12-bf2c-baef5a06cd83",
- "created_at": 1771031906.4359252,
- "updated_at": 1771031906.4359252,
- "child_id": "child3",
- "entity_id": "task2",
- "entity_type": "task",
- "custom_value": 15
- },
- "5": {
- "id": "19466c51-44fb-4759-ad64-6a62bf423e30",
- "created_at": 1771031906.4359252,
- "updated_at": 1771031906.4359252,
- "child_id": "child3",
- "entity_id": "reward1",
- "entity_type": "reward",
- "custom_value": 100
- },
- "33": {
- "id": "3ac70695-0162-4ddb-b773-14cf31145619",
- "created_at": 1771031913.7219265,
- "updated_at": 1771031913.7219265,
- "child_id": "79f98e0e-c893-4699-a63f-e7ce18e3125f",
- "entity_id": "2e5e9abc-ccbe-4d26-a943-a3d739bc55eb",
- "entity_type": "task",
- "custom_value": 5
- },
- "34": {
- "id": "8b71d091-0918-4077-a793-fc088b59e95c",
- "created_at": 1771031913.7279284,
- "updated_at": 1771031913.7279284,
- "child_id": "9fac1589-718a-4cb5-bda6-bbb58d68b62e",
- "entity_id": "2e5e9abc-ccbe-4d26-a943-a3d739bc55eb",
- "entity_type": "task",
- "custom_value": 20
- },
- "35": {
- "id": "4ad1c2e6-3316-4847-97ba-a895f3cc9c40",
- "created_at": 1771031913.9652154,
- "updated_at": 1771031913.9652154,
- "child_id": "5dcea978-0d41-430b-b321-1645bed1e5b3",
- "entity_id": "b5d9775e-7836-4d17-a2a2-59e4141b6c5f",
- "entity_type": "task",
- "custom_value": 0
- },
- "36": {
- "id": "59eb1477-afbd-4e00-b0a1-13f5636e9360",
- "created_at": 1771031914.2012715,
- "updated_at": 1771031914.2012715,
- "child_id": "5dcea978-0d41-430b-b321-1645bed1e5b3",
- "entity_id": "e84a6c84-2eb3-4097-b3f2-30700b7e666b",
- "entity_type": "task",
- "custom_value": 10000
- },
- "37": {
- "id": "0f00c3d9-bf2c-4812-82de-391c9807a3cb",
- "created_at": 1771031914.4634206,
- "updated_at": 1771031914.4634206,
- "child_id": "27736f73-7c95-47cb-b4e3-476c92c517e7",
- "entity_id": "e08c01ea-90aa-46ab-bb8a-6922d0c71b19",
- "entity_type": "reward",
- "custom_value": 75
- }
- }
+ "_default": {}
}
\ No newline at end of file
diff --git a/frontend/vue-app/package-lock.json b/frontend/vue-app/package-lock.json
index ce15722..6c3a2f5 100644
--- a/frontend/vue-app/package-lock.json
+++ b/frontend/vue-app/package-lock.json
@@ -111,7 +111,6 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
@@ -664,7 +663,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
},
@@ -708,7 +706,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18"
}
@@ -1958,7 +1955,6 @@
"integrity": "sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.46.4",
"@typescript-eslint/types": "8.46.4",
@@ -2714,7 +2710,6 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -2909,7 +2904,6 @@
}
],
"license": "MIT",
- "peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751",
@@ -3415,7 +3409,6 @@
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -3476,7 +3469,6 @@
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
@@ -3524,7 +3516,6 @@
"integrity": "sha512-SbR9ZBUFKgvWAbq3RrdCtWaW0IKm6wwUiApxf3BVTNfqUIo4IQQmreMg2iHFJJ6C/0wss3LXURBJ1OwS/MhFcQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"natural-compare": "^1.4.0",
@@ -4204,7 +4195,6 @@
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
@@ -4982,7 +4972,6 @@
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -5553,7 +5542,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -5692,7 +5680,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -5816,7 +5803,6 @@
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@@ -6037,7 +6023,6 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12"
},
@@ -6051,7 +6036,6 @@
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/expect": "3.2.4",
@@ -6144,7 +6128,6 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.24.tgz",
"integrity": "sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg==",
"license": "MIT",
- "peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.24",
"@vue/compiler-sfc": "3.5.24",