Files
PantryHub/controllers/ShoppingListController.js
T

154 lines
6.3 KiB
JavaScript

const ProductRepository = require("../repositories/ProductRepository");
const ShoppingListRepository = require("../repositories/ShoppingListRepository");
const FavoriteService = require("../services/FavoriteService");
const CategoryService = require("../services/CategoryService");
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");
const items = ShoppingListRepository.getItems(list.id, req.user.household_id);
const existingProductIds = new Set(items.map(item => item.product_id));
res.locals.title = list.name;
res.render("lists/show", {
list,
items,
products: ProductRepository.getAll(req.user.household_id)
.filter(product => !existingProductIds.has(product.id)),
categories: CategoryService.getCategories(req.user.household_id),
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, req.user.household_id)
: null;
if (!list || !product || ShoppingListRepository.hasProduct(list.id, product.id) ||
!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}`);
}
updateItemAmount(req, res) {
const list = ShoppingListRepository.findById(req.params.id, req.user.household_id);
const amount = Number.parseFloat(req.body.amount || "");
if (!list || !Number.isFinite(amount) || amount <= 0) {
req.flash("error", "Geef een geldige hoeveelheid op.");
return res.redirect(`/lists/${req.params.id}`);
}
const result = ShoppingListRepository.updateItemAmount(list.id, req.params.itemId, amount);
if (result.changes === 0) {
req.flash("error", "Product niet gevonden op deze lijst.");
return res.redirect(`/lists/${req.params.id}`);
}
this.broadcastUpdate(req, list.id);
req.flash("success", "Hoeveelheid gewijzigd.");
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}`);
}
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}`);
}
clearItems(req, res) {
const list = ShoppingListRepository.findById(req.params.id, req.user.household_id);
if (!list) return res.status(404).render("errors/404");
ShoppingListRepository.clearItems(list.id);
this.broadcastUpdate(req, list.id);
req.flash("success", "Alle producten zijn verwijderd uit de lijst.");
res.redirect(`/lists/${list.id}`);
}
addFavoriteProducts(req, res) {
const list = ShoppingListRepository.findById(req.params.id, req.user.household_id);
if (!list) return res.status(404).render("errors/404");
const favorites = FavoriteService.getFavorites(req.user.id, req.user.household_id);
const items = favorites.map((favorite) => ({
list_id: list.id,
product_id: favorite.id,
amount: 1,
checked: 0,
sort_order: 0
}));
if (items.length === 0) {
req.flash("info", "Je hebt nog geen favorieten om toe te voegen.");
return res.redirect(`/lists/${list.id}`);
}
ShoppingListRepository.addItems(list.id, items);
this.broadcastUpdate(req, list.id);
req.flash("success", `${items.length} favoriete producten toegevoegd aan de lijst.`);
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 });
}
deleteList(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.deleteList(list.id);
if (result.changes === 0) return res.status(404).json({ error: "Lijst 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();