Learn how store employees can create, update, and manage menu items with images, pricing, and availability controls.
CampusBite’s menu management system allows store employees to maintain their restaurant’s menu with full control over items, pricing, categories, and availability status.
Images are optional when creating menu items. If you provide an image, it’s uploaded via multipart form data and stored using the configured upload middleware.
You can update any aspect of a menu item, including its availability status, price, or image.
backend/src/controllers/menuController.js
export const updateMenuItem = async (req, res, next) => { try { const { id } = req.params; const userId = req.user.id; // Find and populate store info const item = await MenuItem.findById(id).populate('store_id', 'owner_id'); if (!item) { return res.status(404).json({ success: false, message: 'Menu item not found.', }); } // Verify authorization if (item.store_id.owner_id.toString() !== userId) { return res.status(403).json({ success: false, message: 'You are not authorized to update this menu item.', }); } const { name, description, price, category, is_available } = req.body; // Update fields if (name) item.name = name; if (description !== undefined) item.description = description; if (price !== undefined) item.price = Number(price); if (category !== undefined) item.category = category; if (is_available !== undefined) { item.is_available = is_available === true || is_available === 'true'; } // Update image if provided if (req.file) { item.image_url = resolveUploadedFilePath(req.file.filename); } await item.save(); res.json({ success: true, message: 'Menu item updated successfully.', data: { menuItem: formatMenuItem(item) }, }); } catch (error) { next(error); }};
Only the store owner can update menu items. The system validates that the authenticated user owns the store associated with the menu item before allowing any modifications.
The client sends a POST or PUT request with Content-Type: multipart/form-data including the image file.
2
Multer middleware processes file
The upload middleware intercepts the request and handles the file upload, saving it to the configured directory.
3
Generate file path
The resolveUploadedFilePath() function generates the public URL for the uploaded image.
4
Store URL in database
The image URL is saved in the menu item’s image_url field.
Example upload usage
import { resolveUploadedFilePath } from '../config/uploads.js';// In controller after file is uploadedif (req.file) { imageUrl = resolveUploadedFilePath(req.file.filename);}
All menu management operations verify that the authenticated user owns the store associated with the menu item.
Authorization pattern
// Find item with store informationconst item = await MenuItem.findById(id).populate('store_id', 'owner_id');if (!item) { return res.status(404).json({ success: false, message: 'Menu item not found.', });}// Verify ownershipif (item.store_id.owner_id.toString() !== userId) { return res.status(403).json({ success: false, message: 'You are not authorized to update this menu item.', });}
The authorization check uses .populate('store_id', 'owner_id') to fetch only the owner_id field from the related Store document, minimizing database overhead while ensuring secure access control.