برنامه نویسی

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

همانطور که ما با 👉 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.

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  • متغیرهای حالت
  • محصولات: ذخیره لیست محصولات.
  1. فرم: مدیریت داده های فرم محصول برای افزودن/ویرایش.

  2. Sellform: ذخیره اطلاعات فروش.

  3. Showaddform ، ShowsEllForm: فرم های افزودن/فروش محصولات.

  4. 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 را بارگذاری کنند.
  1. یک درخواست 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.");
  }
};

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  • ساختار مؤلفه در بیانیه بازگشت.
  • اضافه کردن محصولات جدید
  1. فروش محصولات

  2. وارد کردن/صادرات پرونده های CSV

  3. ویرایش و حذف محصولات

  4. نمایش لیستی از محصولات

  • بخش هدر بازگشت به دکمه داشبورد → به داشبورد حرکت می کند.

عنوان: “مدیریت محصول” → عنوان بخش را نمایش می دهد.

واردات و صادرات 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

{products.map((product) => ( ))}
Product Category Price Stock Actions
{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. ناوبری



حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. بخش نمای کلی سهام

Stock Overview

حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. کارت داده سهام 3 معیار کلیدی را نشان می دهد: کل کالاها ، کل فروخته شده ، کل درآمد

اثر بارگیری اسکلت: در حالی که داده ها را واکشی می کند ، با استفاده از پالس متحرک ، یک مکان نگهدارنده را نشان می دهد.

{loading ? ( [...Array(3)].map((_, i) => ( )) ) : ( <>

Total Items

{stockData.totalItems}

Total Sold

{stockData.totalSold}

Total Revenue

${stockData.totalRevenue.toFixed(2)}

> )}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. لیست موارد فروخته شده
  • موارد فروخته شده را در یک لیست نشان می دهد.

  • اگر داده ها هنوز در حال واگذاری است ، اثر بارگذاری اسکلت را نشان می دهد.

  • داده های خالی را به طرز فجیعی کنترل می کند (هنوز کالای فروخته نشده است.)

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. فیلترها و گزینه های مرتب سازی
  2. ورودی متن: فیلترها براساس دسته.
  3. کشویی: 1.Sort by (TotalRevelue / Totalsold). 2. سفارش (ASC / DESC).
  1. جدول برای داده های سهام

محصول ، دسته ، تعداد فروش و درآمد را نشان می دهد.

از StockData برای تولید ردیف استفاده می کند.


    {stockData.map((product) => (
      
    ))}
  
Product Category Items Sold Revenue
{product.name} {product.category} {product.itemsSold} ${product.totalRevenue ? product.totalRevenue.toFixed(2) : "0.00"}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

  1. نمودار نمودار نوار
  2. اگر 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 (
  
Enter fullscreen mode Exit fullscreen mode
  • 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.

)}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

© {new Date().getFullYear()} Stock Management System By Shaik Reshma
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

کد منبع پروژه من را بررسی کنید 👉github و لینک مستقر را پیدا خواهید کرد ، آن را در آنجا آزمایش کنید.

این همه چیز در مورد کد تنظیمات Frontend است و برنامه NPM Run Dev را اجرا کنید. برای هرگونه نمایش داده شده در بخش نظرات واکنش نشان می دهد.

                       Let's grow together!

TQ

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا