Build an Inventory Management System Using NextJS
Last Updated :
23 Jul, 2025
We will build an Inventory Management System. We will walk through the step-by-step process of creating an inventory management system. This application contains a dashboard that shows a brief report of our inventory. Product sections show all the products listed with a search filter and allow users to add, update, and delete the product.
Output Preview
Inventory Management System Using NextJS
Prerequisites
Installation & Setup
Step 1: Create a Next.js application using the following command.
npx create-next-app@latest inventory-management
Step 2: It will ask you some questions, so choose as the following.
√ Would you like to use TypeScript? ... No
√ Would you like to use ESLint? ... Yes
√ Would you like to use Tailwind CSS? ... Yes
√ Would you like to use `src/` directory? ... Yes
√ Would you like to use App Router? (recommended) ... Yes
√ Would you like to customize the default import alias (@/*)? ... Yes
Step 3: After creating your project folder i.e. inventory-management, move to it using the following command.
cd inventory-management
Step 4: Install the required packages by using following command.
npm i chart.js react-chartjs-2 uuid
The updated pakage.json dependencies will look like this:
"dependencies": {
"chart.js": "^4.4.3",
"next": "14.2.5",
"react": "^18",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18",
"uuid": "^10.0.0"
}
Step 5: Create a Sample Data File inside public/data folder
[
{
"name": "Smartphone",
"category": "Electronics",
"quantity": "25",
"price": "25000",
"maxStock": "50",
"minStock": "10",
"id": "e5f6a7b8-c901-23d4-f567-56789012f3d4"
},
{
"name": "Bookshelf",
"category": "Furniture",
"quantity": "12",
"price": "8000",
"maxStock": "20",
"minStock": "5",
"id": "f6a7b8c9-0123-45e6-g789-67890123g456"
},
{
"name": "Jeans",
"category": "Clothing",
"quantity": "10",
"price": "1200",
"maxStock": "40",
"minStock": "25",
"id": "b8c90123-4567-89f0-i012-89012345i678"
},
{
"name": "Tablet",
"category": "Electronics",
"quantity": "40",
"price": "18000",
"maxStock": "30",
"minStock": "15",
"id": "c9012345-6789-01f2-j345-90123456j789"
},
{
"name": "Laptop",
"category": "Electronics",
"quantity": "21",
"price": "23555",
"maxStock": "10",
"minStock": "5",
"id": "c7989c06-d7ef-4690-b69e-2dd122a3d2df"
},
{
"name": "Book",
"category": "Stationery",
"quantity": "13",
"price": "355",
"maxStock": "20",
"minStock": "15",
"id": "50658c12-b63b-472a-b778-c87c8943991e"
}
]
Project Structure:
Example: This example shows the creation of the inventory management system.
CSS
/* File path: src/app/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
JavaScript
//File path: src/app/page.js
"use client";
import React, { useEffect, useState } from 'react';
import { Bar, Pie } from 'react-chartjs-2';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
ArcElement,
} from 'chart.js';
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
ArcElement
);
export default function Dashboard() {
const [products, setProducts] = useState([])
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async (searchValue = '') => {
let data = await fetch(`/api/products?search=${searchValue}`, {
method: "GET"
});
data = await data.json();
setProducts(data.data);
};
const stockData = {
labels: products.map(product => product.name),
datasets: [
{
label: 'Quantity',
data: products.map(product => Number(product.quantity)),
backgroundColor: 'rgba(54, 162, 235, 0.5)',
},
{
label: 'Max Stock',
data: products.map(product => Number(product.maxStock)),
backgroundColor: 'rgba(255, 99, 132, 0.5)',
},
],
};
const categories = [...new Set(products.map(product => product.category))];
const categoryCounts = categories.map(category => products.filter(product => product.category === category).length);
const categoryData = {
labels: categories,
datasets: [
{
label: 'Category Breakdown',
data: categoryCounts,
backgroundColor: [
'rgba(75, 192, 192, 0.5)',
'rgba(153, 102, 255, 0.5)',
'rgba(255, 159, 64, 0.5)',
'rgba(255, 205, 86, 0.5)',
],
},
],
};
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-4">Inventory Management System</h1>
<div className='grid grid-cols-2 gap-1'>
<div class="max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Total Products</h5>
<h2 class="mb-2 text-6xl font-bold tracking-tight text-gray-900 dark:text-white">{products.length}</h2>
</div>
<div class="max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Total Category</h5>
<h2 class="mb-2 text-6xl font-bold tracking-tight text-gray-900 dark:text-white">{categories.length}</h2>
</div>
<div className="max-w-sm w-full p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Stock Level vs. Max Stock for Each Product</h5>
<div className="h-64">
<Bar data={stockData} options={{ maintainAspectRatio: false }} />
</div>
</div>
<div className="max-w-sm w-full p-6 bg-white border border-gray-200 rounded-lg shadow dark:bg-gray-800 dark:border-gray-700">
<h5 className="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Product Categories Breakdown</h5>
<div className="h-64">
<Pie data={categoryData} options={{ maintainAspectRatio: false }} />
</div>
</div>
</div>
</div>
);
}
JavaScript
//File path: src/app/layout.js
import { Inter } from "next/font/google";
import "./globals.css";
import Link from "next/link";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "Inventory Management App",
description: "Inventory Management",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
<button data-drawer-target="default-sidebar" data-drawer-toggle="default-sidebar" aria-controls="default-sidebar" type="button" className="inline-flex items-center p-2 mt-2 ms-3 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600">
<span className="sr-only">Open sidebar</span>
<svg className="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="https://www.w3.org/2000/svg">
<path clipRule="evenodd" fillRule="evenodd" d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"></path>
</svg>
</button>
<aside id="default-sidebar" className="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0" aria-label="Sidebar">
<div className="h-full px-3 py-4 overflow-y-auto bg-gray-50 dark:bg-gray-800">
<span className="flex items-center ps-2.5 mb-5">
<span className="self-center text-xl font-semibold whitespace-nowrap dark:text-white">Inventory</span>
</span>
<ul className="space-y-2 font-medium">
<li>
<Link href="/" className="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
<span className="ms-3">
Dashboard
</span>
</Link>
</li>
<li>
<Link href="/products" className="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
<span className="ms-3">Products</span>
</Link>
</li>
<li>
<Link href="/products/add" className="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
<span className="ms-3">Add Product</span>
</Link>
</li>
</ul>
</div>
</aside>
<div className="p-4 sm:ml-64">
{children}
</div>
</body>
</html>
);
}
JavaScript
// File path: src/app/products/page.js
"use client";
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
export default function Products() {
const [product, setProduct] = useState([]);
const [search, setSearch] = useState('');
const router = useRouter();
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async (searchValue = '') => {
let data = await fetch(`/api/products?search=${searchValue}`, {
method: "GET"
});
data = await data.json();
setProduct(data.data);
};
const deleteProduct = async (id) => {
let isConfirm = confirm("Are you sure you want to delete this product?")
if(!isConfirm) return
let response = await fetch(`/api/products`,{
method: "DELETE",
body: JSON.stringify(id),
headers:{
"content-type":"application/json"
}
})
response = await response.json()
if(response.success) {
alert(response.message)
return fetchProducts()
}
return alert(response.message)
}
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-4">Products</h1>
<div className="relative shadow-md sm:rounded-lg">
<div className="flex items-center justify-end flex-column flex-wrap md:flex-row space-y-4 md:space-y-0 pb-4 bg-white">
<label htmlFor="table-search" className="sr-only">Search</label>
<div className="relative">
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<svg className="w-4 h-4 text-gray-500" aria-hidden="true" xmlns="https://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
</svg>
</div>
<input
type="text"
value={search}
onChange={(e) => {
const newSearchValue = e.target.value;
setSearch(newSearchValue);
fetchProducts(newSearchValue);
}}
className="block p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg w-80 bg-gray-50 focus:ring-blue-500 focus:border-blue-500"
placeholder="Search for Products"
/>
</div>
</div>
<table className="w-full text-sm text-left text-gray-500">
<thead className="text-xs text-gray-700 uppercase bg-gray-50">
<tr>
<th scope="col" className="px-6 py-3">Name</th>
<th scope="col" className="px-6 py-3">Category</th>
<th scope="col" className="px-6 py-3">Price</th>
<th scope="col" className="px-6 py-3">Available Quantity</th>
<th scope="col" className="px-6 py-3">Max Stock Quantity</th>
<th scope="col" className="px-6 py-3">Min Stock Quantity</th>
<th scope="col" className="px-6 py-3">Action</th>
</tr>
</thead>
<tbody>
{product.map((item) => (
<tr key={item.id} className="bg-white border-b hover:bg-gray-50">
<th scope="row" className="flex items-center px-6 py-4 text-gray-900 whitespace-nowrap">
{item.name}
</th>
<td className="px-6 py-4">{item.category}</td>
<td className="px-6 py-4">{item.price}</td>
<td className="px-6 py-4">
<div className="flex items-center">
{item.quantity}
<div style={{background:`${(Number(item.quantity) < Number(item.minStock)) ? "red":"green" }`}} className={`h-2.5 w-2.5 rounded-full bg-${(Number(item.quantity) < Number(item.minStock)) ? "red":"green" }-500 ml-2`}></div>
</div>
</td>
<td className="px-6 py-4">{item.maxStock}</td>
<td className="px-6 py-4">{item.minStock}</td>
<td className="px-6 py-4 flex">
<button onClick={()=> router.push(`/products/${item.id}`)} className="font-medium text-blue-600 hover:underline">Edit</button>
<button onClick={() => {
deleteProduct(item.id)}} className="font-medium text-red-600 ml-2 hover:underline">Delete</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
JavaScript
// File path: src/app/products/add/page.js
"use client";
import { useState } from 'react';
export default function Add() {
const [productName, setProductName] = useState('');
const [category, setCategory] = useState('');
const [quantity, setQuantity] = useState('');
const [price, setPrice] = useState('');
const [maxStock, setMaxStock] = useState('');
const [minStock, setMinStock] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
if(!Number(quantity)) return alert("Please Enter Valid Quantity")
if(!Number(price)) return alert("Please Enter Valid Price")
if(Number(maxStock) < Number(minStock)) return alert("Please select Valid Min & Max Stock Quantity")
const newProduct = {
name: productName,
category: category,
quantity: quantity,
price: price,
maxStock: maxStock,
minStock: minStock,
};
let response = await fetch('/api/products/add', {
method:"POST",
body: JSON.stringify(newProduct),
headers:{
"content-type":"application/json"
}
})
response = await response.json()
if(response.success){
setProductName('');
setCategory('');
setQuantity('');
setPrice('');
setMaxStock('');
setMinStock('');
return alert(response.message)
};
return alert(response.message)
}
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-4">Add Product</h1>
<form onSubmit={handleSubmit} className="max-w-md mx-auto">
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
value={productName}
onChange={(e) => setProductName(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">
Name
</label>
</div>
<div className="relative z-0 w-full mb-5 group">
<select
value={category}
onChange={(e) => setCategory(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-500 bg-transparent border-0 border-b-2 border-gray-200 appearance-none focus:outline-none focus:ring-0 focus:border-gray-200 peer"
>
<option value="" disabled>Choose Product Category</option>
<option value="Electronics">Electronics</option>
<option value="Clothing">Clothing</option>
<option value="Furniture">Furniture</option>
<option value="Stationery">Stationery</option>
</select>
</div>
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">
Quantity
</label>
</div>
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
value={price}
onChange={(e) => setPrice(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">
Price
</label>
</div>
<div className="grid md:grid-cols-2 md:gap-6">
<div className="relative z-0 w-full mb-5 group">
<select
value={maxStock}
onChange={(e) => setMaxStock(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-500 bg-transparent border-0 border-b-2 border-gray-200 appearance-none focus:outline-none focus:ring-0 focus:border-gray-200 peer"
>
<option value="" disabled>Choose Max Stock Quantity</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
</select>
</div>
<div className="relative z-0 w-full mb-5 group">
<select
value={minStock}
onChange={(e) => setMinStock(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-500 bg-transparent border-0 border-b-2 border-gray-200 appearance-none focus:outline-none focus:ring-0 focus:border-gray-200 peer"
>
<option value="" disabled>Choose Min Stock Quantity</option>
<option value="5">5</option>
<option value="15">15</option>
<option value="25">25</option>
<option value="35">35</option>
<option value="45">45</option>
</select>
</div>
</div>
<button type="submit" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center">
Add Product
</button>
</form>
</div>
);
}
JavaScript
// File path: src/app/products/[update]/page.js
"use client";
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
export default function Update({ params }) {
const [productName, setProductName] = useState('');
const [category, setCategory] = useState('');
const [quantity, setQuantity] = useState('');
const [price, setPrice] = useState('');
const [maxStock, setMaxStock] = useState('');
const [minStock, setMinStock] = useState('');
const router = useRouter()
useEffect(() => {
fetchSingleProduct();
}, []);
const fetchSingleProduct = async () => {
let data = await fetch(`/api/products/${params.update}`, {
method: "GET"
});
data = await data.json();
setProductName(data.data.name);
setCategory(data.data.category);
setQuantity(data.data.quantity);
setPrice(data.data.price);
setMaxStock(data.data.maxStock);
setMinStock(data.data.minStock);
};
const updateForm = async (e) => {
e.preventDefault();
if (!Number(quantity)) return alert("Please Enter Valid Quantity")
if (!Number(price)) return alert("Please Enter Valid Price")
if (Number(maxStock) < Number(minStock)) return alert("Please select Valid Min & Max Stock Quantity")
const newProduct = {
name: productName,
category: category,
quantity: quantity,
price: price,
maxStock: maxStock,
minStock: minStock,
};
let response = await fetch(`/api/products/${params.update}`, {
method: "PUT",
body: JSON.stringify(newProduct),
headers: {
"content-type": "application/json"
}
})
response = await response.json()
if (response.success) {
alert(response.message)
return router.push('/products')
};
}
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-4">Update Product</h1>
<form onSubmit={updateForm} className="max-w-md mx-auto">
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
value={productName}
onChange={(e) => setProductName(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">
Name
</label>
</div>
<div className="relative z-0 w-full mb-5 group">
<select
value={category}
onChange={(e) => setCategory(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-500 bg-transparent border-0 border-b-2 border-gray-200 appearance-none focus:outline-none focus:ring-0 focus:border-gray-200 peer"
>
<option value="" disabled>Choose Product Category</option>
<option value="Electronics">Electronics</option>
<option value="Clothing">Clothing</option>
<option value="Furniture">Furniture</option>
<option value="Stationery">Stationery</option>
</select>
</div>
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">
Quantity
</label>
</div>
<div className="relative z-0 w-full mb-5 group">
<input
type="text"
value={price}
onChange={(e) => setPrice(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-900 bg-transparent border-0 border-b-2 border-gray-300 appearance-none focus:outline-none focus:ring-0 focus:border-blue-600 peer"
placeholder=" "
required
/>
<label className="peer-focus:font-medium absolute text-sm text-gray-500 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 peer-focus:text-blue-600 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">
Price
</label>
</div>
<div className="grid md:grid-cols-2 md:gap-6">
<div className="relative z-0 w-full mb-5 group">
<select
value={maxStock}
onChange={(e) => setMaxStock(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-500 bg-transparent border-0 border-b-2 border-gray-200 appearance-none focus:outline-none focus:ring-0 focus:border-gray-200 peer"
>
<option value="" disabled>Choose Max Stock Quantity</option>
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
</select>
</div>
<div className="relative z-0 w-full mb-5 group">
<select
value={minStock}
onChange={(e) => setMinStock(e.target.value)}
className="block py-2.5 px-0 w-full text-sm text-gray-500 bg-transparent border-0 border-b-2 border-gray-200 appearance-none focus:outline-none focus:ring-0 focus:border-gray-200 peer"
>
<option value="" disabled>Choose Min Stock Quantity</option>
<option value="5">5</option>
<option value="15">15</option>
<option value="25">25</option>
<option value="35">35</option>
<option value="45">45</option>
</select>
</div>
</div>
<button type="submit" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center">
Update Product
</button>
</form>
</div>
);
}
JavaScript
// File path: src/app/api/products/route.js
import { NextResponse } from "next/server";
import { promises as fs } from 'fs';
export async function GET(request) {
const url = new URL(request.url);
const searchValue = url.searchParams.get('search');
// Read the products file and parse it
let products = await fs.readFile(`${process.cwd()}/public/data/products.json`, 'utf8');
products = JSON.parse(products); // Parse the JSON string into an array
// If there is no search value, return all products
if (!searchValue) {
return NextResponse.json({
success: true,
message: "Products Fetched Successfully",
data: products
});
}
// Filter the products based on the search value
let newdata = products.filter((product) => {
return new RegExp(`^${searchValue}`, 'i').test(product.name); // 'i' for case-insensitive matching
});
// Return the filtered products
return NextResponse.json({
success: true,
message: "Products Fetched Successfully",
data: newdata
});
}
export async function DELETE(request) {
const id = await request.json()
let products = await fs.readFile(`${process.cwd()}/public/data/products.json`, 'utf8')
products = JSON.parse(products)
let productIndex = products.findIndex(product => product.id == id)
products.splice(productIndex, 1)
await fs.writeFile(`${process.cwd()}/public/data/products.json`, JSON.stringify(products, null, 4))
return NextResponse.json({
success: true,
message: "Products Deleted Successfully",
});
}
JavaScript
// File path: src/app/api/products/add/route.js
import { NextResponse } from "next/server";
import { promises as fs } from 'fs';
import { v4 } from "uuid";
export async function POST(request) {
let payload = await request.json();
payload.id = v4();
let products = await fs.readFile(`${process.cwd()}/public/data/products.json`, 'utf8')
products = JSON.parse(products)
products.push(payload)
await fs.writeFile(`${process.cwd()}/public/data/products.json`, JSON.stringify(products, null, 4))
return NextResponse.json({success:true, message: "New Product Added Successfully"})
}
JavaScript
// File path: src/app/api/products/[id]/route.js
import { NextResponse } from "next/server";
import { promises as fs } from 'fs';
export async function GET(request, { params }) {
// Read the products file and parse it
let products = await fs.readFile(`${process.cwd()}/public/data/products.json`, 'utf8');
products = JSON.parse(products); // Parse the JSON string into an array
products = products.find(product => product.id == params.id)
return NextResponse.json({
success: true,
message: "Products Fetched Successfully",
data: products
});
}
export async function PUT(request, { params }) {
let payload = await request.json();
// Read the products file and parse it
let products = await fs.readFile(`${process.cwd()}/public/data/products.json`, 'utf8');
products = JSON.parse(products); // Parse the JSON string into an array
let productIndex = products.findIndex(product => product.id == params.id)
products[productIndex] = {...payload, id: params.id}
await fs.writeFile(`${process.cwd()}/public/data/products.json`, JSON.stringify(products, null, 4))
return NextResponse.json({
success: true,
message: "Product Updated Successfully",
});
}
To run the Application open the terminal in the project folder and enter the following command:
npm run dev
Output: