sides category and sides module updated in single pages and create menu item feature updated

This commit is contained in:
alaguraj 2025-07-29 18:26:46 +05:30
parent f9f29e885e
commit 46a3e91bb8
5 changed files with 473 additions and 140 deletions

View File

@ -82,31 +82,39 @@ const AddNewProduct = () => {
} }
setErrors({}); setErrors({});
const body = { const body =
menucategoryname: category, {
menuitemname: formData.menuitemname,
price: formData.price,
is_active: formData.is_active ? 1 : 0,
is_special: formData.is_special ? 1 : 0,
availability_time: formData.availability_time,
preparation_time: formData.preparation_time,
description: formData.description, description: formData.description,
is_active: 0,
doctype: "Dine360 Menu Category",
menuitems_child: [
{
menuitemname: formData.menuitemname,
price: formData.price,
is_active: formData.is_active ? 1 : 0,
is_special: formData.is_special ? 1 : 0,
availability_time: formData.availability_time,
preparation_time: formData.preparation_time,
},
],
}; };
try { try {
const formDataToSend = new FormData(); // const formDataToSend = new FormData();
formDataToSend.append("endpoint", `Dine360%20Menu%20Category/${category}`); // formDataToSend.append("endpoint", `Dine360%20Menu%20Category/${category}`);
formDataToSend.append("body", JSON.stringify(body)); // formDataToSend.append("body", JSON.stringify(body));
formDataToSend.append("file", imageFile); // use imageFile // formDataToSend.append("file", imageFile); // use imageFile
formDataToSend.append("fileid", "image_item"); // formDataToSend.append("fileid", "image_item");
const response = await axios.post(`${Baseurl}/Upload-Image-To-Frappe`, formDataToSend, { // const response = await axios.post(`${Baseurl}/Upload-Image-To-Frappe`, formDataToSend, {
// headers: {
// Authorization: "token 482beca79d9c005:b8778f51fcca82b",
// },
// });
const formDataToSend = new FormData();
formDataToSend.append("endpoint", "Dine360 Menu Category");
formDataToSend.append("file", imageFile); // use imageFile
formDataToSend.append("fileid", "item_image");
formDataToSend.append("childjson", JSON.stringify(body))
formDataToSend.append("childkey", "menuitems_child");
formDataToSend.append("docname", category);
formDataToSend.append("isimageupdateorcreate", 1);
console.log(formDataToSend)
const response = await axios.post(`${Baseurl}/Upload-Image-To-Frappe/parent-child`, formDataToSend, {
headers: { headers: {
Authorization: "token 482beca79d9c005:b8778f51fcca82b", Authorization: "token 482beca79d9c005:b8778f51fcca82b",
}, },

View File

@ -365,8 +365,8 @@ const ProductListInner = () => {
/> />
<div className="p-0"> <div className="p-0">
<h6 className="text-lg mb-1 mt-1">{menu.menuitemname}</h6> <h6 className="text-lg mb-1 mt-1">{menu.menuitemname}</h6>
<span className="text-secondary-light text-sm lh-sm mb-1">{menu.parent}</span> { /*<span className="text-secondary-light text-sm lh-sm mb-1">{menu.parent}</span>*/}
<h6 className="text-md mb-0 mt-1">${menu.price?.toFixed(2)}</h6> <p className="text-sm mb-0 mt-1">${menu.price?.toFixed(2)}</p>
</div> </div>
</div> </div>
<div className="position-absolute top-0 end-0 me-1 mt-1" onClick={(e) => e.stopPropagation()}> <div className="position-absolute top-0 end-0 me-1 mt-1" onClick={(e) => e.stopPropagation()}>

View File

@ -109,36 +109,34 @@ const UpdateProduct = () => {
} }
setErrors({}); setErrors({});
const body = { const body =
menucategoryname: category, {
menuitemname: formData.menuitemname,
price: formData.price,
is_active: formData.is_active ? 1 : 0,
is_special: formData.is_special ? 1 : 0,
availability_time: formData.availability_time,
preparation_time: formData.preparation_time,
description: formData.description, description: formData.description,
is_active: 0,
doctype: "Dine360 Menu Category",
menuitems_child: [
{
menuitemname: formData.menuitemname,
price: formData.price,
is_active: formData.is_active ? 1 : 0,
is_special: formData.is_special ? 1 : 0,
availability_time: formData.availability_time,
preparation_time: formData.preparation_time,
},
],
}; };
try { try {
const formDataToSend = new FormData(); const formDataToSend = new FormData();
formDataToSend.append("endpoint", `Dine360%20Menu%20Category/${category}`); formDataToSend.append("endpoint", "Dine360 Menu Category");
formDataToSend.append("body", JSON.stringify(body));
formDataToSend.append("file", imageFile); // use imageFile formDataToSend.append("file", imageFile); // use imageFile
formDataToSend.append("fileid", "image_item"); formDataToSend.append("fileid", "item_image");
formDataToSend.append("data", JSON.stringify({ name: MenuItemName })); formDataToSend.append("childjson", JSON.stringify(body))
const response = await axios.put(`${Baseurl}/Upload-Image-To-Frappe`, formDataToSend, { formDataToSend.append("childkey", "menuitems_child");
formDataToSend.append("docname", category);
formDataToSend.append("isimageupdateorcreate", 1);
console.log(formDataToSend)
const response = await axios.post(`${Baseurl}/Upload-Image-To-Frappe/parent-child`, formDataToSend, {
headers: { headers: {
Authorization: "token 482beca79d9c005:b8778f51fcca82b", Authorization: "token 482beca79d9c005:b8778f51fcca82b",
}, },
}); });
console.log("response", response); console.log("response", response);
alert("Form submitted successfully!"); alert("Form submitted successfully!");
router.push("/admin/pos/product-list"); router.push("/admin/pos/product-list");
@ -155,7 +153,7 @@ const UpdateProduct = () => {
<div className="col-xxl-6 col-xl-6 col-lg-7 col-md-9"> <div className="col-xxl-6 col-xl-6 col-lg-7 col-md-9">
<div className="card mt-24 p-lg-3"> <div className="card mt-24 p-lg-3">
<div className="card-body"> <div className="card-body">
<h6 className="text-xl mb-3">Add New Product</h6> <h6 className="text-xl mb-3">Update Product</h6>
<form <form
onSubmit={handleSubmit} onSubmit={handleSubmit}
className="d-flex flex-column gap-20" className="d-flex flex-column gap-20"

View File

@ -16,7 +16,6 @@ const SidesPageInner = () => {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const sidesCategoryName = decodeURIComponent(searchParams.get("sidescategoryname")); const sidesCategoryName = decodeURIComponent(searchParams.get("sidescategoryname"));
const [showModal, setShowModal] = useState(false); const [showModal, setShowModal] = useState(false);
const [editMode, setEditMode] = useState(false); const [editMode, setEditMode] = useState(false);
const [editingRoomId, setEditingRoomId] = useState(null); const [editingRoomId, setEditingRoomId] = useState(null);
@ -34,6 +33,19 @@ const SidesPageInner = () => {
const [deleteConfirm, setDeleteConfirm] = useState({ show: false, id: null }); const [deleteConfirm, setDeleteConfirm] = useState({ show: false, id: null });
const [restaruntBranch, setRestaruntBranch] = useState(""); const [restaruntBranch, setRestaruntBranch] = useState("");
// Sides Category
const [activeCategory, setActiveCategory] = useState("")
const [sidesCategoryData, setSidesCategoryData] = useState(null);
const [showSidesCategoryModal, setShowSidesCategoryModal] = useState(false);
const [isSidesCategoryEditMode, setIsSidesCategoryEditMode] = useState(false);
const [selectedSidesCategoryId, setSelectedSidesCategoryId] = useState(null);
const [sidesCategoryFormData, setSidesCategoryFormData] = useState({
sidesCategoryname: "",
description: "",
});
const [sidesCategoryErrors, setSidesCategoryErrors] = useState({});
const [sidesCategoryDeleteConfirm, setSidesCategoryDeleteConfirm] = useState({ show: false, id: null });
useEffect(() => { useEffect(() => {
const restarunt = localStorage.getItem("restaurantbranch"); const restarunt = localStorage.getItem("restaurantbranch");
setRestaruntBranch(restarunt); setRestaruntBranch(restarunt);
@ -47,12 +59,36 @@ const SidesPageInner = () => {
}, [router]); }, [router]);
useEffect(() => { useEffect(() => {
if (sidesCategoryName) { if (restaruntBranch && restaruntBranch !== "")
getSideData(); getSidesCategory();
} }, [restaruntBranch]);
}, [sidesCategoryName]);
const getSideData = async () => {
const getSidesCategory = async () => {
try {
setLoading(true);
// const res = await client?.get(`/Dine360 Floor?fields=[\"*\"]&limit_page_length=100`);
const res = await client?.get(`/Dine360%20Food%20Sides%20Category?fields=[%22*%22]&limit_page_length=100&filters=[["restaurantbranch","=","${restaruntBranch}"]]`);
setSidesCategoryData(res?.data?.data);
getSideData(res?.data?.data[0]?.name);
setActiveCategory(res?.data?.data[0]?.name)
} catch (error) {
console.error("Error fetching floor data:", error);
setError(error?.message || "Failed to fetch floor data");
} finally {
setLoading(false);
}
};
// useEffect(() => {
// if (sidesCategoryName) {
// getSideData();
// }
// }, [sidesCategoryName]);
const getSideData = async (sidesCategoryName) => {
try { try {
setLoading(true); setLoading(true);
setError(null); setError(null);
@ -89,7 +125,7 @@ const SidesPageInner = () => {
sidename: formData.sidename, sidename: formData.sidename,
description: formData.description, description: formData.description,
price: parseFloat(formData.price), price: parseFloat(formData.price),
sidecategoryid: sidesCategoryName, sidecategoryid: activeCategory,
restaurantbranch: restaruntBranch, restaurantbranch: restaruntBranch,
}; };
@ -117,7 +153,7 @@ const SidesPageInner = () => {
}); });
} }
getSideData(); getSideData(activeCategory);
resetForm(); resetForm();
} catch (error) { } catch (error) {
console.error("❌ Submission error:", error); console.error("❌ Submission error:", error);
@ -165,67 +201,358 @@ const SidesPageInner = () => {
try { try {
await client.delete(`/Dine360%20Food%20Sides/${deleteConfirm?.id}`); await client.delete(`/Dine360%20Food%20Sides/${deleteConfirm?.id}`);
setDeleteConfirm({ show: false, id: null }); setDeleteConfirm({ show: false, id: null });
getSideData(); getSideData(activeCategory);
} catch (error) { } catch (error) {
alert("Error deleting. It might be linked to other data."); alert("Error deleting. It might be linked to other data.");
} }
}; };
// sides category
const handleSidesCategoryClick = async (catname) => {
await getSideData(catname);
setActiveCategory(catname);
};
const handleSidesCategoryChange = (e) => {
const { name, value } = e.target;
setSidesCategoryFormData((prev) => ({ ...prev, [name]: value }));
};
const handleSidesCategorySubmit = async (e) => {
e.preventDefault();
const newErrors = {};
Object.entries(sidesCategoryFormData).forEach(([key, value]) => {
if (!value.trim()) newErrors[key] = `${key} is required`;
});
setSidesCategoryErrors(newErrors);
if (Object.keys(newErrors).length > 0) return;
const body = {
// ...(isSidesCategoryEditMode && { name: selectedFloorId }), // only adds `name` if editing
sidecategoryname: sidesCategoryFormData?.sidesCategoryname,
description: sidesCategoryFormData?.description,
restaurantbranch: restaruntBranch
};
try {
if (isSidesCategoryEditMode) {
await client.put(`/Dine360%20Food%20Sides%20Category/${selectedSidesCategoryId}`, body);
} else {
await client.post(`/Dine360%20Food%20Sides%20Category`, body);
}
getSidesCategory();
resetSidesCategoryForm();
} catch (error) {
if (
error?.response?.data?.exception?.includes("DuplicateEntryError") ||
error?.response?.data?.message?.includes("Duplicate entry")
) {
alert("SidesCategory with this name already exists. Please use a different name.");
} else if (
error?.response?.data?.exception?.includes("UniqueValidationError") ||
error?.response?.data?.message?.includes("UniqueValidationError entry")
) {
alert("SidesCategory with this name already exists. Please use a different name.");
} else {
alert("An error occurred. Please try again.");
}
}
};
const resetSidesCategoryForm = () => {
setSidesCategoryFormData({
sidesCategoryname: "", description: "",
});
setShowSidesCategoryModal(false);
setIsSidesCategoryEditMode(false);
setSelectedSidesCategoryId(null);
setSidesCategoryErrors({});
};
const handleSidesCategoryEdit = (sidesCategory) => {
setIsSidesCategoryEditMode(true);
setSelectedSidesCategoryId(sidesCategory.name);
setSidesCategoryFormData({
sidesCategoryname: sidesCategory.sidecategoryname || "",
description: sidesCategory.description || "",
});
setShowSidesCategoryModal(true);
};
const handleSidesCategoryDelete = async () => {
try {
await client.delete(`/Dine360%20Food%20Sides%20Category/${sidesCategoryDeleteConfirm.id}`);
setSidesCategoryDeleteConfirm({ show: false, id: null });
getSidesCategory();
} catch (error) {
if (
error?.response?.data?.exception?.includes("DuplicateEntryError") ||
error?.response?.data?.message?.includes("Duplicate entry")
) {
alert("SidesCategory with this name already exists. Please use a different name.");
} else if (error?.response?.data?.exception?.includes("LinkExistsError") ||
error?.response?.data?.message?.includes("LinkExistsError")) {
alert(" Cannot delete or cancel because Dine360 SidesCategory three is linked with Dine360 Room ");
}
}
};
return ( return (
<div className="container-fluid" style={{ marginBottom: "100px" }}> <div className="container-fluid" style={{ marginBottom: "100px" }}>
<div className=""> <div className="">
<div className=""> <div className="">
<div className="d-flex justify-content-between align-items-center mb-3">
<h6 className="mb-0">Sides</h6>
<button className="btn btn-bg-theme radius-8 px-20 py-11" onClick={() => setShowModal(true)}>Create</button>
</div>
<div className="row gy-3 gx-3 gx-lg-5 gy-lg-5 justify-content-center"> <div className="row gy-3 gx-3 gx-lg-5 gy-lg-5 justify-content-center">
{loading ? (
<PageLoader /> <div className="col-xl-2 col-lg-3 col-md-4">
) : roomData?.length === 0 ? ( <div className="d-inline-block" style={{width:"100%"}}>
<PageNoData /> <div className="card p-0 overflow-hidden radius-12 h-100">
) : ( <div className="card-body p-24">
roomData?.map((room, index) => { <ul className="d-flex flex-column gap-2">
const gradientClass = gradientClasses[index % gradientClasses.length]; <li
return ( className="nav-item border rounded-2 px-3 py-3 d-flex align-items-center gap-3 justify-content-between"
<div className="col-xxl-2 col-lg-4 col-sm-6 cursor-pointer" key={room?.name}> style={{ cursor: "pointer" }}
<div className="card p-3 shadow-2 radius-8 h-100 border border-white position-relative"> onClick={() => setShowSidesCategoryModal(true)}
<div className="position-absolute top-0 end-0 me-1 mt-1 d-flex gap-2"> >
<div className="dropdown"> <div className="d-flex align-items-center gap-3 ">
<button className='btn px-1 py-1 d-flex align-items-center text-primary-light' type='button' data-bs-toggle='dropdown'> <Icon icon="lucide:plus" className="text-lg w-28-px h-28-px " />
<Icon icon='entypo:dots-three-vertical' className='menu-icon' /> <span className="fw-semibold">New</span>
</button>
<ul className='dropdown-menu'>
<li>
<Link href="#" className='dropdown-item' onClick={(e) => { e.preventDefault(); handleEdit(room); }}>
<Icon icon='lucide:edit' className='menu-icon' /> Edit
</Link>
</li>
<li>
<Link href="#" className='dropdown-item' onClick={(e) => { e.preventDefault(); setDeleteConfirm({ show: true, id: room.name }); }}>
<Icon icon='fluent:delete-24-regular' className='menu-icon' /> Delete
</Link>
</li>
</ul>
</div> </div>
</div> </li>
<div className="card-body text-center p-3"> {sidesCategoryData?.map((sidesCategory) => (
<img src={`${ImageBase}/${room.item_image}`} alt="" className="w-100-px h-100-px rounded-circle object-fit-cover" /> <li
<h6 className="text-lg mb-0 mt-1">{room?.sidename}</h6> key={sidesCategory?.name}
<span className="text-secondary-light text-sm">{room?.description}</span> className={`nav-item border rounded-2 px-3 py-3 bg-border-theme d-flex align-items-center gap-3 position-relative
<h6 className="text-md mb-0 mt-1">${room.price.toFixed(2)}</h6> ${activeCategory === sidesCategory.name ? "bg-theme" : ""}`
</div> }
role="presentation"
onClick={() => handleSidesCategoryClick(sidesCategory?.name)}
style={{ cursor: "pointer" }}
>
<img
src="/assets/images/menu/menu-icons/all-menu.png"
alt="menu"
className="w-28-px h-28-px"
/>
<span className="line-height-1">{sidesCategory?.sidecategoryname}</span>
<div className="position-absolute top-0 end-0 me-1 mt-1" onClick={(e) => e.stopPropagation()}>
<div className="dropdown">
<button
className="btn px-1 py-1 d-flex align-items-center text-primary-light"
type="button"
data-bs-toggle="dropdown"
aria-expanded="false"
>
<Icon icon="entypo:dots-three-vertical" className="menu-icon" />
</button>
<ul className="dropdown-menu">
<li>
<Link
href="#"
className='dropdown-item px-16 py-8 d-flex align-items-center gap-2 rounded text-secondary-light bg-hover-neutral-200 text-hover-neutral-900'
onClick={(e) => {
e.preventDefault();
handleSidesCategoryEdit(sidesCategory);
}}
> <Icon icon='lucide:edit' className='menu-icon' />
Edit
</Link>
</li>
<li>
<Link
href="#"
className='dropdown-item px-16 py-8 d-flex align-items-center gap-2 rounded text-secondary-light bg-hover-neutral-200 text-hover-neutral-900'
onClick={(e) => {
e.preventDefault();
setSidesCategoryDeleteConfirm({ show: true, id: sidesCategory.name });
}}
>
<Icon
icon='fluent:delete-24-regular'
className='menu-icon'
/>
Delete
</Link>
</li>
</ul>
</div>
</div>
</li>
))}
</ul>
</div>
</div>
</div>
</div>
<div className="col-xl-10 col-lg-9 col-md-8">
<div className="row gy-3 gx-3 gx-lg-5 gy-lg-5">
<div className="col-xxl-3 col-xl-3 col-lg-4 col-sm-6 col-6 cursor-pointer">
<div className="card p-3 shadow-2 radius-8 h-100 border border-white position-relative">
<div className="card-body text-center p-3 d-flex justify-content-center align-items-center">
<button className="btn radius-8 px-20 py-11" onClick={() => setShowModal(true)}>
<Icon icon="lucide:plus" className="text-lg w-50-px h-50-px " />
</button>
</div> </div>
</div> </div>
); </div>
}) {loading ? (
)} <PageLoader />
) : (
roomData?.map((room, index) => {
const gradientClass = gradientClasses[index % gradientClasses.length];
return (
<div className="col-xxl-3 col-xl-3 col-lg-4 col-sm-6 col-6 cursor-pointer" key={room?.name}>
<div className="card p-3 shadow-2 radius-8 h-100 border border-white position-relative">
<div className="position-absolute top-0 end-0 me-1 mt-1 d-flex gap-2">
<div className="dropdown">
<button className='btn px-1 py-1 d-flex align-items-center text-primary-light' type='button' data-bs-toggle='dropdown'>
<Icon icon='entypo:dots-three-vertical' className='menu-icon' />
</button>
<ul className='dropdown-menu'>
<li>
<Link href="#" className='dropdown-item px-16 py-8 d-flex align-items-center gap-2 rounded text-secondary-light bg-hover-neutral-200 text-hover-neutral-900' onClick={(e) => { e.preventDefault(); handleEdit(room); }}>
<Icon icon='lucide:edit' className='menu-icon' /> Edit
</Link>
</li>
<li>
<Link href="#" className='dropdown-item px-16 py-8 d-flex align-items-center gap-2 rounded text-secondary-light bg-hover-neutral-200 text-hover-neutral-900' onClick={(e) => { e.preventDefault(); setDeleteConfirm({ show: true, id: room.name }); }}>
<Icon icon='fluent:delete-24-regular' className='menu-icon' /> Delete
</Link>
</li>
</ul>
</div>
</div>
<div className="card-body text-center p-3">
<img src={`${ImageBase}/${room.item_image}`} alt="" className="w-100-px h-100-px rounded-circle object-fit-cover" />
<h6 className="text-md mb-0 mt-3">{room?.sidename}</h6>
<span className="text-secondary-light text-sm">${room.price.toFixed(2)}</span>
{/* <h6 className="text-md mb-0 mt-1">${room.price.toFixed(2)}</h6> */}
</div>
</div>
</div>
);
})
)}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
{/* Modal */}
{/* sides category */}
{/* Create/Edit Modal */}
{showSidesCategoryModal && (
<div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}>
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-header border-0 pb-0">
<h6 className="modal-title text-lg">
{isSidesCategoryEditMode ? "Edit SidesCategory" : "Create SidesCategory"}
</h6>
<button type="button" className="btn-close" onClick={resetSidesCategoryForm}></button>
</div>
<div className="modal-body">
<form onSubmit={handleSidesCategorySubmit}>
<div className="mb-3">
<label className="form-label">SidesCategory Name</label>
<input
type="text"
className={`form-control ${sidesCategoryErrors.sidesCategoryname ? "is-invalid" : ""}`}
name="sidesCategoryname"
value={sidesCategoryFormData.sidesCategoryname}
onChange={handleSidesCategoryChange}
/>
{sidesCategoryErrors.sidesCategoryname && (
<div className="invalid-feedback">{sidesCategoryErrors.sidesCategoryname}</div>
)}
</div>
<div className="mb-3">
<label className="form-label">Description</label>
<textarea
className={`form-control ${sidesCategoryErrors.description ? "is-invalid" : ""}`}
name="description"
value={sidesCategoryFormData.description}
onChange={handleSidesCategoryChange}
rows="3"
></textarea>
{sidesCategoryErrors.description && (
<div className="invalid-feedback">{sidesCategoryErrors.description}</div>
)}
</div>
{/* <div className="mb-3">
<label className="form-label">Branch</label>
<select
className={`form-select ${sidesCategoryErrors.branch ? "is-invalid" : ""}`}
name="branch"
value={sidesCategoryFormData.branch}
onChange={handleChange}
>
<option value="">Select Branch</option>
{branchData.map((branch) => (
<option key={branch.name} value={branch.name}>
{branch.branch}
</option>
))}
</select>
{sidesCategoryErrors.branch && (
<div className="invalid-feedback">{sidesCategoryErrors.branch}</div>
)}
</div> */}
<div className="d-flex justify-content-end">
<button type="submit" className="btn btn-bg-theme">
{isSidesCategoryEditMode ? "Update" : "Submit"}
</button>
</div>
</form>
</div>
</div>
</div>
</div>
)}
{/* Delete Confirmation Modal */}
{sidesCategoryDeleteConfirm.show && (
<div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}>
<div className="modal-dialog modal-dialog-centered">
<div className="modal-content">
<div className="modal-body">
<div className="d-flex justify-content-between mb-1">
<h6 className="text-lg mb-0">Confirm Delete</h6>
<button
type="button"
className="btn-close"
onClick={() => setSidesCategoryDeleteConfirm({ show: false, id: null })}
></button>
</div>
<p className="m-0">Are you sure you want to delete this sidesCategory?</p>
<div className="d-flex justify-content-end gap-2 mt-1 ">
<button
className="btn btn-outline-danger px-14 py-6 text-sm"
onClick={() => setSidesCategoryDeleteConfirm({ show: false, id: null })}
>
Cancel
</button>
<button className="btn btn-danger px-14 py-6 text-sm" onClick={handleSidesCategoryDelete}>
Delete
</button>
</div>
</div>
</div>
</div>
</div>
)}
{/*Sides Modal */}
{showModal && ( {showModal && (
<div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}> <div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}>
<div className="modal-dialog modal-dialog-centered"> <div className="modal-dialog modal-dialog-centered">

View File

@ -11,15 +11,15 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
const router = useRouter() const router = useRouter()
const params = useParams(); const params = useParams();
const [showModal, setShowModal] = useState(false); const [showSidesCategoryModal, setShowSidesCategoryModal] = useState(false);
const [isEditMode, setIsEditMode] = useState(false); const [isSidesCategoryEditMode, setIsSidesCategoryEditMode] = useState(false);
const [selectedSidesCategoryId, setSelectedSidesCategoryId] = useState(null); const [selectedSidesCategoryId, setSelectedSidesCategoryId] = useState(null);
const [formData, setFormData] = useState({ const [sidesCategoryFormData, setSidesCategoryFormData] = useState({
sidesCategoryname: "", sidesCategoryname: "",
description: "", description: "",
}); });
const [errors, setErrors] = useState({}); const [sidesCategoryErrors, setSidesCategoryErrors] = useState({});
const [deleteConfirm, setDeleteConfirm] = useState({ show: false, id: null }); const [sidesCategoryDeleteConfirm, setSidesCategoryDeleteConfirm] = useState({ show: false, id: null });
const [restaruntBranch, setRestaruntBranch] = useState("") const [restaruntBranch, setRestaruntBranch] = useState("")
useEffect(() => { useEffect(() => {
@ -34,29 +34,29 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
} }
}, [router]); }, [router]);
const handleChange = (e) => { const handleSidesCategoryChange = (e) => {
const { name, value } = e.target; const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value })); setSidesCategoryFormData((prev) => ({ ...prev, [name]: value }));
}; };
const handleSubmit = async (e) => { const handleSidesCategorySubmit = async (e) => {
e.preventDefault(); e.preventDefault();
const newErrors = {}; const newErrors = {};
Object.entries(formData).forEach(([key, value]) => { Object.entries(sidesCategoryFormData).forEach(([key, value]) => {
if (!value.trim()) newErrors[key] = `${key} is required`; if (!value.trim()) newErrors[key] = `${key} is required`;
}); });
setErrors(newErrors); setSidesCategoryErrors(newErrors);
if (Object.keys(newErrors).length > 0) return; if (Object.keys(newErrors).length > 0) return;
const body = { const body = {
// ...(isEditMode && { name: selectedFloorId }), // only adds `name` if editing // ...(isSidesCategoryEditMode && { name: selectedFloorId }), // only adds `name` if editing
sidecategoryname: formData?.sidesCategoryname, sidecategoryname: sidesCategoryFormData?.sidesCategoryname,
description: formData?.description, description: sidesCategoryFormData?.description,
restaurantbranch: restaruntBranch restaurantbranch: restaruntBranch
}; };
try { try {
if (isEditMode) { if (isSidesCategoryEditMode) {
await client.put(`/Dine360%20Food%20Sides%20Category/${selectedSidesCategoryId}`, body); await client.put(`/Dine360%20Food%20Sides%20Category/${selectedSidesCategoryId}`, body);
} else { } else {
await client.post(`/Dine360%20Food%20Sides%20Category`, body); await client.post(`/Dine360%20Food%20Sides%20Category`, body);
@ -81,29 +81,29 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
}; };
const resetForm = () => { const resetForm = () => {
setFormData({ setSidesCategoryFormData({
sidesCategoryname: "", description: "", sidesCategoryname: "", description: "",
}); });
setShowModal(false); setShowSidesCategoryModal(false);
setIsEditMode(false); setIsSidesCategoryEditMode(false);
setSelectedSidesCategoryId(null); setSelectedSidesCategoryId(null);
setErrors({}); setSidesCategoryErrors({});
}; };
const handleEdit = (sidesCategory) => { const handleEdit = (sidesCategory) => {
setIsEditMode(true); setIsSidesCategoryEditMode(true);
setSelectedSidesCategoryId(sidesCategory.name); setSelectedSidesCategoryId(sidesCategory.name);
setFormData({ setSidesCategoryFormData({
sidesCategoryname: sidesCategory.sidecategoryname || "", sidesCategoryname: sidesCategory.sidecategoryname || "",
description: sidesCategory.description || "", description: sidesCategory.description || "",
}); });
setShowModal(true); setShowSidesCategoryModal(true);
}; };
const handleDelete = async () => { const handleDelete = async () => {
try { try {
await client.delete(`/Dine360%20Food%20Sides%20Category/${deleteConfirm.id}`); await client.delete(`/Dine360%20Food%20Sides%20Category/${sidesCategoryDeleteConfirm.id}`);
setDeleteConfirm({ show: false, id: null }); setSidesCategoryDeleteConfirm({ show: false, id: null });
getSidesCategory(); getSidesCategory();
} catch (error) { } catch (error) {
if ( if (
@ -127,7 +127,7 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
<button <button
type="button" type="button"
className="btn btn-bg-theme radius-8 px-20 py-11" className="btn btn-bg-theme radius-8 px-20 py-11"
onClick={() => setShowModal(true)} onClick={() => setShowSidesCategoryModal(true)}
> >
Create Create
</button> </button>
@ -175,7 +175,7 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
className='dropdown-item px-16 py-8 d-flex align-items-center gap-2 rounded text-secondary-light bg-hover-neutral-200 text-hover-neutral-900' className='dropdown-item px-16 py-8 d-flex align-items-center gap-2 rounded text-secondary-light bg-hover-neutral-200 text-hover-neutral-900'
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
setDeleteConfirm({ show: true, id: sidesCategory.name }); setSidesCategoryDeleteConfirm({ show: true, id: sidesCategory.name });
}} }}
> >
<Icon <Icon
@ -212,52 +212,52 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
</div> </div>
{/* Create/Edit Modal */} {/* Create/Edit Modal */}
{showModal && ( {showSidesCategoryModal && (
<div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}> <div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}>
<div className="modal-dialog modal-dialog-centered"> <div className="modal-dialog modal-dialog-centered">
<div className="modal-content"> <div className="modal-content">
<div className="modal-header border-0 pb-0"> <div className="modal-header border-0 pb-0">
<h6 className="modal-title text-lg"> <h6 className="modal-title text-lg">
{isEditMode ? "Edit SidesCategory" : "Create SidesCategory"} {isSidesCategoryEditMode ? "Edit SidesCategory" : "Create SidesCategory"}
</h6> </h6>
<button type="button" className="btn-close" onClick={resetForm}></button> <button type="button" className="btn-close" onClick={resetForm}></button>
</div> </div>
<div className="modal-body"> <div className="modal-body">
<form onSubmit={handleSubmit}> <form onSubmit={handleSidesCategorySubmit}>
<div className="mb-3"> <div className="mb-3">
<label className="form-label">SidesCategory Name</label> <label className="form-label">SidesCategory Name</label>
<input <input
type="text" type="text"
className={`form-control ${errors.sidesCategoryname ? "is-invalid" : ""}`} className={`form-control ${sidesCategoryErrors.sidesCategoryname ? "is-invalid" : ""}`}
name="sidesCategoryname" name="sidesCategoryname"
value={formData.sidesCategoryname} value={sidesCategoryFormData.sidesCategoryname}
onChange={handleChange} onChange={handleSidesCategoryChange}
/> />
{errors.sidesCategoryname && ( {sidesCategoryErrors.sidesCategoryname && (
<div className="invalid-feedback">{errors.sidesCategoryname}</div> <div className="invalid-feedback">{sidesCategoryErrors.sidesCategoryname}</div>
)} )}
</div> </div>
<div className="mb-3"> <div className="mb-3">
<label className="form-label">Description</label> <label className="form-label">Description</label>
<textarea <textarea
className={`form-control ${errors.description ? "is-invalid" : ""}`} className={`form-control ${sidesCategoryErrors.description ? "is-invalid" : ""}`}
name="description" name="description"
value={formData.description} value={sidesCategoryFormData.description}
onChange={handleChange} onChange={handleSidesCategoryChange}
rows="3" rows="3"
></textarea> ></textarea>
{errors.description && ( {sidesCategoryErrors.description && (
<div className="invalid-feedback">{errors.description}</div> <div className="invalid-feedback">{sidesCategoryErrors.description}</div>
)} )}
</div> </div>
{/* <div className="mb-3"> {/* <div className="mb-3">
<label className="form-label">Branch</label> <label className="form-label">Branch</label>
<select <select
className={`form-select ${errors.branch ? "is-invalid" : ""}`} className={`form-select ${sidesCategoryErrors.branch ? "is-invalid" : ""}`}
name="branch" name="branch"
value={formData.branch} value={sidesCategoryFormData.branch}
onChange={handleChange} onChange={handleChange}
> >
<option value="">Select Branch</option> <option value="">Select Branch</option>
@ -267,14 +267,14 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
</option> </option>
))} ))}
</select> </select>
{errors.branch && ( {sidesCategoryErrors.branch && (
<div className="invalid-feedback">{errors.branch}</div> <div className="invalid-feedback">{sidesCategoryErrors.branch}</div>
)} )}
</div> */} </div> */}
<div className="d-flex justify-content-end"> <div className="d-flex justify-content-end">
<button type="submit" className="btn btn-bg-theme"> <button type="submit" className="btn btn-bg-theme">
{isEditMode ? "Update" : "Submit"} {isSidesCategoryEditMode ? "Update" : "Submit"}
</button> </button>
</div> </div>
</form> </form>
@ -285,7 +285,7 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
)} )}
{/* Delete Confirmation Modal */} {/* Delete Confirmation Modal */}
{deleteConfirm.show && ( {sidesCategoryDeleteConfirm.show && (
<div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}> <div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}>
<div className="modal-dialog modal-dialog-centered"> <div className="modal-dialog modal-dialog-centered">
<div className="modal-content"> <div className="modal-content">
@ -296,14 +296,14 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
<button <button
type="button" type="button"
className="btn-close" className="btn-close"
onClick={() => setDeleteConfirm({ show: false, id: null })} onClick={() => setSidesCategoryDeleteConfirm({ show: false, id: null })}
></button> ></button>
</div> </div>
<p className="m-0">Are you sure you want to delete this sidesCategory?</p> <p className="m-0">Are you sure you want to delete this sidesCategory?</p>
<div className="d-flex justify-content-end gap-2 mt-1 "> <div className="d-flex justify-content-end gap-2 mt-1 ">
<button <button
className="btn btn-outline-danger px-14 py-6 text-sm" className="btn btn-outline-danger px-14 py-6 text-sm"
onClick={() => setDeleteConfirm({ show: false, id: null })} onClick={() => setSidesCategoryDeleteConfirm({ show: false, id: null })}
> >
Cancel Cancel
</button> </button>