From 61d2a258fc2cdb4b556894a54ae75b80b4307ef6 Mon Sep 17 00:00:00 2001 From: Casey Timm Date: Mon, 7 Jul 2025 21:43:36 -0400 Subject: [PATCH] Add account management features and integrate Tailwind CSS typography - Implement setAccountInTotal and deleteBudget functions in db.js - Update budget handling in the budget server API - Add DELETE endpoint for budget removal - Enhance account page with delete functionality and confirmation modal - Include @tailwindcss/typography in package.json and app.css --- package-lock.json | 72 +++++++++++++ package.json | 1 + src/app.css | 3 +- src/lib/db.js | 30 ++++-- src/routes/+layout.svelte | 12 +-- src/routes/account/[slug]/+page.svelte | 4 + src/routes/api/account/[slug]/+server.js | 25 +++++ src/routes/api/budget/[slug]/+server.js | 11 ++ src/routes/api/simplefin/update/+server.js | 3 +- src/routes/budget/+server.js | 4 +- src/routes/budget/[slug]/+page.server.js | 1 + src/routes/budget/[slug]/+page.svelte | 112 +++++++++++++++------ 12 files changed, 233 insertions(+), 45 deletions(-) create mode 100644 src/routes/api/account/[slug]/+server.js create mode 100644 src/routes/api/budget/[slug]/+server.js diff --git a/package-lock.json b/package-lock.json index 5954c32..4dd4396 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@sveltejs/adapter-auto": "^6.0.0", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@tailwindcss/typography": "^0.5.16", "daisyui": "^5.0.43", "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.3", @@ -1104,6 +1105,22 @@ "node": ">= 10" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" + } + }, "node_modules/@tailwindcss/vite": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", @@ -1193,6 +1210,19 @@ "node": ">= 0.6" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/daisyui": { "version": "5.0.43", "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.0.43.tgz", @@ -1615,6 +1645,27 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", @@ -1751,6 +1802,20 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/postgres": { "version": "3.4.7", "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.7.tgz", @@ -1958,6 +2023,13 @@ "node": ">=6" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, "node_modules/vite": { "version": "6.3.5", "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", diff --git a/package.json b/package.json index 2fd8a78..cda814f 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@sveltejs/adapter-auto": "^6.0.0", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@tailwindcss/typography": "^0.5.16", "daisyui": "^5.0.43", "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.3", diff --git a/src/app.css b/src/app.css index 74d8662..017cf90 100644 --- a/src/app.css +++ b/src/app.css @@ -1,2 +1,3 @@ @import "tailwindcss"; -@plugin "daisyui"; \ No newline at end of file +@plugin "daisyui"; +@plugin "@tailwindcss/typography"; \ No newline at end of file diff --git a/src/lib/db.js b/src/lib/db.js index d02b6f0..b5dbd5e 100644 --- a/src/lib/db.js +++ b/src/lib/db.js @@ -3,13 +3,30 @@ import postgres from 'postgres' const db = postgres({ host:'192.168.1.126', username:'budget', password:'budget', database:'budget'}) // will use psql environment variables +export async function setAccountInTotal(accountId, total) { + return await db` + update account + set in_total = ${total} + where id = ${accountId} + ` +} + +export async function deleteBudget(id) { + return await db` + UPDATE budget + SET delete = true + WHERE id = ${id} + ` +} + export async function createBudgetTable() { return await db` create table if not exists budget ( id serial primary key, name text not null, amount numeric(10,2) not null, - notes text + notes text, + delete boolean default false ) ` } @@ -112,7 +129,8 @@ export async function getBudgets() { budget.name as name, budget.amount as amount, budget.notes as notes - from budget + from budget + WHERE budget.delete is false ` if (!budgets) { await createBudgetTable(); @@ -230,15 +248,15 @@ export async function updateAccounts(data) { } console.log(`Preparing to upsert transaction: ${txn.id} with data:`, txn); await db` - insert into transaction (id, account_id, posted, amount, description, pending, extra_id) + insert into transaction (id, account_id, posted, amount, description, pending, transacted_at) values ( ${txn.id}, ${account.id}, ${txn.posted}, ${txn.amount ?? null}, ${txn.description ?? null}, - ${txn.pending}, - ${extraId} + ${txn.pending ?? false}, + ${txn.transacted_at ?? 0} ) on conflict (id) do update set account_id = excluded.account_id, @@ -246,7 +264,7 @@ export async function updateAccounts(data) { amount = excluded.amount, description = excluded.description, pending = excluded.pending, - extra_id = excluded.extra_id + transacted_at = excluded.transacted_at `; } } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index a0cf94d..001fbf1 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -7,11 +7,11 @@ amount: 0, notes: '' }); - async function update() { - let res = await fetch('/api/simplefin/update', { - method: 'POST' - }); - } + async function update() { + let res = await fetch('/api/simplefin/update', { + method: 'POST' + }); + } async function saveBudget() { let res = await fetch('/budget', { method: 'POST', @@ -45,7 +45,7 @@