From 7ef4852efd5710320f2b9463db6188565cb38c78 Mon Sep 17 00:00:00 2001 From: Jurgen Rentinck Date: Sun, 9 Aug 2026 19:55:00 +0200 Subject: [PATCH] zie vorige message --- controllers/AuthController.js | 22 ++++++++++++++++++---- controllers/ShoppingListController.js | 9 +++++++++ database.sqlite-shm | Bin 32768 -> 32768 bytes database.sqlite-wal | Bin 329632 -> 391432 bytes public/css/style.css | 8 ++++++++ public/manifest.json | 6 ------ repositories/ShoppingListRepository.js | 8 ++++++++ routes/web.js | 6 ++++++ services/HouseholdService.js | 17 +++++++++++++++++ sessions.sqlite | Bin 20480 -> 24576 bytes views/auth/register.ejs | 7 +++++++ views/household/index.ejs | 4 ++-- views/lists/show.ejs | 14 +++++++++++--- views/partials/head.ejs | 12 ++++++++++++ views/partials/navbar.ejs | 1 - 15 files changed, 98 insertions(+), 16 deletions(-) diff --git a/controllers/AuthController.js b/controllers/AuthController.js index b29406c..95f73ae 100644 --- a/controllers/AuthController.js +++ b/controllers/AuthController.js @@ -22,6 +22,7 @@ class AuthController { const name = (req.body.name || "").trim(); const email = (req.body.email || "").trim().toLowerCase(); const password = req.body.password || ""; + const inviteCode = (req.body.household_code || "").trim(); if (name.length < 2 || !/^\S+@\S+\.\S+$/.test(email) || password.length < 8) { req.flash("error", "Vul een naam, geldig e-mailadres en een wachtwoord van minimaal 8 tekens in."); @@ -45,6 +46,15 @@ class AuthController { } + const invitedHousehold = inviteCode + ? HouseholdService.findByInviteCode(inviteCode) + : null; + + if (inviteCode && !invitedHousehold) { + req.flash("error", "De huishoudcode bestaat niet."); + return res.redirect("/register"); + } + const passwordHash = await bcrypt.hash( password, @@ -73,10 +83,14 @@ class AuthController { const userId = result.lastInsertRowid; - HouseholdService.createForUser( - userId, - `${name} huishouden` - ); + if (invitedHousehold) { + HouseholdService.addMember(invitedHousehold.id, userId); + } else { + HouseholdService.createForUser( + userId, + `${name} huishouden` + ); + } req.session.userId = userId; diff --git a/controllers/ShoppingListController.js b/controllers/ShoppingListController.js index 5fdc169..00dc966 100644 --- a/controllers/ShoppingListController.js +++ b/controllers/ShoppingListController.js @@ -54,6 +54,15 @@ class ShoppingListController { res.redirect(`/lists/${list.id}`); } + resetItems(req, res) { + const list = ShoppingListRepository.findById(req.params.id, req.user.household_id); + if (!list) return res.status(404).render("errors/404"); + ShoppingListRepository.resetItems(list.id); + this.broadcastUpdate(req, list.id); + req.flash("success", "Alle producten staan weer open."); + res.redirect(`/lists/${list.id}`); + } + deleteItem(req, res) { const list = ShoppingListRepository.findById(req.params.id, req.user.household_id); if (!list) return res.status(404).json({ error: "Lijst niet gevonden" }); diff --git a/database.sqlite-shm b/database.sqlite-shm index acb1895fb3a56edbbbb62277c3970f7c8b4b67dd..e94e8ea6fe3211686bc89c17efe2acba23a92bc8 100644 GIT binary patch delta 278 zcmZo@U}|V!s+V}A%K!p$K+MR%AP^6v1%de5jWkx#iFSXFiHUoy6kV4WoML@LxF~2Y zsp^47fdRCwm}6FheLq zI8fv;)8=n}B0P*CK=wnX$!}u07{h?f&rFkFCGar@0h#ZaCcj9Q;E!O4WQbyjW{6>k NWr$;l2TFXD1^^K@M}PnT delta 193 zcmZo@U}|V!s+V}A%K!qxK+MR%AP@kg1%cR%H{p7-x|Q-VF>$YzqU-XOCuuI)U}YLl zs(PSNU;r}rKN5fnZ>;xZ+|0uC%VDwrlg;LTPI{c1nV3#7ZT{vb!UJSIVw(IWmJ7)E W!Zi6+0w0j^fobxKWQoO0Ofmqx(>Z|v diff --git a/database.sqlite-wal b/database.sqlite-wal index 207409415a7297ad7deadeeeb09b3e42e6bd250a..7926930097fc146bc4808cb98ba4734862251268 100644 GIT binary patch delta 1227 zcmZ3`FVgWzyrG4$g{g(Pg=Gut0`|!P3IZH{uX~tRo&L3DyTEjoh5U>h(>E<+Nt~>` zkyjz(?JPgOgZc}285kHi_|7r#U*TWR-^riMZ^h5Y_m1z}#=vcS3UVB542+^2#wGJh_=3*U|H>)col@u{f@voT1D8Z$5K9P-qpLlh(dD$7X85xWj-HS3)vx`#|D)ZAbN{dQ_ z(Hw1QWnj*-{UIysenxP-s0ylnOFq>N4zXT-V=f^!W=+Q8jQoOv%)IpYoXp~qVq)BH z3UWUWvisMCPPdwKv{Dlktz3Mk8TcRZALd`o-^!oH@4>Ih&&Bte@ASsN^}wj*;$UE8 zWaQv5=HO+(t6bVT-h;JUSbXAB-UWL`EsAKH*QuW z)?lJt9Cab(nJUYsrNkOcw2Ms{*Vs{+D#NC)?mUe-Ut9)dQ6Z2 delta 19 acmeD9B)*_uq@jheg{g(Pg=Gut0(JmRs|L>i diff --git a/public/css/style.css b/public/css/style.css index 32aeb69..79798ca 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -47,6 +47,14 @@ body { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto; gap: .5rem; margin-top: 1.5rem; + +.list-check-button { + width: 2.5rem; + height: 2.5rem; + padding: 0; + font-size: 1.35rem; + line-height: 1; +} align-items: stretch; } diff --git a/public/manifest.json b/public/manifest.json index 08d60c5..b918294 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -8,12 +8,6 @@ "background_color": "#ffffff", "theme_color": "#0066cc", "icons": [ - { - "src": "/icons/icon.svg", - "sizes": "any", - "type": "image/svg+xml", - "purpose": "any" - }, { "src": "/icons/icon.svg", "sizes": "any", diff --git a/repositories/ShoppingListRepository.js b/repositories/ShoppingListRepository.js index 855b8cd..73e1ed3 100644 --- a/repositories/ShoppingListRepository.js +++ b/repositories/ShoppingListRepository.js @@ -62,6 +62,14 @@ class ShoppingListRepository { `).run(itemId, listId); } + resetItems(listId) { + return db.prepare(` + UPDATE shopping_list_items + SET checked = 0 + WHERE list_id = ? + `).run(listId); + } + deleteItem(listId, itemId) { return db.prepare(` DELETE FROM shopping_list_items WHERE id = ? AND list_id = ? diff --git a/routes/web.js b/routes/web.js index 8c42885..26d3c6f 100644 --- a/routes/web.js +++ b/routes/web.js @@ -167,6 +167,12 @@ router.post( ShoppingListController.toggleItem.bind(ShoppingListController) ); +router.post( + "/lists/:id/items/reset", + auth, + ShoppingListController.resetItems.bind(ShoppingListController) +); + router.delete( "/lists/:id/items/:itemId", auth, diff --git a/services/HouseholdService.js b/services/HouseholdService.js index 09bac43..5d95986 100644 --- a/services/HouseholdService.js +++ b/services/HouseholdService.js @@ -3,6 +3,23 @@ const db = require("../config/database"); class HouseholdService { + findByInviteCode(code) { + const match = /^HOUSEHOLD_(\d+)$/.exec((code || "").trim().toUpperCase()); + if (!match) return null; + + return db.prepare( + "SELECT id FROM households WHERE id = ?" + ).get(Number.parseInt(match[1], 10)); + } + + + addMember(householdId, userId) { + return db.prepare(` + INSERT INTO household_members (household_id, user_id, role) + VALUES (?, ?, 'MEMBER') + `).run(householdId, userId); + } + createForUser(userId, name) { diff --git a/sessions.sqlite b/sessions.sqlite index 82b9c083a5e4f32265a5db3445842649667f6a98..60c59e0fc488e847685f1e79ed08201806820c05 100644 GIT binary patch delta 717 zcmZozz}Rqrae@>d3m*dm0~-`GPSh}CV&U7Eu%4gs+hzfQXZ%t?8P*se!Q#dRB;~nV z8F)AF{^GsLy=pR_f*1?`MDEtj8Vb?eUMkGKi~$BF$rk0^`Q5GlWd{!>TeGIQB7Vh2rTA+n# z^F*O4rp+%!g}5gFw&!HwXB1(WEZ`u`EyA-BXdVbSPIMI3XbgyD^=&e?CFI`8hK>%L zCKgsEhI*DJrjswa1e;rg7@Avwgv|6z%?zR%17g4?5%Lt0Nfs6sAd~puCIJmMG~4{l zv7DWW%X)IW=N%RX2By5t_FhLAHJTX{SbbYXiE=52iKUf^iJrN|56`C#Mz{D_KP=g{S6Z=jSSvq!yK?D|nR_rKjd81f}McWacGj lD=Nj->L`^KrxtmpC|Q}-8W|Xw=^9w-8bE^1(h6c`6aay>%k=;N delta 348 zcmZoTz}T>Wae@>dvo`|+11k`N!9)!+CT8!A3G4Y8eK!jTJmZ%zGO#i>15UY#tUAjZPIihtr}Ern?Ai4E$iD$Kr&K7rn;1sT~Pxdooy{z1jbmcdzN z{$5GB+0Ip^y7~Dzv766p8?o@S?PlO%eZj!{oY#bJ7C*?QbF7>|n~V(fOpFaCKNr2i z0<`S%=KW@_oEk!moD4i$xF2%!aanV8v2W+s<%{BNXS>P9#%j!xz}(BUi!+1qIV0y} zLxJ61bup~I&HT1_+|d{v%j(`I%!mI}-!L +
+ + +
Vul de code in als je bij een bestaand huishouden wilt aansluiten.
+
+