diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..091e159 --- /dev/null +++ b/.env.example @@ -0,0 +1,34 @@ +# Server Configuration +NODE_ENV=development +PORT=5000 + +# Frontend URL (used in emails, CORS, etc.) +# For production: https://your-frontend.vercel.app +FRONTEND_URL=http://localhost:5173 + +# CORS Configuration (comma-separated list of allowed origins) +ALLOWED_ORIGINS=http://localhost:3000,http://localhost:5173 + +# MongoDB Connection (Docker Container) +# Option 1: If using existing mongo-dev container (no auth) +MONGO_URI=mongodb://localhost:27017/pizza-delivery-app + +# Option 2: If using docker-compose.yml with authentication +# MONGO_URI=mongodb://admin:password123@localhost:27017/pizza-delivery-app?authSource=admin + +# Authentication +# Generate a strong secret for production: openssl rand -base64 32 +JWT_SECRET=your_super_secret_jwt_key_change_this_in_production +SALT=10 + +# Email Configuration (Nodemailer) +# For Gmail: Enable 2FA and create an App Password +SENDER_EMAIL=your_email@example.com +SENDER_PASSWORD=your_email_app_password +SUPERADMIN_EMAIL=admin@example.com + +# Payment Gateway (Razorpay) +# Sign up at https://razorpay.com/ to get API keys +RAZORPAY_KEY_ID=your_razorpay_key_id +RAZORPAY_KEY_SECRET=your_razorpay_key_secret +RAZORPAY_WEBHOOK_SECRET=your_razorpay_webhook_secret diff --git a/README.md b/README.md index ed6e263..3b431aa 100644 --- a/README.md +++ b/README.md @@ -30,34 +30,165 @@ ## Features -- **User & Admin Authentication:** Secure login and registration system with role-based access control for users and administrators. -- **Pizza Management System:** Full CRUD operations for pizzas, allowing both admins and users to create custom pizzas with various ingredients (bases, sauces, cheeses, veggies). -- **Inventory Management:** Complete tracking system for pizza ingredients with quantity monitoring, threshold alerts, and price management for bases, sauces, cheeses, and vegetables. -- **Order Processing System:** End-to-end order management with order creation, status tracking, and delivery monitoring functionality. -- **Payment Integration:** Secure payment processing through Razorpay API with order checkout capabilities and payment verification. -- **Multi-level Access Control:** Differentiated capabilities for users and admins, with specific permissions for pizza creation, order management, and inventory control. -- **Order History & Tracking:** Users can view their order history and track current order status through the delivery process. -- **Admin Dashboard:** Comprehensive order management system allowing admins to view all orders, update order status, and manage inventory levels. -- **Automatic Inventory Deduction:** System automatically updates ingredient quantities when orders are placed to maintain accurate inventory levels. - -## Built With - -- **Frontend:** React.js (Vite.js) (Tailwind CSS) (React Router) (@reduxjs/toolkit) (React Redux) () -- **Backend:** Node.js (Express) (bcryptjs) (cors) (dotenv) (express-async-handler) (jsonwebtoken) -- **Database:** MongoDB (Atlas) (Mongoose) (MongoDB Compass) -- **Payment:** Razorpay API (Test Mode) -- **Authentication:** JSON Web Tokens (JWT) -- **Email Notifications:** Nodemailer -- **Version Control:** Git and GitHub +### User Features +- ✅ **User Authentication:** Secure registration and login with JWT tokens +- ✅ **Email Verification:** Email-based account verification system +- ✅ **Custom Pizza Creation:** Build your own pizza with custom ingredients +- ✅ **Pizza Browsing:** View all available pizzas with details +- ✅ **Shopping Cart:** Add items, update quantities, remove items +- ✅ **Secure Checkout:** Razorpay payment integration +- ✅ **Order History:** Track past and current orders +- ✅ **Order Status Tracking:** Real-time order status updates +- ✅ **Profile Management:** Update user information +- ✅ **Password Reset:** Forgot password functionality + +### Admin Features +- ✅ **Admin Authentication:** Secure admin login with approval system +- ✅ **Dashboard Analytics:** View key metrics (users, orders, revenue) +- ✅ **User Management:** View and manage all users +- ✅ **Pizza Management:** Full CRUD operations on pizzas +- ✅ **Inventory Management:** Track and update ingredient stock +- ✅ **Order Management:** View and update all orders +- ✅ **Order Status Updates:** Change order status with email notifications +- ✅ **Low Stock Alerts:** Automatic alerts for low inventory +- ✅ **Admin Approval System:** New admins require approval + +### Technical Features +- ✅ **Enterprise Error Handling:** Standardized API error responses with codes +- ✅ **Centralized Constants:** Single source of truth for enums and types +- ✅ **Email Notifications:** Automated emails for orders and account actions +- ✅ **Inventory Deduction:** Automatic stock updates on orders +- ✅ **Payment Verification:** Secure Razorpay signature verification +- ✅ **Responsive Design:** Mobile-first, works on all devices +- ✅ **Security:** JWT auth, password hashing, input validation, rate limiting + +## Documentation + +📚 **[Complete Documentation](./docs/README.md)** + +### Quick Links + +- **[Setup Guide](./docs/SETUP.md)** - Complete installation and configuration +- **[API Reference](./docs/API.md)** - All API endpoints with examples +- **[Architecture](./docs/ARCHITECTURE.md)** - System design and data flows +- **[Error Handling](./docs/ERROR_HANDLING.md)** - Error handling patterns +- **[Constants](./docs/CONSTANTS.md)** - Constants and enums reference +- **[Testing](./docs/TESTING.md)** - Testing guide with test credentials +- **[Deployment](./docs/DEPLOYMENT.md)** - Deploy to Vercel (production) +- **[Contributing](./docs/CONTRIBUTING.md)** - Contribution guidelines +- **[Changelog](./docs/CHANGELOG.md)** - Version history + +### Quick References + +- **[Test Credentials](./TEST_CREDENTIALS.md)** - Login credentials for testing +- **[Razorpay Setup](./RAZORPAY_SETUP.md)** - Payment gateway configuration + +--- + +## Tech Stack + +### Frontend +- **React 18** - UI library +- **Vite 4** - Build tool and dev server +- **Redux Toolkit** - State management +- **React Router v6** - Client-side routing +- **Tailwind CSS** - Utility-first CSS framework +- **Axios** - HTTP client +- **React Icons** - Icon library + +### Backend +- **Node.js** - JavaScript runtime +- **Express.js** - Web framework +- **MongoDB** - NoSQL database +- **Mongoose** - MongoDB ODM +- **JWT** - Authentication +- **bcryptjs** - Password hashing +- **express-validator** - Input validation +- **Nodemailer** - Email sending +- **Razorpay SDK** - Payment processing + +### Security & Middleware +- **Helmet** - Security headers +- **express-mongo-sanitize** - NoSQL injection prevention +- **express-rate-limit** - Rate limiting +- **CORS** - Cross-origin resource sharing + +### Deployment +- **Vercel** - Frontend and backend hosting +- **MongoDB Atlas** - Cloud database +- **GitHub** - Version control and CI/CD + +--- + +## Architecture + +### High-Level Overview + +``` +User Browser + ↓ +React Frontend (Vercel) + ↓ +Express Backend (Vercel Serverless) + ↓ +MongoDB Atlas + ↓ +Razorpay Payment Gateway +``` + +### Key Design Patterns + +- **RESTful API** - Standard REST architecture +- **JWT Authentication** - Stateless token-based auth +- **Redux State Management** - Centralized state +- **Error Handling** - Standardized error responses with codes +- **Constants Management** - Duplicated constants (frontend/backend) +- **Middleware Pipeline** - Modular request processing + +See [Architecture Documentation](./docs/ARCHITECTURE.md) for detailed diagrams and explanations. + +--- + +## Error Handling + +Version 2.0.0 introduces enterprise-grade error handling: + +### Standardized Error Response +```json +{ + "success": false, + "error": { + "code": "VALIDATION_ERROR", + "message": "User-friendly error message", + "details": [ + { "field": "email", "message": "Email is required" } + ], + "timestamp": "2026-02-22T...", + "path": "/api/users/register", + "requestId": "req_unique_id" + } +} +``` + +### Features +- **Error Codes** - Machine-readable codes (e.g., `AUTH_1001`, `VALIDATION_3001`) +- **Field-Level Details** - Specific validation errors per field +- **Request Tracking** - Unique request IDs for debugging +- **User-Friendly Messages** - Clear, actionable error messages + +See [Error Handling Guide](./docs/ERROR_HANDLING.md) for complete reference. ## Getting Started +> **📖 For detailed setup instructions, see the [Setup Guide](./docs/SETUP.md)** + ### Prerequisites -- [Node.js](https://nodejs.org/en/) - JavaScript runtime built on Chrome's V8 JavaScript engine -- [NPM](https://www.npmjs.com/) - Node Package Manager +- **Node.js** (v16 or higher) - [Download](https://nodejs.org/) +- **MongoDB** - Local installation or [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) account +- **Razorpay Account** - [Sign up](https://razorpay.com/) for test keys -### Installation +### Quick Start 1. **Clone the repository** @@ -80,51 +211,23 @@ 3. **Configure environment variables** - Create a `.env` file in the root directory: - ```sh - # Server Configuration - NODE_ENV=development - PORT=5000 - - # MongoDB Connection - MONGO_URI=your_mongodb_uri - - # Authentication - JWT_SECRET=your_jwt_secret - SALT=10 - - # Email Configuration - SENDER_EMAIL=your_email@example.com - SENDER_PASSWORD=your_email_password - SUPERADMIN_EMAIL=admin@example.com - - # Payment Gateway - RAZORPAY_KEY_ID=your_razorpay_key_id - RAZORPAY_KEY_SECRET=your_razorpay_key_secret + # Copy example files + cp .env.example .env + cd client && cp .env.example .env && cd .. + + # Edit .env files with your credentials ``` - Create a `.env` file in the client directory: + **Required variables:** See [Setup Guide](./docs/SETUP.md#environment-configuration) for complete list - ```sh - VITE_SERVER_URL=http://localhost:5000 - VITE_CLIENT_URL=http://localhost:3000 - VITE_RAZORPAY_KEY_ID=your_razorpay_key_id - ``` - -4. **Seed the database (Optional)** - - Populate the database with initial data: +4. **Seed the database** ```sh - npm run data:import + npm run seed ``` - To reset the database: - - ```sh - npm run data:destroy - ``` + **Test Credentials:** See [TEST_CREDENTIALS.md](./TEST_CREDENTIALS.md) for login details 5. **Start the application** @@ -141,10 +244,158 @@ 6. **Access the application** -- Frontend: [http://localhost:3000](http://localhost:3000) -- Backend API: [http://localhost:5000](http://localhost:5000) + - **Frontend:** [http://localhost:5173](http://localhost:5173) + - **Backend API:** [http://localhost:5000](http://localhost:5000) + +7. **Login with test credentials** + + - **Admin:** `admin1@pizzapalette.com` / `Admin@123456` + - **User:** `john@example.com` / `User@123456` + +> **📖 For troubleshooting, see [Setup Guide - Troubleshooting](./docs/SETUP.md#troubleshooting)** + +--- + +## API Documentation + +Complete API documentation with request/response examples: + +### Base URL +- **Development:** `http://localhost:5000/api` +- **Production:** `https://your-backend.vercel.app/api` + +### Authentication +Most endpoints require JWT token in Authorization header: +```http +Authorization: Bearer +``` + +### Endpoint Categories +- **User Endpoints** - Registration, login, profile management +- **Pizza Endpoints** - CRUD operations on pizzas +- **Order Endpoints** - Order creation and tracking +- **Inventory Endpoints** - Ingredient management +- **Admin Endpoints** - Admin authentication and approval +- **Analytics Endpoints** - Dashboard statistics + +**[View Complete API Reference →](./docs/API.md)** + +--- + +## Testing + +### Test Credentials -> **Note:** Make sure MongoDB is running locally or you're using MongoDB Atlas with the correct connection string. +**Admin Account:** +``` +Email: admin1@pizzapalette.com +Password: Admin@123456 +``` + +**User Account:** +``` +Email: john@example.com +Password: User@123456 +``` + +### Razorpay Test Cards + +**Successful Payment:** +``` +Card: 4111 1111 1111 1111 +CVV: 123 +Expiry: Any future date +``` + +**Failed Payment:** +``` +Card: 4000 0000 0000 0002 +``` + +**[View Complete Testing Guide →](./docs/TESTING.md)** + +--- + +## Deployment + +### Vercel Deployment (Recommended) + +1. **Fork this repository** +2. **Import to Vercel** (separate projects for frontend and backend) +3. **Configure environment variables** in Vercel dashboard +4. **Deploy** with auto-deploy on push + +**[View Complete Deployment Guide →](./docs/DEPLOYMENT.md)** + +### Environment Setup + +**Backend (Vercel):** +- Set all environment variables from `.env` +- Update `FRONTEND_URL` to your frontend URL + +**Frontend (Vercel):** +- Set `VITE_SERVER_URL` to your backend URL +- Set `VITE_RAZORPAY_KEY_ID` (use live key for production) + +--- + +## Project Structure + +``` +pizza-palette-app-mern/ +├── client/ # React frontend +│ ├── src/ +│ │ ├── components/ # Reusable components +│ │ ├── screens/ # Page components +│ │ ├── redux/ # Redux store and slices +│ │ ├── constants/ # Frontend constants +│ │ └── utils/ # Utility functions +│ └── package.json +├── server/ # Express backend +│ ├── controllers/ # Route controllers +│ ├── schemas/ # Mongoose models +│ ├── routes/ # API routes +│ ├── middlewares/ # Custom middleware +│ ├── validators/ # Input validation +│ ├── constants/ # Backend constants +│ ├── utils/ # Utility functions +│ └── package.json +├── docs/ # Documentation +│ ├── README.md # Docs index +│ ├── SETUP.md # Setup guide +│ ├── API.md # API reference +│ └── ... # More guides +├── README.md # This file +├── TEST_CREDENTIALS.md # Test accounts +└── RAZORPAY_SETUP.md # Razorpay config +``` + +--- + +## Version 2.0.0 - What's New + +### Enterprise Features +- ✨ Standardized error handling with error codes +- ✨ Centralized constants management +- ✨ Enhanced validation with field-level details +- ✨ Request tracking with unique IDs +- ✨ Comprehensive documentation suite + +### Improvements +- 🔄 Updated seed data with stronger passwords +- 🔄 Constants integrated in schemas and validators +- 🔄 Enhanced email templates with action links +- 🔄 Improved frontend error display +- 🔄 Updated UI components to use constants + +### Documentation +- 📚 10 comprehensive documentation files +- 📚 Architecture diagrams +- 📚 Complete API reference +- 📚 Testing guide with credentials +- 📚 Deployment guide for Vercel + +**[View Complete Changelog →](./docs/CHANGELOG.md)** ## Contributing diff --git a/client/.env.example b/client/.env.example new file mode 100644 index 0000000..a71ee20 --- /dev/null +++ b/client/.env.example @@ -0,0 +1,9 @@ +# Server URL +VITE_SERVER_URL=http://localhost:5000/api + +# Client URL (Vite default port is 5173) +VITE_CLIENT_URL=http://localhost:5173 + +# Payment Gateway (Razorpay) +# This should match the RAZORPAY_KEY_ID in the server .env +VITE_RAZORPAY_KEY_ID=your_razorpay_key_id diff --git a/client/package.json b/client/package.json index 1091a03..7c68181 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@reduxjs/toolkit": "^1.9.5", + "@stripe/stripe-js": "^8.8.0", "axios": "^1.4.0", "prop-types": "^15.8.1", "react": "^18.2.0", diff --git a/client/src/components/route/AdminRoute.jsx b/client/src/components/route/AdminRoute.jsx new file mode 100644 index 0000000..6bdedde --- /dev/null +++ b/client/src/components/route/AdminRoute.jsx @@ -0,0 +1,20 @@ +import { useSelector } from 'react-redux'; +import { Navigate } from 'react-router-dom'; +import PropTypes from 'prop-types'; + +function AdminRoute({ children }) { + const admin = useSelector((state) => state.admin); + const { adminUserInfo } = admin; + + if (!adminUserInfo) { + return ; + } + + return children; +} + +AdminRoute.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default AdminRoute; diff --git a/client/src/components/route/ProtectedRoute.jsx b/client/src/components/route/ProtectedRoute.jsx new file mode 100644 index 0000000..66fb73a --- /dev/null +++ b/client/src/components/route/ProtectedRoute.jsx @@ -0,0 +1,23 @@ +import { useSelector } from 'react-redux'; +import { Navigate } from 'react-router-dom'; +import PropTypes from 'prop-types'; + +function ProtectedRoute({ children }) { + const user = useSelector((state) => state.user); + const { userInfo } = user; + + const admin = useSelector((state) => state.admin); + const { adminUserInfo } = admin; + + if (!userInfo && !adminUserInfo) { + return ; + } + + return children; +} + +ProtectedRoute.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default ProtectedRoute; diff --git a/client/src/components/route/UserRoute.jsx b/client/src/components/route/UserRoute.jsx new file mode 100644 index 0000000..59fb911 --- /dev/null +++ b/client/src/components/route/UserRoute.jsx @@ -0,0 +1,20 @@ +import { useSelector } from 'react-redux'; +import { Navigate } from 'react-router-dom'; +import PropTypes from 'prop-types'; + +function UserRoute({ children }) { + const user = useSelector((state) => state.user); + const { userInfo } = user; + + if (!userInfo) { + return ; + } + + return children; +} + +UserRoute.propTypes = { + children: PropTypes.node.isRequired, +}; + +export default UserRoute; diff --git a/client/src/components/ui/Admin/Dashboard/Home.jsx b/client/src/components/ui/Admin/Dashboard/Home.jsx index 4c63c05..7f4f2fb 100644 --- a/client/src/components/ui/Admin/Dashboard/Home.jsx +++ b/client/src/components/ui/Admin/Dashboard/Home.jsx @@ -2,6 +2,9 @@ import { useState } from 'react'; import { FaPlus } from 'react-icons/fa'; import { useSelector } from 'react-redux'; +// Import Constants +import { ORDER_STATUS } from '../../../../constants'; + // Import Components import Button from '../../Button'; import Loader from '../../Loader'; @@ -50,16 +53,16 @@ function Home() { // Filter orders based on status const ordersReceived = orderList.filter( - (order) => order.status === 'Received' + (order) => order.status === ORDER_STATUS.RECEIVED ); const ordersInTheKitchen = orderList.filter( - (order) => order.status === 'In the Kitchen' + (order) => order.status === ORDER_STATUS.IN_KITCHEN ); const ordersSentForDelivery = orderList.filter( - (order) => order.status === 'Sent for Delivery' + (order) => order.status === ORDER_STATUS.OUT_FOR_DELIVERY ); const ordersDelivered = orderList.filter( - (order) => order.status === 'Delivered' + (order) => order.status === ORDER_STATUS.DELIVERED ); const CardList = [ diff --git a/client/src/components/ui/Admin/Dashboard/Lists/OrdersList.jsx b/client/src/components/ui/Admin/Dashboard/Lists/OrdersList.jsx index e7594c2..b7a5cfa 100644 --- a/client/src/components/ui/Admin/Dashboard/Lists/OrdersList.jsx +++ b/client/src/components/ui/Admin/Dashboard/Lists/OrdersList.jsx @@ -1,11 +1,15 @@ import { useDispatch, useSelector } from 'react-redux'; import { useEffect } from 'react'; +// Import Constants +import { ORDER_STATUS } from '../../../../../constants'; + // Import Thunks import { deleteOrderById, listOrders, updateOrderById, + updateOrderPaymentStatus, } from '../../../../../redux/asyncThunks/orderThunks'; // Import Components @@ -18,6 +22,7 @@ function OrdersList() { '_id', 'user', 'status', + 'paymentStatus', 'salesTax', 'deliveryCharges', 'totalPrice', @@ -39,14 +44,14 @@ function OrdersList() { } = order; const ordersReceived = - orderList && orderList.filter((order) => order.status === 'Received'); + orderList && orderList.filter((order) => order.status === ORDER_STATUS.RECEIVED); const ordersInTheKitchen = - orderList && orderList.filter((order) => order.status === 'In the Kitchen'); + orderList && orderList.filter((order) => order.status === ORDER_STATUS.IN_KITCHEN); const ordersSentForDelivery = orderList && - orderList.filter((order) => order.status === 'Sent for Delivery'); + orderList.filter((order) => order.status === ORDER_STATUS.OUT_FOR_DELIVERY); const ordersDelivered = - orderList && orderList.filter((order) => order.status === 'Delivered'); + orderList && orderList.filter((order) => order.status === ORDER_STATUS.DELIVERED); const handleDelete = (id) => { dispatch(deleteOrderById(id)).then(() => dispatch(listOrders({}))); @@ -57,13 +62,24 @@ function OrdersList() { message: 'Order Deleted Successfully!', }; - const handleUpdate = (id, selectedStatus) => { - dispatch( - updateOrderById({ - id, - status: selectedStatus, - }) - ).then(() => dispatch(listOrders({}))); + const handleUpdate = (id, selectedValue, updateType = 'status') => { + if (updateType === 'payment') { + // Update payment status + dispatch( + updateOrderPaymentStatus({ + orderId: id, + paymentStatus: selectedValue, + }) + ).then(() => dispatch(listOrders({}))); + } else { + // Update order status + dispatch( + updateOrderById({ + id, + status: selectedValue, + }) + ).then(() => dispatch(listOrders({}))); + } }; const successMessageUpdate = orderUpdateByIdSuccess && { diff --git a/client/src/components/ui/Admin/Dashboard/Lists/PizzasList.jsx b/client/src/components/ui/Admin/Dashboard/Lists/PizzasList.jsx index f4ab63b..ca941cf 100644 --- a/client/src/components/ui/Admin/Dashboard/Lists/PizzasList.jsx +++ b/client/src/components/ui/Admin/Dashboard/Lists/PizzasList.jsx @@ -1,6 +1,9 @@ import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +// Import Constants +import { USER_ROLES } from '../../../../../constants'; + // Import Thunks import { deletePizzaById, @@ -13,7 +16,7 @@ import Message from '../../../Message'; import Table from '../Table'; function PizzasList() { - const pizzaColumns = ['_id', 'name', 'price', 'size']; + const pizzaColumns = ['_id', 'name', 'price']; const dispatch = useDispatch(); @@ -35,8 +38,8 @@ function PizzasList() { message: 'pizza Deleted Successfully!', }; - const PizzaByAdmin = pizzaList.filter((pizza) => pizza.createdBy === 'admin'); - const customPizzas = pizzaList.filter((pizza) => pizza.createdBy === 'user'); + const PizzaByAdmin = pizzaList.filter((pizza) => pizza.createdBy === USER_ROLES.ADMIN); + const customPizzas = pizzaList.filter((pizza) => pizza.createdBy === USER_ROLES.USER); useEffect(() => { if (!pizzaList) { diff --git a/client/src/components/ui/Admin/Dashboard/Modals/PizzaCreateModal.jsx b/client/src/components/ui/Admin/Dashboard/Modals/PizzaCreateModal.jsx index 7678c82..e08d633 100644 --- a/client/src/components/ui/Admin/Dashboard/Modals/PizzaCreateModal.jsx +++ b/client/src/components/ui/Admin/Dashboard/Modals/PizzaCreateModal.jsx @@ -10,6 +10,9 @@ import { listPizzas, } from '../../../../../redux/asyncThunks/pizzaThunks'; +// Import Constants +import { PIZZA_SIZE_OPTIONS } from '../../../../../constants'; + // Import Components import Button from '../../../Button'; import Loader from '../../../Loader'; @@ -24,11 +27,8 @@ function PizzaCreateModal({ onClose }) { const [cheeses, setCheeses] = useState([]); const [veggies, setVeggies] = useState([]); const [price, setPrice] = useState(''); - const [size, setSize] = useState(''); const [imageUrl, setImageUrl] = useState(''); - const PizzaSizes = ['small', 'medium', 'large', 'extra-large']; - const dispatch = useDispatch(); const pizza = useSelector((state) => state.pizza); @@ -65,7 +65,6 @@ function PizzaCreateModal({ onClose }) { cheeses, veggies, price, - size, imageUrl, }; @@ -194,22 +193,22 @@ function PizzaCreateModal({ onClose }) {

Size

- {PizzaSizes.map((size, index) => ( + {PIZZA_SIZE_OPTIONS.map((option, index) => ( ))}
diff --git a/client/src/components/ui/Admin/Dashboard/Modals/StockCreateModal.jsx b/client/src/components/ui/Admin/Dashboard/Modals/StockCreateModal.jsx index b2efab6..5f5e0f2 100644 --- a/client/src/components/ui/Admin/Dashboard/Modals/StockCreateModal.jsx +++ b/client/src/components/ui/Admin/Dashboard/Modals/StockCreateModal.jsx @@ -3,6 +3,9 @@ import { useEffect, useState } from 'react'; import { FaPlusCircle, FaTimes } from 'react-icons/fa'; import { useDispatch, useSelector } from 'react-redux'; +// Import Constants +import { INVENTORY_TYPES } from '../../../../../constants'; + // Import Thunks import { createStock, @@ -22,8 +25,6 @@ function StockCreateModal({ onClose }) { const [price, setPrice] = useState(''); const [threshold, setThreshold] = useState(''); - const stockTypes = ['Base', 'Sauce', 'Cheese', 'Veggie']; - const dispatch = useDispatch(); const inventory = useSelector((state) => state.inventory); @@ -92,7 +93,7 @@ function StockCreateModal({ onClose }) { Select Stock Type
- {stockTypes.map((type, index) => ( + {INVENTORY_TYPES.map((type, index) => (