Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 64 additions & 2 deletions BACKEND/controllers/product.controller.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Product from "../models/product.model.js";
import Product from '../models/product.model.js';
import mongoose from "mongoose";
import { escapeRegex } from '../utils/escapeRegex.js';
import cloudinary from '../config/cloudinary.js';
Expand Down Expand Up @@ -202,6 +202,11 @@ export const createProduct = async (req, res, next) => {
export const updateProduct = async (req, res, next) => {
const { id } = req.params;

if (!product.name || !product.price || !product.image) {
return res.status(400).json({ success: false, message: "Please provide all fields" });
}

// ─── VALIDATE TAGS ─────────────────────────────────────────────
if (!mongoose.Types.ObjectId.isValid(id)) {
return next(new AppError("Invalid Product Id format", 404));
}
Expand All @@ -210,6 +215,11 @@ export const updateProduct = async (req, res, next) => {
return next(new AppError("No update fields provided", 400));
}

const newProduct = new Product(product);

try {
await newProduct.save();
res.status(201).json({ success: true, data: newProduct });
let existing;
try {
existing = await Product.findById(id);
Expand Down Expand Up @@ -317,11 +327,17 @@ export const deleteProduct = async (req, res, next) => {
await invalidateProductCache();
res.status(200).json({ success: true, message: "Product deleted successfully" });
} catch (error) {
console.log("error in deleting product:", error.message);
console.error("Error in Create product:", error.message);
res.status(500).json({ success: false, message: "Server Error" });
}
};

export const updateProduct = async (req, res) => {
const { id } = req.params;
const product = req.body;
// ─── SEARCH PRODUCTS (INCLUDING TAGS) ────────────────────────────
export const searchProducts = async (req, res) => {
const { q } = req.query;
// @desc Get product by ID
export const getProductById = async (req, res, next) => {
const { id } = req.params;
Expand All @@ -330,6 +346,27 @@ export const getProductById = async (req, res, next) => {
return next(new AppError("Invalid Product Id format", 404));
}

// ─── VALIDATE TAGS ON UPDATE ────────────────────────────────────
if (product.tags && product.tags.length > 5) {
return res.status(400).json({
success: false,
message: "Maximum 5 tags allowed per product"
});
}

try {
const updatedProduct = await Product.findByIdAndUpdate(id, product, {
new: true,
runValidators: true
});

if (!updatedProduct) {
return res.status(404).json({ success: false, message: "Product not found" });
}

res.status(200).json({ success: true, data: updatedProduct });
} catch (error) {
console.error("Update error:", error);
try {
const product = await Product.findOne({ _id: id, isDeleted: { $ne: true } });
if (!product) {
Expand Down Expand Up @@ -423,6 +460,7 @@ export const getRelatedProducts = async (req, res) => {
}
};

export const deleteProduct = async (req, res) => {
export const getProductBundle = async (req, res) => {
const { id } = req.params;

Expand All @@ -431,6 +469,10 @@ export const getProductBundle = async (req, res) => {
}

try {
await Product.findByIdAndDelete(id);
res.status(200).json({ success: true, message: "Product deleted" });
} catch (error) {
console.log("error in deleting product:", error.message);
const product = await Product.findById(id).populate('complementaryItems.product');
if (!product || product.isDeleted === true) {
return res.status(404).json({ success: false, message: "Product not found" });
Expand Down Expand Up @@ -467,6 +509,25 @@ export const getProductBundle = async (req, res) => {
}
};

// ─── SEARCH PRODUCTS (INCLUDING TAGS) ────────────────────────────
export const searchProducts = async (req, res) => {
const { q } = req.query;

if (!q) {
return res.status(400).json({ success: false, message: "Search query required" });
}

try {
const regex = new RegExp(q, 'i');

const products = await Product.find({
$or: [
{ name: regex },
{ tags: { $in: [regex] } }
]
});

res.status(200).json({ success: true, data: products });
// @desc Search products
export const searchProducts = async (req, res, next) => {
const { q } = req.query;
Expand All @@ -491,3 +552,4 @@ export const searchProducts = async (req, res, next) => {
next(error);
}
};
};
20 changes: 19 additions & 1 deletion BACKEND/models/product.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,25 @@ const productSchema = new mongoose.Schema({
type: [String],
default: [],
},


// ─── TAGS ──────────────────────────────────────────────────────
tags: {
type: [String],
default: [],
validate: {
validator: function (tags) {
return tags.length <= 5 && tags.every(tag => tag.length >= 2 && tag.length <= 30);
},
message: "Maximum 5 tags, each 2-30 characters"
}
}
}, {
timestamps: true
});

const Product = mongoose.model("Product", productSchema);

export default Product;
// Optional Fields - Extra Product Details
description: {
type: String,
Expand Down
Loading
Loading