const List = require("../models/list.model.v2"); const { isValidItemType, isValidItemGroup, isValidZone } = require("../constants/classifications"); /** * Get list items for household and store * GET /households/:householdId/stores/:storeId/list */ exports.getList = async (req, res) => { try { const { householdId, storeId } = req.params; const items = await List.getHouseholdStoreList(householdId, storeId); res.json({ items }); } catch (error) { console.error("Error getting list:", error); res.status(500).json({ message: "Failed to get list" }); } }; /** * Get specific item by name * GET /households/:householdId/stores/:storeId/list/item */ exports.getItemByName = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name } = req.query; if (!item_name) { return res.status(400).json({ message: "Item name is required" }); } const item = await List.getItemByName(householdId, storeId, item_name); if (!item) { return res.status(404).json({ message: "Item not found" }); } res.json(item); } catch (error) { console.error("Error getting item:", error); res.status(500).json({ message: "Failed to get item" }); } }; /** * Add or update item in household store list * POST /households/:householdId/stores/:storeId/list/add */ exports.addItem = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name, quantity, notes } = req.body; const userId = req.user.id; if (!item_name || item_name.trim() === "") { return res.status(400).json({ message: "Item name is required" }); } // Get processed image if uploaded const imageBuffer = req.processedImage?.buffer || null; const mimeType = req.processedImage?.mimeType || null; const result = await List.addOrUpdateItem( householdId, storeId, item_name, quantity || "1", userId, imageBuffer, mimeType, notes ); // Add history record await List.addHistoryRecord(result.listId, quantity || "1", userId); res.json({ message: result.isNew ? "Item added" : "Item updated", item: { id: result.listId, item_name: result.itemName, quantity: quantity || "1", bought: false } }); } catch (error) { console.error("Error adding item:", error); res.status(500).json({ message: "Failed to add item" }); } }; /** * Mark item as bought or unbought * PATCH /households/:householdId/stores/:storeId/list/item */ exports.markBought = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name, bought, quantity_bought } = req.body; if (!item_name) return res.status(400).json({ message: "Item name is required" }); const item = await List.getItemByName(householdId, storeId, item_name); if (!item) return res.status(404).json({ message: "Item not found" }); // Update bought status (with optional partial purchase) await List.setBought(item.id, bought, quantity_bought); res.json({ message: bought ? "Item marked as bought" : "Item unmarked" }); } catch (error) { console.error("Error marking bought:", error); res.status(500).json({ message: "Failed to update item" }); } }; /** * Update item details (quantity, notes) * PUT /households/:householdId/stores/:storeId/list/item */ exports.updateItem = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name, quantity, notes } = req.body; if (!item_name) { return res.status(400).json({ message: "Item name is required" }); } // Get the list item const item = await List.getItemByName(householdId, storeId, item_name); if (!item) { return res.status(404).json({ message: "Item not found" }); } // Update item await List.updateItem(item.id, item_name, quantity, notes); res.json({ message: "Item updated", item: { id: item.id, item_name, quantity, notes } }); } catch (error) { console.error("Error updating item:", error); res.status(500).json({ message: "Failed to update item" }); } }; /** * Delete item from list * DELETE /households/:householdId/stores/:storeId/list/item */ exports.deleteItem = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name } = req.body; if (!item_name) { return res.status(400).json({ message: "Item name is required" }); } // Get the list item const item = await List.getItemByName(householdId, storeId, item_name); if (!item) { return res.status(404).json({ message: "Item not found" }); } await List.deleteItem(item.id); res.json({ message: "Item deleted" }); } catch (error) { console.error("Error deleting item:", error); res.status(500).json({ message: "Failed to delete item" }); } }; /** * Get item suggestions based on query * GET /households/:householdId/stores/:storeId/list/suggestions */ exports.getSuggestions = async (req, res) => { try { const { householdId, storeId } = req.params; const { query } = req.query; const suggestions = await List.getSuggestions(query || "", householdId, storeId); res.json(suggestions); } catch (error) { console.error("Error getting suggestions:", error); res.status(500).json({ message: "Failed to get suggestions" }); } }; /** * Get recently bought items * GET /households/:householdId/stores/:storeId/list/recent */ exports.getRecentlyBought = async (req, res) => { try { const { householdId, storeId } = req.params; const items = await List.getRecentlyBoughtItems(householdId, storeId); res.json(items); } catch (error) { console.error("Error getting recent items:", error); res.status(500).json({ message: "Failed to get recent items" }); } }; /** * Get item classification * GET /households/:householdId/stores/:storeId/list/classification */ exports.getClassification = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name } = req.query; if (!item_name) { return res.status(400).json({ message: "Item name is required" }); } // Get item ID from name const item = await List.getItemByName(householdId, storeId, item_name); if (!item) { return res.json({ classification: null }); } const classification = await List.getClassification(householdId, item.item_id); res.json({ classification }); } catch (error) { console.error("Error getting classification:", error); res.status(500).json({ message: "Failed to get classification" }); } }; /** * Set/update item classification * POST /households/:householdId/stores/:storeId/list/classification */ exports.setClassification = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name, classification } = req.body; if (!item_name) { return res.status(400).json({ message: "Item name is required" }); } if (!classification) { return res.status(400).json({ message: "Classification is required" }); } // Validate classification const validClassifications = ['produce', 'dairy', 'meat', 'bakery', 'frozen', 'pantry', 'snacks', 'beverages', 'household', 'other']; if (!validClassifications.includes(classification)) { return res.status(400).json({ message: "Invalid classification value" }); } // Get item - add to master items if not exists const item = await List.getItemByName(householdId, storeId, item_name); let itemId; if (!item) { // Item doesn't exist in list, need to get from items table or create const itemResult = await List.addOrUpdateItem( householdId, storeId, item_name, "1", req.user.id, null, null ); itemId = itemResult.itemId; } else { itemId = item.item_id; } // Set classification (using item_type field for simplicity) await List.upsertClassification(householdId, itemId, { item_type: classification, item_group: null, zone: null }); res.json({ message: "Classification set", classification }); } catch (error) { console.error("Error setting classification:", error); res.status(500).json({ message: "Failed to set classification" }); } }; /** * Update item image * POST /households/:householdId/stores/:storeId/list/update-image */ exports.updateItemImage = async (req, res) => { try { const { householdId, storeId } = req.params; const { item_name, quantity } = req.body; const userId = req.user.id; // Get processed image const imageBuffer = req.processedImage?.buffer || null; const mimeType = req.processedImage?.mimeType || null; if (!imageBuffer) { return res.status(400).json({ message: "No image provided" }); } // Update the item with new image await List.addOrUpdateItem(householdId, storeId, item_name, quantity, userId, imageBuffer, mimeType); res.json({ message: "Image updated successfully" }); } catch (error) { console.error("Error updating image:", error); res.status(500).json({ message: "Failed to update image" }); } };