Wire up MongoDB and implement all CRUD route handlers
- Enable MongoDB connection in server - Add Customer and Expense models - Implement full CRUD for products, orders, customers, expenses - Implement analytics dashboard with revenue, sales chart, top products/customers - Add MongoDB service to docker-compose.deploy.yml with persistent volume Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0ebcc26425
commit
87e4147e8c
9 changed files with 410 additions and 93 deletions
|
|
@ -35,9 +35,12 @@ services:
|
|||
- NODE_ENV=production
|
||||
- PORT=8080
|
||||
- CLIENT_URL=http://nginx
|
||||
- MONGODB_URI=mongodb://mongodb:27017/etsy-tracker
|
||||
volumes:
|
||||
- etsy_data:/app/data
|
||||
- etsy_uploads:/app/uploads
|
||||
depends_on:
|
||||
- mongodb
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- etsy-network
|
||||
|
|
@ -48,11 +51,28 @@ services:
|
|||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
mongodb:
|
||||
image: mongo:7
|
||||
container_name: etsy-mongodb
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- etsy_mongodb:/data/db
|
||||
networks:
|
||||
- etsy-network
|
||||
healthcheck:
|
||||
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 20s
|
||||
|
||||
volumes:
|
||||
etsy_uploads:
|
||||
driver: local
|
||||
etsy_data:
|
||||
driver: local
|
||||
etsy_mongodb:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
etsy-network:
|
||||
|
|
|
|||
|
|
@ -54,12 +54,9 @@ app.get('/health', (req, res) => {
|
|||
});
|
||||
});
|
||||
|
||||
// Database connection (temporarily disabled for development)
|
||||
// mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/etsy-tracker')
|
||||
// .then(() => console.log('Connected to MongoDB'))
|
||||
// .catch((error) => console.error('MongoDB connection error:', error));
|
||||
|
||||
console.log('Running in development mode without MongoDB - using in-memory storage');
|
||||
mongoose.connect(process.env.MONGODB_URI || 'mongodb://localhost:27017/etsy-tracker')
|
||||
.then(() => console.log('Connected to MongoDB'))
|
||||
.catch((error) => console.error('MongoDB connection error:', error));
|
||||
|
||||
// Routes
|
||||
app.use('/api/auth', authRoutes);
|
||||
|
|
|
|||
44
server/src/models/Customer.ts
Normal file
44
server/src/models/Customer.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import mongoose, { Document, Schema } from 'mongoose';
|
||||
|
||||
export interface ICustomer extends Document {
|
||||
name: string;
|
||||
email: string;
|
||||
etsyUserId?: string;
|
||||
address?: {
|
||||
street1: string;
|
||||
street2?: string;
|
||||
city: string;
|
||||
state: string;
|
||||
zipCode: string;
|
||||
country: string;
|
||||
};
|
||||
totalOrders: number;
|
||||
totalSpent: number;
|
||||
dateCreated: Date;
|
||||
dateUpdated: Date;
|
||||
}
|
||||
|
||||
const CustomerSchema: Schema = new Schema({
|
||||
name: { type: String, required: true, trim: true },
|
||||
email: { type: String, required: true, trim: true, lowercase: true },
|
||||
etsyUserId: { type: String },
|
||||
address: {
|
||||
street1: { type: String },
|
||||
street2: { type: String },
|
||||
city: { type: String },
|
||||
state: { type: String },
|
||||
zipCode: { type: String },
|
||||
country: { type: String },
|
||||
},
|
||||
totalOrders: { type: Number, default: 0 },
|
||||
totalSpent: { type: Number, default: 0 },
|
||||
dateCreated: { type: Date, default: Date.now },
|
||||
dateUpdated: { type: Date, default: Date.now },
|
||||
});
|
||||
|
||||
CustomerSchema.pre('save', function (next) {
|
||||
this.dateUpdated = new Date();
|
||||
next();
|
||||
});
|
||||
|
||||
export default mongoose.model<ICustomer>('Customer', CustomerSchema);
|
||||
34
server/src/models/Expense.ts
Normal file
34
server/src/models/Expense.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import mongoose, { Document, Schema } from 'mongoose';
|
||||
|
||||
export interface IExpense extends Document {
|
||||
category: 'materials' | 'shipping' | 'fees' | 'advertising' | 'tools' | 'other';
|
||||
description: string;
|
||||
amount: number;
|
||||
date: Date;
|
||||
receiptUrl?: string;
|
||||
notes?: string;
|
||||
dateCreated: Date;
|
||||
dateUpdated: Date;
|
||||
}
|
||||
|
||||
const ExpenseSchema: Schema = new Schema({
|
||||
category: {
|
||||
type: String,
|
||||
enum: ['materials', 'shipping', 'fees', 'advertising', 'tools', 'other'],
|
||||
required: true,
|
||||
},
|
||||
description: { type: String, required: true, trim: true },
|
||||
amount: { type: Number, required: true, min: 0 },
|
||||
date: { type: Date, required: true },
|
||||
receiptUrl: { type: String },
|
||||
notes: { type: String },
|
||||
dateCreated: { type: Date, default: Date.now },
|
||||
dateUpdated: { type: Date, default: Date.now },
|
||||
});
|
||||
|
||||
ExpenseSchema.pre('save', function (next) {
|
||||
this.dateUpdated = new Date();
|
||||
next();
|
||||
});
|
||||
|
||||
export default mongoose.model<IExpense>('Expense', ExpenseSchema);
|
||||
|
|
@ -1,35 +1,126 @@
|
|||
import { Router } from 'express';
|
||||
import { Router, Request, Response } from 'express';
|
||||
import Order from '../models/Order';
|
||||
import Product from '../models/Product';
|
||||
import Customer from '../models/Customer';
|
||||
import Expense from '../models/Expense';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /api/analytics/dashboard
|
||||
router.get('/dashboard', (req, res) => {
|
||||
router.get('/dashboard', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const [totalOrders, totalProducts, totalCustomers, revenueResult, expenseResult, recentOrders] = await Promise.all([
|
||||
Order.countDocuments({ paymentStatus: 'paid' }),
|
||||
Product.countDocuments({ isActive: true }),
|
||||
Customer.countDocuments(),
|
||||
Order.aggregate([
|
||||
{ $match: { paymentStatus: 'paid' } },
|
||||
{ $group: { _id: null, total: { $sum: '$total' } } },
|
||||
]),
|
||||
Expense.aggregate([
|
||||
{ $group: { _id: null, total: { $sum: '$amount' } } },
|
||||
]),
|
||||
Order.find({ paymentStatus: 'paid' })
|
||||
.populate('customerId', 'name email')
|
||||
.sort({ dateOrdered: -1 })
|
||||
.limit(5),
|
||||
]);
|
||||
|
||||
const totalRevenue = revenueResult[0]?.total ?? 0;
|
||||
const totalExpenses = expenseResult[0]?.total ?? 0;
|
||||
|
||||
const twelveMonthsAgo = new Date();
|
||||
twelveMonthsAgo.setMonth(twelveMonthsAgo.getMonth() - 11);
|
||||
twelveMonthsAgo.setDate(1);
|
||||
twelveMonthsAgo.setHours(0, 0, 0, 0);
|
||||
|
||||
const salesChart = await Order.aggregate([
|
||||
{ $match: { paymentStatus: 'paid', dateOrdered: { $gte: twelveMonthsAgo } } },
|
||||
{
|
||||
$group: {
|
||||
_id: { year: { $year: '$dateOrdered' }, month: { $month: '$dateOrdered' } },
|
||||
revenue: { $sum: '$total' },
|
||||
orders: { $sum: 1 },
|
||||
},
|
||||
},
|
||||
{ $sort: { '_id.year': 1, '_id.month': 1 } },
|
||||
]);
|
||||
|
||||
res.json({
|
||||
message: 'Dashboard analytics endpoint',
|
||||
data: {
|
||||
totalRevenue: 0,
|
||||
totalOrders: 0,
|
||||
totalProducts: 0,
|
||||
totalCustomers: 0,
|
||||
recentOrders: [],
|
||||
salesChart: [],
|
||||
}
|
||||
totalRevenue,
|
||||
totalExpenses,
|
||||
totalOrders,
|
||||
totalProducts,
|
||||
totalCustomers,
|
||||
recentOrders,
|
||||
salesChart,
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch dashboard data', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/analytics/sales
|
||||
router.get('/sales', (req, res) => {
|
||||
res.json({ message: 'Sales analytics endpoint - coming soon!' });
|
||||
router.get('/sales', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { from, to } = req.query;
|
||||
const match: any = { paymentStatus: 'paid' };
|
||||
if (from || to) {
|
||||
match.dateOrdered = {};
|
||||
if (from) match.dateOrdered.$gte = new Date(from as string);
|
||||
if (to) match.dateOrdered.$lte = new Date(to as string);
|
||||
}
|
||||
|
||||
const data = await Order.aggregate([
|
||||
{ $match: match },
|
||||
{
|
||||
$group: {
|
||||
_id: { year: { $year: '$dateOrdered' }, month: { $month: '$dateOrdered' } },
|
||||
revenue: { $sum: '$total' },
|
||||
orders: { $sum: 1 },
|
||||
},
|
||||
},
|
||||
{ $sort: { '_id.year': 1, '_id.month': 1 } },
|
||||
]);
|
||||
|
||||
res.json(data);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch sales data', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/analytics/products
|
||||
router.get('/products', (req, res) => {
|
||||
res.json({ message: 'Product analytics endpoint - coming soon!' });
|
||||
router.get('/products', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const topProducts = await Order.aggregate([
|
||||
{ $match: { paymentStatus: 'paid' } },
|
||||
{ $unwind: '$items' },
|
||||
{
|
||||
$group: {
|
||||
_id: '$items.productId',
|
||||
title: { $first: '$items.title' },
|
||||
totalSold: { $sum: '$items.quantity' },
|
||||
totalRevenue: { $sum: { $multiply: ['$items.quantity', '$items.price'] } },
|
||||
},
|
||||
},
|
||||
{ $sort: { totalRevenue: -1 } },
|
||||
{ $limit: 10 },
|
||||
]);
|
||||
|
||||
res.json(topProducts);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch product analytics', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/analytics/customers
|
||||
router.get('/customers', (req, res) => {
|
||||
res.json({ message: 'Customer analytics endpoint - coming soon!' });
|
||||
router.get('/customers', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const topCustomers = await Customer.find()
|
||||
.sort({ totalSpent: -1 })
|
||||
.limit(10)
|
||||
.select('name email totalOrders totalSpent');
|
||||
|
||||
res.json(topCustomers);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch customer analytics', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -1,25 +1,50 @@
|
|||
import { Router } from 'express';
|
||||
import { Router, Request, Response } from 'express';
|
||||
import Customer from '../models/Customer';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /api/customers
|
||||
router.get('/', (req, res) => {
|
||||
res.json({ message: 'Get customers endpoint - coming soon!', customers: [] });
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { page = 1, limit = 20 } = req.query;
|
||||
const customers = await Customer.find()
|
||||
.sort({ dateCreated: -1 })
|
||||
.limit(Number(limit))
|
||||
.skip((Number(page) - 1) * Number(limit));
|
||||
const total = await Customer.countDocuments();
|
||||
res.json({ customers, total, page: Number(page), limit: Number(limit) });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch customers', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/customers
|
||||
router.post('/', (req, res) => {
|
||||
res.json({ message: 'Create customer endpoint - coming soon!' });
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const customer = new Customer(req.body);
|
||||
await customer.save();
|
||||
res.status(201).json(customer);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to create customer', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/customers/:id
|
||||
router.get('/:id', (req, res) => {
|
||||
res.json({ message: 'Get customer by ID endpoint - coming soon!' });
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const customer = await Customer.findById(req.params.id);
|
||||
if (!customer) return res.status(404).json({ message: 'Customer not found' });
|
||||
res.json(customer);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch customer', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT /api/customers/:id
|
||||
router.put('/:id', (req, res) => {
|
||||
res.json({ message: 'Update customer endpoint - coming soon!' });
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const customer = await Customer.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
||||
if (!customer) return res.status(404).json({ message: 'Customer not found' });
|
||||
res.json(customer);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to update customer', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -1,30 +1,64 @@
|
|||
import { Router } from 'express';
|
||||
import { Router, Request, Response } from 'express';
|
||||
import Expense from '../models/Expense';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /api/expenses
|
||||
router.get('/', (req, res) => {
|
||||
res.json({ message: 'Get expenses endpoint - coming soon!', expenses: [] });
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { page = 1, limit = 20, category } = req.query;
|
||||
const filter: any = {};
|
||||
if (category) filter.category = category;
|
||||
|
||||
const expenses = await Expense.find(filter)
|
||||
.sort({ date: -1 })
|
||||
.limit(Number(limit))
|
||||
.skip((Number(page) - 1) * Number(limit));
|
||||
const total = await Expense.countDocuments(filter);
|
||||
|
||||
res.json({ expenses, total, page: Number(page), limit: Number(limit) });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch expenses', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/expenses
|
||||
router.post('/', (req, res) => {
|
||||
res.json({ message: 'Create expense endpoint - coming soon!' });
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const expense = new Expense(req.body);
|
||||
await expense.save();
|
||||
res.status(201).json(expense);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to create expense', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/expenses/:id
|
||||
router.get('/:id', (req, res) => {
|
||||
res.json({ message: 'Get expense by ID endpoint - coming soon!' });
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const expense = await Expense.findById(req.params.id);
|
||||
if (!expense) return res.status(404).json({ message: 'Expense not found' });
|
||||
res.json(expense);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch expense', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT /api/expenses/:id
|
||||
router.put('/:id', (req, res) => {
|
||||
res.json({ message: 'Update expense endpoint - coming soon!' });
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const expense = await Expense.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
||||
if (!expense) return res.status(404).json({ message: 'Expense not found' });
|
||||
res.json(expense);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to update expense', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /api/expenses/:id
|
||||
router.delete('/:id', (req, res) => {
|
||||
res.json({ message: 'Delete expense endpoint - coming soon!' });
|
||||
router.delete('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const expense = await Expense.findByIdAndDelete(req.params.id);
|
||||
if (!expense) return res.status(404).json({ message: 'Expense not found' });
|
||||
res.json({ message: 'Expense deleted' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to delete expense', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -1,25 +1,62 @@
|
|||
import { Router } from 'express';
|
||||
import { Router, Request, Response } from 'express';
|
||||
import Order from '../models/Order';
|
||||
import Customer from '../models/Customer';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /api/orders
|
||||
router.get('/', (req, res) => {
|
||||
res.json({ message: 'Get orders endpoint - coming soon!', orders: [] });
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { page = 1, limit = 20, status, paymentStatus } = req.query;
|
||||
const filter: any = {};
|
||||
if (status) filter.status = status;
|
||||
if (paymentStatus) filter.paymentStatus = paymentStatus;
|
||||
|
||||
const orders = await Order.find(filter)
|
||||
.populate('customerId', 'name email')
|
||||
.sort({ dateOrdered: -1 })
|
||||
.limit(Number(limit))
|
||||
.skip((Number(page) - 1) * Number(limit));
|
||||
const total = await Order.countDocuments(filter);
|
||||
|
||||
res.json({ orders, total, page: Number(page), limit: Number(limit) });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch orders', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/orders
|
||||
router.post('/', (req, res) => {
|
||||
res.json({ message: 'Create order endpoint - coming soon!' });
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const order = new Order(req.body);
|
||||
await order.save();
|
||||
|
||||
await Customer.findByIdAndUpdate(order.customerId, {
|
||||
$inc: { totalOrders: 1, totalSpent: order.total },
|
||||
});
|
||||
|
||||
res.status(201).json(order);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to create order', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/orders/:id
|
||||
router.get('/:id', (req, res) => {
|
||||
res.json({ message: 'Get order by ID endpoint - coming soon!' });
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const order = await Order.findById(req.params.id).populate('customerId', 'name email');
|
||||
if (!order) return res.status(404).json({ message: 'Order not found' });
|
||||
res.json(order);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch order', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT /api/orders/:id
|
||||
router.put('/:id', (req, res) => {
|
||||
res.json({ message: 'Update order endpoint - coming soon!' });
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const order = await Order.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
||||
if (!order) return res.status(404).json({ message: 'Order not found' });
|
||||
res.json(order);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to update order', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -1,30 +1,65 @@
|
|||
import { Router } from 'express';
|
||||
import { Router, Request, Response } from 'express';
|
||||
import Product from '../models/Product';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// GET /api/products
|
||||
router.get('/', (req, res) => {
|
||||
res.json({ message: 'Get products endpoint - coming soon!', products: [] });
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { page = 1, limit = 20, category, active } = req.query;
|
||||
const filter: any = {};
|
||||
if (category) filter.category = category;
|
||||
if (active !== undefined) filter.isActive = active === 'true';
|
||||
|
||||
const products = await Product.find(filter)
|
||||
.sort({ dateCreated: -1 })
|
||||
.limit(Number(limit))
|
||||
.skip((Number(page) - 1) * Number(limit));
|
||||
const total = await Product.countDocuments(filter);
|
||||
|
||||
res.json({ products, total, page: Number(page), limit: Number(limit) });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch products', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// POST /api/products
|
||||
router.post('/', (req, res) => {
|
||||
res.json({ message: 'Create product endpoint - coming soon!' });
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const product = new Product(req.body);
|
||||
await product.save();
|
||||
res.status(201).json(product);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to create product', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/products/:id
|
||||
router.get('/:id', (req, res) => {
|
||||
res.json({ message: 'Get product by ID endpoint - coming soon!' });
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const product = await Product.findById(req.params.id);
|
||||
if (!product) return res.status(404).json({ message: 'Product not found' });
|
||||
res.json(product);
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to fetch product', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// PUT /api/products/:id
|
||||
router.put('/:id', (req, res) => {
|
||||
res.json({ message: 'Update product endpoint - coming soon!' });
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const product = await Product.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
||||
if (!product) return res.status(404).json({ message: 'Product not found' });
|
||||
res.json(product);
|
||||
} catch (err) {
|
||||
res.status(400).json({ message: 'Failed to update product', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
// DELETE /api/products/:id
|
||||
router.delete('/:id', (req, res) => {
|
||||
res.json({ message: 'Delete product endpoint - coming soon!' });
|
||||
router.delete('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const product = await Product.findByIdAndDelete(req.params.id);
|
||||
if (!product) return res.status(404).json({ message: 'Product not found' });
|
||||
res.json({ message: 'Product deleted' });
|
||||
} catch (err) {
|
||||
res.status(500).json({ message: 'Failed to delete product', error: err });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Loading…
Reference in a new issue