sides category and sides module updated in single pages and create menu item feature updated
This commit is contained in:
parent
f9f29e885e
commit
46a3e91bb8
@ -82,31 +82,39 @@ const AddNewProduct = () => {
|
||||
}
|
||||
setErrors({});
|
||||
|
||||
const body = {
|
||||
menucategoryname: category,
|
||||
const body =
|
||||
{
|
||||
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,
|
||||
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 {
|
||||
const formDataToSend = new FormData();
|
||||
formDataToSend.append("endpoint", `Dine360%20Menu%20Category/${category}`);
|
||||
formDataToSend.append("body", JSON.stringify(body));
|
||||
formDataToSend.append("file", imageFile); // ✅ use imageFile
|
||||
formDataToSend.append("fileid", "image_item");
|
||||
// const formDataToSend = new FormData();
|
||||
// formDataToSend.append("endpoint", `Dine360%20Menu%20Category/${category}`);
|
||||
// formDataToSend.append("body", JSON.stringify(body));
|
||||
// formDataToSend.append("file", imageFile); // ✅ use imageFile
|
||||
// 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: {
|
||||
Authorization: "token 482beca79d9c005:b8778f51fcca82b",
|
||||
},
|
||||
|
||||
@ -365,8 +365,8 @@ const ProductListInner = () => {
|
||||
/>
|
||||
<div className="p-0">
|
||||
<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>
|
||||
<h6 className="text-md mb-0 mt-1">${menu.price?.toFixed(2)}</h6>
|
||||
{ /*<span className="text-secondary-light text-sm lh-sm mb-1">{menu.parent}</span>*/}
|
||||
<p className="text-sm mb-0 mt-1">${menu.price?.toFixed(2)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="position-absolute top-0 end-0 me-1 mt-1" onClick={(e) => e.stopPropagation()}>
|
||||
|
||||
@ -109,36 +109,34 @@ const UpdateProduct = () => {
|
||||
}
|
||||
setErrors({});
|
||||
|
||||
const body = {
|
||||
menucategoryname: category,
|
||||
const body =
|
||||
{
|
||||
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,
|
||||
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 {
|
||||
const formDataToSend = new FormData();
|
||||
formDataToSend.append("endpoint", `Dine360%20Menu%20Category/${category}`);
|
||||
formDataToSend.append("body", JSON.stringify(body));
|
||||
formDataToSend.append("endpoint", "Dine360 Menu Category");
|
||||
formDataToSend.append("file", imageFile); // ✅ use imageFile
|
||||
formDataToSend.append("fileid", "image_item");
|
||||
formDataToSend.append("data", JSON.stringify({ name: MenuItemName }));
|
||||
const response = await axios.put(`${Baseurl}/Upload-Image-To-Frappe`, formDataToSend, {
|
||||
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: {
|
||||
Authorization: "token 482beca79d9c005:b8778f51fcca82b",
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
console.log("response", response);
|
||||
alert("Form submitted successfully!");
|
||||
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="card mt-24 p-lg-3">
|
||||
<div className="card-body">
|
||||
<h6 className="text-xl mb-3">Add New Product</h6>
|
||||
<h6 className="text-xl mb-3">Update Product</h6>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className="d-flex flex-column gap-20"
|
||||
|
||||
@ -16,7 +16,6 @@ const SidesPageInner = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const sidesCategoryName = decodeURIComponent(searchParams.get("sidescategoryname"));
|
||||
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [editMode, setEditMode] = useState(false);
|
||||
const [editingRoomId, setEditingRoomId] = useState(null);
|
||||
@ -34,6 +33,19 @@ const SidesPageInner = () => {
|
||||
const [deleteConfirm, setDeleteConfirm] = useState({ show: false, id: null });
|
||||
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(() => {
|
||||
const restarunt = localStorage.getItem("restaurantbranch");
|
||||
setRestaruntBranch(restarunt);
|
||||
@ -47,12 +59,36 @@ const SidesPageInner = () => {
|
||||
}, [router]);
|
||||
|
||||
useEffect(() => {
|
||||
if (sidesCategoryName) {
|
||||
getSideData();
|
||||
}
|
||||
}, [sidesCategoryName]);
|
||||
if (restaruntBranch && restaruntBranch !== "")
|
||||
getSidesCategory();
|
||||
}, [restaruntBranch]);
|
||||
|
||||
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 {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
@ -89,7 +125,7 @@ const SidesPageInner = () => {
|
||||
sidename: formData.sidename,
|
||||
description: formData.description,
|
||||
price: parseFloat(formData.price),
|
||||
sidecategoryid: sidesCategoryName,
|
||||
sidecategoryid: activeCategory,
|
||||
restaurantbranch: restaruntBranch,
|
||||
};
|
||||
|
||||
@ -117,7 +153,7 @@ const SidesPageInner = () => {
|
||||
});
|
||||
}
|
||||
|
||||
getSideData();
|
||||
getSideData(activeCategory);
|
||||
resetForm();
|
||||
} catch (error) {
|
||||
console.error("❌ Submission error:", error);
|
||||
@ -165,67 +201,358 @@ const SidesPageInner = () => {
|
||||
try {
|
||||
await client.delete(`/Dine360%20Food%20Sides/${deleteConfirm?.id}`);
|
||||
setDeleteConfirm({ show: false, id: null });
|
||||
getSideData();
|
||||
getSideData(activeCategory);
|
||||
} catch (error) {
|
||||
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 (
|
||||
<div className="container-fluid" style={{ marginBottom: "100px" }}>
|
||||
<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">
|
||||
{loading ? (
|
||||
<PageLoader />
|
||||
) : roomData?.length === 0 ? (
|
||||
<PageNoData />
|
||||
) : (
|
||||
roomData?.map((room, index) => {
|
||||
const gradientClass = gradientClasses[index % gradientClasses.length];
|
||||
return (
|
||||
<div className="col-xxl-2 col-lg-4 col-sm-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' 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 className="col-xl-2 col-lg-3 col-md-4">
|
||||
<div className="d-inline-block" style={{width:"100%"}}>
|
||||
<div className="card p-0 overflow-hidden radius-12 h-100">
|
||||
<div className="card-body p-24">
|
||||
<ul className="d-flex flex-column gap-2">
|
||||
<li
|
||||
className="nav-item border rounded-2 px-3 py-3 d-flex align-items-center gap-3 justify-content-between"
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => setShowSidesCategoryModal(true)}
|
||||
>
|
||||
<div className="d-flex align-items-center gap-3 ">
|
||||
<Icon icon="lucide:plus" className="text-lg w-28-px h-28-px " />
|
||||
<span className="fw-semibold">New</span>
|
||||
</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-lg mb-0 mt-1">{room?.sidename}</h6>
|
||||
<span className="text-secondary-light text-sm">{room?.description}</span>
|
||||
<h6 className="text-md mb-0 mt-1">${room.price.toFixed(2)}</h6>
|
||||
</div>
|
||||
</li>
|
||||
{sidesCategoryData?.map((sidesCategory) => (
|
||||
<li
|
||||
key={sidesCategory?.name}
|
||||
className={`nav-item border rounded-2 px-3 py-3 bg-border-theme d-flex align-items-center gap-3 position-relative
|
||||
${activeCategory === sidesCategory.name ? "bg-theme" : ""}`
|
||||
}
|
||||
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>
|
||||
{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>
|
||||
|
||||
{/* 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 && (
|
||||
<div className="modal fade show" style={{ display: "block", backgroundColor: "rgba(0,0,0,0.5)" }}>
|
||||
<div className="modal-dialog modal-dialog-centered">
|
||||
|
||||
@ -11,15 +11,15 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
|
||||
const router = useRouter()
|
||||
const params = useParams();
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
const [showSidesCategoryModal, setShowSidesCategoryModal] = useState(false);
|
||||
const [isSidesCategoryEditMode, setIsSidesCategoryEditMode] = useState(false);
|
||||
const [selectedSidesCategoryId, setSelectedSidesCategoryId] = useState(null);
|
||||
const [formData, setFormData] = useState({
|
||||
const [sidesCategoryFormData, setSidesCategoryFormData] = useState({
|
||||
sidesCategoryname: "",
|
||||
description: "",
|
||||
});
|
||||
const [errors, setErrors] = useState({});
|
||||
const [deleteConfirm, setDeleteConfirm] = useState({ show: false, id: null });
|
||||
const [sidesCategoryErrors, setSidesCategoryErrors] = useState({});
|
||||
const [sidesCategoryDeleteConfirm, setSidesCategoryDeleteConfirm] = useState({ show: false, id: null });
|
||||
const [restaruntBranch, setRestaruntBranch] = useState("")
|
||||
|
||||
useEffect(() => {
|
||||
@ -34,29 +34,29 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
const handleChange = (e) => {
|
||||
const handleSidesCategoryChange = (e) => {
|
||||
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();
|
||||
|
||||
const newErrors = {};
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
Object.entries(sidesCategoryFormData).forEach(([key, value]) => {
|
||||
if (!value.trim()) newErrors[key] = `${key} is required`;
|
||||
});
|
||||
setErrors(newErrors);
|
||||
setSidesCategoryErrors(newErrors);
|
||||
if (Object.keys(newErrors).length > 0) return;
|
||||
|
||||
const body = {
|
||||
// ...(isEditMode && { name: selectedFloorId }), // only adds `name` if editing
|
||||
sidecategoryname: formData?.sidesCategoryname,
|
||||
description: formData?.description,
|
||||
// ...(isSidesCategoryEditMode && { name: selectedFloorId }), // only adds `name` if editing
|
||||
sidecategoryname: sidesCategoryFormData?.sidesCategoryname,
|
||||
description: sidesCategoryFormData?.description,
|
||||
restaurantbranch: restaruntBranch
|
||||
};
|
||||
try {
|
||||
if (isEditMode) {
|
||||
if (isSidesCategoryEditMode) {
|
||||
await client.put(`/Dine360%20Food%20Sides%20Category/${selectedSidesCategoryId}`, body);
|
||||
} else {
|
||||
await client.post(`/Dine360%20Food%20Sides%20Category`, body);
|
||||
@ -81,29 +81,29 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
setFormData({
|
||||
setSidesCategoryFormData({
|
||||
sidesCategoryname: "", description: "",
|
||||
});
|
||||
setShowModal(false);
|
||||
setIsEditMode(false);
|
||||
setShowSidesCategoryModal(false);
|
||||
setIsSidesCategoryEditMode(false);
|
||||
setSelectedSidesCategoryId(null);
|
||||
setErrors({});
|
||||
setSidesCategoryErrors({});
|
||||
};
|
||||
|
||||
const handleEdit = (sidesCategory) => {
|
||||
setIsEditMode(true);
|
||||
setIsSidesCategoryEditMode(true);
|
||||
setSelectedSidesCategoryId(sidesCategory.name);
|
||||
setFormData({
|
||||
setSidesCategoryFormData({
|
||||
sidesCategoryname: sidesCategory.sidecategoryname || "",
|
||||
description: sidesCategory.description || "",
|
||||
});
|
||||
setShowModal(true);
|
||||
setShowSidesCategoryModal(true);
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
try {
|
||||
await client.delete(`/Dine360%20Food%20Sides%20Category/${deleteConfirm.id}`);
|
||||
setDeleteConfirm({ show: false, id: null });
|
||||
await client.delete(`/Dine360%20Food%20Sides%20Category/${sidesCategoryDeleteConfirm.id}`);
|
||||
setSidesCategoryDeleteConfirm({ show: false, id: null });
|
||||
getSidesCategory();
|
||||
} catch (error) {
|
||||
if (
|
||||
@ -127,7 +127,7 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-bg-theme radius-8 px-20 py-11"
|
||||
onClick={() => setShowModal(true)}
|
||||
onClick={() => setShowSidesCategoryModal(true)}
|
||||
>
|
||||
Create
|
||||
</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'
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setDeleteConfirm({ show: true, id: sidesCategory.name });
|
||||
setSidesCategoryDeleteConfirm({ show: true, id: sidesCategory.name });
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
@ -212,52 +212,52 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
</div>
|
||||
|
||||
{/* Create/Edit Modal */}
|
||||
{showModal && (
|
||||
{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">
|
||||
{isEditMode ? "Edit SidesCategory" : "Create SidesCategory"}
|
||||
{isSidesCategoryEditMode ? "Edit SidesCategory" : "Create SidesCategory"}
|
||||
</h6>
|
||||
<button type="button" className="btn-close" onClick={resetForm}></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form onSubmit={handleSidesCategorySubmit}>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">SidesCategory Name</label>
|
||||
<input
|
||||
type="text"
|
||||
className={`form-control ${errors.sidesCategoryname ? "is-invalid" : ""}`}
|
||||
className={`form-control ${sidesCategoryErrors.sidesCategoryname ? "is-invalid" : ""}`}
|
||||
name="sidesCategoryname"
|
||||
value={formData.sidesCategoryname}
|
||||
onChange={handleChange}
|
||||
value={sidesCategoryFormData.sidesCategoryname}
|
||||
onChange={handleSidesCategoryChange}
|
||||
/>
|
||||
{errors.sidesCategoryname && (
|
||||
<div className="invalid-feedback">{errors.sidesCategoryname}</div>
|
||||
{sidesCategoryErrors.sidesCategoryname && (
|
||||
<div className="invalid-feedback">{sidesCategoryErrors.sidesCategoryname}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Description</label>
|
||||
<textarea
|
||||
className={`form-control ${errors.description ? "is-invalid" : ""}`}
|
||||
className={`form-control ${sidesCategoryErrors.description ? "is-invalid" : ""}`}
|
||||
name="description"
|
||||
value={formData.description}
|
||||
onChange={handleChange}
|
||||
value={sidesCategoryFormData.description}
|
||||
onChange={handleSidesCategoryChange}
|
||||
rows="3"
|
||||
></textarea>
|
||||
{errors.description && (
|
||||
<div className="invalid-feedback">{errors.description}</div>
|
||||
{sidesCategoryErrors.description && (
|
||||
<div className="invalid-feedback">{sidesCategoryErrors.description}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* <div className="mb-3">
|
||||
<label className="form-label">Branch</label>
|
||||
<select
|
||||
className={`form-select ${errors.branch ? "is-invalid" : ""}`}
|
||||
className={`form-select ${sidesCategoryErrors.branch ? "is-invalid" : ""}`}
|
||||
name="branch"
|
||||
value={formData.branch}
|
||||
value={sidesCategoryFormData.branch}
|
||||
onChange={handleChange}
|
||||
>
|
||||
<option value="">Select Branch</option>
|
||||
@ -267,14 +267,14 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
{errors.branch && (
|
||||
<div className="invalid-feedback">{errors.branch}</div>
|
||||
{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">
|
||||
{isEditMode ? "Update" : "Submit"}
|
||||
{isSidesCategoryEditMode ? "Update" : "Submit"}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@ -285,7 +285,7 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
)}
|
||||
|
||||
{/* 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-dialog modal-dialog-centered">
|
||||
<div className="modal-content">
|
||||
@ -296,14 +296,14 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setDeleteConfirm({ show: false, id: null })}
|
||||
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={() => setDeleteConfirm({ show: false, id: null })}
|
||||
onClick={() => setSidesCategoryDeleteConfirm({ show: false, id: null })}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user