Untitled

 avatar
unknown
jsx
10 months ago
26 kB
5
Indexable
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { pdf } from "@react-pdf/renderer";
import axiosInstance from "../../utils/axiosInstance";
import BarcodeCheckerPDF from "./SellProductPdf";
import ConfirmationModal from "./ConfirmationModal";
import { toast, ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

const BarcodeChecker = () => {
  const navigate = useNavigate();
  const [barcode, setBarcode] = useState("");
  const [id, setId] = useState("");
  const [items, setItems] = useState([]);
  const [customerName, setCustomerName] = useState("");
  const [customerDetails, setCustomerDetails] = useState(null);
  const [loading, setLoading] = useState(false);
  const [errors, setErrors] = useState({});
  const [quantity, setQuantity] = useState(0);
  const [name, setName] = useState("");
  const [price, setPrice] = useState(0);
  const [payment, setPayment] = useState(0);
  const [paidAmount, setPaidAmount] = useState(0);
  const [remainingAmount, setRemainingAmount] = useState(0);
  const [suggestions, setSuggestions] = useState([]);
  const [customers, setCustomers] = useState([]);
  const [debt, setDebt] = useState(0);
  const [availableQuantity, setAvailableQuantity] = useState(0);
  const [editIndex, setEditIndex] = useState(null);
  const [editQuantity, setEditQuantity] = useState(0);
  const [editPrice, setEditPrice] = useState(0);
  const [discount, setDiscount] = useState(0);
  const [showModal, setShowModal] = useState(false);
  const [deleteIndex, setDeleteIndex] = useState(null);

  useEffect(() => {
    const fetchCustomers = async () => {
      setLoading(true);
      try {
        const response = await axiosInstance.get("/customers?perPage=100");
        setCustomers(response.data);
      } catch (error) {
        console.error("Error fetching customers:", error);
      } finally {
        setLoading(false);
      }
    };

    fetchCustomers();
  }, []);

  useEffect(() => {
    if (barcode) {
      const fetchItem = async () => {
        setLoading(true);
        try {
          const response = await axiosInstance.get(`/items/${barcode}`);
          const item = response.data.data;
          setName(item.name);
          setPrice(item.salePrice);

          setId(item.id);
          setAvailableQuantity(item.quantity);
        } catch (error) {
          console.error("Error fetching item:", error);
          setName("");
          setPrice(0);
          setId(null);
          setAvailableQuantity(0);
        } finally {
          setLoading(false);
        }
      };

      fetchItem();
    }
  }, [barcode]);

  useEffect(() => {
    if (customerName) {
      const filteredSuggestions = customers.data.filter((customer) =>
        customer.username.toLowerCase().startsWith(customerName.toLowerCase())
      );
      setSuggestions(filteredSuggestions);
    } else {
      setSuggestions([]);
    }
  }, [customerName, customers]);

  useEffect(() => {
    if (customerDetails && customerDetails.id) {
      const fetchDebt = async () => {
        setLoading(true);
        try {
          const response = await axiosInstance.get(
            `/debts/${customerDetails.id}`
          );
          const debt = response.data.data.total;
          setDebt(debt);
        } catch (error) {
          console.error("Error fetching customer debt:", error);
        } finally {
          setLoading(false);
        }
      };

      fetchDebt();
    }
  }, [customerDetails]);

  const validate = () => {
    const newErrors = {};
    if (!barcode) newErrors.barcode = "بارکۆد پێویستە";
    if (!name) newErrors.name = "ناوی بەرهەم پێویستە";
    if (!price) newErrors.price = "نرخ پێویستە";
    if (!quantity) newErrors.quantity = "دانە پێویستە";
    return newErrors;
  };

  const formatPhoneNumber = (phone) => {
    const part1 = phone.slice(7, 11);
    const part2 = phone.slice(4, 7);
    const part3 = phone.slice(0, 4);
    return `${part1} ${part2} ${part3}`;
  };

  const formatNumber = (value) => {
    if (!value) return "";
    const parts = value.toString().split(".");
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    return parts.join(".");
  };

  const handlePaymentChange = (e) => {
    const value = e.target.value.replace(/,/g, ""); // Remove commas for parsing
    setPayment(value ? parseFloat(value) : 0); // Update state with numeric value
  };

  const handlePriceChange = (e) => {
    const value = e.target.value.replace(/,/g, ""); // Remove commas for parsing
    setPrice(value ? parseFloat(value) : 0); // Update state with numeric value
  };

  const handleDiscountChange = (e) => {
    const value = e.target.value.replace(/,/g, ""); // Remove commas for parsing
    setDiscount(value ? parseFloat(value) : 0); // Update state with numeric value
  };

  const handleEditPriceChange = (e) => {
    const value = e.target.value.replace(/,/g, ""); // Remove commas for parsing
    setEditPrice(value ? parseFloat(value) : 0); // Update state with numeric value
  };

  const handleAddItem = () => {
    const validationErrors = validate();
    if (Object.keys(validationErrors).length > 0) {
      setErrors(validationErrors);
      return;
    }
    setErrors({});
    const newItem = {
      barcode,
      name,
      price: parseFloat(price),
      quantity: parseInt(quantity),
      id,
      availableQuantity,
    };
    setItems([...items, newItem]);
    setBarcode("");
    setName("");
    setPrice(0);
    setQuantity(0);
  };

  const handleDeleteItem = () => {
    const newItems = items.filter((_, i) => i !== deleteIndex);
    setItems(newItems);
    setShowModal(false);
  };

  const handleShowModal = (index) => {
    setDeleteIndex(index);
    setShowModal(true);
  };

  const handleSearchCustomer = (customer) => {
    const selectedCustomer = customers.data.find(
      (c) => c.username === customer
    );
    if (selectedCustomer) {
      setCustomerDetails(selectedCustomer);
      setCustomerName(selectedCustomer.username);
      setSuggestions([]);
      setPaidAmount(0);
      setRemainingAmount(totalPriceAfterDiscount);
    } else {
      setCustomerDetails(null);
      setErrors({ customerName: "Customer not found" });
    }
  };

  const handleSuggestionClick = (customer) => {
    setCustomerName(customer.username);
    handleSearchCustomer(customer.username);
  };

  const handleKeyDown = (e) => {
    if (e.key === "Enter") {
      handleSearchCustomer(customerName);
    }
  };

  const totalPrice = items.reduce(
    (sum, item) => sum + item.price * item.quantity,
    0
  );

  const totalPriceAfterDiscount = totalPrice - discount;

  const handlePayment = async () => {
    const newPaidAmount = paidAmount + payment;
    const newRemainingAmount = totalPriceAfterDiscount - newPaidAmount;
    const newAmountLent = customerDetails.amountLent + newRemainingAmount;

    setPaidAmount(newPaidAmount);
    setRemainingAmount(newRemainingAmount > 0 ? newRemainingAmount : 0);

    setCustomerDetails((prevDetails) => ({
      ...prevDetails,
      amountLent: newAmountLent,
    }));

    try {
      const paymentData = {
        customer_id: customerDetails.id,
        paidAmount: payment,
        soldItems: items.map((item) => ({
          item_id: item.id,
          quantity: item.quantity,
          salePrice: parseFloat(item.price),
        })),
        discount,
      };

      await axiosInstance.post("/sales", paymentData);
      console.log("Payment recorded successfully");

      // Show success toast
      toast.success("وەسڵەکە بە سەرکەوتوویی دروستکرا!", {
        position: "top-right",
        autoClose: 2000, // 2 seconds
      });
    } catch (error) {
      console.error("Error recording payment:", error);
      toast.error("هەڵەیەک ڕویدا لە دروستکردنی وەسڵەکە.");
    }

    setPayment(0);
  };

  const handlePrint = async () => {
    const doc = (
      <BarcodeCheckerPDF
        customerDetails={customerDetails}
        items={items}
        totalPrice={totalPriceAfterDiscount}
        paidAmount={paidAmount}
        remainingAmount={remainingAmount}
        discount={discount}
        customers={customers}
      />
    );

    const blob = await pdf(doc).toBlob();
    const url = URL.createObjectURL(blob);

    const printWindow = window.open(url);

    if (printWindow) {
      printWindow.onload = () => {
        printWindow.print();
      };
    } else {
      console.error("Failed to open new window for printing.");
    }
  };

  const handleEditRow = (index) => {
    setEditIndex(index);
    setEditQuantity(items[index].quantity);
    setEditPrice(items[index].price);
  };

  const handleSaveEdit = (index) => {
    const updatedItems = items.map((item, i) => {
      if (i === index) {
        return {
          ...item,
          quantity: editQuantity,
          price: parseFloat(editPrice),
        };
      }
      return item;
    });
    setItems(updatedItems);
    // Reset editing state
    setEditIndex(null);
    setEditQuantity(0);
    setEditPrice(0);
  };

  const handleCancelEdit = () => {
    setEditIndex(null);
    setEditQuantity(0);
    setEditPrice(0);
  };

  return (
    <div className="flex items-center justify-center min-h-screen overflow-hidden bg-secondary">
      <ToastContainer />
      <div className="flex flex-col w-full p-8 m-2 border-2 rounded-lg shadow-lg bg-accent border-primary">
        <button
          className="flex text-invert border border-primary py-2 px-4 rounded-md w-[10%] text-center text-lg mb-4"
          onClick={() => {
            navigate("/");
          }}
        >
          گەڕانەوە
        </button>

        <div className="relative flex mb-4">
          <input
            type="text"
            value={customerName}
            onChange={(e) => setCustomerName(e.target.value)}
            placeholder="ناوی کڕیار"
            onKeyDown={handleKeyDown}
            className={`flex-grow px-4 py-2 text-xl border rounded-md bg-secondary text-invert text-right focus:outline-none focus:ring focus:ring-primary ${
              errors.customerName ? "border-red-500" : "border-primary"
            }`}
          />
          <button
            onClick={() => handleSearchCustomer(customerName)}
            disabled={loading}
            className="px-10 py-[10px] mr-4 bg-primary text-invert rounded-md hover:bg-primary focus:outline-none focus:ring-2 focus:ring-invert focus:ring-opacity-75 text-xl font-medium"
          >
            گەڕان
          </button>
          {suggestions.length > 0 && (
            <ul className="absolute z-10 w-full mt-1 text-xl rounded-md shadow-lg top-full bg-accent">
              {suggestions.map((suggestion) => (
                <li
                  key={suggestion.id}
                  onClick={() => handleSuggestionClick(suggestion)}
                  className="px-4 py-2 text-xl text-right cursor-pointer hover:bg-primary text-invert"
                >
                  {suggestion.username} - {suggestion.city} - {suggestion.phone}
                </li>
              ))}
            </ul>
          )}
        </div>
        {errors.customerName && (
          <p className="mt-1 text-sm text-right text-red-500">
            {errors.customerName}
          </p>
        )}
        <h2 className="mb-6 text-2xl font-bold text-center text-invert">
          زانیاری بەرهەم
        </h2>
        <div className="grid grid-cols-1 gap-4 mb-4 text-2xl md:grid-cols-2 lg:grid-cols-4">
          <div className="flex flex-col">
            <label className="mb-2 text-invert">بارکۆد</label>
            <input
              type="text"
              value={barcode}
              onChange={(e) => setBarcode(e.target.value)}
              placeholder="بارکۆد"
              className={`px-4 py-2 border rounded-md text-xl bg-secondary text-invert text-right focus:outline-none focus:ring focus:ring-primary ${
                errors.barcode ? "border-red-500" : "border-primary"
              }`}
            />
          </div>
          <div className="flex flex-col">
            <label className="mb-2 text-invert">ناوی بەرهەم</label>
            <input
              type="text"
              value={name}
              readOnly
              placeholder="ناوی بەرهەم"
              className={`px-4 py-2 border rounded-md text-xl bg-secondary text-invert text-right focus:outline-none focus:ring focus:ring-primary ${
                errors.name ? "border-red-500" : "border-primary"
              }`}
            />
          </div>
          <div className="flex flex-col">
            <label className="mb-2 text-invert">نرخ</label>
            <input
              type="text"
              value={formatNumber(price)}
              onChange={handlePriceChange}
              placeholder="نرخ"
              className={`px-4 py-2 border rounded-md text-xl bg-secondary text-invert text-right focus:outline-none focus:ring focus:ring-primary ${
                errors.price ? "border-red-500" : "border-primary"
              }`}
            />
          </div>
          <div className="flex flex-col">
            <label className="mb-2 text-invert">عدد</label>
            <input
              type="number"
              value={quantity}
              onChange={(e) => setQuantity(parseInt(e.target.value))}
              placeholder="دانە"
              className={`w-16   px-4 py-2 border rounded-md text-xl bg-secondary text-invert text-right focus:outline-none focus:ring focus:ring-primary ${
                errors.quantity ? "border-red-500" : "border-primary"
              }`}
            />
          </div>
        </div>

        <div className="flex justify-center">
          <button
            onClick={handleAddItem}
            disabled={quantity === 0}
            className="w-40 px-4 py-2 mt-2 text-4xl rounded-md bg-primary disabled:bg-gray-900 disabled:cursor-not-allowed text-invert hover:bg-primary focus:outline-none focus:ring-2 focus:ring-invert focus:ring-opacity-75"
          >
            +
          </button>
        </div>
        {errors.barcode && (
          <p className="mt-1 text-xl text-right text-red-500">
            {errors.barcode}
          </p>
        )}
        <div className="flex flex-1">
          <div className="w-1/4 pl-4">
            {customerDetails && (
              <div className="">
                <h3 className="text-2xl font-semibold text-right text-invert">
                  زانیاری کڕیار
                </h3>
                <div className="p-4 px-2 my-4 border-2 rounded-lg shadow bg-secondary border-primary">
                  <div className="grid grid-cols-2 gap-8">
                    <div>
                      <p className="py-2 m-2 mb-2 text-xl text-invert">
                        {customerDetails.username}
                      </p>
                      <p
                        className={`m-2 mb-2 py-2 ${
                          customerDetails.amountLent <= 1500
                            ? "text-green-500 text-xl"
                            : "text-red-500 text-xl"
                        }`}
                      >
                        قەرز : ${debt?.toLocaleString("en-US")}
                      </p>

                      <p className="py-2 m-2 mb-2 text-xl text-invert">
                        {customerDetails.phone1 &&
                          formatPhoneNumber(customerDetails.phone1)}
                      </p>
                    </div>
                    <div>
                      <p className="py-2 m-2 mb-2 text-xl text-invert">
                        {customerDetails.province}
                      </p>
                      <p className="py-2 m-2 mb-2 text-xl text-invert">
                        {customerDetails.city}
                      </p>
                      <p className="py-2 m-2 mb-2 text-xl text-invert">
                        {customerDetails.address}
                      </p>
                    </div>
                  </div>
                  <div className="p-2 mb-4 border-2 rounded-lg shadow bg-secondary border-primary">
                    <p className="py-2 text-xl text-invert">
                      پارەی دراو: {paidAmount.toLocaleString("en-US")} $
                    </p>
                    <p className="py-2 text-xl text-invert">
                      ماوە: {remainingAmount.toLocaleString("en-US")} $
                    </p>
                  </div>
                </div>
              </div>
            )}
            {customerDetails && (
              <>
                {" "}
                <div className="flex items-center justify-center w-full gap-4 mb-4 text-2xl">
                  <label className="w-3/5 ml-4 mr-2 text-sm font-semibold text-invert">
                    بڕی داشکاندن
                  </label>
                  <input
                    type="text"
                    value={formatNumber(discount)}
                    onChange={handleDiscountChange}
                    placeholder="(دینار)"
                    className={`px-4 py-2 border rounded-md text-xl w-full bg-secondary text-invert text-right focus:outline-none focus:ring focus:ring-primary ${
                      errors.discount ? "border-red-500" : "border-primary"
                    }`}
                  />
                </div>
                <div className="w-full p-4 ml-auto text-right border-2 rounded-lg shadow bg-secondary border-primary">
                  <div className="flex items-center mb-2 text-right">
                    <label className="ml-4 mr-2 text-xl font-semibold text-invert">
                      بڕی پارە
                    </label>
                    <input
                      type="text"
                      value={formatNumber(payment)}
                      onChange={handlePaymentChange}
                      className="w-40 p-4 py-2 text-2xl text-right border rounded-md border-primary bg-secondary text-invert focus:outline-none focus:ring focus:ring-primary"
                    />
                  </div>
                  <button
                    onClick={handlePayment}
                    disabled={loading}
                    className="w-full px-4 py-2 mt-2 mb-4 text-xl font-semibold rounded-md bg-primary text-invert hover:bg-primary focus:outline-none focus:ring-2 focus:ring-invert focus:ring-opacity-75"
                  >
                    پارەدان
                  </button>
                </div>
              </>
            )}
          </div>

          <div className="flex flex-col w-3/4 pr-4">
            {items.length > 0 && (
              <>
                <div className="flex-1 ">
                  <h3 className="text-2xl font-semibold text-right text-invert">
                    زانیاری بەرهەمەکان
                  </h3>
                  <div className="mt-[23px] overflow-y-auto max-h-96 text-xl flex-1 border-1 border-primary rounded-md">
                    <table className="min-w-full border-2 bg-secondary text-invert border-primary">
                      <thead>
                        <tr>
                          <th className="w-1/12 px-4 py-2 text-xl text-right border-2 border-primary">
                            #
                          </th>
                          <th className="w-3/12 px-4 py-2 text-xl text-right border-2 border-primary">
                            بەرهەم
                          </th>
                          <th className="w-2/12 px-4 py-2 text-xl text-right border-2 border-primary">
                            دانە
                          </th>
                          <th className="w-2/12 px-4 py-2 text-xl text-right border-2 border-primary">
                            نرخ
                          </th>
                          <th className="w-2/12 px-4 py-2 text-xl text-right border-2 border-primary">
                            کۆ
                          </th>
                          <th className="w-2/12 px-4 py-2 text-xl text-right border-2 border-primary">
                            هەڵەبوو
                          </th>
                        </tr>
                      </thead>
                      <tbody>
                        {items.map((item, index) => (
                          <tr key={index}>
                            <td className="px-4 py-2 text-xl text-right border">
                              {index + 1}
                            </td>
                            <td className="px-4 py-2 text-xl text-right border">
                              {item.name}
                            </td>
                            <td className="px-4 py-2 text-xl text-right border">
                              {editIndex === index ? (
                                <input
                                  type="number"
                                  value={editQuantity}
                                  onChange={(e) =>
                                    setEditQuantity(parseInt(e.target.value))
                                  }
                                  className="w-full p-2 text-right text-black rounded-md"
                                />
                              ) : (
                                item.quantity
                              )}
                            </td>
                            <td className="px-4 py-2 text-xl text-right border">
                              {editIndex === index ? (
                                <input
                                  type="text"
                                  value={formatNumber(editPrice)}
                                  onChange={handleEditPriceChange}
                                  className="w-full p-2 text-right text-black rounded-md"
                                />
                              ) : (
                                formatNumber(item.price) // Ensure the price is formatted correctly
                              )}
                            </td>
                            <td className="px-4 py-2 text-xl text-right border">
                              {formatNumber(item.price * item.quantity)}
                            </td>
                            <td className="px-4 py-2 text-xl text-right border">
                              {editIndex === index ? (
                                <div className="flex justify-end gap-2">
                                  <button
                                    onClick={() => handleSaveEdit(index)}
                                    className="px-2 py-1 text-white rounded bg-primary"
                                  >
                                    نوێکردنەوە
                                  </button>
                                  <button
                                    onClick={handleCancelEdit}
                                    className="px-2 py-1 text-white bg-red-600 rounded"
                                  >
                                    هەڵوەشاندنەوە
                                  </button>
                                </div>
                              ) : (
                                <div className="flex justify-center gap-2">
                                  <button
                                    onClick={() => handleEditRow(index)}
                                    className="px-2 py-1 text-white rounded bg-primary"
                                  >
                                    گۆڕین
                                  </button>
                                  <button
                                    onClick={() => handleShowModal(index)}
                                    className="px-2 py-1 text-white bg-red-600 rounded"
                                  >
                                    سڕینەوە
                                  </button>
                                </div>
                              )}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                  <h3 className="mt-4 text-2xl font-semibold text-right text-invert">
                    کۆی نرخ: {totalPrice.toLocaleString("en-US")}
                  </h3>
                  <h3 className="mt-4 text-2xl font-semibold text-right text-invert">
                    بڕی داشکاندن: {discount.toLocaleString("en-US")}
                  </h3>
                  <h3 className="mt-4 text-2xl font-semibold text-right text-invert">
                    کۆی نرخ دوای داشکاندن:{" "}
                    {totalPriceAfterDiscount.toLocaleString("en-US")}
                  </h3>
                </div>
              </>
            )}
          </div>
        </div>

        <button
          onClick={handlePrint}
          className="flex justify-center w-full px-4 py-2 mt-8 text-2xl rounded-md bg-primary text-invert hover:bg-primary focus:outline-none focus:ring-2 focus:ring-invert focus:ring-opacity-75"
        >
          پرینت کردن
        </button>
      </div>
      <ConfirmationModal
        show={showModal}
        onClose={() => setShowModal(false)}
        onConfirm={handleDeleteItem}
      />
    </div>
  );
};

export default BarcodeChecker;
Editor is loading...
Leave a Comment