1009 lines
42 KiB
JavaScript
1009 lines
42 KiB
JavaScript
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))) && (
|
|
<div
|
|
key={itemTypeId}
|
|
className={`${styles["item-lister"]} ${isEdit ? styles["fullscreen"] : ""
|
|
}`}
|
|
style={{ paddingBottom: isEdit ? "258px" : "" }}
|
|
>
|
|
|
|
{(isEdit && isFirstStep || !isEdit) &&
|
|
<div className={styles["title-container"]}>
|
|
{isEdit && <ItemType blank={true} imageUrl={previewUrl} />}
|
|
<input
|
|
ref={typeNameInputRef}
|
|
className={`${styles.title} ${isEdit ? styles.border : styles.noborder
|
|
}`}
|
|
value={editedTypeName}
|
|
placeholder="Nama tipe"
|
|
onChange={(e) => setEditedTypeName(e.target.value)}
|
|
disabled={!isEdit}
|
|
/>
|
|
{isEditMode && !isEdit && (
|
|
<>
|
|
<div
|
|
style={{
|
|
width: '32px',
|
|
height: '32px', // Add a height to the div
|
|
display: 'flex', // Use flexbox
|
|
justifyContent: 'center', // Center horizontally
|
|
alignItems: 'center', // Center vertically
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={index == 0 ? null : () => moveItemTypeUp(itemTypeId)} // Move onClick here for the whole div
|
|
>
|
|
<svg
|
|
viewBox="0 0 16 16"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="#000000"
|
|
style={{ width: '100%', height: '100%' }} // Ensure SVG fits the div
|
|
>
|
|
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
|
|
<g id="SVGRepo_iconCarrier">
|
|
<path d="m 1 11 c 0 -0.265625 0.105469 -0.519531 0.292969 -0.707031 l 6 -6 c 0.390625 -0.390625 1.023437 -0.390625 1.414062 0 l 6 6 c 0.1875 0.1875 0.292969 0.441406 0.292969 0.707031 s -0.105469 0.519531 -0.292969 0.707031 c -0.390625 0.390625 -1.023437 0.390625 -1.414062 0 l -5.292969 -5.292969 l -5.292969 5.292969 c -0.390625 0.390625 -1.023437 0.390625 -1.414062 0 c -0.1875 -0.1875 -0.292969 -0.441406 -0.292969 -0.707031 z m 0 0" fill={index === 0 ? "gray" : "#2e3436"}></path>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
<div
|
|
style={{
|
|
width: '32px',
|
|
height: '32px', // Add a height to the div
|
|
display: 'flex', // Use flexbox
|
|
justifyContent: 'center', // Center horizontally
|
|
alignItems: 'center', // Center vertically
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={index == indexTotal - 1 ? null : () => moveItemTypeDown(itemTypeId)} // Move onClick here for the whole div
|
|
>
|
|
<svg
|
|
viewBox="0 0 16 16"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="#000000"
|
|
style={{ width: '100%', height: '100%' }} // Ensure SVG fits the div
|
|
>
|
|
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
|
|
<g id="SVGRepo_iconCarrier">
|
|
<path d="m 1 5 c 0 -0.265625 0.105469 -0.519531 0.292969 -0.707031 c 0.390625 -0.390625 1.023437 -0.390625 1.414062 0 l 5.292969 5.292969 l 5.292969 -5.292969 c 0.390625 -0.390625 1.023437 -0.390625 1.414062 0 c 0.1875 0.1875 0.292969 0.441406 0.292969 0.707031 s -0.105469 0.519531 -0.292969 0.707031 l -6 6 c -0.390625 0.390625 -1.023437 0.390625 -1.414062 0 l -6 -6 c -0.1875 -0.1875 -0.292969 -0.441406 -0.292969 -0.707031 z m 0 0" fill={index === indexTotal - 1 ? "gray" : "#2e3436"}></path>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
|
|
<div
|
|
style={{
|
|
width: '32px',
|
|
height: '32px', // Add a height to the div
|
|
display: 'flex', // Use flexbox
|
|
justifyContent: 'center', // Center horizontally
|
|
alignItems: 'center', // Center vertically
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={toggleEditTypeItem} // Move onClick here for the whole div
|
|
>
|
|
<svg
|
|
fill="#000000"
|
|
viewBox="0 0 32 32"
|
|
style={{ fillRule: 'evenodd', clipRule: 'evenodd', strokeLinejoin: 'round', strokeMiterlimit: 2 }}
|
|
version="1.1"
|
|
xmlSpace="preserve"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
xmlnsSerif="http://www.serif.com/"
|
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
|
>
|
|
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
|
|
<g id="SVGRepo_iconCarrier">
|
|
<path d="M12.965,5.462c0,-0 -2.584,0.004 -4.979,0.008c-3.034,0.006 -5.49,2.467 -5.49,5.5l0,13.03c0,1.459 0.579,2.858 1.611,3.889c1.031,1.032 2.43,1.611 3.889,1.611l13.003,0c3.038,-0 5.5,-2.462 5.5,-5.5c0,-2.405 0,-5.004 0,-5.004c0,-0.828 -0.672,-1.5 -1.5,-1.5c-0.827,-0 -1.5,0.672 -1.5,1.5l0,5.004c0,1.381 -1.119,2.5 -2.5,2.5l-13.003,0c-0.663,-0 -1.299,-0.263 -1.768,-0.732c-0.469,-0.469 -0.732,-1.105 -0.732,-1.768l0,-13.03c0,-1.379 1.117,-2.497 2.496,-2.5c2.394,-0.004 4.979,-0.008 4.979,-0.008c0.828,-0.002 1.498,-0.675 1.497,-1.503c-0.001,-0.828 -0.675,-1.499 -1.503,-1.497Z"></path>
|
|
<path d="M20.046,6.411l-6.845,6.846c-0.137,0.137 -0.232,0.311 -0.271,0.501l-1.081,5.152c-0.069,0.329 0.032,0.671 0.268,0.909c0.237,0.239 0.577,0.343 0.907,0.277l5.194,-1.038c0.193,-0.039 0.371,-0.134 0.511,-0.274l6.845,-6.845l-5.528,-5.528Zm1.415,-1.414l5.527,5.528l1.112,-1.111c1.526,-1.527 1.526,-4.001 -0,-5.527c-0.001,-0 -0.001,-0.001 -0.001,-0.001c-1.527,-1.526 -4.001,-1.526 -5.527,-0l-1.111,1.111Z"></path>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
|
|
</>
|
|
)}
|
|
</div>
|
|
}
|
|
{isEdit && isFirstStep && (
|
|
<>
|
|
<div className={styles["grid-container"]}>
|
|
<ItemType
|
|
rectangular={true}
|
|
blank={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/addnew.png")}
|
|
/>
|
|
{/* {typeImage != null && !previewUrl.includes(typeImage) && (
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl(typeImage)}
|
|
/>
|
|
)} */}
|
|
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/beverage4.jpg")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/beverage1.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/beverage2.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/beverage3.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/snack5.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/dessert1.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/dessert2.jpg")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/food4.jpg")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/food1.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/food2.jpg")}
|
|
/>
|
|
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/food3.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/packet1.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/packet2.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/snack1.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/snack2.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl("uploads/assets/snack3.png")}
|
|
/>
|
|
<ItemType
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
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 (
|
|
<ItemType
|
|
key={sampleNumber}
|
|
rectangular={true}
|
|
onClick={(previewUrl, selectedImage) =>
|
|
handleImageChange(previewUrl, selectedImage)
|
|
}
|
|
imageUrl={getImageUrl(`uploads/samples/sample (${sampleNumber}).png`)}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
<button onClick={() => setIsFirstStep(false)} style={{ width: '100%', height: '40px', borderRadius: '20px' }}>selanjutnya</button>
|
|
</>
|
|
)}
|
|
{(isEdit && !isFirstStep || !isEdit) &&
|
|
<>
|
|
{isEdit && <div style={{ display: 'flex', justifyContent: 'flex-start' }}><div style={{ marginTop: '49px', marginRight: '10px', marginLeft: '10px' }} onClick={() => setIsFirstStep(true)}><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 512 512"><path d="M48,256c0,114.87,93.13,208,208,208s208-93.13,208-208S370.87,48,256,48,48,141.13,48,256Zm212.65-91.36a16,16,0,0,1,.09,22.63L208.42,240H342a16,16,0,0,1,0,32H208.42l52.32,52.73A16,16,0,1,1,238,347.27l-79.39-80a16,16,0,0,1,0-22.54l79.39-80A16,16,0,0,1,260.65,164.64Z" /></svg></div>
|
|
<h2 className={styles["item-list-title"]}>{items && items.length < 1 ? 'Buat item' : 'Daftar item'}</h2></div>}
|
|
<div className={styles["item-list"]}>
|
|
{user && (
|
|
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
|
isEditMode && (
|
|
<>
|
|
{!isAddingNewItem && (
|
|
<button
|
|
className={styles["add-item-button"]}
|
|
onClick={toggleAddNewItem}
|
|
style={{
|
|
display: "inline-block",
|
|
height: "120px",
|
|
fontSize: "20px",
|
|
}}
|
|
>
|
|
Tambah item +
|
|
</button>
|
|
)}
|
|
{isAddingNewItem && (
|
|
<>
|
|
<button
|
|
className={styles["add-item-button"]}
|
|
onClick={toggleAddNewItem}
|
|
style={{ display: "inline-block" }}
|
|
>
|
|
batal
|
|
</button>
|
|
<Item blank={true} handleCreateItem={onCreateItem} />
|
|
</>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{itemsToCreate.map((item) => {
|
|
return !forCart || (forCart && item.qty > 0) ? (
|
|
<>
|
|
{isEditItem == item.itemId && (
|
|
<button
|
|
className={styles["add-item-button"]}
|
|
onClick={() => editItem(0)}
|
|
style={{ display: "inline-block" }}
|
|
>
|
|
batal
|
|
</button>
|
|
)}
|
|
<div className={styles["itemWrapper"]}>
|
|
{isEditMode && isEditItem != item.itemId && (
|
|
<div className={styles["editModeLayout"]}>
|
|
{isEditMode && (
|
|
<Switch
|
|
onChange={() => handleChange(item.itemId)}
|
|
checked={item.availability}
|
|
/>
|
|
)}
|
|
<h3>
|
|
{item.availability ? "Tersedia" : "Tidak tersedia"}
|
|
</h3>
|
|
<div
|
|
style={{
|
|
width: '32px',
|
|
height: '32px', // Add a height to the div
|
|
display: 'flex', // Use flexbox
|
|
justifyContent: 'center', // Center horizontally
|
|
alignItems: 'center', // Center vertically
|
|
cursor: 'pointer'
|
|
}}
|
|
onClick={() => editItem(item.itemId)}
|
|
>
|
|
<svg
|
|
fill="white"
|
|
viewBox="0 0 32 32"
|
|
style={{ fillRule: 'evenodd', clipRule: 'evenodd', strokeLinejoin: 'round', strokeMiterlimit: 2 }}
|
|
version="1.1"
|
|
xmlSpace="preserve"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
xmlnsSerif="http://www.serif.com/"
|
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
|
>
|
|
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
|
|
<g id="SVGRepo_iconCarrier">
|
|
<path d="M12.965,5.462c0,-0 -2.584,0.004 -4.979,0.008c-3.034,0.006 -5.49,2.467 -5.49,5.5l0,13.03c0,1.459 0.579,2.858 1.611,3.889c1.031,1.032 2.43,1.611 3.889,1.611l13.003,0c3.038,-0 5.5,-2.462 5.5,-5.5c0,-2.405 0,-5.004 0,-5.004c0,-0.828 -0.672,-1.5 -1.5,-1.5c-0.827,-0 -1.5,0.672 -1.5,1.5l0,5.004c0,1.381 -1.119,2.5 -2.5,2.5l-13.003,0c-0.663,-0 -1.299,-0.263 -1.768,-0.732c-0.469,-0.469 -0.732,-1.105 -0.732,-1.768l0,-13.03c0,-1.379 1.117,-2.497 2.496,-2.5c2.394,-0.004 4.979,-0.008 4.979,-0.008c0.828,-0.002 1.498,-0.675 1.497,-1.503c-0.001,-0.828 -0.675,-1.499 -1.503,-1.497Z"></path>
|
|
<path d="M20.046,6.411l-6.845,6.846c-0.137,0.137 -0.232,0.311 -0.271,0.501l-1.081,5.152c-0.069,0.329 0.032,0.671 0.268,0.909c0.237,0.239 0.577,0.343 0.907,0.277l5.194,-1.038c0.193,-0.039 0.371,-0.134 0.511,-0.274l6.845,-6.845l-5.528,-5.528Zm1.415,-1.414l5.527,5.528l1.112,-1.111c1.526,-1.527 1.526,-4.001 -0,-5.527c-0.001,-0 -0.001,-0.001 -0.001,-0.001c-1.527,-1.526 -4.001,-1.526 -5.527,-0l-1.111,1.111Z"></path>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<Item
|
|
key={item.itemId}
|
|
forCart={forCart}
|
|
forInvoice={forInvoice}
|
|
name={item.name}
|
|
price={item.price}
|
|
qty={item.qty}
|
|
imageUrl={item.image}
|
|
imageFile={item.selectedImage}
|
|
onPlusClick={() => 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)
|
|
}
|
|
/>
|
|
</div>
|
|
</>
|
|
) : null;
|
|
})}
|
|
|
|
{items.map((item) => {
|
|
return !forCart || (forCart && item.qty > 0) ? (
|
|
<>
|
|
{isEditItem == item.itemId && (
|
|
<button
|
|
className={styles["add-item-button"]}
|
|
onClick={() => editItem(0)}
|
|
style={{ display: "inline-block" }}
|
|
>
|
|
batal
|
|
</button>
|
|
)}
|
|
<div className={styles["itemWrapper"]}>
|
|
{isEditMode && isEditItem != item.itemId && (
|
|
<div className={styles["editModeLayout"]}>
|
|
<div style={{display: 'flex', alignItems: 'center', height: '40px', marginLeft: '7.5vw'}}>
|
|
{isEditMode && (
|
|
<Switch
|
|
onChange={() => handleChange(item.itemId)}
|
|
checked={item.availability}
|
|
/>
|
|
)}
|
|
<h3>
|
|
{item.availability ? "Tersedia" : "Tidak tersedia"}
|
|
</h3>
|
|
</div>
|
|
|
|
<div onClick={() => editItem(item.itemId)} style={{display: 'flex', alignItems: 'center', height: '40px', marginRight: '7.5vw'}}>
|
|
<div
|
|
style={{
|
|
width: '32px',
|
|
height: '32px', // Add a height to the div
|
|
display: 'flex', // Use flexbox
|
|
justifyContent: 'center', // Center horizontally
|
|
alignItems: 'center', // Center vertically
|
|
cursor: 'pointer'
|
|
}}
|
|
>
|
|
<svg
|
|
fill="white"
|
|
viewBox="0 0 32 32"
|
|
style={{ fillRule: 'evenodd', clipRule: 'evenodd', strokeLinejoin: 'round', strokeMiterlimit: 2 }}
|
|
version="1.1"
|
|
xmlSpace="preserve"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
xmlnsSerif="http://www.serif.com/"
|
|
xmlnsXlink="http://www.w3.org/1999/xlink"
|
|
>
|
|
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
<g id="SVGRepo_tracerCarrier" strokeLinecap="round" strokeLinejoin="round"></g>
|
|
<g id="SVGRepo_iconCarrier">
|
|
<path d="M12.965,5.462c0,-0 -2.584,0.004 -4.979,0.008c-3.034,0.006 -5.49,2.467 -5.49,5.5l0,13.03c0,1.459 0.579,2.858 1.611,3.889c1.031,1.032 2.43,1.611 3.889,1.611l13.003,0c3.038,-0 5.5,-2.462 5.5,-5.5c0,-2.405 0,-5.004 0,-5.004c0,-0.828 -0.672,-1.5 -1.5,-1.5c-0.827,-0 -1.5,0.672 -1.5,1.5l0,5.004c0,1.381 -1.119,2.5 -2.5,2.5l-13.003,0c-0.663,-0 -1.299,-0.263 -1.768,-0.732c-0.469,-0.469 -0.732,-1.105 -0.732,-1.768l0,-13.03c0,-1.379 1.117,-2.497 2.496,-2.5c2.394,-0.004 4.979,-0.008 4.979,-0.008c0.828,-0.002 1.498,-0.675 1.497,-1.503c-0.001,-0.828 -0.675,-1.499 -1.503,-1.497Z"></path>
|
|
<path d="M20.046,6.411l-6.845,6.846c-0.137,0.137 -0.232,0.311 -0.271,0.501l-1.081,5.152c-0.069,0.329 0.032,0.671 0.268,0.909c0.237,0.239 0.577,0.343 0.907,0.277l5.194,-1.038c0.193,-0.039 0.371,-0.134 0.511,-0.274l6.845,-6.845l-5.528,-5.528Zm1.415,-1.414l5.527,5.528l1.112,-1.111c1.526,-1.527 1.526,-4.001 -0,-5.527c-0.001,-0 -0.001,-0.001 -0.001,-0.001c-1.527,-1.526 -4.001,-1.526 -5.527,-0l-1.111,1.111Z"></path>
|
|
</g>
|
|
</svg>
|
|
</div>
|
|
<h3>Edit item</h3>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<Item
|
|
key={item.itemId}
|
|
forCart={forCart}
|
|
forInvoice={forInvoice}
|
|
name={item.name}
|
|
price={item.price}
|
|
qty={item.qty}
|
|
imageUrl={
|
|
itemTypeId ? getImageUrl(item.image) : item.image
|
|
}
|
|
onPlusClick={() => 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)
|
|
}
|
|
/>
|
|
</div>
|
|
</>
|
|
) : null;
|
|
})}
|
|
|
|
{user &&
|
|
user.roleId == 1 &&
|
|
user.userId == shopOwnerId &&
|
|
isEdit && (
|
|
<>
|
|
{/* <button
|
|
className={styles["add-item-button"]}
|
|
onClick={handleRemoveType}
|
|
>
|
|
Remove
|
|
</button> */}
|
|
</>
|
|
)}
|
|
|
|
</div>
|
|
</>
|
|
}
|
|
{isEdit && (
|
|
<div className={styles.PaymentOption}>
|
|
<div className={styles.TotalContainer}>
|
|
<span>Pengaturan</span>
|
|
<span></span>
|
|
</div>
|
|
<div className={styles.OptionContainer}>
|
|
<span>sembunyikan semua</span>
|
|
<span>
|
|
<Switch
|
|
onChange={() => setIsVisible(!isVisible)}
|
|
checked={!isVisible}
|
|
/>
|
|
</span>
|
|
</div>
|
|
<button onClick={handleSaveType} className={styles.PayButton}>
|
|
{false ? (
|
|
<ColorRing height="50" width="50" color="white" />
|
|
) : (
|
|
"Simpan"
|
|
)}
|
|
</button>
|
|
<div className={styles.Pay2Button} onClick={resetItems}>
|
|
Kembali
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ItemLister;
|