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 acb1895..e94e8ea 100644 Binary files a/database.sqlite-shm and b/database.sqlite-shm differ diff --git a/database.sqlite-wal b/database.sqlite-wal index 2074094..7926930 100644 Binary files a/database.sqlite-wal and b/database.sqlite-wal differ 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 82b9c08..60c59e0 100644 Binary files a/sessions.sqlite and b/sessions.sqlite differ diff --git a/views/auth/register.ejs b/views/auth/register.ejs index db86ba1..9be667c 100644 --- a/views/auth/register.ejs +++ b/views/auth/register.ejs @@ -55,6 +55,13 @@ +
+ + +
Vul de code in als je bij een bestaand huishouden wilt aansluiten.
+
+