From 46a3e91bb8a32e82ec94742c06114011a468ded8 Mon Sep 17 00:00:00 2001 From: alaguraj Date: Tue, 29 Jul 2025 18:26:46 +0530 Subject: [PATCH] sides category and sides module updated in single pages and create menu item feature updated --- .../pos/(product)/create-product/page.jsx | 48 +- .../pos/(product)/product-list/page.jsx | 4 +- .../pos/(product)/update-product/page.jsx | 38 +- src/app/admin/(pos-system)/pos/sides/page.jsx | 431 +++++++++++++++--- .../admin/SidesCategoryComponent.jsx | 92 ++-- 5 files changed, 473 insertions(+), 140 deletions(-) diff --git a/src/app/admin/(pos-system)/pos/(product)/create-product/page.jsx b/src/app/admin/(pos-system)/pos/(product)/create-product/page.jsx index f1707a3..2dca08b 100644 --- a/src/app/admin/(pos-system)/pos/(product)/create-product/page.jsx +++ b/src/app/admin/(pos-system)/pos/(product)/create-product/page.jsx @@ -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", }, diff --git a/src/app/admin/(pos-system)/pos/(product)/product-list/page.jsx b/src/app/admin/(pos-system)/pos/(product)/product-list/page.jsx index 8a1b250..0ed806f 100644 --- a/src/app/admin/(pos-system)/pos/(product)/product-list/page.jsx +++ b/src/app/admin/(pos-system)/pos/(product)/product-list/page.jsx @@ -365,8 +365,8 @@ const ProductListInner = () => { />
{menu.menuitemname}
- {menu.parent} -
${menu.price?.toFixed(2)}
+ { /*{menu.parent}*/} +

${menu.price?.toFixed(2)}

e.stopPropagation()}> diff --git a/src/app/admin/(pos-system)/pos/(product)/update-product/page.jsx b/src/app/admin/(pos-system)/pos/(product)/update-product/page.jsx index daa4576..c2521ce 100644 --- a/src/app/admin/(pos-system)/pos/(product)/update-product/page.jsx +++ b/src/app/admin/(pos-system)/pos/(product)/update-product/page.jsx @@ -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 = () => {
-
Add New Product
+
Update Product
{ 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 (
-
-
Sides
- -
-
- {loading ? ( - - ) : roomData?.length === 0 ? ( - - ) : ( - roomData?.map((room, index) => { - const gradientClass = gradientClasses[index % gradientClasses.length]; - return ( -
-
-
-
- -
    -
  • - { e.preventDefault(); handleEdit(room); }}> - Edit - -
  • -
  • - { e.preventDefault(); setDeleteConfirm({ show: true, id: room.name }); }}> - Delete - -
  • -
+ +
+
+
+
+
    +
  • setShowSidesCategoryModal(true)} + > +
    + + New
    -
-
- -
{room?.sidename}
- {room?.description} -
${room.price.toFixed(2)}
-
+ + {sidesCategoryData?.map((sidesCategory) => ( +
  • handleSidesCategoryClick(sidesCategory?.name)} + style={{ cursor: "pointer" }} + > + menu + {sidesCategory?.sidecategoryname} +
    e.stopPropagation()}> +
    + +
      +
    • + { + e.preventDefault(); + handleSidesCategoryEdit(sidesCategory); + }} + > + Edit + +
    • +
    • + { + e.preventDefault(); + setSidesCategoryDeleteConfirm({ show: true, id: sidesCategory.name }); + }} + > + + Delete + +
    • +
    +
    +
    +
  • + ))} + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    - ); - }) - )} +
    + {loading ? ( + + ) : ( + roomData?.map((room, index) => { + const gradientClass = gradientClasses[index % gradientClasses.length]; + return ( +
    +
    +
    +
    + +
      +
    • + { e.preventDefault(); handleEdit(room); }}> + Edit + +
    • +
    • + { e.preventDefault(); setDeleteConfirm({ show: true, id: room.name }); }}> + Delete + +
    • +
    +
    +
    +
    + +
    {room?.sidename}
    + ${room.price.toFixed(2)} + {/*
    ${room.price.toFixed(2)}
    */} +
    +
    +
    + ); + }) + )} +
    +
    + +
    - {/* Modal */} + + {/* sides category */} + {/* Create/Edit Modal */} + {showSidesCategoryModal && ( +
    +
    +
    +
    +
    + {isSidesCategoryEditMode ? "Edit SidesCategory" : "Create SidesCategory"} +
    + +
    +
    + +
    + + + {sidesCategoryErrors.sidesCategoryname && ( +
    {sidesCategoryErrors.sidesCategoryname}
    + )} +
    + +
    + + + {sidesCategoryErrors.description && ( +
    {sidesCategoryErrors.description}
    + )} +
    + + {/*
    + + + {sidesCategoryErrors.branch && ( +
    {sidesCategoryErrors.branch}
    + )} +
    */} + +
    + +
    + +
    +
    +
    +
    + )} + + {/* Delete Confirmation Modal */} + {sidesCategoryDeleteConfirm.show && ( +
    +
    +
    + +
    +
    +
    Confirm Delete
    + +
    +

    Are you sure you want to delete this sidesCategory?

    +
    + + +
    +
    +
    +
    +
    + )} + + + {/*Sides Modal */} {showModal && (
    diff --git a/src/components/admin/SidesCategoryComponent.jsx b/src/components/admin/SidesCategoryComponent.jsx index af23e8d..d53c0a6 100644 --- a/src/components/admin/SidesCategoryComponent.jsx +++ b/src/components/admin/SidesCategoryComponent.jsx @@ -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 }) => { @@ -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 }); }} > {
    {/* Create/Edit Modal */} - {showModal && ( + {showSidesCategoryModal && (
    - {isEditMode ? "Edit SidesCategory" : "Create SidesCategory"} + {isSidesCategoryEditMode ? "Edit SidesCategory" : "Create SidesCategory"}
    -
    +
    - {errors.sidesCategoryname && ( -
    {errors.sidesCategoryname}
    + {sidesCategoryErrors.sidesCategoryname && ( +
    {sidesCategoryErrors.sidesCategoryname}
    )}
    - {errors.description && ( -
    {errors.description}
    + {sidesCategoryErrors.description && ( +
    {sidesCategoryErrors.description}
    )}
    {/*
    - {errors.branch && ( -
    {errors.branch}
    + {sidesCategoryErrors.branch && ( +
    {sidesCategoryErrors.branch}
    )}
    */}
    @@ -285,7 +285,7 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => { )} {/* Delete Confirmation Modal */} - {deleteConfirm.show && ( + {sidesCategoryDeleteConfirm.show && (
    @@ -296,14 +296,14 @@ const SidesCategoryComponent = ({ sidesCategoryData, getSidesCategory }) => {

    Are you sure you want to delete this sidesCategory?