ok
This commit is contained in:
@@ -386,7 +386,7 @@ const Header = ({
|
|||||||
Desain kafe
|
Desain kafe
|
||||||
</Child>
|
</Child>
|
||||||
<Child onClick={() => setModal("edit_tables")}>
|
<Child onClick={() => setModal("edit_tables")}>
|
||||||
Daftar meja
|
QR kedai dan meja
|
||||||
</Child>
|
</Child>
|
||||||
<Child onClick={() => setModal("payment_option")}>
|
<Child onClick={() => setModal("payment_option")}>
|
||||||
Metode pembayaran
|
Metode pembayaran
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ const ItemLister = ({
|
|||||||
const [itemsToCreate, setItemsToCreate] = useState([]);
|
const [itemsToCreate, setItemsToCreate] = useState([]);
|
||||||
const [itemsToUpdate, setItemsToUpdate] = useState([]);
|
const [itemsToUpdate, setItemsToUpdate] = useState([]);
|
||||||
|
|
||||||
|
const [isFirstStep, setIsFirstStep] = useState(true);
|
||||||
|
|
||||||
const handlePlusClick = (itemId) => {
|
const handlePlusClick = (itemId) => {
|
||||||
const updatedItems = items.map((item) => {
|
const updatedItems = items.map((item) => {
|
||||||
if (item.itemId === itemId) {
|
if (item.itemId === itemId) {
|
||||||
@@ -483,6 +485,7 @@ const ItemLister = ({
|
|||||||
setItemsToUpdate([]);
|
setItemsToUpdate([]);
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
if (handleUnEdit) handleUnEdit();
|
if (handleUnEdit) handleUnEdit();
|
||||||
|
setIsFirstStep(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -495,6 +498,8 @@ const ItemLister = ({
|
|||||||
}`}
|
}`}
|
||||||
style={{ paddingBottom: isEdit ? "28vh" : "" }}
|
style={{ paddingBottom: isEdit ? "28vh" : "" }}
|
||||||
>
|
>
|
||||||
|
|
||||||
|
{ (isEdit && isFirstStep || !isEdit) &&
|
||||||
<div className={styles["title-container"]}>
|
<div className={styles["title-container"]}>
|
||||||
{isEdit && <ItemType blank={true} imageUrl={previewUrl} />}
|
{isEdit && <ItemType blank={true} imageUrl={previewUrl} />}
|
||||||
<input
|
<input
|
||||||
@@ -590,7 +595,9 @@ const ItemLister = ({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isEdit && (
|
}
|
||||||
|
{isEdit && isFirstStep && (
|
||||||
|
<>
|
||||||
<div className={styles["grid-container"]}>
|
<div className={styles["grid-container"]}>
|
||||||
<ItemType
|
<ItemType
|
||||||
rectangular={true}
|
rectangular={true}
|
||||||
@@ -744,8 +751,13 @@ const ItemLister = ({
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
<button onClick={()=>setIsFirstStep(false)}style={{width: '100%', height: '40px', borderRadius: '20px'}}>selanjutnya</button>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
|
{ (isEdit && !isFirstStep || !isEdit) &&
|
||||||
|
<>
|
||||||
|
{isEdit && <div style={{display: 'flex', justifyContent: 'space-between'}}><div onClick={()=>setIsFirstStep(true)}style={{color: 'black', fontSize: '50px', width: '30px'}}>←</div>
|
||||||
|
<h3 style={{color: 'black'}}>Daftar item</h3><button style={{visibility: 'hidden', width: '30px'}}></button></div>}
|
||||||
<div className={styles["item-list"]}>
|
<div className={styles["item-list"]}>
|
||||||
{user && (
|
{user && (
|
||||||
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
||||||
@@ -943,15 +955,18 @@ const ItemLister = ({
|
|||||||
user.userId == shopOwnerId &&
|
user.userId == shopOwnerId &&
|
||||||
isEdit && (
|
isEdit && (
|
||||||
<>
|
<>
|
||||||
<button
|
{/* <button
|
||||||
className={styles["add-item-button"]}
|
className={styles["add-item-button"]}
|
||||||
onClick={handleRemoveType}
|
onClick={handleRemoveType}
|
||||||
>
|
>
|
||||||
Remove
|
Remove
|
||||||
</button>
|
</button> */}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
}
|
||||||
{isEdit && (
|
{isEdit && (
|
||||||
<div className={styles.PaymentOption}>
|
<div className={styles.PaymentOption}>
|
||||||
<div className={styles.TotalContainer}>
|
<div className={styles.TotalContainer}>
|
||||||
|
|||||||
@@ -22,11 +22,63 @@
|
|||||||
grid-template-columns: repeat(4, 1fr);
|
grid-template-columns: repeat(4, 1fr);
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
/* padding: 10px; */
|
/* padding: 10px; */
|
||||||
max-height: calc(3 * (25vw - 20px) + 20px);
|
/* max-height: calc(3 * (25vw - 20px) + 20px); */
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: calc(49vw - 20px);
|
height: calc(49vw - 20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (min-height: 0px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 27vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 630px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 27vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 636px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 29vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 650px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 34vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 705px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 37vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 735px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 38vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 759px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 40vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 819px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 44vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-height: 830px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 47vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (min-height: 892px) {
|
||||||
|
.grid-container {
|
||||||
|
height: 49vh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title-container {
|
.title-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -124,7 +176,6 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
margin-bottom: 17px;
|
|
||||||
}
|
}
|
||||||
.OptionContainer {
|
.OptionContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -136,7 +187,6 @@
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
margin-bottom: 17px;
|
|
||||||
}
|
}
|
||||||
.PayButton {
|
.PayButton {
|
||||||
font-family: "Plus Jakarta Sans", sans-serif;
|
font-family: "Plus Jakarta Sans", sans-serif;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const Modal = ({ user, shop, isOpen, onClose, modalContent, setModal, handleMove
|
|||||||
{modalContent === "transaction_end" && <Transaction_end />}
|
{modalContent === "transaction_end" && <Transaction_end />}
|
||||||
{modalContent === "transaction_failed" && <Transaction_failed />}
|
{modalContent === "transaction_failed" && <Transaction_failed />}
|
||||||
{modalContent === "payment_option" && (
|
{modalContent === "payment_option" && (
|
||||||
<PaymentOptions shopId={shop.cafeId} />
|
<PaymentOptions shop={shop} shopId={shop.cafeId} />
|
||||||
)}
|
)}
|
||||||
{modalContent === "add_material" && (
|
{modalContent === "add_material" && (
|
||||||
<MaterialList handleClose={handleOverlayClick} cafeId={shop.cafeId} />
|
<MaterialList handleClose={handleOverlayClick} cafeId={shop.cafeId} />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useRef, useEffect } from "react";
|
import React, { useState, useRef, useEffect } from "react";
|
||||||
import jsQR from "jsqr";
|
import jsQR from "jsqr";
|
||||||
import { getImageUrl } from "../helpers/itemHelper";
|
import { getImageUrl } from "../helpers/itemHelper";
|
||||||
|
import { getTables, updateTable, createTable } from "../helpers/tableHelper";
|
||||||
import {
|
import {
|
||||||
getCafe,
|
getCafe,
|
||||||
saveCafeDetails,
|
saveCafeDetails,
|
||||||
@@ -8,158 +9,195 @@ import {
|
|||||||
} from "../helpers/cafeHelpers";
|
} from "../helpers/cafeHelpers";
|
||||||
import Switch from "react-switch"; // Import the Switch component
|
import Switch from "react-switch"; // Import the Switch component
|
||||||
|
|
||||||
const SetPaymentQr = ({ shopId }) => {
|
const SetPaymentQr = ({ shop }) => {
|
||||||
const [qrPosition, setQrPosition] = useState([50, 50]);
|
const [initialPos, setInitialPos] = useState({
|
||||||
const [qrSize, setQrSize] = useState(50);
|
left: shop.xposition,
|
||||||
const [qrPayment, setQrPayment] = useState();
|
top: shop.yposition,
|
||||||
const [qrCodeDetected, setQrCodeDetected] = useState(false);
|
});
|
||||||
const [isNeedConfirmationState, setIsNeedConfirmationState] = useState(0);
|
const [initialSize, setInitialSize] = useState(shop.scale);
|
||||||
const qrPaymentInputRef = useRef(null);
|
const [bgImageUrl, setBgImageUrl] = useState(getImageUrl(shop.qrBackground));
|
||||||
const qrCodeContainerRef = useRef(null);
|
const qrBackgroundInputRef = useRef(null);
|
||||||
const [cafe, setCafe] = useState({});
|
const shopUrl = window.location.hostname + "/" + shop.cafeId;
|
||||||
|
|
||||||
|
const generateQRCodeUrl = (tableCode) => {
|
||||||
|
if (tableCode != null) {
|
||||||
|
return `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(
|
||||||
|
shopUrl + "/" + tableCode
|
||||||
|
)}`;
|
||||||
|
} else {
|
||||||
|
return `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(
|
||||||
|
shopUrl
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const [isConfig, setIsConfig] = useState(false);
|
||||||
|
const [isViewTables, setIsViewTables] = useState(false);
|
||||||
|
|
||||||
|
const [tables, setTables] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchCafe = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await getCafe(shopId);
|
console.log(shop);
|
||||||
setCafe(response);
|
const fetchedTables = await getTables(shop.cafeId);
|
||||||
setQrPayment(getImageUrl(response.qrPayment));
|
setTables(fetchedTables);
|
||||||
console.log(response.needsConfirmation);
|
|
||||||
|
|
||||||
setIsNeedConfirmationState(response.needsConfirmation === true ? 1 : 0); // Set state based on fetched data
|
|
||||||
setQrPosition([response.xposition, response.yposition]);
|
|
||||||
setQrSize(response.scale);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching cafe:", error);
|
console.error("Error fetching tables:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchCafe();
|
|
||||||
}, [shopId]);
|
|
||||||
|
|
||||||
// Detect QR code when qrPayment updates
|
fetchData();
|
||||||
useEffect(() => {
|
}, [shop.cafeId]);
|
||||||
if (qrPayment) {
|
|
||||||
detectQRCodeFromContainer();
|
const handleSave = () => {
|
||||||
}
|
const qrBackgroundFile = qrBackgroundInputRef.current.files[0]; // Get the selected file for qrBackground
|
||||||
}, [qrPayment]);
|
|
||||||
|
// Prepare the details object
|
||||||
|
const details = {
|
||||||
|
qrSize: initialSize,
|
||||||
|
qrPosition: initialPos,
|
||||||
|
qrBackgroundFile, // Include qrBackground file
|
||||||
|
};
|
||||||
|
|
||||||
|
// Call saveCafeDetails function with the updated details object
|
||||||
|
saveCafeDetails(shop.cafeId, details)
|
||||||
|
.then((response) => {
|
||||||
|
console.log("Cafe details saved:", response);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error saving cafe details:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handlePositionChange = (e) => {
|
||||||
|
const { name, value } = e.target;
|
||||||
|
setInitialPos((prevPosition) => ({
|
||||||
|
...prevPosition,
|
||||||
|
[name]: parseFloat(value).toFixed(2),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSizeChange = (e) => {
|
||||||
|
setInitialSize(parseFloat(e.target.value).toFixed(2));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Handle file input change
|
|
||||||
const handleFileChange = (e) => {
|
const handleFileChange = (e) => {
|
||||||
const file = e.target.files[0];
|
const file = e.target.files[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
const newqrPayment = URL.createObjectURL(file);
|
const newBgImage = URL.createObjectURL(file); // Create a temporary URL for display
|
||||||
setQrPayment(newqrPayment);
|
setBgImageUrl(newBgImage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Detect QR code from the container
|
|
||||||
const detectQRCodeFromContainer = () => {
|
|
||||||
const container = qrCodeContainerRef.current;
|
|
||||||
const canvas = document.createElement("canvas");
|
|
||||||
const context = canvas.getContext("2d");
|
|
||||||
const img = new Image();
|
|
||||||
img.crossOrigin = "Anonymous";
|
|
||||||
img.onload = () => {
|
|
||||||
canvas.width = container.offsetWidth;
|
|
||||||
canvas.height = container.offsetHeight;
|
|
||||||
context.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
||||||
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
|
||||||
const qrCode = jsQR(imageData.data, canvas.width, canvas.height);
|
|
||||||
setQrCodeDetected(!!qrCode);
|
|
||||||
if (qrCode) {
|
|
||||||
console.log("QR Code detected:", qrCode.data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
img.src = qrPayment;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Save cafe details
|
|
||||||
const handleSave = async () => {
|
|
||||||
const qrPaymentFile = qrPaymentInputRef.current.files[0];
|
|
||||||
const details = {
|
|
||||||
qrPosition,
|
|
||||||
qrSize,
|
|
||||||
qrPaymentFile,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await saveCafeDetails(cafe.cafeId, details);
|
|
||||||
console.log("Cafe details saved:", response);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error saving cafe details:", error);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await setConfirmationStatus(cafe.cafeId, isNeedConfirmationState === 1);
|
|
||||||
setIsNeedConfirmationState(response.needsConfirmation ? 1 : 0); // Update state after saving
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
setIsNeedConfirmationState(cafe.needsConfirmation ? 1 : 0); // Fallback to initial value
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle Switch toggle
|
|
||||||
const handleChange = (checked) => {
|
|
||||||
setIsNeedConfirmationState(checked ? 1 : 0); // Toggle state based on the switch
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleError = () => {
|
|
||||||
setQrPayment('https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPsNr0TPq8dHT3nBwDQ6OHQQTrqzVFoeBOmuWfgyErrLbJi6f6CnnYhpNHEvkJ_2X-kyI&usqp=CAU'); // Set your fallback image here
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={styles.container}>
|
<div style={styles.container}>
|
||||||
<h3 style={styles.title}>Konfigurasi pembayaran</h3>
|
<h3 style={styles.title}>Konfigurasi pembayaran</h3>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="qr-code-container"
|
id="qr-code-container"
|
||||||
ref={qrCodeContainerRef}
|
|
||||||
onClick={() => qrPaymentInputRef.current.click()}
|
|
||||||
style={{
|
style={{
|
||||||
|
background: `center center / contain no-repeat url(${bgImageUrl})`,
|
||||||
|
backgroundSize: "contain",
|
||||||
|
border: "1px solid #ddd",
|
||||||
|
|
||||||
...styles.qrCodeContainer,
|
...styles.qrCodeContainer,
|
||||||
backgroundImage: `url(${qrPayment})`,
|
backgroundImage: `url(${bgImageUrl})`,
|
||||||
backgroundPosition: "center",
|
backgroundPosition: "center",
|
||||||
backgroundRepeat: "no-repeat",
|
backgroundRepeat: "no-repeat",
|
||||||
backgroundSize: "contain",
|
backgroundSize: "contain",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={qrPayment}
|
src={generateQRCodeUrl(shopUrl)}
|
||||||
onError={handleError}
|
alt="QR Code"
|
||||||
alt="QR Payment"
|
style={{
|
||||||
style={{ maxWidth: '100%',visibility: 'hidden' }} // hide the img element
|
position: "absolute",
|
||||||
/>
|
width: `${initialSize}%`,
|
||||||
|
left: `${initialPos.left}%`,
|
||||||
|
top: `${initialPos.top}%`,
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
}} />
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
ref={qrPaymentInputRef}
|
ref={qrBackgroundInputRef}
|
||||||
style={{ display: "none" }}
|
style={{ display: "none" }}
|
||||||
onChange={handleFileChange}
|
onChange={handleFileChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.uploadMessage}>
|
<div style={styles.uploadMessage}>
|
||||||
<p>Klik untuk unggah QRIS</p>
|
<p>Klik untuk ganti background</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.resultMessage}>
|
<div style={styles.resultMessage}>
|
||||||
{qrCodeDetected && qrPayment !== 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPsNr0TPq8dHT3nBwDQ6OHQQTrqzVFoeBOmuWfgyErrLbJi6f6CnnYhpNHEvkJ_2X-kyI&usqp=CAU' ? <p>QR terdeteksi</p> : <p>Tidak ada qr terdeteksi</p>}
|
<p onClick={() => setIsConfig(!isConfig)}> {isConfig ? '˅' : '˃'} Konfigurasi QR</p>
|
||||||
{qrCodeDetected && qrPayment !== 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSPsNr0TPq8dHT3nBwDQ6OHQQTrqzVFoeBOmuWfgyErrLbJi6f6CnnYhpNHEvkJ_2X-kyI&usqp=CAU' ? <div
|
<div
|
||||||
onClick={() => qrPaymentInputRef.current.click()} style={styles.uploadButton}>Ganti</div> : <div
|
onClick={() => qrBackgroundInputRef.current.click()} style={styles.uploadButton}>Ganti</div>
|
||||||
onClick={() => qrPaymentInputRef.current.click()} style={styles.uploadButton}>Unggah</div>}
|
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.switchContainer}>
|
<div style={styles.switchContainer}>
|
||||||
<h3>Pengecekan ketersediaan ganda</h3>
|
{isConfig && <>
|
||||||
<p style={styles.description}>
|
<div style={styles.sliderContainer}>
|
||||||
Nyalakan agar kasir memeriksa kembali ketersediaan produk sebelum pelanggan membayar.
|
<label style={styles.label}>
|
||||||
|
QR Code Size:
|
||||||
|
<div style={styles.sliderWrapper}>
|
||||||
|
<span style={styles.labelStart}>10%</span>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
step="0.25"
|
||||||
|
min="10"
|
||||||
|
max="100"
|
||||||
|
value={initialSize}
|
||||||
|
onChange={handleSizeChange}
|
||||||
|
style={styles.input}
|
||||||
|
/>
|
||||||
|
<span style={styles.value}>{initialSize}%</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div style={styles.sliderContainer}>
|
||||||
|
<label style={styles.label}>
|
||||||
|
QR Code Position X:
|
||||||
|
<div style={styles.sliderWrapper}>
|
||||||
|
<span style={styles.labelStart}>0%</span>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
step="0.25"
|
||||||
|
name="left"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
value={initialPos.left}
|
||||||
|
onChange={handlePositionChange}
|
||||||
|
style={styles.input}
|
||||||
|
/>
|
||||||
|
<span style={styles.value}>{initialPos.left}%</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div style={styles.sliderContainer}>
|
||||||
|
<label style={styles.label}>
|
||||||
|
QR Code Position Y:
|
||||||
|
<div style={styles.sliderWrapper}>
|
||||||
|
<span style={styles.labelStart}>0%</span>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
step="0.25"
|
||||||
|
name="top"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
value={initialPos.top}
|
||||||
|
onChange={handlePositionChange}
|
||||||
|
style={styles.input}
|
||||||
|
/>
|
||||||
|
<span style={styles.value}>{initialPos.top}%</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</>}
|
||||||
|
<p style={styles.description} onClick={() => setIsViewTables(!isViewTables)}>
|
||||||
|
{isViewTables ? '˅' : '˃'} Daftar meja
|
||||||
</p>
|
</p>
|
||||||
<Switch
|
|
||||||
onChange={handleChange}
|
|
||||||
checked={isNeedConfirmationState === 1} // Convert to boolean
|
|
||||||
offColor="#888"
|
|
||||||
onColor="#4CAF50"
|
|
||||||
uncheckedIcon={false}
|
|
||||||
checkedIcon={false}
|
|
||||||
height={25}
|
|
||||||
width={50}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={styles.buttonContainer}>
|
<div style={styles.buttonContainer}>
|
||||||
@@ -174,6 +212,7 @@ const SetPaymentQr = ({ shopId }) => {
|
|||||||
// Styles
|
// Styles
|
||||||
const styles = {
|
const styles = {
|
||||||
container: {
|
container: {
|
||||||
|
width: '100%',
|
||||||
backgroundColor: "white",
|
backgroundColor: "white",
|
||||||
padding: "20px",
|
padding: "20px",
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
@@ -230,13 +269,25 @@ const styles = {
|
|||||||
transition: "background-color 0.3s",
|
transition: "background-color 0.3s",
|
||||||
},
|
},
|
||||||
switchContainer: {
|
switchContainer: {
|
||||||
marginTop: "20px",
|
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
margin: "10px 0",
|
margin: "10px 0",
|
||||||
fontSize: "14px",
|
},
|
||||||
color: "#666",
|
sliderContainer: {
|
||||||
|
marginBottom: "20px",
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
display: "block",
|
||||||
|
marginBottom: "10px",
|
||||||
|
},
|
||||||
|
sliderWrapper: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
flex: "1",
|
||||||
|
margin: "0 10px",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ import {
|
|||||||
|
|
||||||
import Switch from "react-switch"; // Import the Switch component
|
import Switch from "react-switch"; // Import the Switch component
|
||||||
import Carousel from '../components/Carousel'
|
import Carousel from '../components/Carousel'
|
||||||
|
import styles from './MaterialList.module.css'; // Import the CSS Module
|
||||||
|
|
||||||
const SetPaymentQr = ({ cafeId }) => {
|
const SetPaymentQr = ({ cafeId }) => {
|
||||||
|
// All your state and logic goes here (unchanged)
|
||||||
const [materials, setMaterials] = useState([]);
|
const [materials, setMaterials] = useState([]);
|
||||||
const [mutations, setMutations] = useState([]);
|
const [mutations, setMutations] = useState([]);
|
||||||
const [newMaterialName, setNewMaterialName] = useState("");
|
const [newMaterialName, setNewMaterialName] = useState("");
|
||||||
@@ -34,6 +36,7 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
const [latestMutation, setLatestMutation] = useState([]);
|
const [latestMutation, setLatestMutation] = useState([]);
|
||||||
const [currentQuantity, setCurrentQuantity] = useState(-1);
|
const [currentQuantity, setCurrentQuantity] = useState(-1);
|
||||||
const [currentPrice, setCurrentPrice] = useState(0);
|
const [currentPrice, setCurrentPrice] = useState(0);
|
||||||
|
const [newPrice, setNewPrice] = useState(0);
|
||||||
const [quantityChange, setQuantityChange] = useState(0);
|
const [quantityChange, setQuantityChange] = useState(0);
|
||||||
const [sortOrder, setSortOrder] = useState("desc");
|
const [sortOrder, setSortOrder] = useState("desc");
|
||||||
const [isEditCurrentPrice, setIsEditCurrentPrice] = useState(false);
|
const [isEditCurrentPrice, setIsEditCurrentPrice] = useState(false);
|
||||||
@@ -53,7 +56,7 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const formattedValue = formatCurrency(e.target.value);
|
const formattedValue = formatCurrency(e.target.value);
|
||||||
setCurrentPrice(formattedValue);
|
setNewPrice(formattedValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -87,11 +90,7 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
fetchMutations();
|
fetchMutations();
|
||||||
}, [cafeId]);
|
}, [cafeId]);
|
||||||
|
|
||||||
const handleSortChange = (e) => {
|
const filteredMutations = mutations.filter((mutation) => mutation.materialId === materials[selectedMaterialIndex]?.materialId) || [];
|
||||||
setSortOrder(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const filteredMutations = mutations.filter((mutation) => mutation.materialId === materials[selectedMaterialIndex].materialId) || [];
|
|
||||||
|
|
||||||
const sortedMutations = filteredMutations
|
const sortedMutations = filteredMutations
|
||||||
.filter((mutation) => mutation.materialId === materials[selectedMaterialIndex].materialId)
|
.filter((mutation) => mutation.materialId === materials[selectedMaterialIndex].materialId)
|
||||||
@@ -156,32 +155,11 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePrevious = () => {
|
|
||||||
if (selectedMaterialIndex) {
|
|
||||||
setQuantityChange(0);
|
|
||||||
const currentIndex = materials.findIndex(
|
|
||||||
(material) => material.materialId === selectedMaterialIndex
|
|
||||||
);
|
|
||||||
if (currentIndex > 0) {
|
|
||||||
setSelectedMaterialIndex(materials[currentIndex - 1].materialId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleNext = () => {
|
|
||||||
if (selectedMaterialIndex) {
|
|
||||||
setQuantityChange(0);
|
|
||||||
const currentIndex = materials.findIndex(
|
|
||||||
(material) => material.materialId === selectedMaterialIndex
|
|
||||||
);
|
|
||||||
if (currentIndex < materials.length - 1) {
|
|
||||||
setSelectedMaterialIndex(materials[currentIndex + 1].materialId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleQuantityChange = (change) => {
|
const handleQuantityChange = (change) => {
|
||||||
setQuantityChange((prev) => prev + change);
|
setQuantityChange((prev) => prev + change);
|
||||||
|
if (quantityChange + change < 1) setNewPrice(currentPrice);
|
||||||
|
|
||||||
|
setIsEditCurrentPrice(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -202,24 +180,27 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
setLatestMutation(latestMutation);
|
setLatestMutation(latestMutation);
|
||||||
setCurrentQuantity(latestMutation.newStock);
|
setCurrentQuantity(latestMutation.newStock);
|
||||||
setCurrentPrice(formatCurrency(latestMutation.priceAtp));
|
setCurrentPrice(formatCurrency(latestMutation.priceAtp));
|
||||||
|
setNewPrice(formatCurrency(latestMutation.priceAtp));
|
||||||
} else {
|
} else {
|
||||||
setCurrentQuantity(0); // Default value if no mutations exist
|
setCurrentQuantity(0); // Default value if no mutations exist
|
||||||
setLatestMutation({ newStock: 0 });
|
setLatestMutation({ newStock: 0 });
|
||||||
setCurrentPrice(0);
|
setCurrentPrice(0);
|
||||||
|
setNewPrice(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setIsViewingHistory(false);
|
||||||
}, [materials, mutations, selectedMaterialIndex]);
|
}, [materials, mutations, selectedMaterialIndex]);
|
||||||
|
|
||||||
const handleUpdateStock = async () => {
|
const handleUpdateStock = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const newPrice = convertToInteger(currentPrice)
|
const newprice = convertToInteger(newPrice)
|
||||||
const newStock = currentQuantity + quantityChange;
|
const newStock = currentQuantity + quantityChange;
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("newStock", newStock);
|
formData.append("newStock", newStock);
|
||||||
formData.append("priceAtp", newPrice);
|
formData.append("priceAtp", newprice);
|
||||||
formData.append("reason", "Stock update");
|
formData.append("reason", "Stock update");
|
||||||
|
|
||||||
await createMaterialMutation(materials[selectedMaterialIndex].materialId, formData);
|
await createMaterialMutation(materials[selectedMaterialIndex].materialId, formData);
|
||||||
@@ -244,103 +225,106 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
return date.toLocaleString();
|
return date.toLocaleString();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={styles.container}>
|
<div className={styles.container}>
|
||||||
{loading ?
|
{loading ? (
|
||||||
|
<></>
|
||||||
|
) : (
|
||||||
<>
|
<>
|
||||||
</>
|
<h3 className={styles.title}>Bahan baku</h3>
|
||||||
:
|
|
||||||
<>
|
|
||||||
<h3 style={styles.title}>Bahan baku</h3>
|
|
||||||
<Carousel items={materials} onSelect={(e) => setSelectedMaterialIndex(e)} selectedIndex={selectedMaterialIndex} />
|
<Carousel items={materials} onSelect={(e) => setSelectedMaterialIndex(e)} selectedIndex={selectedMaterialIndex} />
|
||||||
{selectedMaterialIndex != -1 ?
|
{selectedMaterialIndex !== -1 ? (
|
||||||
<>
|
<>
|
||||||
<div style={styles.switchContainer}>
|
<div className={styles.switchContainer}>
|
||||||
<h3>Stok sekarang {currentQuantity}</h3>
|
<h3>Stok sekarang {currentQuantity}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={styles.stokContainer}>
|
<div className={styles.stokContainer}>
|
||||||
<button onClick={() => handleQuantityChange(currentQuantity + quantityChange > 0 ? -1 : 0)} style={styles.stockButton}>
|
<button onClick={() => handleQuantityChange(currentQuantity + quantityChange > 0 ? -1 : 0)} className={styles.stockButton}>
|
||||||
-
|
-
|
||||||
</button>
|
</button>
|
||||||
<p>{currentQuantity + quantityChange}</p>
|
<p>{currentQuantity + quantityChange}</p>
|
||||||
<button onClick={() => handleQuantityChange(1)} style={styles.stockButton}>
|
<button onClick={() => handleQuantityChange(1)} className={styles.stockButton}>
|
||||||
+
|
+
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.uploadMessage}>
|
<div className={styles.uploadMessage}>
|
||||||
<p>harga per {materials && materials[selectedMaterialIndex]?.unit} sekarang</p>
|
<p>harga per {materials && materials[selectedMaterialIndex]?.unit} sekarang</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.resultMessage}>
|
<div className={styles.resultMessage}>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
className={styles.resultMessageInput} // Replace inline style with CSS module class
|
||||||
style={{
|
|
||||||
width: "200px",
|
|
||||||
border: isEditCurrentPrice ? "1px solid #ccc" : "1px solid transparent",
|
|
||||||
backgroundColor: isEditCurrentPrice ? "white" : "transparent",
|
|
||||||
}}
|
|
||||||
disabled={!isEditCurrentPrice || quantityChange < 1}
|
disabled={!isEditCurrentPrice || quantityChange < 1}
|
||||||
value={currentPrice}
|
value={newPrice}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
placeholder="Enter amount"
|
placeholder="Enter amount"
|
||||||
/>
|
/>
|
||||||
<div onClick={() => quantityChange < 1 ? null : setIsEditCurrentPrice(!isEditCurrentPrice)} style={quantityChange < 1 ? styles.changeButtonDisabled : styles.changeButtonEnabled}>{isEditCurrentPrice ? 'Terapkan' : 'Ganti'}</div>
|
<div onClick={() => quantityChange < 1 ? null : setIsEditCurrentPrice(!isEditCurrentPrice)} className={quantityChange < 1 ? styles.changeButtonDisabled : styles.changeButtonEnabled}>
|
||||||
|
{isEditCurrentPrice ? 'Terapkan' : 'Ganti'}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.buttonContainer}>
|
<div className={styles.buttonContainer}>
|
||||||
<button onClick={handleUpdateStock} style={styles.saveButton}>
|
<button onClick={handleUpdateStock} className={styles.saveButton}>
|
||||||
Laporkan {quantityChange > 0 ? 'penambahan' : 'stok sekarang'} {quantityChange < 1 ? currentQuantity + quantityChange : quantityChange} {materials[selectedMaterialIndex]?.unit}
|
Laporkan {quantityChange > 0 ? 'penambahan' : 'stok sekarang'} {quantityChange < 1 ? currentQuantity + quantityChange : quantityChange} {materials[selectedMaterialIndex]?.unit}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div onClick={() => setIsViewingHistory(!isViewingHistory)} style={styles.historyTab}>
|
<div className={styles.historyTab}>
|
||||||
<h3> {isViewingHistory ? '˅' : '˃'} Riwayat stok</h3>
|
<h3 onClick={() => setIsViewingHistory(!isViewingHistory)}> {isViewingHistory ? '˅' : '˃'} Riwayat stok</h3>
|
||||||
<div style={styles.historyContainer}>
|
{selectedMaterialIndex !== -1 && isViewingHistory && !loading && (
|
||||||
{selectedMaterialIndex != -1 && isViewingHistory && !loading && (
|
<>
|
||||||
<div style={styles.mutationContainer}>
|
<div className={styles.sorter} onClick={() => setSortOrder(sortOrder == 'asc' ? 'desc' : 'asc')}>
|
||||||
{sortedMutations.length > 0 ? (
|
Urutkan: {sortOrder === 'asc' ? "terlama" : "terbaru"} <div style={{ transform: 'rotate(90deg)' }}><></div>
|
||||||
sortedMutations.map((mutation) => (
|
|
||||||
<div key={mutation.id} style={styles.mutationCard}>
|
|
||||||
<h4 style={styles.mutationTitle}>
|
|
||||||
{formatDate(mutation.createdAt)}
|
|
||||||
</h4>
|
|
||||||
<p>Details: {mutation.reason}</p>
|
|
||||||
<p>stok {mutation.newStock}</p>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<p>No mutations available.</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className={styles.historyContainer}>
|
||||||
</div>
|
<div className={styles.mutationContainer}>
|
||||||
|
{sortedMutations.length > 0 ? (
|
||||||
|
sortedMutations.map((mutation) => (
|
||||||
|
<div key={mutation.id} className={styles.mutationCard}>
|
||||||
|
<div style={{ width: '42px', backgroundColor: '#b9b9b9', borderRadius: '10px', padding: '3px', paddingBottom: '0' }}>
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
||||||
|
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
||||||
|
<g id="SVGRepo_iconCarrier">
|
||||||
|
<g id="Interface / Book">
|
||||||
|
<path id="Vector" d="M5 19.5002V6.2002C5 5.08009 5 4.51962 5.21799 4.0918C5.40973 3.71547 5.71547 3.40973 6.0918 3.21799C6.51962 3 7.08009 3 8.2002 3H17.4002C17.9602 3 18.2407 3 18.4546 3.10899C18.6427 3.20487 18.7948 3.35774 18.8906 3.5459C18.9996 3.75981 19 4.04005 19 4.6001V16.4001C19 16.9601 18.9996 17.2398 18.8906 17.4537C18.7948 17.6419 18.6429 17.7952 18.4548 17.8911C18.2411 18 17.961 18 17.402 18H7.25C6.00736 18 5 19.0074 5 20.25C5 20.6642 5.33579 21 5.75 21H16.402C16.961 21 17.2411 21 17.4548 20.8911C17.6429 20.7952 17.7948 20.642 17.8906 20.4538C17.9996 20.2399 18 19.9601 18 19.4V18" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div className={styles.mutationTitle}>
|
||||||
|
<h4>{formatDate(mutation.createdAt)}</h4>
|
||||||
|
<p>Total stok: {mutation.newStock} || +{mutation.newStock - mutation.oldStock} || {formatCurrency((mutation.newStock - mutation.oldStock) * mutation.priceAtp)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<p>Tidak ada laporan perubahan stok.</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</> :
|
</>
|
||||||
|
) : (
|
||||||
<>
|
<>
|
||||||
<div
|
<div className={styles.description}>
|
||||||
style={{ display: "flex", alignItems: "center", margin: "10px", marginTop: '17px', marginBottom: '34px' }}
|
|
||||||
>
|
|
||||||
<div style={{ marginRight: "5px", fontSize: "1.2em" }}>ⓘ</div>
|
<div style={{ marginRight: "5px", fontSize: "1.2em" }}>ⓘ</div>
|
||||||
<h6 style={{ margin: 0, textAlign: "left" }}>
|
<h6 style={{ margin: 0, textAlign: "left", fontSize: '12px' }}>
|
||||||
Fitur ini mempermudah mengelola biaya dan memantau pengeluaran bahan.
|
Fitur ini mempermudah mengelola biaya dan memantau pengeluaran bahan.
|
||||||
</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={styles.switchContainer}>
|
<div className={styles.switchContainer}>
|
||||||
<h3>Buat bahan baru</h3>
|
<h3>Buat bahan baru</h3>
|
||||||
</div>
|
</div>
|
||||||
<div style={styles.resultMessage}>
|
<div className={styles.resultMessage}>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
|
className={styles.resultMessageInput}
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
height: '31px',
|
|
||||||
border: "1px solid #ccc"
|
|
||||||
}}
|
|
||||||
value={newMaterialName}
|
value={newMaterialName}
|
||||||
onChange={(event) => setNewMaterialName(event.target.value)}
|
onChange={(event) => setNewMaterialName(event.target.value)}
|
||||||
placeholder="Masukkan nama barang"
|
placeholder="Masukkan nama barang"
|
||||||
|
style={{width: '100%', height: '31px'}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -348,7 +332,8 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
id="materialUnit"
|
id="materialUnit"
|
||||||
value={newMaterialUnit}
|
value={newMaterialUnit}
|
||||||
onChange={(e) => setNewMaterialUnit(e.target.value)}
|
onChange={(e) => setNewMaterialUnit(e.target.value)}
|
||||||
style={styles.unit}
|
className={styles.unit}
|
||||||
|
style={{height: '37px'}}
|
||||||
>
|
>
|
||||||
<option value="gram">Satuan: gram</option>
|
<option value="gram">Satuan: gram</option>
|
||||||
<option value="ons">Satuan: ons</option>
|
<option value="ons">Satuan: ons</option>
|
||||||
@@ -362,131 +347,17 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
<option value="box">Satuan: box</option>
|
<option value="box">Satuan: box</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<div style={styles.buttonContainer}>
|
<div className={styles.buttonContainer}>
|
||||||
<button style={styles.saveButton}>
|
<button className={styles.saveButton} onClick={handleCreateMaterial}>
|
||||||
Buat bahan baku
|
Buat bahan baku
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
)}
|
||||||
</>
|
</>
|
||||||
}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Styles
|
|
||||||
const styles = {
|
|
||||||
container: {
|
|
||||||
width: '100%',
|
|
||||||
minHeight: '50vh',
|
|
||||||
backgroundColor: "white",
|
|
||||||
padding: "20px",
|
|
||||||
borderRadius: "8px",
|
|
||||||
boxShadow: "0 2px 10px rgba(0, 0, 0, 0.1)",
|
|
||||||
textAlign: "center", // Center text and children
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
marginBottom: "20px",
|
|
||||||
fontWeight: "bold",
|
|
||||||
},
|
|
||||||
qrCodeContainer: {
|
|
||||||
backgroundColor: '#999999',
|
|
||||||
borderRadius: '20px',
|
|
||||||
position: "relative",
|
|
||||||
width: "100%",
|
|
||||||
height: "200px",
|
|
||||||
backgroundSize: "contain",
|
|
||||||
overflow: "hidden",
|
|
||||||
margin: "0 auto", // Center the QR code container
|
|
||||||
},
|
|
||||||
uploadMessage: {
|
|
||||||
fontWeight: 600,
|
|
||||||
textAlign: "left",
|
|
||||||
},
|
|
||||||
changeButtonEnabled: {
|
|
||||||
paddingRight: '10px',
|
|
||||||
backgroundColor: 'green',
|
|
||||||
borderRadius: '30px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: 700,
|
|
||||||
height: '36px',
|
|
||||||
lineHeight: '36px',
|
|
||||||
paddingLeft: '10px',
|
|
||||||
paddingHeight: '10px',
|
|
||||||
},
|
|
||||||
changeButtonDisabled: {
|
|
||||||
paddingRight: '10px',
|
|
||||||
backgroundColor: '#a1a1a1',
|
|
||||||
borderRadius: '30px',
|
|
||||||
color: 'white',
|
|
||||||
fontWeight: 700,
|
|
||||||
height: '36px',
|
|
||||||
lineHeight: '36px',
|
|
||||||
paddingLeft: '10px',
|
|
||||||
paddingHeight: '10px',
|
|
||||||
},
|
|
||||||
resultMessage: {
|
|
||||||
marginTop: "-13px",
|
|
||||||
textAlign: "left",
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between'
|
|
||||||
},
|
|
||||||
stokContainer: {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-evenly',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: '18px',
|
|
||||||
marginBottom: "6px",
|
|
||||||
textAlign: "left",
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
marginTop: "11px",
|
|
||||||
textAlign: "left",
|
|
||||||
},
|
|
||||||
stockButton: {
|
|
||||||
padding: "10px 20px",
|
|
||||||
fontSize: "3.5vw",
|
|
||||||
backgroundColor: "#28a745",
|
|
||||||
color: "#fff",
|
|
||||||
border: "none",
|
|
||||||
borderRadius: "30px",
|
|
||||||
cursor: "pointer",
|
|
||||||
transition: "background-color 0.3s",
|
|
||||||
},
|
|
||||||
saveButton: {
|
|
||||||
width: '100%',
|
|
||||||
padding: "10px 20px",
|
|
||||||
fontSize: "3.5vw",
|
|
||||||
backgroundColor: "#28a745",
|
|
||||||
color: "#fff",
|
|
||||||
border: "none",
|
|
||||||
borderRadius: "30px",
|
|
||||||
cursor: "pointer",
|
|
||||||
transition: "background-color 0.3s",
|
|
||||||
},
|
|
||||||
switchContainer: {
|
|
||||||
marginTop: "20px",
|
|
||||||
textAlign: "left",
|
|
||||||
},
|
|
||||||
historyTab: {
|
|
||||||
textAlign: "left",
|
|
||||||
},
|
|
||||||
historyContainer: {
|
|
||||||
textAlign: "left",
|
|
||||||
maxHeight: '200px',
|
|
||||||
overflowY: 'auto'
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
margin: "10px 0",
|
|
||||||
fontSize: "14px",
|
|
||||||
color: "#666",
|
|
||||||
},
|
|
||||||
unit: {
|
|
||||||
marginTop: '11px',
|
|
||||||
width: '100%',
|
|
||||||
height: '31px',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default SetPaymentQr;
|
export default SetPaymentQr;
|
||||||
|
|||||||
144
src/pages/MaterialList.module.css
Normal file
144
src/pages/MaterialList.module.css
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/* SetPaymentQr.module.css */
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 47vh;
|
||||||
|
background-color: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploadMessage {
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changeButtonEnabled {
|
||||||
|
padding-right: 10px;
|
||||||
|
background-color: green;
|
||||||
|
border-radius: 30px;
|
||||||
|
color: white;
|
||||||
|
font-weight: 700;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.changeButtonDisabled {
|
||||||
|
padding-right: 10px;
|
||||||
|
background-color: #a1a1a1;
|
||||||
|
border-radius: 30px;
|
||||||
|
color: white;
|
||||||
|
font-weight: 700;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resultMessage {
|
||||||
|
margin-top: -13px;
|
||||||
|
text-align: left;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stokContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: -20px;
|
||||||
|
margin-bottom: -15px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonContainer {
|
||||||
|
margin-top: 11px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stockButton {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 3.5vw;
|
||||||
|
background-color: #28a745;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.saveButton {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 3.5vw;
|
||||||
|
background-color: #28a745;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchContainer {
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.historyTab {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.historyContainer {
|
||||||
|
text-align: left;
|
||||||
|
max-height: 15vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
display: flex;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
margin-top: 11px;
|
||||||
|
width: 100%;
|
||||||
|
height: 31px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sorter {
|
||||||
|
border: 1px solid #c3c3c3;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: -10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mutationCard {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 7px;
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mutationTitle {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
.mutationTitle h4 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mutationTitle p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user