This commit is contained in:
zadit
2025-02-17 07:23:32 +07:00
parent df0dbafe18
commit 05c5545cbb
9 changed files with 169 additions and 52 deletions

View File

@@ -6,7 +6,7 @@ const AccountUpdatePage = ({ user, showEmail, onSubmit }) => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
username: user.username || '', username: user.username || '',
email: user.email || '', email: user.email || '',
password: user.password === 'unsetunsetunset' ? '' : user.password || '', password: '●●●●●',
}); });
const [errorMessage, setErrorMessage] = useState(''); const [errorMessage, setErrorMessage] = useState('');
@@ -58,7 +58,7 @@ const AccountUpdatePage = ({ user, showEmail, onSubmit }) => {
<div className={styles.LoginForm}> <div className={styles.LoginForm}>
<div className={`${styles.FormUsername} ${inputtingPassword ? styles.animateForm : wasInputtingPassword ? styles.reverseForm : ''}`}> <div className={`${styles.FormUsername} ${inputtingPassword ? styles.animateForm : wasInputtingPassword ? styles.reverseForm : ''}`}>
<label htmlFor="username" className={styles.usernameLabel}>----------------------------------------------</label> <label htmlFor="username" className={styles.usernameLabel}>--------------------------------------------</label>
<input <input
name="username" name="username"
@@ -85,7 +85,7 @@ const AccountUpdatePage = ({ user, showEmail, onSubmit }) => {
<div className={`${styles.FormPassword} ${inputtingPassword ? styles.animateForm : wasInputtingPassword ? styles.reverseForm : ''}`}> <div className={`${styles.FormPassword} ${inputtingPassword ? styles.animateForm : wasInputtingPassword ? styles.reverseForm : ''}`}>
<span> <span>
<label onClick={() => setInputtingPassword(false)} htmlFor="password" className={styles.usernameLabel}> &lt;--- &lt;-- kembali </label> <label onClick={() => setInputtingPassword(false)} htmlFor="password" className={styles.usernameLabel}> &lt;--- &lt;-- kembali </label>
<label htmlFor="password" className={styles.usernameLabel}> &nbsp; ------------------------- &nbsp; </label> <label htmlFor="password" className={styles.usernameLabel}>-------------------------</label>
</span> </span>
<input <input

View File

@@ -52,6 +52,7 @@
} }
.bussinessName { .bussinessName {
position: absolute; position: absolute;
width: 60vw;
top: 50%; top: 50%;
left: 50%; left: 50%;
color: rgba(0, 0, 0, 0); color: rgba(0, 0, 0, 0);
@@ -80,7 +81,7 @@
} }
.bussinessQR { .bussinessQR {
position: absolute; position: absolute;
height: 480%; height: 570%;
width: 480%; width: 480%;
top: 50%; top: 50%;
left: 50%; left: 50%;
@@ -93,11 +94,84 @@
position: absolute; position: absolute;
top: -321%; top: -321%;
transform: translate(-50%, -80%); transform: translate(-50%, -80%);
display: flex;
align-items: center;
flex-direction: column;
transition: all 0.5s ease-in-out; transition: all 0.5s ease-in-out;
z-index: 201; /* Behind the button */ z-index: 201; /* Behind the button */
} }
.downloadQR{
font-size: 115%;
padding-top: 10px;
background-color: transparent;
color: transparent;
width: 21.7%;
}
.downloadQR.active{
background-color: #8f8f8f;
color: white;
transition: all 0.5s ease-in-out;
}
.trapezoid {
z-index: 201;
position: absolute;
top: 50%;
left: 50%;
color: rgba(0, 0, 0, 0);
transform: translate(-200%, -50%);
width: 0;
height: 80px;
border-top: 70px solid transparent;
border-left: 100px solid transparent;
border-bottom: 70px solid transparent;
transition: all 0.5s ease-in-out;
}
.trapezoid.active {
position: absolute;
top: 50%;
left: 50%;
color: rgba(0, 0, 0, 0);
transform: translate(-200%, -160%);
width: 0;
height: 80px;
border-top: 70px solid transparent;
border-left: 100px solid #EE2E3B;
border-bottom: 70px solid transparent;
transition: all 0.5s ease-in-out;
}
.rightTriangle {
z-index: 201;
position: absolute;
top: 50%;
left: 50%;
color: rgba(0, 0, 0, 0);
transform: translate(-4%, 120%);
width: 0;
height: 0;
border-left: 184px solid transparent;
border-right: 0px solid transparent;
border-bottom: 128px solid #ee2e3b;
transition: all 0.5s ease-in-out;
}
.rightTriangle.active {
position: absolute;
top: 50%;
left: 50%;
color: rgba(0, 0, 0, 0);
transform: translate(-4%, 10%);
width: 0;
height: 0;
border-left: 184px solid transparent;
border-right: 0px solid transparent;
border-bottom: 128px solid #ee2e3b;
transition: all 0.5s ease-in-out;
}
.price { .price {
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -113,7 +187,7 @@
.price.active { .price.active {
position: absolute; position: absolute;
color: rgb(0, 0, 0); color: rgb(0, 0, 0);
transform: translate(-50%, -150%); transform: translate(-50%, -140%);
z-index: 201; /* Behind the button */ z-index: 201; /* Behind the button */
font-size: 3vw; font-size: 3vw;
text-align: center; text-align: center;

View File

@@ -126,7 +126,22 @@ const ButtonWithReplica = ({
console.log(qrisComponent.nmid); // Log the QR value console.log(qrisComponent.nmid); // Log the QR value
Open(); Open();
}; };
const downloadQR = () => {
const imageUrl = "https://dev.api.kedaimaster.com/uploads/1739542152564.jpg"; // Image URL
// Create a new XMLHttpRequest to fetch the image as a Blob
fetch(imageUrl)
.then((response) => response.blob()) // Convert the response to a Blob
.then((blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob); // Create a URL for the Blob
link.download = "QRCode.jpg"; // Set the download filename
link.click(); // Trigger the download
})
.catch((error) => {
console.error("Failed to download the image:", error);
});
}
return ( return (
<div className="container"> <div className="container">
<button <button
@@ -138,13 +153,17 @@ const ButtonWithReplica = ({
</button> </button>
<> <>
<div className={`replica ${isActive ? "active" : ""}`}></div> <div className={`replica ${isActive ? "active" : ""}`}></div>
<div className={`bussinessQR ${isActive ? "active" : ""}`}>
<QRCodeSVG <QRCodeSVG
className={`bussinessQR ${isActive ? "active" : ""}`} width={400}
height={400}
style={{pointerEvents: 'none'}} style={{pointerEvents: 'none'}}
bgColor={"transparent"} bgColor={"transparent"}
fgColor={fgColor} fgColor={fgColor}
value={QRValue} value={QRValue}
/> />
<div onClick={downloadQR} className={`downloadQR ${isActive ? "active" : ""}`} >Download QRIS</div>
</div>
<div className={`bussinessName ${isActive ? "active" : ""}`}> <div className={`bussinessName ${isActive ? "active" : ""}`}>
<h2>{qrisComponent.merchantName}</h2> <h2>{qrisComponent.merchantName}</h2>
{qrisComponent.nmid != "" && <h4>NMID : {qrisComponent.nmid}</h4>} {qrisComponent.nmid != "" && <h4>NMID : {qrisComponent.nmid}</h4>}
@@ -152,6 +171,8 @@ const ButtonWithReplica = ({
<div className={`price ${isActive ? "active" : ""}`}> <div className={`price ${isActive ? "active" : ""}`}>
<h1>{price}</h1> <h1>{price}</h1>
</div> </div>
<div className={`trapezoid ${isActive ? "active" : ""}`}></div>
<div className={`rightTriangle ${isActive ? "active" : ""}`}></div>
</> </>
</div> </div>
); );

View File

@@ -14,7 +14,7 @@ const ItemConfig = ({
handleCreateItem, handleCreateItem,
handleUpdateItem handleUpdateItem
}) => { }) => {
const [selectedImage, setSelectedImage] = useState(imageFile); const [selectedImage, setSelectedImage] = useState();
const [previewUrl, setPreviewUrl] = useState(imageUrl); const [previewUrl, setPreviewUrl] = useState(imageUrl);
const [itemName, setItemName] = useState(initialName); const [itemName, setItemName] = useState(initialName);
const [itemPrice, setItemPrice] = useState(initialPrice); const [itemPrice, setItemPrice] = useState(initialPrice);
@@ -83,7 +83,7 @@ const ItemConfig = ({
handleCreateItem(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice); handleCreateItem(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice);
}; };
const handleUpdate = () => { const handleUpdate = () => {
console.log(itemDescription) console.log(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice)
handleUpdateItem(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice); handleUpdateItem(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice);
}; };

View File

@@ -224,7 +224,7 @@ const ItemLister = ({
); );
setisEditItem(0); setisEditItem(0);
}; };
const onUpdateItem = (itemId, name, price, image, description, promoPrice) => { const onUpdateItem = async (itemId, name, price, image, description, promoPrice) => {
if (isEdit) if (isEdit)
setItemsToUpdate((prev) => [...prev, { itemId, name, price,promoPrice, image, description }]); setItemsToUpdate((prev) => [...prev, { itemId, name, price,promoPrice, image, description }]);
else { else {
@@ -237,24 +237,44 @@ const ItemLister = ({
// Create a copy of the current items array // Create a copy of the current items array
const updatedItems = [...items]; const updatedItems = [...items];
const item = updatedItems[itemIndex]; const item = updatedItems[itemIndex];
console.log(items) console.log(item)
console.log(image)
// Toggle the availability locally // Toggle the availability locally
if(image){ const readImage = (image) => {
const reader = new FileReader(); return new Promise((resolve, reject) => {
reader.onloadend = () => { // Check if image is a valid File or Blob object
updatedItems[itemIndex].selectedImage = reader.result; if (!(image instanceof Blob)) {
console.log(reader.result) return;
}; }
reader.readAsDataURL(image);
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
reader.readAsDataURL(image); // read the image as a data URL
});
};
let newImage = null;
if (image) {
try {
newImage = await readImage(image);
console.log(newImage);
} catch (error) {
console.error("Error reading image:", error);
}
} }
updatedItems[itemIndex] = { updatedItems[itemIndex] = {
itemId: item.itemId, itemId: item.itemId,
name, name,
price, price,
availability: item.availability description: description,
availability: item.availability,
image: image ? newImage : item.image,
selectedImage: image ? newImage : null
}; };
console.log(updatedItems) console.log(updatedItems)
// Update the state with the local change // Update the state with the local change
@@ -800,7 +820,7 @@ const ItemLister = ({
</> </>
)} )}
{(isEdit && !isFirstStep || !isEdit) && {(isEdit && !isFirstStep || !isEdit) &&
<> <div key={randomKey}>
{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> {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>} <h2 className={styles["item-list-title"]}>{items && items.length < 1 ? 'Buat item' : 'Daftar item'}</h2></div>}
<div className={styles["item-list"]}> <div className={styles["item-list"]}>
@@ -835,7 +855,7 @@ const ItemLister = ({
{itemsToCreate.map((item) => { {itemsToCreate.map((item) => {
return !forCart || (forCart && item.qty > 0) ? ( return !forCart || (forCart && item.qty > 0) ? (
<div key={randomKey}> <div>
{isEditItem == item.itemId && ( {isEditItem == item.itemId && (
<ItemConfig <ItemConfig
isBeingEdit={true} isBeingEdit={true}
@@ -937,23 +957,25 @@ const ItemLister = ({
// batal // batal
// </button> // </button>
<ItemConfig <ItemConfig
isBeingEdit={true} isBeingEdit={true}
name={item.name} name={item.name}
price={item.price} price={item.price}
promoPrice={item.promoPrice} promoPrice={item.promoPrice}
description={item.description} description={item.description}
imageUrl={ imageUrl={itemTypeId ? getImageUrl(item.image) : item.image}
itemTypeId ? getImageUrl(item.image) : item.image imageFile={item.selectedImage}
} cancelEdit={() => editItem(0)}
imageFile={item.selectedImage} handleCreateItem={onCreateItem}
cancelEdit={() => editItem(0)} handleUpdateItem={async (name, price, image, description, promoPrice) => {
handleCreateItem={onCreateItem} try {
handleUpdateItem={(name, price, image, description, promoPrice) => { console.log(description);
console.log(description) await onUpdateItem(item.itemId, name, price, image, description, promoPrice);
onUpdateItem(item.itemId, name, price, image, description, promoPrice); } catch (error) {
} console.error("Error updating item:", error);
} }
/> }}
/>
)} )}
<div className={styles["itemWrapper"]}> <div className={styles["itemWrapper"]}>
{isEditMode && isEditItem != item.itemId && ( {isEditMode && isEditItem != item.itemId && (
@@ -1047,7 +1069,7 @@ const ItemLister = ({
)} )}
</div> </div>
</> </div>
} }
{isEdit && ( {isEdit && (
<div className={styles.PaymentOption}> <div className={styles.PaymentOption}>

View File

@@ -121,11 +121,11 @@ export async function updateItem(
selectedImage, selectedImage,
description); description);
const formData = new FormData(); const formData = new FormData();
formData.append("name", name); if(name != null )formData.append("name", name);
formData.append("price", price); if(price != null )formData.append("price", price);
formData.append("image", selectedImage); if(selectedImage != null )formData.append("image", selectedImage);
formData.append("description", description); if(description != null )formData.append("description", description);
formData.append("promoPrice", promoPrice); if(promoPrice != null )formData.append("promoPrice", promoPrice);
const response = await fetch(`${API_BASE_URL}/item/set-item/${itemId}`, { const response = await fetch(`${API_BASE_URL}/item/set-item/${itemId}`, {
method: "PUT", method: "PUT",

View File

@@ -294,7 +294,7 @@ function CafePage({
} }
/> />
))} ))}
{(user.username || cartItemsLength > 0) && {!isEditMode && (user.username || cartItemsLength > 0) &&
<div style={{ marginTop: '10px', height: '40px', position: 'sticky', bottom: '40px', display: 'flex', justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}> <div style={{ marginTop: '10px', height: '40px', position: 'sticky', bottom: '40px', display: 'flex', justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>
{cartItemsLength > 0 && {cartItemsLength > 0 &&
<div onClick={goToCart} style={{ backgroundColor: '#73a585', width: user.username ? '55vw' : '70vw', height: '40px', borderRadius: '30px', display: 'flex', justifyContent: 'space-between', padding: '0 20px' }}> <div onClick={goToCart} style={{ backgroundColor: '#73a585', width: user.username ? '55vw' : '70vw', height: '40px', borderRadius: '30px', display: 'flex', justifyContent: 'space-between', padding: '0 20px' }}>

View File

@@ -571,8 +571,8 @@ const App = ({ forCafe = true, cafeId = -1,
<RoundedRectangle <RoundedRectangle
title={"Total promo"} title={"Total promo"}
loading={loading} loading={loading}
value={'Rp'+analytics?.currentTotals.totalPromoSpend} value={'Rp'+analytics?.currentTotals?.totalPromoSpend}
// width="calc(50% - 10px)" width= {`calc(${!forCafe && selectedCafeId !== 0 ? '50%' : '100%'} - 10px)`}
onClick={() => window.location.href = window.location.origin + '/' + otherCafes.find(item => item.cafeId === selectedCafeId).cafeIdentifyName} onClick={() => window.location.href = window.location.origin + '/' + otherCafes.find(item => item.cafeId === selectedCafeId).cafeIdentifyName}
/> />
)} )}
@@ -580,7 +580,7 @@ const App = ({ forCafe = true, cafeId = -1,
<RoundedRectangle <RoundedRectangle
title={"Kunjungi bisnis"} title={"Kunjungi bisnis"}
loading={loading} loading={loading}
// width="calc(100% - 10px)" width= {`calc(${selectedCafeId !== 0 ? '50%' : '100%'} - 10px)`}
onClick={() => window.location.href = window.location.origin + '/' + otherCafes.find(item => item.cafeId === selectedCafeId).cafeIdentifyName} onClick={() => window.location.href = window.location.origin + '/' + otherCafes.find(item => item.cafeId === selectedCafeId).cafeIdentifyName}
/> />
)} )}

View File

@@ -137,7 +137,7 @@ export default function Transactions({
<div className={styles['receipt-header']}> <div className={styles['receipt-header']}>
<ColorRing className={styles['receipt-logo']} /> <ColorRing className={styles['receipt-logo']} />
<div className={styles['receipt-info']}> <div className={styles['receipt-info']}>
{transaction.payment_type == 'cashless' ? <h3>silahkan bayar QR</h3> : <h3>silahkan bayar ke kasir</h3>} {transaction.payment_type == 'cashless' ? <h3>silahkan bayar dengan QRIS</h3> : <h3>silahkan bayar ke kasir</h3>}
<p>Transaction ID: {transaction.transactionId}</p> <p>Transaction ID: {transaction.transactionId}</p>
<p>Payment Type: {transaction.payment_type}</p> <p>Payment Type: {transaction.payment_type}</p>
</div> </div>