fix: inventory adjustment
This commit is contained in:
parent
86a4a19209
commit
87880dcdd5
@ -155,6 +155,7 @@ export const all_routes = {
|
|||||||
taxreport: "/tax-report",
|
taxreport: "/tax-report",
|
||||||
profitloss: "/profit-loss-report",
|
profitloss: "/profit-loss-report",
|
||||||
notes: "/notes",
|
notes: "/notes",
|
||||||
|
outletlist: "/outlet-list",
|
||||||
filemanager: "/file-manager",
|
filemanager: "/file-manager",
|
||||||
profile: "/profile",
|
profile: "/profile",
|
||||||
signin: "/signin",
|
signin: "/signin",
|
||||||
|
|||||||
@ -206,6 +206,7 @@ import ProductList3 from "../feature-module/inventory/productlist3";
|
|||||||
import { all_routes } from "./all_routes";
|
import { all_routes } from "./all_routes";
|
||||||
import PaymentMethodList from "../feature-module/FinanceAccounts/paymentmethodlist";
|
import PaymentMethodList from "../feature-module/FinanceAccounts/paymentmethodlist";
|
||||||
import CompanyList from "../feature-module/superadmin/companylist";
|
import CompanyList from "../feature-module/superadmin/companylist";
|
||||||
|
import OutletList from "../feature-module/inventory/outletlist";
|
||||||
|
|
||||||
export const publicRoutes = [
|
export const publicRoutes = [
|
||||||
{
|
{
|
||||||
@ -1499,13 +1500,20 @@ export const publicRoutes = [
|
|||||||
route: Route,
|
route: Route,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 121,
|
||||||
path: routes.companylist,
|
path: routes.companylist,
|
||||||
name: "companies",
|
name: "companies",
|
||||||
element: <CompanyList />,
|
element: <CompanyList />,
|
||||||
route: Route,
|
route: Route,
|
||||||
role: 'superadmin'
|
role: 'superadmin'
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
id: 122,
|
||||||
|
path: routes.outletlist,
|
||||||
|
name: "outlets",
|
||||||
|
element: <OutletList />,
|
||||||
|
route: Route
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const posRoutes = [
|
export const posRoutes = [
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import { useSelector } from "react-redux";
|
|||||||
const CustomPagination = ({
|
const CustomPagination = ({
|
||||||
currentPage = 1,
|
currentPage = 1,
|
||||||
pageSize = 10,
|
pageSize = 10,
|
||||||
totalCount = 0,
|
|
||||||
totalPages = 1,
|
totalPages = 1,
|
||||||
loading = false,
|
loading = false,
|
||||||
onPageChange,
|
onPageChange,
|
||||||
@ -70,8 +69,6 @@ const CustomPagination = ({
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
console.log(totalCount);
|
|
||||||
|
|
||||||
// Handle page change
|
// Handle page change
|
||||||
const handlePageClick = (page) => {
|
const handlePageClick = (page) => {
|
||||||
if (!loading && page !== currentPage && onPageChange) {
|
if (!loading && page !== currentPage && onPageChange) {
|
||||||
|
|||||||
@ -145,6 +145,13 @@ export const SidebarData = [
|
|||||||
showSubRoute: false,
|
showSubRoute: false,
|
||||||
submenu: false,
|
submenu: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "Outlets",
|
||||||
|
link: "/outlet-list",
|
||||||
|
icon: <Icon.Home />,
|
||||||
|
showSubRoute: false,
|
||||||
|
submenu: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "Warranty",
|
label: "Warranty",
|
||||||
link: "/warranty",
|
link: "/warranty",
|
||||||
|
|||||||
211
src/core/modals/financeaccount/addpaymentmethod.jsx
Normal file
211
src/core/modals/financeaccount/addpaymentmethod.jsx
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import {
|
||||||
|
createPaymentMethod,
|
||||||
|
fetchPaymentMethods,
|
||||||
|
} from "../../redux/actions/paymentMethodActions";
|
||||||
|
import Select from "react-select";
|
||||||
|
|
||||||
|
const AddPaymentMethod = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const { creating } = useSelector((state) => state.paymentMethods);
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
name: "",
|
||||||
|
is_active: false,
|
||||||
|
requires_receipt: false,
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleInputChange = (e) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
[e.target.name]: e.target.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckboxChange = (e) => {
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[e.target.name]: e.target.checked,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectChange = (field, selectedOption) => {
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[field]: selectedOption.value,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dispatch(createPaymentMethod(formData));
|
||||||
|
|
||||||
|
await dispatch(fetchPaymentMethods());
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Success!",
|
||||||
|
text: "Payment Method created successfully!",
|
||||||
|
icon: "success",
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 1500,
|
||||||
|
}).then(() => {
|
||||||
|
const closeButton = document.querySelector(
|
||||||
|
"#add-payment-method .btn-close"
|
||||||
|
);
|
||||||
|
closeButton.click();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating Payment Method:", error);
|
||||||
|
|
||||||
|
// Show error message
|
||||||
|
Swal.fire({
|
||||||
|
icon: "error",
|
||||||
|
title: "Error!",
|
||||||
|
text:
|
||||||
|
error?.response?.data?.errors[0]?.cause ||
|
||||||
|
"Failed to create Payment Method. Please try again.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeOptions = [
|
||||||
|
{
|
||||||
|
label: "Card",
|
||||||
|
value: "card",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cash",
|
||||||
|
value: "cash",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Digital Wallet",
|
||||||
|
value: "digital_wallet",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* Add Payment Method */}
|
||||||
|
<div className="modal fade" id="add-payment-method">
|
||||||
|
<div className="modal-dialog modal-dialog-centered custom-modal-two">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="page-wrapper-new p-0">
|
||||||
|
<div className="content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<div className="page-title">
|
||||||
|
<h4>Create Payment Method</h4>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body custom-modal-body">
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control border"
|
||||||
|
name="name"
|
||||||
|
value={formData.name}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Type</label>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
className="select"
|
||||||
|
options={typeOptions}
|
||||||
|
placeholder="Choose"
|
||||||
|
name="type"
|
||||||
|
value={typeOptions.find(
|
||||||
|
(option) => option.value === formData.type
|
||||||
|
)}
|
||||||
|
onChange={(selectedOption) =>
|
||||||
|
handleSelectChange("type", selectedOption)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<div className="status-toggle modal-status d-flex justify-content-between align-items-center">
|
||||||
|
<span className="status-label">Status</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="is_active"
|
||||||
|
className="check"
|
||||||
|
defaultChecked="true"
|
||||||
|
checked={formData.is_active}
|
||||||
|
name="is_active"
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
|
<label htmlFor="is_active" className="checktoggle" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-0">
|
||||||
|
<div className="status-toggle modal-status d-flex justify-content-between align-items-center">
|
||||||
|
<span className="status-label">Require Receipt</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="requires_reciept"
|
||||||
|
className="check"
|
||||||
|
defaultChecked="true"
|
||||||
|
checked={formData.requires_receipt}
|
||||||
|
name="requires_receipt"
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="requires_reciept"
|
||||||
|
className="checktoggle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer-btn">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-dark me-2"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={creating}
|
||||||
|
className="btn btn-submit"
|
||||||
|
>
|
||||||
|
{creating ? (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
className="spinner-border spinner-border-sm me-2"
|
||||||
|
role="status"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
Creating...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"Create"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* /Add Category */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddPaymentMethod;
|
||||||
222
src/core/modals/financeaccount/editpaymentmethod.jsx
Normal file
222
src/core/modals/financeaccount/editpaymentmethod.jsx
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import Select from "react-select";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import {
|
||||||
|
fetchPaymentMethods,
|
||||||
|
updatePaymentMethod,
|
||||||
|
} from "../../redux/actions/paymentMethodActions";
|
||||||
|
|
||||||
|
const EditPaymentMethod = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const { updating, currentPaymentMethod, currentPage, pageSize } = useSelector(
|
||||||
|
(state) => state.paymentMethods
|
||||||
|
);
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
name: "",
|
||||||
|
is_active: false,
|
||||||
|
requires_receipt: false,
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentPaymentMethod) {
|
||||||
|
setFormData(currentPaymentMethod);
|
||||||
|
}
|
||||||
|
}, [currentPaymentMethod]);
|
||||||
|
|
||||||
|
const handleInputChange = (e) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
[e.target.name]: e.target.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckboxChange = (e) => {
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[e.target.name]: e.target.checked,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectChange = (field, selectedOption) => {
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[field]: selectedOption.value,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dispatch(updatePaymentMethod(currentPaymentMethod?.id, formData));
|
||||||
|
|
||||||
|
await dispatch(
|
||||||
|
fetchPaymentMethods({ page: currentPage, limit: pageSize })
|
||||||
|
);
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Success!",
|
||||||
|
text: "Payment Method Updated successfully!",
|
||||||
|
icon: "success",
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 1500,
|
||||||
|
}).then(() => {
|
||||||
|
const closeButton = document.querySelector(
|
||||||
|
"#edit-payment-method .btn-close"
|
||||||
|
);
|
||||||
|
closeButton.click();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating Payment Method:", error);
|
||||||
|
|
||||||
|
// Show error message
|
||||||
|
Swal.fire({
|
||||||
|
icon: "error",
|
||||||
|
title: "Error!",
|
||||||
|
text:
|
||||||
|
error?.response?.data?.errors[0]?.cause ||
|
||||||
|
"Failed to Update Payment Method. Please try again.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const typeOptions = [
|
||||||
|
{
|
||||||
|
label: "Card",
|
||||||
|
value: "card",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cash",
|
||||||
|
value: "cash",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Digital Wallet",
|
||||||
|
value: "digital_wallet",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* Edit Payment Method */}
|
||||||
|
<div className="modal fade" id="edit-payment-method">
|
||||||
|
<div className="modal-dialog modal-dialog-centered custom-modal-two">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="page-wrapper-new p-0">
|
||||||
|
<div className="content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<div className="page-title">
|
||||||
|
<h4>Edit Payment Method</h4>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body custom-modal-body">
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control border"
|
||||||
|
name="name"
|
||||||
|
value={formData.name}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Type</label>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
className="select"
|
||||||
|
options={typeOptions}
|
||||||
|
isSearchable={false}
|
||||||
|
placeholder="Choose"
|
||||||
|
name="type"
|
||||||
|
value={typeOptions.find(
|
||||||
|
(option) => option.value === formData.type
|
||||||
|
)}
|
||||||
|
onChange={(selectedOption) =>
|
||||||
|
handleSelectChange("type", selectedOption)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<div className="status-toggle modal-status d-flex justify-content-between align-items-center">
|
||||||
|
<span className="status-label">Status</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="is_active"
|
||||||
|
className="check"
|
||||||
|
defaultChecked="true"
|
||||||
|
checked={formData.is_active}
|
||||||
|
name="is_active"
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
|
<label htmlFor="is_active" className="checktoggle" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-0">
|
||||||
|
<div className="status-toggle modal-status d-flex justify-content-between align-items-center">
|
||||||
|
<span className="status-label">Require Receipt</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="requires_reciept"
|
||||||
|
className="check"
|
||||||
|
defaultChecked="true"
|
||||||
|
checked={formData.requires_receipt}
|
||||||
|
name="requires_receipt"
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
htmlFor="requires_reciept"
|
||||||
|
className="checktoggle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer-btn">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-dark me-2"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={updating}
|
||||||
|
className="btn btn-submit"
|
||||||
|
>
|
||||||
|
{updating ? (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
className="spinner-border spinner-border-sm me-2"
|
||||||
|
role="status"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
Updating...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"Update"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* /Add Category */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditPaymentMethod;
|
||||||
186
src/core/modals/inventory/editoutletlist.jsx
Normal file
186
src/core/modals/inventory/editoutletlist.jsx
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import { fetchOutlets, updateOutlet } from "../../redux/actions/outletActions";
|
||||||
|
|
||||||
|
const EditOutletList = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const { currentOutlet, updating, currentPage, pageSize } = useSelector(
|
||||||
|
(state) => state.outlets
|
||||||
|
);
|
||||||
|
|
||||||
|
const [formData, setFormData] = useState({
|
||||||
|
name: "",
|
||||||
|
address: "",
|
||||||
|
phone_number: "",
|
||||||
|
email: "",
|
||||||
|
is_active: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (currentOutlet) {
|
||||||
|
setFormData(currentOutlet);
|
||||||
|
}
|
||||||
|
}, [currentOutlet]);
|
||||||
|
|
||||||
|
const handleInputChange = (e) => {
|
||||||
|
setFormData({
|
||||||
|
...formData,
|
||||||
|
[e.target.name]: e.target.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCheckboxChange = (e) => {
|
||||||
|
setFormData((prevData) => ({
|
||||||
|
...prevData,
|
||||||
|
[e.target.name]: e.target.checked,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dispatch(updateOutlet(currentOutlet?.id, formData));
|
||||||
|
|
||||||
|
await dispatch(fetchOutlets({ page: currentPage, limit: pageSize }));
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: "Success!",
|
||||||
|
text: "Outlet updated successfully!",
|
||||||
|
icon: "success",
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 1500,
|
||||||
|
}).then(() => {
|
||||||
|
const closeButton = document.querySelector("#edit-outlet .btn-close");
|
||||||
|
closeButton.click();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error updating outlet:", error);
|
||||||
|
|
||||||
|
// Show error message
|
||||||
|
Swal.fire({
|
||||||
|
icon: "error",
|
||||||
|
title: "Error!",
|
||||||
|
text: error?.response?.data?.errors[0]?.cause || "Failed to update outlet. Please try again.",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{/* Edit Outlet */}
|
||||||
|
<div className="modal fade" id="edit-outlet">
|
||||||
|
<div className="modal-dialog modal-dialog-centered custom-modal-two">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="page-wrapper-new p-0">
|
||||||
|
<div className="content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<div className="page-title">
|
||||||
|
<h4>Edit Outlet</h4>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-close"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body custom-modal-body">
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control border"
|
||||||
|
name="name"
|
||||||
|
value={formData.name}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Address</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control border"
|
||||||
|
name="address"
|
||||||
|
value={formData.address}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Phone</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control border"
|
||||||
|
name="phone_number"
|
||||||
|
value={formData.phone_number}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Email</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
className="form-control border"
|
||||||
|
name="email"
|
||||||
|
value={formData.email}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-0">
|
||||||
|
<div className="status-toggle modal-status d-flex justify-content-between align-items-center">
|
||||||
|
<span className="status-label">Status</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="user3"
|
||||||
|
className="check"
|
||||||
|
name="is_active"
|
||||||
|
checked={formData.is_active}
|
||||||
|
onChange={handleCheckboxChange}
|
||||||
|
/>
|
||||||
|
<label htmlFor="user3" className="checktoggle" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer-btn">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-outline-dark me-2"
|
||||||
|
data-bs-dismiss="modal"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={updating}
|
||||||
|
className="btn btn-submit"
|
||||||
|
>
|
||||||
|
{updating ? (
|
||||||
|
<>
|
||||||
|
<span
|
||||||
|
className="spinner-border spinner-border-sm me-2"
|
||||||
|
role="status"
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
Updating...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"Update"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* /Edit Outlet */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditOutletList;
|
||||||
@ -5,9 +5,9 @@ import Swal from "sweetalert2";
|
|||||||
import outletsApi from "../../../services/outletsApi";
|
import outletsApi from "../../../services/outletsApi";
|
||||||
import productsApi from "../../../services/productsApi";
|
import productsApi from "../../../services/productsApi";
|
||||||
import {
|
import {
|
||||||
|
adjustInventory,
|
||||||
createInventory,
|
createInventory,
|
||||||
fetchInventories,
|
fetchInventories,
|
||||||
updateInventory,
|
|
||||||
} from "../../redux/actions/inventoryActions";
|
} from "../../redux/actions/inventoryActions";
|
||||||
|
|
||||||
const ManageStockModal = () => {
|
const ManageStockModal = () => {
|
||||||
@ -21,8 +21,10 @@ const ManageStockModal = () => {
|
|||||||
outlet_id: "",
|
outlet_id: "",
|
||||||
product_id: "",
|
product_id: "",
|
||||||
quantity: "",
|
quantity: "",
|
||||||
|
delta: "",
|
||||||
min_stock_level: "",
|
min_stock_level: "",
|
||||||
max_stock_level: "",
|
max_stock_level: "",
|
||||||
|
reason: "",
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -85,7 +87,7 @@ const ManageStockModal = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await dispatch(updateInventory(currentInventory?.id, formData));
|
await dispatch(adjustInventory(formData));
|
||||||
|
|
||||||
await dispatch(fetchInventories());
|
await dispatch(fetchInventories());
|
||||||
|
|
||||||
@ -107,7 +109,9 @@ const ManageStockModal = () => {
|
|||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: "error",
|
icon: "error",
|
||||||
title: "Error!",
|
title: "Error!",
|
||||||
text: error.message || "Failed to update stock. Please try again.",
|
text:
|
||||||
|
error?.response?.data?.errors[0]?.cause ||
|
||||||
|
"Failed to update stock. Please try again.",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -273,7 +277,7 @@ const ManageStockModal = () => {
|
|||||||
<div className="content">
|
<div className="content">
|
||||||
<div className="modal-header">
|
<div className="modal-header">
|
||||||
<div className="page-title">
|
<div className="page-title">
|
||||||
<h4>Edit Stock</h4>
|
<h4>Adjust Stock</h4>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@ -285,33 +289,57 @@ const ManageStockModal = () => {
|
|||||||
<div className="modal-body custom-modal-body">
|
<div className="modal-body custom-modal-body">
|
||||||
<form onSubmit={handleUpdate}>
|
<form onSubmit={handleUpdate}>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="form-label">Quantity</label>
|
<label className="form-label">Outlet</label>
|
||||||
|
<AsyncSelect
|
||||||
|
className="select"
|
||||||
|
loadOptions={loadOutlets}
|
||||||
|
placeholder="Choose"
|
||||||
|
isClearable
|
||||||
|
cacheOptions={true}
|
||||||
|
defaultOptions={true}
|
||||||
|
value={selectedOutlet}
|
||||||
|
onChange={(selectedOption) => {
|
||||||
|
handleSelectChange("outlet_id", selectedOption);
|
||||||
|
setSelectedOutlet(selectedOption);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Product</label>
|
||||||
|
<AsyncSelect
|
||||||
|
className="select"
|
||||||
|
loadOptions={loadProducts}
|
||||||
|
placeholder="Choose"
|
||||||
|
isClearable
|
||||||
|
cacheOptions={true}
|
||||||
|
defaultOptions={true}
|
||||||
|
value={selectedProduct}
|
||||||
|
onChange={(selectedOption) => {
|
||||||
|
handleSelectChange("product_id", selectedOption);
|
||||||
|
setSelectedProduct(selectedOption);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label className="form-label">Delta</label>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
className="form-control border"
|
className="form-control border"
|
||||||
name="quantity"
|
name="delta"
|
||||||
value={formData.quantity}
|
value={formData.delta}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="form-label">Min Stock</label>
|
<label className="form-label">Reason</label>
|
||||||
<input
|
<textarea
|
||||||
type="number"
|
className="form-control h-75 border"
|
||||||
className="form-control border"
|
rows={5}
|
||||||
name="min_stock_level"
|
name="reason"
|
||||||
value={formData.min_stock_level}
|
value={formData.reason}
|
||||||
onChange={handleInputChange}
|
onChange={(e) =>
|
||||||
/>
|
setFormData({ ...formData, reason: e.target.value })
|
||||||
</div>
|
}
|
||||||
<div className="mb-3">
|
|
||||||
<label className="form-label">Max Stock</label>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control border"
|
|
||||||
name="max_stock_level"
|
|
||||||
value={formData.max_stock_level}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -338,7 +366,7 @@ const ManageStockModal = () => {
|
|||||||
Updating...
|
Updating...
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
"Update"
|
"Save"
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,45 +1,52 @@
|
|||||||
import { inventoryApi } from '../../../services/inventoriesApi';
|
import { inventoryApi } from "../../../services/inventoriesApi";
|
||||||
|
|
||||||
// Action Types
|
// Action Types
|
||||||
export const INVENTORY_ACTIONS = {
|
export const INVENTORY_ACTIONS = {
|
||||||
// Fetch Inventories
|
// Fetch Inventories
|
||||||
FETCH_INVENTORIES_REQUEST: 'FETCH_INVENTORIES_REQUEST',
|
FETCH_INVENTORIES_REQUEST: "FETCH_INVENTORIES_REQUEST",
|
||||||
FETCH_INVENTORIES_SUCCESS: 'FETCH_INVENTORIES_SUCCESS',
|
FETCH_INVENTORIES_SUCCESS: "FETCH_INVENTORIES_SUCCESS",
|
||||||
FETCH_INVENTORIES_FAILURE: 'FETCH_INVENTORIES_FAILURE',
|
FETCH_INVENTORIES_FAILURE: "FETCH_INVENTORIES_FAILURE",
|
||||||
|
|
||||||
// Fetch Single Inventory
|
// Fetch Single Inventory
|
||||||
FETCH_INVENTORY_REQUEST: 'FETCH_INVENTORY_REQUEST',
|
FETCH_INVENTORY_REQUEST: "FETCH_INVENTORY_REQUEST",
|
||||||
FETCH_INVENTORY_SUCCESS: 'FETCH_INVENTORY_SUCCESS',
|
FETCH_INVENTORY_SUCCESS: "FETCH_INVENTORY_SUCCESS",
|
||||||
FETCH_INVENTORY_FAILURE: 'FETCH_INVENTORY_FAILURE',
|
FETCH_INVENTORY_FAILURE: "FETCH_INVENTORY_FAILURE",
|
||||||
|
|
||||||
// Create Inventory
|
// Create Inventory
|
||||||
CREATE_INVENTORY_REQUEST: 'CREATE_INVENTORY_REQUEST',
|
CREATE_INVENTORY_REQUEST: "CREATE_INVENTORY_REQUEST",
|
||||||
CREATE_INVENTORY_SUCCESS: 'CREATE_INVENTORY_SUCCESS',
|
CREATE_INVENTORY_SUCCESS: "CREATE_INVENTORY_SUCCESS",
|
||||||
CREATE_INVENTORY_FAILURE: 'CREATE_INVENTORY_FAILURE',
|
CREATE_INVENTORY_FAILURE: "CREATE_INVENTORY_FAILURE",
|
||||||
|
|
||||||
|
// Adjust Inventory
|
||||||
|
ADJUST_INVENTORY_REQUEST: "ADJUST_INVENTORY_REQUEST",
|
||||||
|
ADJUST_INVENTORY_SUCCESS: "ADJUST_INVENTORY_SUCCESS",
|
||||||
|
ADJUST_INVENTORY_FAILURE: "ADJUST_INVENTORY_FAILURE",
|
||||||
|
|
||||||
// Update Inventory
|
// Update Inventory
|
||||||
UPDATE_INVENTORY_REQUEST: 'UPDATE_INVENTORY_REQUEST',
|
UPDATE_INVENTORY_REQUEST: "UPDATE_INVENTORY_REQUEST",
|
||||||
UPDATE_INVENTORY_SUCCESS: 'UPDATE_INVENTORY_SUCCESS',
|
UPDATE_INVENTORY_SUCCESS: "UPDATE_INVENTORY_SUCCESS",
|
||||||
UPDATE_INVENTORY_FAILURE: 'UPDATE_INVENTORY_FAILURE',
|
UPDATE_INVENTORY_FAILURE: "UPDATE_INVENTORY_FAILURE",
|
||||||
|
|
||||||
// Delete Inventory
|
// Delete Inventory
|
||||||
DELETE_INVENTORY_REQUEST: 'DELETE_INVENTORY_REQUEST',
|
DELETE_INVENTORY_REQUEST: "DELETE_INVENTORY_REQUEST",
|
||||||
DELETE_INVENTORY_SUCCESS: 'DELETE_INVENTORY_SUCCESS',
|
DELETE_INVENTORY_SUCCESS: "DELETE_INVENTORY_SUCCESS",
|
||||||
DELETE_INVENTORY_FAILURE: 'DELETE_INVENTORY_FAILURE',
|
DELETE_INVENTORY_FAILURE: "DELETE_INVENTORY_FAILURE",
|
||||||
|
|
||||||
// Search Inventories
|
// Search Inventories
|
||||||
SEARCH_INVENTORIES_REQUEST: 'SEARCH_INVENTORIES_REQUEST',
|
SEARCH_INVENTORIES_REQUEST: "SEARCH_INVENTORIES_REQUEST",
|
||||||
SEARCH_INVENTORIES_SUCCESS: 'SEARCH_INVENTORIES_SUCCESS',
|
SEARCH_INVENTORIES_SUCCESS: "SEARCH_INVENTORIES_SUCCESS",
|
||||||
SEARCH_INVENTORIES_FAILURE: 'SEARCH_INVENTORIES_FAILURE',
|
SEARCH_INVENTORIES_FAILURE: "SEARCH_INVENTORIES_FAILURE",
|
||||||
|
|
||||||
// Clear States
|
// Clear States
|
||||||
CLEAR_INVENTORY_ERROR: 'CLEAR_INVENTORY_ERROR',
|
CLEAR_INVENTORY_ERROR: "CLEAR_INVENTORY_ERROR",
|
||||||
CLEAR_CURRENT_INVENTORY: 'CLEAR_CURRENT_INVENTORY',
|
CLEAR_CURRENT_INVENTORY: "CLEAR_CURRENT_INVENTORY",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
export const fetchInventories = (params = {}) => async (dispatch) => {
|
export const fetchInventories =
|
||||||
|
(params = {}) =>
|
||||||
|
async (dispatch) => {
|
||||||
dispatch({ type: INVENTORY_ACTIONS.FETCH_INVENTORIES_REQUEST });
|
dispatch({ type: INVENTORY_ACTIONS.FETCH_INVENTORIES_REQUEST });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -52,7 +59,10 @@ export const fetchInventories = (params = {}) => async (dispatch) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: INVENTORY_ACTIONS.FETCH_INVENTORIES_FAILURE,
|
type: INVENTORY_ACTIONS.FETCH_INVENTORIES_FAILURE,
|
||||||
payload: error.response?.data?.message || error.message || 'Failed to fetch inventories',
|
payload:
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to fetch inventories",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@ -71,7 +81,10 @@ export const fetchInventory = (id) => async (dispatch) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: INVENTORY_ACTIONS.FETCH_INVENTORY_FAILURE,
|
type: INVENTORY_ACTIONS.FETCH_INVENTORY_FAILURE,
|
||||||
payload: error.response?.data?.message || error.message || 'Failed to fetch inventory',
|
payload:
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to fetch inventory",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@ -90,7 +103,32 @@ export const createInventory = (inventoryData) => async (dispatch) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: INVENTORY_ACTIONS.CREATE_INVENTORY_FAILURE,
|
type: INVENTORY_ACTIONS.CREATE_INVENTORY_FAILURE,
|
||||||
payload: error.response?.data?.message || error.message || 'Failed to create inventory',
|
payload:
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to create inventory",
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const adjustInventory = (inventoryData) => async (dispatch) => {
|
||||||
|
dispatch({ type: INVENTORY_ACTIONS.ADJUST_INVENTORY_REQUEST });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await inventoryApi.adjustInventory(inventoryData);
|
||||||
|
dispatch({
|
||||||
|
type: INVENTORY_ACTIONS.ADJUST_INVENTORY_SUCCESS,
|
||||||
|
payload: data,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
dispatch({
|
||||||
|
type: INVENTORY_ACTIONS.ADJUST_INVENTORY_FAILURE,
|
||||||
|
payload:
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to adjust inventory",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@ -109,7 +147,10 @@ export const updateInventory = (id, inventoryData) => async (dispatch) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: INVENTORY_ACTIONS.UPDATE_INVENTORY_FAILURE,
|
type: INVENTORY_ACTIONS.UPDATE_INVENTORY_FAILURE,
|
||||||
payload: error.response?.data?.message || error.message || 'Failed to update inventory',
|
payload:
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to update inventory",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@ -128,7 +169,10 @@ export const deleteInventory = (id) => async (dispatch) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: INVENTORY_ACTIONS.DELETE_INVENTORY_FAILURE,
|
type: INVENTORY_ACTIONS.DELETE_INVENTORY_FAILURE,
|
||||||
payload: error.response?.data?.message || error.message || 'Failed to delete inventory',
|
payload:
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.message ||
|
||||||
|
"Failed to delete inventory",
|
||||||
});
|
});
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { INVENTORY_ACTIONS } from '../actions/inventoryActions';
|
import { INVENTORY_ACTIONS } from "../actions/inventoryActions";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
// Inventory list
|
// Inventory list
|
||||||
@ -15,7 +15,7 @@ const initialState = {
|
|||||||
|
|
||||||
// Search results
|
// Search results
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
searchQuery: '',
|
searchQuery: "",
|
||||||
|
|
||||||
// Loading states
|
// Loading states
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -115,6 +115,32 @@ const inventoryReducer = (state = initialState, action) => {
|
|||||||
error: action.payload,
|
error: action.payload,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Adjust Inventory
|
||||||
|
case INVENTORY_ACTIONS.ADJUST_INVENTORY_REQUEST:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
updating: true,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
case INVENTORY_ACTIONS.ADJUST_INVENTORY_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
updating: false,
|
||||||
|
inventories: state.inventories.map((inv) =>
|
||||||
|
inv.id === action.payload.data.id ? action.payload.data : inv
|
||||||
|
),
|
||||||
|
currentInventory: action.payload.data,
|
||||||
|
error: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
case INVENTORY_ACTIONS.ADJUST_INVENTORY_FAILURE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
updating: false,
|
||||||
|
error: action.payload,
|
||||||
|
};
|
||||||
|
|
||||||
// Update Inventory
|
// Update Inventory
|
||||||
case INVENTORY_ACTIONS.UPDATE_INVENTORY_REQUEST:
|
case INVENTORY_ACTIONS.UPDATE_INVENTORY_REQUEST:
|
||||||
return {
|
return {
|
||||||
@ -127,7 +153,7 @@ const inventoryReducer = (state = initialState, action) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
updating: false,
|
updating: false,
|
||||||
inventories: state.inventories.map(inv =>
|
inventories: state.inventories.map((inv) =>
|
||||||
inv.id === action.payload.data.id ? action.payload.data : inv
|
inv.id === action.payload.data.id ? action.payload.data : inv
|
||||||
),
|
),
|
||||||
currentInventory: action.payload.data,
|
currentInventory: action.payload.data,
|
||||||
@ -153,7 +179,9 @@ const inventoryReducer = (state = initialState, action) => {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
deleting: false,
|
deleting: false,
|
||||||
inventories: state.inventories.filter(inv => inv.id !== action.payload),
|
inventories: state.inventories.filter(
|
||||||
|
(inv) => inv.id !== action.payload
|
||||||
|
),
|
||||||
totalInventories: state.totalInventories - 1,
|
totalInventories: state.totalInventories - 1,
|
||||||
error: null,
|
error: null,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Select, Tag } from "antd";
|
import { Tag } from "antd";
|
||||||
import {
|
import {
|
||||||
ChevronUp,
|
ChevronUp,
|
||||||
PlusCircle,
|
PlusCircle,
|
||||||
@ -13,11 +13,15 @@ import Swal from "sweetalert2";
|
|||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import CustomPagination from "../../components/CustomPagination";
|
import CustomPagination from "../../components/CustomPagination";
|
||||||
import ImageWithBasePath from "../../core/img/imagewithbasebath";
|
import ImageWithBasePath from "../../core/img/imagewithbasebath";
|
||||||
import AddCategoryList from "../../core/modals/inventory/addcategorylist";
|
import AddPaymentMethod from "../../core/modals/financeaccount/addpaymentmethod";
|
||||||
import EditCategoryList from "../../core/modals/inventory/editcategorylist";
|
import EditPaymentMethod from "../../core/modals/financeaccount/editpaymentmethod";
|
||||||
import Table from "../../core/pagination/datatable";
|
import Table from "../../core/pagination/datatable";
|
||||||
import { setToogleHeader } from "../../core/redux/action";
|
import { setToogleHeader } from "../../core/redux/action";
|
||||||
import { deletePaymentMethod, fetchPaymentMethod, fetchPaymentMethods } from "../../core/redux/actions/paymentMethodActions";
|
import {
|
||||||
|
deletePaymentMethod,
|
||||||
|
fetchPaymentMethods,
|
||||||
|
PAYMENT_METHOD_ACTIONS
|
||||||
|
} from "../../core/redux/actions/paymentMethodActions";
|
||||||
import { formatDate } from "../../utils/date";
|
import { formatDate } from "../../utils/date";
|
||||||
|
|
||||||
const PaymentMethodList = () => {
|
const PaymentMethodList = () => {
|
||||||
@ -149,14 +153,15 @@ const PaymentMethodList = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
|
||||||
const dateOptions = [
|
|
||||||
{ label: "Sort By: Last 7 Days", value: "last7days" },
|
|
||||||
{ label: "Sort By: Last Month", value: "lastmonth" },
|
|
||||||
{ label: "Sort By: Ascending", value: "ascending" },
|
|
||||||
{ label: "Sort By: Descending", value: "descending" },
|
|
||||||
];
|
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
{
|
||||||
|
title: "Organization",
|
||||||
|
dataIndex: "organization",
|
||||||
|
render: (_, record) => {
|
||||||
|
return <span>{record.ogrganization_name || "-"}</span>;
|
||||||
|
},
|
||||||
|
sorter: (a, b) => a.name.length - b.name.length,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Payment Method",
|
title: "Payment Method",
|
||||||
dataIndex: "paymentmethod",
|
dataIndex: "paymentmethod",
|
||||||
@ -200,8 +205,13 @@ const PaymentMethodList = () => {
|
|||||||
className="me-2 p-2"
|
className="me-2 p-2"
|
||||||
to="#"
|
to="#"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#edit-category"
|
data-bs-target="#edit-payment-method"
|
||||||
onClick={() => dispatch(fetchPaymentMethod(record.id))}
|
onClick={() =>
|
||||||
|
dispatch({
|
||||||
|
type: PAYMENT_METHOD_ACTIONS.FETCH_PAYMENT_METHOD_SUCCESS,
|
||||||
|
payload: { data: record },
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<i data-feather="edit" className="feather-edit"></i>
|
<i data-feather="edit" className="feather-edit"></i>
|
||||||
</Link>
|
</Link>
|
||||||
@ -234,7 +244,6 @@ const PaymentMethodList = () => {
|
|||||||
];
|
];
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="page-wrapper">
|
<div className="page-wrapper">
|
||||||
@ -302,10 +311,10 @@ const PaymentMethodList = () => {
|
|||||||
to="#"
|
to="#"
|
||||||
className="btn btn-added"
|
className="btn btn-added"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#add-category"
|
data-bs-target="#add-payment-method"
|
||||||
>
|
>
|
||||||
<PlusCircle className="me-2" />
|
<PlusCircle className="me-2" />
|
||||||
Add New Category
|
Add New
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -326,12 +335,6 @@ const PaymentMethodList = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Select
|
|
||||||
style={{ height: 36 }}
|
|
||||||
defaultValue={dateOptions[0]?.value}
|
|
||||||
options={dateOptions}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="table-responsive">
|
<div className="table-responsive">
|
||||||
@ -378,8 +381,8 @@ const PaymentMethodList = () => {
|
|||||||
{/* /category list */}
|
{/* /category list */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AddCategoryList />
|
<AddPaymentMethod />
|
||||||
<EditCategoryList />
|
<EditPaymentMethod />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Select, Tag } from "antd";
|
import { Select, Tag } from "antd";
|
||||||
import {
|
import {
|
||||||
ChevronUp,
|
ChevronUp,
|
||||||
PlusCircle,
|
|
||||||
RotateCcw,
|
RotateCcw,
|
||||||
Trash2,
|
Trash2,
|
||||||
} from "feather-icons-react/build/IconComponents";
|
} from "feather-icons-react/build/IconComponents";
|
||||||
@ -14,30 +13,30 @@ import withReactContent from "sweetalert2-react-content";
|
|||||||
import CustomPagination from "../../components/CustomPagination";
|
import CustomPagination from "../../components/CustomPagination";
|
||||||
import ImageWithBasePath from "../../core/img/imagewithbasebath";
|
import ImageWithBasePath from "../../core/img/imagewithbasebath";
|
||||||
import AddCategoryList from "../../core/modals/inventory/addcategorylist";
|
import AddCategoryList from "../../core/modals/inventory/addcategorylist";
|
||||||
import EditCategoryList from "../../core/modals/inventory/editcategorylist";
|
import EditOutletList from "../../core/modals/inventory/editoutletlist";
|
||||||
import Table from "../../core/pagination/datatable";
|
import Table from "../../core/pagination/datatable";
|
||||||
import { setToogleHeader } from "../../core/redux/action";
|
import { setToogleHeader } from "../../core/redux/action";
|
||||||
import {
|
import {
|
||||||
deleteCategory,
|
deleteOutlet,
|
||||||
fetchCategories,
|
fetchOutlets,
|
||||||
fetchCategory,
|
OUTLET_ACTIONS,
|
||||||
} from "../../core/redux/actions/categoryActions";
|
} from "../../core/redux/actions/outletActions";
|
||||||
import { formatDate } from "../../utils/date";
|
import { formatRupiah } from "../../utils/currency";
|
||||||
|
|
||||||
const OutletList = () => {
|
const OutletList = () => {
|
||||||
const {
|
const {
|
||||||
categories: apiCategories,
|
outlets: apiOutlets,
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
totalCategories,
|
totalOutlets,
|
||||||
totalPages,
|
totalPages,
|
||||||
pageSize: reduxPageSize,
|
pageSize: reduxPageSize,
|
||||||
currentPage: reduxCurrentPage,
|
currentPage: reduxCurrentPage,
|
||||||
} = useSelector((state) => state.categories);
|
} = useSelector((state) => state.outlets);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const data = useSelector((state) => state.toggle_header);
|
const data = useSelector((state) => state.toggle_header);
|
||||||
const dataSource = apiCategories?.length > 0 ? apiCategories : [];
|
const dataSource = apiOutlets?.length > 0 ? apiOutlets : [];
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState(reduxCurrentPage || 1);
|
const [currentPage, setCurrentPage] = useState(reduxCurrentPage || 1);
|
||||||
const [pageSize, setPageSize] = useState(reduxPageSize || 10);
|
const [pageSize, setPageSize] = useState(reduxPageSize || 10);
|
||||||
@ -46,7 +45,7 @@ const OutletList = () => {
|
|||||||
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadCategories = async () => {
|
const loadOutlets = async () => {
|
||||||
try {
|
try {
|
||||||
const searchParams = {
|
const searchParams = {
|
||||||
page: currentPage,
|
page: currentPage,
|
||||||
@ -59,13 +58,13 @@ const OutletList = () => {
|
|||||||
Object.entries(searchParams).filter(([, value]) => value !== "")
|
Object.entries(searchParams).filter(([, value]) => value !== "")
|
||||||
);
|
);
|
||||||
|
|
||||||
await dispatch(fetchCategories(cleanParams));
|
await dispatch(fetchOutlets(cleanParams));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to load categories", error);
|
console.error("Failed to load categories", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loadCategories();
|
loadOutlets();
|
||||||
}, [dispatch, currentPage, pageSize, debouncedSearchTerm]);
|
}, [dispatch, currentPage, pageSize, debouncedSearchTerm]);
|
||||||
|
|
||||||
// Debounce search term
|
// Debounce search term
|
||||||
@ -96,13 +95,13 @@ const OutletList = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Calculate pagination info
|
// Calculate pagination info
|
||||||
const totalRecords = totalCategories || dataSource.length;
|
const totalRecords = totalOutlets || dataSource.length;
|
||||||
const calculatedTotalPages = Math.ceil(totalRecords / pageSize);
|
const calculatedTotalPages = Math.ceil(totalRecords / pageSize);
|
||||||
const actualTotalPages = totalPages || calculatedTotalPages;
|
const actualTotalPages = totalPages || calculatedTotalPages;
|
||||||
|
|
||||||
const handleDeleteCategory = async (categoryId) => {
|
const handleDeleteOutlet = async (categoryId) => {
|
||||||
try {
|
try {
|
||||||
await dispatch(deleteCategory(categoryId));
|
await dispatch(deleteOutlet(categoryId));
|
||||||
// Show success message
|
// Show success message
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
title: "Deleted!",
|
title: "Deleted!",
|
||||||
@ -162,33 +161,57 @@ const OutletList = () => {
|
|||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: "Category",
|
title: "Organization",
|
||||||
dataIndex: "category",
|
dataIndex: "organization",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return <span>{record.name}</span>;
|
return <span>{record.organization_name || "-"}</span>;
|
||||||
},
|
},
|
||||||
sorter: (a, b) => a.category.length - b.category.length,
|
sorter: (a, b) => a.category.length - b.category.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Category Slug",
|
title: "Name",
|
||||||
dataIndex: "categoryslug",
|
dataIndex: "name",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return <span>{record?.name?.toLowerCase()}</span>;
|
return <span>{record?.name || "-"}</span>;
|
||||||
},
|
},
|
||||||
sorter: (a, b) => a.categoryslug.length - b.categoryslug.length,
|
sorter: (a, b) => a.categoryslug.length - b.categoryslug.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Created On",
|
title: "Address",
|
||||||
dataIndex: "createdon",
|
dataIndex: "address",
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return <span>{formatDate(record.created_at)}</span>;
|
return <span>{record.address || "-"}</span>;
|
||||||
},
|
},
|
||||||
sorter: (a, b) => a.createdon.length - b.createdon.length,
|
sorter: (a, b) => a.createdon.length - b.createdon.length,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Phone Number",
|
||||||
|
dataIndex: "phonenumber",
|
||||||
|
render: (_, record) => <span>{record.phone_number || "-"}</span>,
|
||||||
|
sorter: (a, b) => a.status.length - b.status.length,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "Status",
|
title: "Status",
|
||||||
dataIndex: "status",
|
dataIndex: "status",
|
||||||
render: () => <Tag color="#87d068">active</Tag>,
|
render: (_, record) => (
|
||||||
|
<Tag color={record.is_active ? "green" : "red"}>
|
||||||
|
{record.is_active ? "Active" : "Inactive"}
|
||||||
|
</Tag>
|
||||||
|
),
|
||||||
|
sorter: (a, b) => a.status.length - b.status.length,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Tax",
|
||||||
|
dataIndex: "tax",
|
||||||
|
render: (_, record) => (
|
||||||
|
<span>{formatRupiah(record.tax_rate) || "-"}</span>
|
||||||
|
),
|
||||||
|
sorter: (a, b) => a.status.length - b.status.length,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Currency",
|
||||||
|
dataIndex: "currency",
|
||||||
|
render: (_, record) => <span>{record.currency || "-"}</span>,
|
||||||
sorter: (a, b) => a.status.length - b.status.length,
|
sorter: (a, b) => a.status.length - b.status.length,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -202,8 +225,13 @@ const OutletList = () => {
|
|||||||
className="me-2 p-2"
|
className="me-2 p-2"
|
||||||
to="#"
|
to="#"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#edit-category"
|
data-bs-target="#edit-outlet"
|
||||||
onClick={() => dispatch(fetchCategory(record.id))}
|
onClick={() =>
|
||||||
|
dispatch({
|
||||||
|
type: OUTLET_ACTIONS.FETCH_OUTLET_SUCCESS,
|
||||||
|
payload: { data: record },
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<i data-feather="edit" className="feather-edit"></i>
|
<i data-feather="edit" className="feather-edit"></i>
|
||||||
</Link>
|
</Link>
|
||||||
@ -222,7 +250,7 @@ const OutletList = () => {
|
|||||||
cancelButtonText: "Cancel",
|
cancelButtonText: "Cancel",
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
handleDeleteCategory(record.id || record.key);
|
handleDeleteOutlet(record.id || record.key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@ -234,6 +262,7 @@ const OutletList = () => {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const MySwal = withReactContent(Swal);
|
const MySwal = withReactContent(Swal);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -243,8 +272,8 @@ const OutletList = () => {
|
|||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="add-item d-flex">
|
<div className="add-item d-flex">
|
||||||
<div className="page-title">
|
<div className="page-title">
|
||||||
<h4>Category</h4>
|
<h4>Outlet</h4>
|
||||||
<h6>Manage your categories</h6>
|
<h6>Manage your outlets</h6>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className="table-top-head">
|
<ul className="table-top-head">
|
||||||
@ -298,17 +327,6 @@ const OutletList = () => {
|
|||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className="page-btn">
|
|
||||||
<Link
|
|
||||||
to="#"
|
|
||||||
className="btn btn-added"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#add-category"
|
|
||||||
>
|
|
||||||
<PlusCircle className="me-2" />
|
|
||||||
Add New Category
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/* /product list */}
|
{/* /product list */}
|
||||||
<div className="card table-list-card">
|
<div className="card table-list-card">
|
||||||
@ -348,7 +366,7 @@ const OutletList = () => {
|
|||||||
<strong>Error:</strong> {error}
|
<strong>Error:</strong> {error}
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-outline-danger ms-2"
|
className="btn btn-sm btn-outline-danger ms-2"
|
||||||
onClick={() => dispatch(fetchCategories())}
|
onClick={() => dispatch(fetchOutlets())}
|
||||||
>
|
>
|
||||||
Retry
|
Retry
|
||||||
</button>
|
</button>
|
||||||
@ -376,11 +394,11 @@ const OutletList = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* /category list */}
|
{/* /outlet list */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AddCategoryList />
|
<AddCategoryList />
|
||||||
<EditCategoryList />
|
<EditOutletList />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Tag } from "antd";
|
import { Tag } from "antd";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import { Edit, Trash2 } from "react-feather";
|
import { Trash2 } from "react-feather";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
@ -13,8 +13,7 @@ import ManageStockModal from "../../core/modals/stocks/managestockModal";
|
|||||||
import Table from "../../core/pagination/datatable";
|
import Table from "../../core/pagination/datatable";
|
||||||
import {
|
import {
|
||||||
deleteInventory,
|
deleteInventory,
|
||||||
fetchInventories,
|
fetchInventories
|
||||||
INVENTORY_ACTIONS,
|
|
||||||
} from "../../core/redux/actions/inventoryActions";
|
} from "../../core/redux/actions/inventoryActions";
|
||||||
import { formatDate } from "../../utils/date";
|
import { formatDate } from "../../utils/date";
|
||||||
|
|
||||||
@ -180,21 +179,6 @@ const Managestock = () => {
|
|||||||
<div className="edit-delete-action">
|
<div className="edit-delete-action">
|
||||||
<div className="input-block add-lists"></div>
|
<div className="input-block add-lists"></div>
|
||||||
|
|
||||||
<Link
|
|
||||||
className="me-2 p-2"
|
|
||||||
to="#"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#edit-units"
|
|
||||||
onClick={() =>
|
|
||||||
dispatch({
|
|
||||||
type: INVENTORY_ACTIONS.FETCH_INVENTORY_SUCCESS,
|
|
||||||
payload: { data: record },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Edit className="feather-edit" />
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
className="confirm-text p-2"
|
className="confirm-text p-2"
|
||||||
to="#"
|
to="#"
|
||||||
|
|||||||
@ -1,18 +1,15 @@
|
|||||||
|
import { Tag } from "antd";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import { Edit, Trash2 } from "react-feather";
|
import { PlusCircle } from "react-feather";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import Swal from "sweetalert2";
|
|
||||||
import withReactContent from "sweetalert2-react-content";
|
|
||||||
import CustomPagination from "../../components/CustomPagination";
|
import CustomPagination from "../../components/CustomPagination";
|
||||||
import Breadcrumbs from "../../core/breadcrumbs";
|
|
||||||
import ImageWithBasePath from "../../core/img/imagewithbasebath";
|
import ImageWithBasePath from "../../core/img/imagewithbasebath";
|
||||||
import StockadjustmentModal from "../../core/modals/stocks/stockadjustmentModal";
|
import ManageStockModal from "../../core/modals/stocks/managestockModal";
|
||||||
import Table from "../../core/pagination/datatable";
|
import Table from "../../core/pagination/datatable";
|
||||||
import { fetchInventories } from "../../core/redux/actions/inventoryActions";
|
import { fetchInventories } from "../../core/redux/actions/inventoryActions";
|
||||||
import { formatDate } from "../../utils/date";
|
import { formatDate } from "../../utils/date";
|
||||||
import { Tag } from "antd";
|
|
||||||
|
|
||||||
const StockAdjustment = () => {
|
const StockAdjustment = () => {
|
||||||
const {
|
const {
|
||||||
@ -149,73 +146,30 @@ const StockAdjustment = () => {
|
|||||||
),
|
),
|
||||||
sorter: (a, b) => a.Quantity.length - b.Quantity.length,
|
sorter: (a, b) => a.Quantity.length - b.Quantity.length,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
title: "Action",
|
|
||||||
dataIndex: "action",
|
|
||||||
render: () => (
|
|
||||||
<td className="action-table-data">
|
|
||||||
<div className="edit-delete-action">
|
|
||||||
<div className="input-block add-lists"></div>
|
|
||||||
|
|
||||||
<Link
|
|
||||||
className="me-2 p-2"
|
|
||||||
to="#"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#edit-units"
|
|
||||||
>
|
|
||||||
<Edit className="feather-edit" />
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link
|
|
||||||
className="confirm-text p-2"
|
|
||||||
to="#"
|
|
||||||
onClick={showConfirmationAlert}
|
|
||||||
>
|
|
||||||
<Trash2 className="feather-trash-2" />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
),
|
|
||||||
sorter: (a, b) => a.createdby.length - b.createdby.length,
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const MySwal = withReactContent(Swal);
|
|
||||||
|
|
||||||
const showConfirmationAlert = () => {
|
|
||||||
MySwal.fire({
|
|
||||||
title: "Are you sure?",
|
|
||||||
text: "You won't be able to revert this!",
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonColor: "#00ff00",
|
|
||||||
confirmButtonText: "Yes, delete it!",
|
|
||||||
cancelButtonColor: "#ff0000",
|
|
||||||
cancelButtonText: "Cancel",
|
|
||||||
}).then((result) => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
MySwal.fire({
|
|
||||||
title: "Deleted!",
|
|
||||||
text: "Your file has been deleted.",
|
|
||||||
className: "btn btn-success",
|
|
||||||
confirmButtonText: "OK",
|
|
||||||
customClass: {
|
|
||||||
confirmButton: "btn btn-success",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
MySwal.close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div className="page-wrapper">
|
<div className="page-wrapper">
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<Breadcrumbs
|
<div className="page-header">
|
||||||
maintitle="Stock Adjustment"
|
<div className="add-item d-flex">
|
||||||
subtitle=" Manage your stock adjustment"
|
<div className="page-title">
|
||||||
addButton="Add New"
|
<h4>Stock Adjusment</h4>
|
||||||
/>
|
<h6>Adjust your stocks</h6>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="page-btn">
|
||||||
|
<Link
|
||||||
|
to="#"
|
||||||
|
className="btn btn-added"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#edit-units"
|
||||||
|
>
|
||||||
|
<PlusCircle className="me-2" />
|
||||||
|
Add New
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{/* /product list */}
|
{/* /product list */}
|
||||||
<div className="card table-list-card">
|
<div className="card table-list-card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
@ -283,7 +237,7 @@ const StockAdjustment = () => {
|
|||||||
</div>
|
</div>
|
||||||
{/* /product list */}
|
{/* /product list */}
|
||||||
</div>
|
</div>
|
||||||
<StockadjustmentModal />
|
<ManageStockModal />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import api from './api';
|
import api from "./api";
|
||||||
|
|
||||||
const ENDPOINTS = {
|
const ENDPOINTS = {
|
||||||
INVENTORIES: 'inventory',
|
INVENTORIES: "inventory",
|
||||||
INVENTORY_BY_ID: (id) => `inventory/${id}`,
|
INVENTORY_BY_ID: (id) => `inventory/${id}`,
|
||||||
|
INVENTORY_ADJUST: "inventory/adjust",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const inventoryApi = {
|
export const inventoryApi = {
|
||||||
@ -11,7 +12,7 @@ export const inventoryApi = {
|
|||||||
const response = await api.get(ENDPOINTS.INVENTORIES, { params });
|
const response = await api.get(ENDPOINTS.INVENTORIES, { params });
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching inventories:', error);
|
console.error("Error fetching inventories:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -31,14 +32,17 @@ export const inventoryApi = {
|
|||||||
const response = await api.post(ENDPOINTS.INVENTORIES, inventoryData);
|
const response = await api.post(ENDPOINTS.INVENTORIES, inventoryData);
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating inventory:', error);
|
console.error("Error creating inventory:", error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
updateInventory: async (id, inventoryData) => {
|
updateInventory: async (id, inventoryData) => {
|
||||||
try {
|
try {
|
||||||
const response = await api.put(ENDPOINTS.INVENTORY_BY_ID(id), inventoryData);
|
const response = await api.put(
|
||||||
|
ENDPOINTS.INVENTORY_BY_ID(id),
|
||||||
|
inventoryData
|
||||||
|
);
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error updating inventory ${id}:`, error);
|
console.error(`Error updating inventory ${id}:`, error);
|
||||||
@ -46,6 +50,19 @@ export const inventoryApi = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
adjustInventory: async (inventoryData) => {
|
||||||
|
try {
|
||||||
|
const response = await api.post(
|
||||||
|
ENDPOINTS.INVENTORY_ADJUST,
|
||||||
|
inventoryData
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error adjusting inventory:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
deleteInventory: async (id) => {
|
deleteInventory: async (id) => {
|
||||||
try {
|
try {
|
||||||
const response = await api.delete(ENDPOINTS.INVENTORY_BY_ID(id));
|
const response = await api.delete(ENDPOINTS.INVENTORY_BY_ID(id));
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import api from './api';
|
|||||||
// Outlets API endpoints
|
// Outlets API endpoints
|
||||||
const ENDPOINTS = {
|
const ENDPOINTS = {
|
||||||
OUTLETS: 'outlets/list',
|
OUTLETS: 'outlets/list',
|
||||||
OUTLET_BY_ID: (id) => `outlets/${id}`,
|
OUTLET_BY_ID: (id) => `outlets/detail/${id}`,
|
||||||
OUTLET_PRODUCTS: (id) => `outlets/${id}/products`,
|
OUTLET_PRODUCTS: (id) => `outlets/${id}/products`,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user