import React, { useEffect, useState, useRef } from "react"; import styles from "./ItemLister.module.css"; import Item from "./Item"; import Switch from "react-switch"; import { ThreeDots, ColorRing } from "react-loader-spinner"; import { getItemQtyFromCart, updateItemQtyInCart, removeItemFromCart, } from "../helpers/cartHelpers.js"; import { getImageUrl, updateItemAvalilability, updateItemType, deleteItemType, } from "../helpers/itemHelper.js"; import ItemType from "./ItemType.js"; import { createItemType } from "../helpers/itemHelper.js"; const ItemLister = ({ index, indexTotal, itemTypeId, typeVisibility = true, refreshTotal, shopId, shopOwnerId, user, typeName, typeImage, setShopItems, itemList, forCart, forInvoice, moveItemTypeUp, moveItemTypeDown, isEditMode, handleCreateItem, handleUpdateItem, handleUnEdit, beingEditedType, setBeingEditedType, alwaysEdit, }) => { const [items, setItems] = useState( itemList.map((item) => ({ ...item, qty: getItemQtyFromCart(shopId, item.itemId), })) ); useEffect(() => { setItems( itemList.map((item) => ({ ...item, qty: getItemQtyFromCart(shopId, item.itemId), })) ); }, [itemList]); const [isVisible, setIsVisible] = useState(typeVisibility); const [isEdit, setIsEditing] = useState(alwaysEdit); const [isEditItem, setisEditItem] = useState(0); const [isAddingNewItem, setIsAddingNewItem] = useState(alwaysEdit); const [editedTypeName, setEditedTypeName] = useState(typeName); const typeNameInputRef = useRef(null); const [itemsToCreate, setItemsToCreate] = useState([]); const [itemsToUpdate, setItemsToUpdate] = useState([]); const [isFirstStep, setIsFirstStep] = useState(true); const handlePlusClick = (itemId) => { const updatedItems = items.map((item) => { if (item.itemId === itemId) { const newQty = item.qty + 1; updateItemQtyInCart(shopId, itemId, newQty); if (forCart) refreshTotal(); return { ...item, qty: newQty }; } return item; }); setItems(updatedItems); }; const handleNegativeClick = (itemId) => { const updatedItems = items .map((item) => { if (item.itemId === itemId && item.qty > 0) { const newQty = item.qty - 1; updateItemQtyInCart(shopId, itemId, newQty); if (forCart) { refreshTotal(); return newQty > 0 ? { ...item, qty: newQty } : null; } else return { ...item, qty: newQty }; } return item; }) .filter((item) => item !== null); setItems(updatedItems); }; const handleRemoveClick = (itemId) => { removeItemFromCart(shopId, itemId); const updatedItems = items.filter((item) => item.itemId !== itemId); setItems(updatedItems); if (!forCart) return; refreshTotal(); }; const toggleEditTypeItem = () => { setIsEditing((prev) => !prev); }; const handleRemoveType = async () => { try { await deleteItemType(shopId, itemTypeId); setIsEditing(false); // Optionally, you might want to refresh or update the parent component state here } catch (error) { console.error("Failed to delete item type:", error); } }; useEffect(() => { if (beingEditedType == itemTypeId) return; setisEditItem(0); setIsAddingNewItem(false); }, [beingEditedType]); const toggleAddNewItem = () => { setBeingEditedType(itemTypeId); setIsAddingNewItem((prev) => !prev); setisEditItem(0); }; const editItem = (itemId) => { setBeingEditedType(itemTypeId); setIsAddingNewItem(false); setisEditItem(itemId); }; const [selectedImage, setSelectedImage] = useState(null); const [previewUrl, setPreviewUrl] = useState(getImageUrl(typeImage)); // useEffect(() => { // if (!selectedImage) { // setPreviewUrl(getImageUrl(typeImage)); // } else { // setPreviewUrl(selectedImage); // } // console.log(selectedImage); // }, [selectedImage]); const handleImageChange = (previewUrl, selectedImage) => { setSelectedImage(selectedImage); console.log(selectedImage); console.log(previewUrl); setPreviewUrl(previewUrl); }; const onCreateItem = async (itemName, itemPrice, selectedImage, previewUrl) => { if (isEdit) setItemsToCreate((prevItems) => [ ...prevItems, { itemId: -(prevItems.length + 1), name: itemName, price: itemPrice, selectedImage, image: previewUrl, availability: true }, ]); else { const newItem = await handleCreateItem(itemTypeId, itemName, itemPrice, selectedImage); console.log(newItem) if (newItem) { setShopItems((prevShopItems) => { return prevShopItems.map((itemType) => { // Check if the itemTypeId matches if (itemType.itemTypeId === itemTypeId) { return { ...itemType, itemList: [...itemType.itemList, newItem], // Add the new item to the itemList }; } return itemType; // Return the unchanged item type }); }); } } console.log(items); console.log(itemsToCreate); setIsAddingNewItem(false); }; const updateItemInCreate = ( itemId, name, price, selectedImage, previewUrl ) => { setItemsToCreate((prevItems) => prevItems.map((item) => item.itemId === itemId ? { ...item, name, price, selectedImage, image: previewUrl } : item ) ); setisEditItem(0); }; const onUpdateItem = (itemId, name, price, image) => { if (isEdit) setItemsToUpdate((prev) => [...prev, { itemId, name, price, image }]); else handleUpdateItem(itemId, name, price, image); console.log(itemsToUpdate); }; const handleChange = async (itemId) => { console.log(itemId); const itemIndex = items.findIndex((item) => item.itemId === itemId); if (itemIndex === -1) return; // Item not found // Create a copy of the current items array const updatedItems = [...items]; const item = updatedItems[itemIndex]; // Toggle the availability locally const newAvailability = !item.availability; updatedItems[itemIndex] = { ...item, availability: newAvailability, }; // Update the state with the local change setItems(updatedItems); if (isEdit) { // If isEdit, add item to the list of items to update setItemsToUpdate((prev) => [...prev, { itemId, newAvailability }]); } else { await executeUpdateAvailability(itemId, newAvailability); // Update shopItems state setShopItems((prevShopItems) => { return prevShopItems.map((itemType) => { // Map through the itemList to find the item by itemId and update its availability const updatedItemList = itemType.itemList.map((item) => { if (item.itemId === itemId) { return { ...item, availability: newAvailability, // Update the availability }; } return item; // Return unchanged item }); return { ...itemType, itemList: updatedItemList, // Update the itemList with modified item }; }); }); } console.log(itemsToUpdate); }; const executeUpdateAvailability = async ( itemId, newAvailability, updatedItems, itemIndex ) => { try { console.log(itemId + newAvailability); const response = await updateItemAvalilability(itemId, newAvailability); const updatedItem = response; console.log(updatedItem); // Update only the specified item in the state setItems((prevItems) => prevItems.map((prevItem) => prevItem.itemId === itemId ? updatedItem : prevItem ) ); } catch (error) { console.error("Error updating item availability:", error); updatedItems[itemIndex].availability = !newAvailability; // revert back setItems(updatedItems); } }; const handleSaveType = async () => { try { console.log(isVisible); if (itemTypeId) { // Call the updateItemType function const updatedItemType = await updateItemType( shopId, itemTypeId, typeNameInputRef.current.value, previewUrl, selectedImage, isVisible ); // Update shopItems state setShopItems((prevShopItems) => { return prevShopItems.map((itemType) => { if (itemType.itemTypeId === itemTypeId) { return { ...itemType, name: updatedItemType.name || typeNameInputRef.current.value, // Update name if provided image: updatedItemType.image || itemType.image, // Update image if provided visibility: updatedItemType.visibility !== undefined ? updatedItemType.visibility : isVisible, // Update visibility if provided }; } return itemType; // Return unchanged item type }); }); // Iterate through itemsToUpdate and call the API for (const { itemId, newAvailability, name, price, image, } of itemsToUpdate) { if (newAvailability != undefined) { await executeUpdateAvailability( itemId, newAvailability, items, items.findIndex((item) => item.itemId === itemId) ); // Update shopItems state setShopItems((prevShopItems) => { return prevShopItems.map((itemType) => { // Map through the itemList to find the item by itemId and update its availability const updatedItemList = itemType.itemList.map((item) => { if (item.itemId === itemId) { return { ...item, availability: newAvailability, // Update the availability }; } return item; // Return unchanged item }); return { ...itemType, itemList: updatedItemList, // Update the itemList with modified item }; }); }); } else { // Call the handleUpdateItem function const updatedItem = await handleUpdateItem(itemId, name, price, image); // Update shopItems state setShopItems((prevShopItems) => { return prevShopItems.map((itemType) => { // Map through the itemList to find the item by itemId and update it const updatedItemList = itemType.itemList.map((item) => { if (item.itemId === itemId) { return { ...item, name: updatedItem.name || name, // Update fields as needed price: updatedItem.price || price, image: updatedItem.image || image, }; } return item; // Return unchanged item }); return { ...itemType, itemList: updatedItemList, // Update the itemList with modified item }; }); }); } } console.log(itemsToCreate) for (const { name, price, selectedImage } of itemsToCreate) { const newItem = await handleCreateItem(itemTypeId, name, price, selectedImage); console.log(newItem) if (newItem) { setShopItems((prevShopItems) => { return prevShopItems.map((itemType) => { // Check if the itemTypeId matches if (itemType.itemTypeId === itemTypeId) { return { ...itemType, itemList: [...itemType.itemList, newItem], // Add the new item to the itemList }; } return itemType; // Return the unchanged item type }); }); } } } else { console.log(selectedImage); console.log(previewUrl); try { // Call the createItemType function const newItemType = await createItemType(shopId, editedTypeName, selectedImage, previewUrl); // Update shopItems state with the new item type setShopItems((prevShopItems) => [ ...prevShopItems, { itemTypeId: newItemType.itemTypeId, // API should return this name: newItemType.name, image: newItemType.image, cafeId: shopId, // Adjust as necessary itemList: [], // Start with an empty itemList }, ]); // Loop through itemsToCreate and create each item for (const { name, price, selectedImage } of itemsToCreate) { // Call handleCreateItem to create a new item const newItem = await handleCreateItem(newItemType.itemTypeId, name, price, selectedImage); // If the item was created successfully, update the shopItems state if (newItem) { setShopItems((prevShopItems) => prevShopItems.map((itemType) => { if (itemType.itemTypeId === newItemType.itemTypeId) { return { ...itemType, itemList: [...itemType.itemList, newItem], // Add the new item to the itemList }; } return itemType; // Return unchanged item type }) ); } } } catch (error) { console.error("Error creating item type or items:", error); } } // Clear the itemsToUpdate after saving setItemsToCreate([]); setItemsToUpdate([]); setIsEditing(false); if (handleUnEdit) handleUnEdit(); } catch (error) { console.error("Failed to save item type:", error); } }; const resetItems = () => { // Create a copy of the current items to revert const updatedItems = [...items]; // Iterate over itemsToUpdate and reset the availability itemsToUpdate.forEach(({ itemId, newAvailability }) => { const itemIndex = updatedItems.findIndex( (item) => item.itemId === itemId ); if (itemIndex !== -1) { updatedItems[itemIndex].availability = !newAvailability; // revert back to original } }); // Update the items state and clear itemsToUpdate setItems(updatedItems); setItemsToUpdate([]); setIsEditing(false); if (handleUnEdit) handleUnEdit(); setIsFirstStep(true); }; return ( <> {(items.length > 0 || (user && (user.cafeId == shopId || user.userId == shopOwnerId))) && (
{(isEdit && isFirstStep || !isEdit) &&
{isEdit && } setEditedTypeName(e.target.value)} disabled={!isEdit} /> {isEditMode && !isEdit && ( <>
moveItemTypeUp(itemTypeId)} // Move onClick here for the whole div >
moveItemTypeDown(itemTypeId)} // Move onClick here for the whole div >
)}
} {isEdit && isFirstStep && ( <>
handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/addnew.png")} /> {/* {typeImage != null && !previewUrl.includes(typeImage) && ( handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl(typeImage)} /> )} */} handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/beverage4.jpg")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/beverage1.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/beverage2.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/beverage3.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/snack5.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/dessert1.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/dessert2.jpg")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/food4.jpg")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/food1.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/food2.jpg")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/food3.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/packet1.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/packet2.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/snack1.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/snack2.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/snack3.png")} /> handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl("uploads/assets/snack4.png")} /> {Array.from({ length: 16 }, (_, index) => { const sampleNumber = index + 1; // To get numbers from 1 to 16 return ( handleImageChange(previewUrl, selectedImage) } imageUrl={getImageUrl(`uploads/samples/sample (${sampleNumber}).png`)} /> ); })}
)} {(isEdit && !isFirstStep || !isEdit) && <> {isEdit &&
setIsFirstStep(true)}>

{items && items.length < 1 ? 'Buat item' :'Daftar item'}

}
{user && ( user.userId == shopOwnerId || user.cafeId == shopId) && isEditMode && ( <> {!isAddingNewItem && ( )} {isAddingNewItem && ( <> )} )} {itemsToCreate.map((item) => { return !forCart || (forCart && item.qty > 0) ? ( <> {isEditItem == item.itemId && ( )}
{isEditMode && isEditItem != item.itemId && (
{isEditMode && ( handleChange(item.itemId)} checked={item.availability} /> )}

 {item.availability ? "tersedia" : "tidak tersedia"}  

editItem(item.itemId)} >
)} handlePlusClick(item.itemId)} onNegativeClick={() => handleNegativeClick(item.itemId)} onRemoveClick={() => handleRemoveClick(item.itemId)} isBeingEdit={isEditItem == item.itemId} isAvailable={item.availability} handleUpdateItem={(name, price, image) => updateItemInCreate(item.itemId, name, price, image) } />
) : null; })} {items.map((item) => { return !forCart || (forCart && item.qty > 0) ? ( <> {isEditItem == item.itemId && ( )}
{isEditMode && isEditItem != item.itemId && (
{isEditMode && ( handleChange(item.itemId)} checked={item.availability} /> )}

 {item.availability ? "tersedia" : "tidak tersedia"} 

editItem(item.itemId)} >
)} handlePlusClick(item.itemId)} onNegativeClick={() => handleNegativeClick(item.itemId)} onRemoveClick={() => handleRemoveClick(item.itemId)} isBeingEdit={isEditItem == item.itemId} isAvailable={item.availability} handleUpdateItem={(name, price, image) => onUpdateItem(item.itemId, name, price, image) } />
) : null; })} {user && user.roleId == 1 && user.userId == shopOwnerId && isEdit && ( <> {/* */} )}
} {isEdit && (
Pengaturan
sembunyikan semua setIsVisible(!isVisible)} checked={!isVisible} />
Kembali
)}
)} ); }; export default ItemLister;