Applicatie afmaken en GUI-flow herstellen
Voegt boodschappenlijsten, productbeheer, realtime synchronisatie en browsercache-updates toe. Herstelt login- en sessiegedrag en maakt database-seeding herhaalbaar.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -19,11 +19,14 @@ class AuthController {
|
||||
|
||||
async register(req, res) {
|
||||
|
||||
const {
|
||||
name,
|
||||
email,
|
||||
password
|
||||
} = req.body;
|
||||
const name = (req.body.name || "").trim();
|
||||
const email = (req.body.email || "").trim().toLowerCase();
|
||||
const password = req.body.password || "";
|
||||
|
||||
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.");
|
||||
return res.redirect("/register");
|
||||
}
|
||||
|
||||
|
||||
const existingUser = db.prepare(
|
||||
@@ -97,10 +100,8 @@ class AuthController {
|
||||
|
||||
async login(req, res) {
|
||||
|
||||
const {
|
||||
email,
|
||||
password
|
||||
} = req.body;
|
||||
const email = (req.body.email || "").trim().toLowerCase();
|
||||
const password = req.body.password || "";
|
||||
|
||||
|
||||
const user = db.prepare(
|
||||
|
||||
@@ -1,29 +1,50 @@
|
||||
const ProductService =
|
||||
require("../services/ProductService");
|
||||
|
||||
const db = require("../config/database");
|
||||
|
||||
class ProductController {
|
||||
|
||||
|
||||
index(req,res) {
|
||||
|
||||
index(req, res) {
|
||||
|
||||
const products =
|
||||
ProductService.getProducts();
|
||||
|
||||
const categories = db.prepare(
|
||||
"SELECT * FROM categories ORDER BY name"
|
||||
).all();
|
||||
|
||||
res.render(
|
||||
"products/index",
|
||||
{
|
||||
|
||||
title:"Producten",
|
||||
|
||||
products
|
||||
|
||||
products,
|
||||
categories
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
create(req, res) {
|
||||
const name = (req.body.name || "").trim();
|
||||
const categoryId = req.body.category_id
|
||||
? Number.parseInt(req.body.category_id, 10)
|
||||
: null;
|
||||
|
||||
if (!name || (categoryId !== null && !Number.isInteger(categoryId))) {
|
||||
req.flash("error", "Geef een geldige productnaam en categorie op.");
|
||||
return res.redirect("/products");
|
||||
}
|
||||
|
||||
ProductService.createProduct({
|
||||
name,
|
||||
category_id: categoryId
|
||||
});
|
||||
|
||||
req.flash("success", "Product toegevoegd.");
|
||||
res.redirect("/products");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
const ProductRepository = require("../repositories/ProductRepository");
|
||||
const ShoppingListRepository = require("../repositories/ShoppingListRepository");
|
||||
|
||||
class ShoppingListController {
|
||||
index(req, res) {
|
||||
const lists = ShoppingListRepository.getByHousehold(req.user.household_id);
|
||||
res.locals.title = "Boodschappenlijsten";
|
||||
res.render("lists/index", { lists, user: req.user });
|
||||
}
|
||||
|
||||
create(req, res) {
|
||||
const name = (req.body.name || "").trim();
|
||||
if (!name) {
|
||||
req.flash("error", "Geef een lijstnaam op");
|
||||
return res.redirect("/lists");
|
||||
}
|
||||
ShoppingListRepository.create(req.user.household_id, name);
|
||||
req.flash("success", "Boodschappenlijst aangemaakt");
|
||||
res.redirect("/lists");
|
||||
}
|
||||
|
||||
show(req, res) {
|
||||
const list = ShoppingListRepository.findById(req.params.id, req.user.household_id);
|
||||
if (!list) return res.status(404).render("errors/404");
|
||||
res.locals.title = list.name;
|
||||
res.render("lists/show", {
|
||||
list,
|
||||
items: ShoppingListRepository.getItems(list.id),
|
||||
products: ProductRepository.getAll(),
|
||||
user: req.user
|
||||
});
|
||||
}
|
||||
|
||||
addItem(req, res) {
|
||||
const list = ShoppingListRepository.findById(req.params.id, req.user.household_id);
|
||||
const productId = Number.parseInt(req.body.product_id, 10);
|
||||
const amount = Number.parseFloat(req.body.amount || "1");
|
||||
const product = Number.isInteger(productId) ? ProductRepository.findById(productId) : null;
|
||||
if (!list || !product || !Number.isFinite(amount) || amount <= 0) {
|
||||
req.flash("error", "Ongeldig product of ongeldige hoeveelheid");
|
||||
return res.redirect(`/lists/${req.params.id}`);
|
||||
}
|
||||
ShoppingListRepository.addItem(list.id, product.id, amount);
|
||||
res.redirect(`/lists/${list.id}`);
|
||||
}
|
||||
|
||||
toggleItem(req, res) {
|
||||
const list = ShoppingListRepository.findById(req.params.id, req.user.household_id);
|
||||
if (!list) return res.status(404).render("errors/404");
|
||||
ShoppingListRepository.toggleItem(list.id, req.params.itemId);
|
||||
this.broadcastUpdate(req, list.id);
|
||||
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" });
|
||||
const result = ShoppingListRepository.deleteItem(list.id, req.params.itemId);
|
||||
if (result.changes === 0) return res.status(404).json({ error: "Product niet gevonden" });
|
||||
this.broadcastUpdate(req, list.id);
|
||||
res.json({ success: true });
|
||||
}
|
||||
|
||||
broadcastUpdate(req, listId) {
|
||||
if (req.app.locals.io) {
|
||||
req.app.locals.io.to(`list:${listId}`).emit("list:updated", { listId });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ShoppingListController();
|
||||
Reference in New Issue
Block a user