سیستم مدیریت سهام – جبهه

همانطور که ما با 👉 auth و راه اندازی مسیر خصوصی انجام می شود. بیایید ادامه دهیم تا بخش جلوی پروژه خود را به دنبال نیازهای زیر تکمیل کنیم.
1. یک صفحه داشبورد ایجاد کنید pages/Dashboard.jsx
من یک داشبورد می خواستم که تمام اجزای مورد نیاز من را بر روی صفحه نمایش داده شود.
-
همانطور که ، داشبورد باید یک مسیر خصوصی باشد ، یعنی پس از ورود به سیستم فقط کاربر اجازه دسترسی به آن را داشته باشد.
-
واگذاری جزئیات کاربر از AuthContext.
-
اگر کاربر در دسترس نباشد ، صفحه بارگیری را ارائه می دهد.
-
نمایش یک داشبورد با مضمون تیره با یک ناوبر.
-
نشان دادن پیام خوش آمدید با کاربر. name.
-
ارائه سه پیوند ناوبری به بخش های مختلف با استفاده از یک طرح شبکه با یک ظاهر طراحی مناسب.
import { useContext } from "react";
import { AuthContext } from "../context/AuthContext";
import { Link } from "react-router-dom";
import Navbar from "../components/Navbar";
const Dashboard = () => {
const { user } = useContext(AuthContext);
if (!user) {
return Loading...
;
}
return (
{/* Navbar */}
{/* Dashboard Content */}
Manage your stock efficiently with real-time insights.
{/* Dashboard Cards */}
Manage Products
Stock Overview
Analytics Dashboard
);
};
export default Dashboard;
بیایید مؤلفه هایی را که در بالا تعریف کردیم پیاده سازی کنیم.
2 components/ProductManagement.jsx
- تنظیم واردات مورد نیاز.
import { useEffect, useState } from "react"; //for statemanagement and sideeffects.
import { toast } from "react-toastify"; //for notification pop-ups
import { Trash2, Edit3 } from "lucide-react"; //Icons for delete and edit operations.
import api from "../utils/api"; //for api calls.
import Navbar from "./Navbar"; //navbar component
import { useNavigate } from "react-router-dom"; //React router navigation function.
- متغیرهای حالت
- محصولات: ذخیره لیست محصولات.
-
فرم: مدیریت داده های فرم محصول برای افزودن/ویرایش.
-
Sellform: ذخیره اطلاعات فروش.
-
Showaddform ، ShowsEllForm: فرم های افزودن/فروش محصولات.
-
EditingProduct: شناسه محصول ویرایش شده را ذخیره می کند.
const [products, setProducts] = useState([]);
const [form, setForm] = useState({ name: "", category: "", price: "", quantityInStock: "" });
const [sellForm, setSellForm] = useState({ productId: "", quantity: "" });
const [showAddForm, setShowAddForm] = useState(false);
const [showSellForm, setShowSellForm] = useState(false);
const [editingProduct, setEditingProduct] = useState(null);
- هنگامی که مؤلفه از API بارگیری می شود ، داده های محصولات را واکشی می کند ، سپس حالت را با پاسخ API به روز می کند.
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async () => {
try {
const { data } = await api.get("/products");
setProducts(data);
} catch (error) {
console.error(error);
toast.error("Failed to fetch products. Please try again.");
}
};
به روزرسانی ها به صورت پویا به عنوان انواع کاربر شکل می گیرند.
const handleChange = (e) => setForm({ ...form, [e.target.name]: e.target.value });
const handleSellChange = (e) => {
const { name, value } = e.target;
setSellForm((prev) => ({
...prev,
[name]: name === "quantity" ? Number(value) : value, // Ensures quantity is a number
}));
};
- رسیدگی به ویرایش محصول
const handleEdit = (product) => {
setEditingProduct(product._id); // Store product ID
setForm({ ...product }); // Populate form with product data
setShowAddForm(true); // Open form modal
};
- افزودن یا به روزرسانی محصولات 1.If EditingProduct وجود دارد → محصول را به روز کنید (Put /Products /: ID).
2.else → ایجاد محصول جدید (پست /محصولات).
const handleSubmit = async (e) => {
e.preventDefault();
if (!form.name || !form.category || !form.price || !form.quantityInStock) {
toast.warn("Please fill in all fields before submitting.");
return;
}
try {
if (editingProduct) {
await api.put(`/products/${editingProduct}`, form);
toast.success("Product updated successfully");
setEditingProduct(null);
} else {
await api.post("/products", form);
toast.success("Product added successfully");
}
fetchProducts();
setForm({ name: "", category: "", price: "", quantityInStock: "" });
setShowAddForm(false);
} catch (error) {
toast.error(error.response?.data?.message || "Error adding product.");
}
};
- فروش یک محصول 1. درخواست فروش (پست /فروش /فروش) را ارائه می دهد.
2. هنگام فروش یک محصول ، تعداد سهام را کاهش می دهد.
const handleSellSubmit = async (e) => {
e.preventDefault();
if (!sellForm.productId || !sellForm.quantity || sellForm.quantity <= 0) {
toast.warn("Please select a product and enter a valid quantity.");
return;
}
try {
await api.post("/sales/sell", sellForm);
toast.success("Product sold successfully! 💰");
fetchProducts();
setSellForm({ productId: "", quantity: "" });
setShowSellForm(false);
} catch (error) {
toast.error(error.response?.data?.message || "Error selling product.");
}
};
const handleDelete = async (id) => {
try {
await api.delete(`/products/${id}`);
toast.success("Product deleted successfully! 🗑️");
fetchProducts();
} catch (error) {
console.error(error);
toast.error("Error deleting product. Please try again.");
}
};
- واردات CSV
- به کاربران اجازه می دهد تا یک فایل CSV را بارگذاری کنند.
- یک درخواست Data Multipart/Form را به/CSV/Import-CSV ارسال می کند.
const handleImportCSV = async (e) => {
e.preventDefault();
const file = e.target.files[0];
if (!file) {
toast.warn("Please select a CSV file to import.");
return;
}
const formData = new FormData();
formData.append("file", file);
try {
await api.post("/csv/import-csv", formData, { headers: { "Content-Type": "multipart/form-data" } });
toast.success("CSV imported successfully! 📂");
fetchProducts();
} catch (error) {
console.error(error);
toast.error("Error importing CSV. Please check the file format, and duplicates before Import.");
}
};
- صادرات CSV 1. داده های CSV از /CSV /Export-CSV.
2. فایل را برای کاربر بارگیری می کند.
const handleExportCSV = async () => {
try {
const response = await api.get("/csv/export-csv", { responseType: "blob" });
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", "products.csv");
document.body.appendChild(link);
link.click();
toast.success("CSV exported successfully! 📤");
} catch (error) {
console.error(error);
toast.error("Error exporting CSV. Please try again.");
}
};
- ساختار مؤلفه در بیانیه بازگشت.
- اضافه کردن محصولات جدید
-
فروش محصولات
-
وارد کردن/صادرات پرونده های CSV
-
ویرایش و حذف محصولات
-
نمایش لیستی از محصولات
- بخش هدر بازگشت به دکمه داشبورد → به داشبورد حرکت می کند.
عنوان: “مدیریت محصول” → عنوان بخش را نمایش می دهد.
واردات و صادرات CSV → اجازه می دهد تا یک فایل CSV وارد شود.
list لیست محصول را به عنوان CSV صادر می کند.
{/* Header */}
- دکمه های اکشن 1. دکمه “اضافه کردن محصول” → فرم محصول Add/Edit را تغییر می دهد.
2. دکمه “فروش محصول” → فرم محصول فروش را تغییر می دهد.
{/* Action Buttons */}
- فرم محصول را اضافه یا ویرایش کنید 1. در هنگام اضافه کردن یک محصول جدید یا ویرایش یک محصول موجود ، فرم را نشان می دهد.
2.Fields: نام محصول ، دسته ، قیمت ، مقدار سهام
دکمه 3.Submit → محصول را اضافه یا به روز می کند.
دکمه 4.cancel → فرم را می بندد و حالت را تنظیم می کند.
{/* Add Product Form */}
{showAddForm && (
)}
- فرم محصول را به فروش می رساند.
2.Fields:
کشویی: محصولی را از کالاهای موجود انتخاب می کند.
ورودی کمیت: تعداد واحدهای فروش را مشخص می کند.
ارسال دکمه → سهام فروش و به روزرسانی را پردازش می کند.
{/* Sell Product Form */}
{showSellForm && (
)}
1. همه محصولات موجود را در یک جدول نشان می دهد.
2.Columns:
نام محصول ، دسته ، قیمت ، مقدار سهام ، اقدامات
دکمه ویرایش → فرم ویرایش را با جزئیات از پیش پر شده باز می کند.
DELETE BUTTON → محصول انتخاب شده را حذف می کند.
{/* Product List */}
Product List
Product
Category
Price
Stock
Actions
{products.map((product) => (
{product.name}
{product.category}
${product.price}
{product.quantityInStock}
))}
3. مؤلفه نمای کلی سهام components/StockOverview.jsx
import { useEffect, useState } from "react"; //Manages state and API calls.
import { toast } from "react-toastify"; //Displays error messages if API calls fail.
import api from "../utils/api"; //Axios instance for API requests.
import { useNavigate } from "react-router-dom"; //Enables navigation between pages.
- اولیه سازی مؤلفه و مدیریت دولت
1.StockData the جزئیات سهام برگرفته از API را ذخیره می کند.
بارگیری → پیگیری می کند که آیا داده ها هنوز در حال واگذاری هستند یا خیر.
const navigate = useNavigate();
const [stockData, setStockData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchStockOverview();
}, []);
- واکشی اجمالی سهام از API
1. برای بازیابی جزئیات سهام ، API (/نمای سهام) را بازیابی می کند.
2. خطاهای HANDLES (خطای سیاهه ها + یک اعلان نان تست را نمایش می دهد).
3.Sets بارگیری به FALSE پس از واکشی داده ها.
const fetchStockOverview = async () => {
try {
const { data } = await api.get("/stock-overview");
setStockData(data);
} catch (error) {
console.error(error);
toast.error("Failed to fetch stock overview");
} finally {
setLoading(false);
}
};
- بیانیه بازگشت UI یا مؤلفه
1. ناوبری
- بخش نمای کلی سهام
Stock Overview
- کارت داده سهام 3 معیار کلیدی را نشان می دهد: کل کالاها ، کل فروخته شده ، کل درآمد
اثر بارگیری اسکلت: در حالی که داده ها را واکشی می کند ، با استفاده از پالس متحرک ، یک مکان نگهدارنده را نشان می دهد.
{loading ? (
[...Array(3)].map((_, i) => (
))
) : (
<>
Total Items
{stockData.totalItems}
Total Sold
{stockData.totalSold}
Total Revenue
${stockData.totalRevenue.toFixed(2)}
>
)}
- لیست موارد فروخته شده
-
موارد فروخته شده را در یک لیست نشان می دهد.
-
اگر داده ها هنوز در حال واگذاری است ، اثر بارگذاری اسکلت را نشان می دهد.
-
داده های خالی را به طرز فجیعی کنترل می کند (هنوز کالای فروخته نشده است.)
Sold Items
{loading ? (
[...Array(5)].map((_, i) => (
-
))
) : stockData.soldItems.length > 0 ? (
stockData.soldItems.map((item, index) => (
-
{item.name}
{item.category}
Sold: {item.quantitySold}
Revenue: ${item.revenueGenerated.toFixed(2)}
))
) : (
No items sold yet.
)}
4. مؤلفه تحلیلی components/Analytics.jsx
- واردات و تنظیم اولیه.
import { useEffect, useState } from "react";
import { Bar } from "react-chartjs-2"; //Registers bar chart components.
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
} from "chart.js";
import api from "../utils/api"; // Using baseURL configured API
import { useNavigate } from "react-router-dom";
const [stockData, setStockData] = useState([]); //Stores fetched product stock data
const [chartData, setChartData] = useState(null); // Stores formatted data for Chart.js
const [category, setCategory] = useState(""); //Stores user-input filter for product category
const [sortBy, setSortBy] = useState("totalRevenue"); //Stores sorting criteria (totalRevenue or totalSold)
const [order, setOrder] = useState("desc"); //Determines sort order (asc or desc)
const [loading, setLoading] = useState(true); //Tracks data fetching state
const [error, setError] = useState(null); //Stores error messages
- داده های واکشی با استفاده از تماس های UseEffect fetchstockdata و fetchchartdata هر زمان که دسته بندی ، مرتب سازی یا سفارش را تغییر دهند.
useEffect(() => {
fetchStockData();
fetchChartData();
}, [category, sortBy, order]);
- واکشی داده های سهام 1. درخواست API را به /تجزیه و تحلیل /سهام برای به دست آوردن جزئیات سهام.
2. محصولات فیلتر بر اساس گروه (مورد حساس).
3.Updates StockData با نتایج فیلتر شده.
const fetchStockData = async () => {
setLoading(true);
try {
const response = await api.get(`/analytics/stock`, {
params: { sortBy, order },
});
let filteredData = response.data;
// Apply case-insensitive filtering on the frontend
if (category.trim() !== "") {
const searchQuery = category.toLowerCase();
filteredData = filteredData.filter(product =>
product.category.toLowerCase().includes(searchQuery) ||
product.name.toLowerCase().includes(searchQuery)
);
}
setStockData(filteredData);
} catch (error) {
setError("Error fetching stock data");
console.error("Error fetching stock data:", error);
} finally {
setLoading(false);
}
};
1.Calls API /Analytics /Chart-Data برای به دست آوردن کل درآمد و کل فروخته شده در هر گروه.
2. پاسخ به ChartData برای نمودار نمودار.
const fetchChartData = async () => {
try {
const response = await api.get(`/analytics/chart-data`);
const data = response.data;
setChartData({
labels: data.map((item) => item.category),
datasets: [
{
label: "Total Revenue",
data: data.map((item) => item.totalRevenue || 0),
backgroundColor: "rgba(54, 162, 235, 0.6)",
},
{
label: "Total Sold",
data: data.map((item) => item.totalSold || 0),
backgroundColor: "rgba(255, 99, 132, 0.6)",
},
],
});
} catch (error) {
setError("Error fetching chart data");
console.error("Error fetching chart data:", error);
}
};
- پیاز
- دکمه ناوبری
- فیلترها و گزینه های مرتب سازی
- ورودی متن: فیلترها براساس دسته.
- کشویی: 1.Sort by (TotalRevelue / Totalsold). 2. سفارش (ASC / DESC).
- جدول برای داده های سهام
محصول ، دسته ، تعداد فروش و درآمد را نشان می دهد.
از StockData برای تولید ردیف استفاده می کند.
Product
Category
Items Sold
Revenue
{stockData.map((product) => (
{product.name}
{product.category}
{product.itemsSold}
${product.totalRevenue ? product.totalRevenue.toFixed(2) : "0.00"}
))}
- نمودار نمودار نوار
- اگر ChartData وجود دارد ، نمودار نوار را ارائه می دهد.
{chartData && (
Sales & Revenue Overview
)}
5 صفحه فرود pages/LandingPage.jsx
import { useNavigate } from "react-router-dom";
import { ShoppingCart, BarChart3, FileText, LogIn } from "lucide-react";
import { AuthContext } from "../context/AuthContext";
import { useContext, useState } from "react";
- تعریف مؤلفه و AuthChecks
1. کاربر را برای مدیریت احراز هویت از AuthContext خارج کنید.
2.Isopen دیدگاه کشویی پروفایل را کنترل می کند.
در صورت ورود کاربر با استفاده از نشانه های محلی ، چک های 3.isauthenticated را بررسی می کند.
const LandingPage = () => {
const { user, logout } = useContext(AuthContext);
const [isOpen, setIsOpen] = useState(false);
const navigate = useNavigate();
const handleLogout = () => {
logout();
navigate("https://dev.to/");
setIsOpen(false);
};
const isAuthenticated = !!localStorage.getItem("token");
- روی مشخصات Handling ، هنگام کلیک بر روی صفحه نمایش پروفایل قرار می گیرد.
const handleProfileClick = async () => {
if (!isOpen) {
await user;
}
setIsOpen(!isOpen);
};
const handleNavigation = (path) => {
navigate(isAuthenticated ? path : "/login");
};
- طرح صفحه فرود // یک ظاهر طراحی شده حالت تاریک.
return (
- Navbar section
1.If the user is logged in, show a profile button.
2.Clicking Profile reveals a dropdown with name, email, and a logout button.
3.If not logged in, show Login & Register buttons.
{user ? (
) : (
|
)}
- عنوان بخش قهرمان و توضیحات برای صفحه فرود.
A powerful tool to track inventory, manage stock levels, and generate reports efficiently.
1.Displays 3 کارت ویژگی (مدیریت محصول ، نمای کلی سهام ، تجزیه و تحلیل).
2. اگر کاربر تأیید نشده باشد ، کارت اضافی برای ورود به سیستم ایمن ظاهر می شود.
{[
{
path: "/products",
icon: ,
title: "Product Management",
description: "Easily add, edit, and delete products in stock.",
},
{
path: "/stock-overview",
icon: ,
title: "Stock Overview",
description: "Monitor available stock, items sold, and revenue trends.",
},
{
path: "/analytics",
icon: ,
title: "Analysis",
description: "Generate reports in charts.",
},
].map((feature, index) => (
handleNavigation(feature.path)}
className="bg-gray-800 p-6 rounded-lg shadow-md cursor-pointer hover:bg-gray-700 transition duration-300">
{feature.icon}
{feature.title}
{feature.description}
))}
{!isAuthenticated && (
navigate("/login")}
className="bg-gray-800 p-6 rounded-lg shadow-md cursor-pointer hover:bg-gray-700 transition duration-300">
Secure Login
Ensure security with JWT-based authentication.
)}
کد منبع پروژه من را بررسی کنید 👉github و لینک مستقر را پیدا خواهید کرد ، آن را در آنجا آزمایش کنید.
این همه چیز در مورد کد تنظیمات Frontend است و برنامه NPM Run Dev را اجرا کنید. برای هرگونه نمایش داده شده در بخش نظرات واکنش نشان می دهد.
Let's grow together!
