Compare commits
10 Commits
b726ae6919
...
ba896106d4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ba896106d4 | ||
|
|
e039fc8acc | ||
|
|
dd0227ab80 | ||
|
|
67cf759b31 | ||
|
|
53e091d3a4 | ||
|
|
3a431b1b14 | ||
|
|
69a07be3cd | ||
|
|
b012517568 | ||
|
|
3e35468f2c | ||
|
|
df7c4f737c |
11030
package-lock.json
generated
11030
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,15 @@
|
|||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>KedaiMaster</title>
|
<title>KedaiMaster</title>
|
||||||
|
|
||||||
|
<!-- Google tag (gtag.js) -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-2SKSCVFB2N"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){ dataLayer.push(arguments); }
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', 'G-2SKSCVFB2N');
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|||||||
@@ -3,17 +3,17 @@
|
|||||||
"name": "jangan pernah ragukan pelanggan",
|
"name": "jangan pernah ragukan pelanggan",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "favicon.ico",
|
"src": "kedai.png",
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
"type": "image/x-icon"
|
"type": "image/x-icon"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "logo192.png",
|
"src": "kedai.png",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"sizes": "192x192"
|
"sizes": "192x192"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "logo512.png",
|
"src": "kedai.png",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"sizes": "512x512"
|
"sizes": "512x512"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@200;300;400;500;600;700;800&ital,wght@0,200..800;1,200..800&display=swap");
|
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@200;300;400;500;600;700;800&ital,wght@0,200..800;1,200..800&display=swap");
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
-ms-overflow-style: none; /* IE and Edge */
|
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none; /* Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
.App {
|
.App {
|
||||||
/* overflow-x: hidden; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.Cafe {
|
.Cafe {
|
||||||
|
|||||||
134
src/App.js
134
src/App.js
@@ -71,6 +71,12 @@ function App() {
|
|||||||
const [depth, setDepth] = useState(-1);
|
const [depth, setDepth] = useState(-1);
|
||||||
const [queue, setQueue] = useState([]);
|
const [queue, setQueue] = useState([]);
|
||||||
|
|
||||||
|
const [newTransaction, setNewTransaction] = useState({});
|
||||||
|
|
||||||
|
|
||||||
|
const queryParams = new URLSearchParams(location.search);
|
||||||
|
const tokenParams = queryParams.get("token");
|
||||||
|
if(tokenParams) localStorage.setItem('auth', tokenParams)
|
||||||
|
|
||||||
const validTransactionStates = [
|
const validTransactionStates = [
|
||||||
'new_transaction',
|
'new_transaction',
|
||||||
@@ -109,6 +115,10 @@ function App() {
|
|||||||
|
|
||||||
const handleStorageChange = () => {
|
const handleStorageChange = () => {
|
||||||
calculateTotalsFromLocalStorage();
|
calculateTotalsFromLocalStorage();
|
||||||
|
|
||||||
|
if (!localStorage.getItem("lastTransaction")) {
|
||||||
|
setLastTransaction(null);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener("localStorageUpdated", handleStorageChange);
|
window.addEventListener("localStorageUpdated", handleStorageChange);
|
||||||
@@ -135,6 +145,7 @@ function App() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setModal('transaction_confirmed', { transactionId: lastTransaction.transactionId })
|
||||||
const myLastTransaction = await checkIsMyTransaction(lastTransaction.transactionId);
|
const myLastTransaction = await checkIsMyTransaction(lastTransaction.transactionId);
|
||||||
console.log(myLastTransaction)
|
console.log(myLastTransaction)
|
||||||
if (myLastTransaction.isMyTransaction) {
|
if (myLastTransaction.isMyTransaction) {
|
||||||
@@ -219,7 +230,7 @@ function App() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
socket.emit("checkUserToken", {
|
socket.emit("checkUserToken", {
|
||||||
token: getLocalStorage("auth"),
|
token: getLocalStorage("auth") || tokenParams,
|
||||||
shopId,
|
shopId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -236,24 +247,23 @@ function App() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on("transaction_confirmed", async (data) => {
|
socket.on("transaction_confirmed", async (data) => {
|
||||||
console.log("transaction notification: " + data);
|
console.log(JSON.stringify(data));
|
||||||
setModal("transaction_confirmed", data);
|
setModal("transaction_confirmed", data);
|
||||||
|
|
||||||
localStorage.setItem('cart', []);
|
localStorage.setItem('cart', []);
|
||||||
|
|
||||||
const startTime = Date.now(); // Capture the start time
|
// const startTime = Date.now(); // Capture the start time
|
||||||
const timeout = 10000; // 10 seconds timeout in milliseconds
|
// const timeout = 10000; // 10 seconds timeout in milliseconds
|
||||||
|
|
||||||
calculateTotalsFromLocalStorage();
|
calculateTotalsFromLocalStorage();
|
||||||
|
|
||||||
while (localStorage.getItem("lastTransaction") === null) {
|
// while (localStorage.getItem("lastTransaction") === null) {
|
||||||
if (Date.now() - startTime > timeout) {
|
// if (Date.now() - startTime > timeout) {
|
||||||
return; // Exit the function and don't proceed further
|
// return; // Exit the function and don't proceed further
|
||||||
}
|
// }
|
||||||
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second
|
||||||
|
// }
|
||||||
|
|
||||||
// If 'lastTransaction' exists, proceed
|
// If 'lastTransaction' exists, proceed
|
||||||
const lastTransaction = JSON.parse(localStorage.getItem("lastTransaction"));
|
const lastTransaction = JSON.parse(localStorage.getItem("lastTransaction"));
|
||||||
@@ -270,17 +280,23 @@ function App() {
|
|||||||
setModal("transaction_success", data);
|
setModal("transaction_success", data);
|
||||||
|
|
||||||
// If 'lastTransaction' exists, proceed
|
// If 'lastTransaction' exists, proceed
|
||||||
localStorage.removeItem("lastTransaction");
|
if (localStorage.getItem("lastTransaction")) {
|
||||||
|
|
||||||
if (lastTransaction != null) {
|
|
||||||
setLastTransaction(null);
|
setLastTransaction(null);
|
||||||
console.log('remove last transaction')
|
localStorage.removeItem("lastTransaction");
|
||||||
|
window.dispatchEvent(new Event("localStorageUpdated"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("transaction_end", async (data) => {
|
socket.on("transaction_end", async (data) => {
|
||||||
console.log("transaction notification");
|
console.log("transaction notification");
|
||||||
setModal("transaction_end", data);
|
setModal("transaction_end", data);
|
||||||
|
|
||||||
|
// If 'lastTransaction' exists, proceed
|
||||||
|
if (localStorage.getItem("lastTransaction")) {
|
||||||
|
setLastTransaction(null);
|
||||||
|
localStorage.removeItem("lastTransaction");
|
||||||
|
window.dispatchEvent(new Event("localStorageUpdated"));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("payment_claimed", async (data) => {
|
socket.on("payment_claimed", async (data) => {
|
||||||
@@ -289,8 +305,15 @@ function App() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on("transaction_failed", async (data) => {
|
socket.on("transaction_failed", async (data) => {
|
||||||
console.log("transaction notification");
|
console.log(JSON.stringify(data));
|
||||||
setModal("transaction_failed", data);
|
setModal("transaction_failed", data);
|
||||||
|
|
||||||
|
// If 'lastTransaction' exists, proceed
|
||||||
|
if (localStorage.getItem("lastTransaction")) {
|
||||||
|
setLastTransaction(null);
|
||||||
|
localStorage.removeItem("lastTransaction");
|
||||||
|
window.dispatchEvent(new Event("localStorageUpdated"));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -324,7 +347,7 @@ function App() {
|
|||||||
setDeviceType("guestDevice");
|
setDeviceType("guestDevice");
|
||||||
} else {
|
} else {
|
||||||
console.log(data)
|
console.log(data)
|
||||||
if(data.data.user.cafeId != null) navigate(`/${data.data.user.cafeIdentityName}`, { replace: true });
|
if (data.data.user.cafeId != null) navigate(`/${data.data.user.cafeIdentityName}`, { replace: true });
|
||||||
setUser(data.data.user);
|
setUser(data.data.user);
|
||||||
if (data.data.latestOpenBillTransaction != null) localStorage.setItem('lastTransaction', JSON.stringify(data.data.latestOpenBillTransaction))
|
if (data.data.latestOpenBillTransaction != null) localStorage.setItem('lastTransaction', JSON.stringify(data.data.latestOpenBillTransaction))
|
||||||
if (
|
if (
|
||||||
@@ -378,30 +401,32 @@ function App() {
|
|||||||
};
|
};
|
||||||
}, [socket, shopId]);
|
}, [socket, shopId]);
|
||||||
|
|
||||||
async function checkIfStillViewingOtherTransaction() {
|
async function checkIfStillViewingOtherTransaction(data) {
|
||||||
|
|
||||||
console.log("transaction notification");
|
console.log("transaction notification");
|
||||||
console.log(modalContent);
|
console.log(modalContent);
|
||||||
|
|
||||||
let response;
|
let response;
|
||||||
response = await getTransactionsFromCafe(shopId, 0, true);
|
response = await getTransactionsFromCafe(shopId, 0, true);
|
||||||
transactionList.current = response;
|
|
||||||
console.log(response);
|
console.log(response);
|
||||||
|
|
||||||
// Get current URL's search parameters inside the socket event handler
|
// Get current URL's search parameters inside the socket event handler
|
||||||
const searchParams = new URLSearchParams(location.search);
|
const searchParams = new URLSearchParams(location.search);
|
||||||
let transaction_info = searchParams.get("transactionId") || ''; // Get transactionId or set it to empty string
|
let transaction_info = searchParams.get("transactionId") || ''; // Get transactionId or set it to empty string
|
||||||
console.log(transaction_info); // Log the updated transaction_info
|
|
||||||
|
|
||||||
|
if(response[0].transactionId != transaction_info) transactionList.current = response;
|
||||||
|
|
||||||
let depthh = transactionList.current.findIndex(
|
let depthh = transactionList.current.findIndex(
|
||||||
item => item.transactionId.toString() === transaction_info.toString()
|
item => item.transactionId.toString() === transaction_info.toString()
|
||||||
);
|
);
|
||||||
if(depthh == 0 && transaction_info.toString() != '') depthh = 1;
|
|
||||||
setDepth(depthh);
|
if (transaction_info != response[0].transactionId)
|
||||||
|
setDepth(depthh);
|
||||||
|
else setModal("new_transaction", data);
|
||||||
|
|
||||||
console.log(transaction_info == response[0].transactionId)
|
console.log(transaction_info == response[0].transactionId)
|
||||||
// If transaction_info is an empty string, set the modal
|
// If transaction_info is an empty string, set the modal
|
||||||
if (transaction_info.toString() == '' || transaction_info.toString() == response[0].transactionId) return false;
|
if (transaction_info.toString() == '') return false;
|
||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,12 +434,15 @@ function App() {
|
|||||||
// This will ensure that searchParams and transaction_info get updated on each render
|
// This will ensure that searchParams and transaction_info get updated on each render
|
||||||
socket.on("transaction_created", async (data) => {
|
socket.on("transaction_created", async (data) => {
|
||||||
console.log("transaction notification");
|
console.log("transaction notification");
|
||||||
const isViewingOtherTransaction = await checkIfStillViewingOtherTransaction();
|
setNewTransaction(data);
|
||||||
|
|
||||||
|
if(!location.pathname.endsWith('/transactions')){
|
||||||
|
const isViewingOtherTransaction = await checkIfStillViewingOtherTransaction(data);
|
||||||
// If transaction_info is an empty string, set the modal
|
// If transaction_info is an empty string, set the modal
|
||||||
if (!isViewingOtherTransaction) {
|
if (!isViewingOtherTransaction) {
|
||||||
setModal("new_transaction", data);
|
setModal("new_transaction", data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Show browser notification
|
// Show browser notification
|
||||||
let permission = Notification.permission;
|
let permission = Notification.permission;
|
||||||
if (permission !== "granted") return;
|
if (permission !== "granted") return;
|
||||||
@@ -429,12 +457,15 @@ function App() {
|
|||||||
socket.on("transaction_canceled", async (data) => {
|
socket.on("transaction_canceled", async (data) => {
|
||||||
console.log("transaction notification");
|
console.log("transaction notification");
|
||||||
|
|
||||||
const isViewingOtherTransaction = await checkIfStillViewingOtherTransaction();
|
setNewTransaction(data);
|
||||||
|
if(location.pathname != '/transactions'){
|
||||||
|
const isViewingOtherTransaction = await checkIfStillViewingOtherTransaction(data);
|
||||||
// If transaction_info is an empty string, set the modal
|
// If transaction_info is an empty string, set the modal
|
||||||
if (!isViewingOtherTransaction) {
|
if (!isViewingOtherTransaction) {
|
||||||
setModal("new_transaction", data);
|
setModal("new_transaction", data);
|
||||||
navigate(`?transactionId=${data.transactionId}`, { replace: true });
|
navigate(`?transactionId=${data.transactionId}`, { replace: true });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clean up the socket event listener on unmount or when dependencies change
|
// Clean up the socket event listener on unmount or when dependencies change
|
||||||
@@ -444,17 +475,6 @@ function App() {
|
|||||||
};
|
};
|
||||||
}, [socket, shopId, location]); // Ensure location is in the dependencies to respond to changes in the URL
|
}, [socket, shopId, location]); // Ensure location is in the dependencies to respond to changes in the URL
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// if (user.cafeId != null && user.cafeId !== shopId) {
|
|
||||||
// // Preserve existing query parameters
|
|
||||||
// const currentParams = new URLSearchParams(location.search).toString();
|
|
||||||
|
|
||||||
// // Navigate to the new cafeId while keeping existing params
|
|
||||||
// navigate(`/${user.cafeId}?${currentParams}`, { replace: true });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }, [user, shopId]);
|
|
||||||
|
|
||||||
function handleMoveToTransaction(direction, from) {
|
function handleMoveToTransaction(direction, from) {
|
||||||
console.log(direction);
|
console.log(direction);
|
||||||
console.log(from);
|
console.log(from);
|
||||||
@@ -472,7 +492,7 @@ function App() {
|
|||||||
: from; // If already at the end, stay on the current transactionId
|
: from; // If already at the end, stay on the current transactionId
|
||||||
} else if (direction === 'previous') {
|
} else if (direction === 'previous') {
|
||||||
|
|
||||||
setDepth(currentIndex -1);
|
setDepth(currentIndex - 1);
|
||||||
// If we're not at the first transaction, get the previous transactionId
|
// If we're not at the first transaction, get the previous transactionId
|
||||||
newTransactionId = currentIndex > 0
|
newTransactionId = currentIndex > 0
|
||||||
? transactionList.current[currentIndex - 1].transactionId
|
? transactionList.current[currentIndex - 1].transactionId
|
||||||
@@ -683,36 +703,6 @@ function App() {
|
|||||||
totalPrice={totalPrice}
|
totalPrice={totalPrice}
|
||||||
lastTransaction={lastTransaction}
|
lastTransaction={lastTransaction}
|
||||||
/>
|
/>
|
||||||
{/* <Footer
|
|
||||||
showTable={true}
|
|
||||||
shopId={shopIdentifier}
|
|
||||||
table={table}
|
|
||||||
cartItemsLength={totalItemsCount}
|
|
||||||
selectedPage={0}
|
|
||||||
/> */}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="/:shopIdentifier/:tableCode?/search"
|
|
||||||
element={
|
|
||||||
<>
|
|
||||||
<SearchResult
|
|
||||||
cafeId={shopId}
|
|
||||||
sendParam={handleSetParam}
|
|
||||||
user={user}
|
|
||||||
shopItems={shopItems}
|
|
||||||
guestSides={guestSides}
|
|
||||||
guestSideOfClerk={guestSideOfClerk}
|
|
||||||
removeConnectedGuestSides={rmConnectedGuestSides}
|
|
||||||
setModal={setModal} // Pass the function to open modal
|
|
||||||
/>
|
|
||||||
{/* <Footer
|
|
||||||
shopId={shopIdentifier}
|
|
||||||
table={table}
|
|
||||||
cartItemsLength={totalItemsCount}
|
|
||||||
selectedPage={1}
|
|
||||||
/> */}
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -732,12 +722,6 @@ function App() {
|
|||||||
shopItems={shopItems}
|
shopItems={shopItems}
|
||||||
setShopItems={setShopItems}
|
setShopItems={setShopItems}
|
||||||
/>
|
/>
|
||||||
{/* <Footer
|
|
||||||
shopId={shopIdentifier}
|
|
||||||
table={table}
|
|
||||||
cartItemsLength={totalItemsCount}
|
|
||||||
selectedPage={2}
|
|
||||||
/> */}
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -771,6 +755,8 @@ function App() {
|
|||||||
sendParam={handleSetParam}
|
sendParam={handleSetParam}
|
||||||
deviceType={deviceType}
|
deviceType={deviceType}
|
||||||
paymentUrl={shop.qrPayment}
|
paymentUrl={shop.qrPayment}
|
||||||
|
setModal={setModal}
|
||||||
|
newTransaction={newTransaction}
|
||||||
/>
|
/>
|
||||||
{/* <Footer
|
{/* <Footer
|
||||||
shopId={shopIdentifier}
|
shopId={shopIdentifier}
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ const App = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const shopId = window.location.pathname.split('/')[1]; // Get shopId from the URL
|
const shopId = window.location.pathname.split('/')[1]; // Get shopId from the URL
|
||||||
const userId = localStorage.getItem('userId');
|
const user_id = localStorage.getItem('user_id');
|
||||||
|
|
||||||
// Connect to Socket.IO if userId is present
|
// Connect to Socket.IO if user_id is present
|
||||||
// if (userId) {
|
// if (user_id) {
|
||||||
// connectSocket(shopId, 1);
|
// connectSocket(shopId, 1);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|||||||
@@ -23,41 +23,50 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ
|
|||||||
"21-24",
|
"21-24",
|
||||||
];
|
];
|
||||||
console.log(dayData)
|
console.log(dayData)
|
||||||
|
const sumSold = (transactions) =>
|
||||||
|
Array.isArray(transactions) ? transactions.reduce((acc, t) => acc + t.sold, 0) : transactions.transaction || 0;
|
||||||
|
|
||||||
|
const sumTotal = (transactions) =>
|
||||||
|
Array.isArray(transactions) ? transactions.reduce((acc, t) => acc + t.totalPrice, 0) : transactions.income || 0;
|
||||||
|
|
||||||
|
const sumOutcome = (transactions) =>
|
||||||
|
Array.isArray(transactions) ? transactions.reduce((acc, t) => acc + t.materialOutcome || t.price, 0) : transactions.outcome || 0;
|
||||||
|
|
||||||
let seriesData = []
|
let seriesData = []
|
||||||
if(graphFilter == 'transactions'){
|
if (graphFilter == 'transactions') {
|
||||||
seriesData = [
|
|
||||||
dayData.hour0To3Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour3To6Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour6To9Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour9To12Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour12To15Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour15To18Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour18To21Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
dayData.hour21To24Transactions.reduce((acc, t) => acc + t.sold, 0),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
else if(graphFilter == 'income'){
|
|
||||||
seriesData = [
|
seriesData = [
|
||||||
dayData.hour0To3Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour0To3Transactions),
|
||||||
dayData.hour3To6Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour3To6Transactions),
|
||||||
dayData.hour6To9Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour6To9Transactions),
|
||||||
dayData.hour9To12Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour9To12Transactions),
|
||||||
dayData.hour12To15Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour12To15Transactions),
|
||||||
dayData.hour15To18Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour15To18Transactions),
|
||||||
dayData.hour18To21Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour18To21Transactions),
|
||||||
dayData.hour21To24Transactions.reduce((acc, t) => acc + t.totalPrice, 0),
|
sumSold(dayData?.hour21To24Transactions),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
else if(graphFilter == 'outcome'){
|
else if (graphFilter == 'income') {
|
||||||
seriesData = [
|
seriesData = [
|
||||||
dayData.hour3To6MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour0To3Transactions),
|
||||||
dayData.hour6To9MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour3To6Transactions),
|
||||||
dayData.hour0To3MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour6To9Transactions),
|
||||||
dayData.hour9To12MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour9To12Transactions),
|
||||||
dayData.hour12To15MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour12To15Transactions),
|
||||||
dayData.hour15To18MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour15To18Transactions),
|
||||||
dayData.hour18To21MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour18To21Transactions),
|
||||||
dayData.hour21To24MaterialIds.reduce((acc, t) => acc + t.materialOutcome, 0),
|
sumTotal(dayData?.hour21To24Transactions),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else if (graphFilter == 'outcome') {
|
||||||
|
seriesData = [
|
||||||
|
sumOutcome(dayData?.hour0To3MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour3To6MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour6To9MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour9To12MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour12To15MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour15To18MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour18To21MaterialIds),
|
||||||
|
sumOutcome(dayData?.hour21To24MaterialIds),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -85,20 +94,20 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
const formatDate = (dateString) => {
|
const formatDate = (dateString) => {
|
||||||
const date = new Date(dateString); // Parse the date string
|
const date = new Date(dateString); // Parse the date string
|
||||||
|
|
||||||
// Create an array of month names (use the same names you had earlier)
|
// Create an array of month names (use the same names you had earlier)
|
||||||
const monthNames = [
|
const monthNames = [
|
||||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||||
];
|
];
|
||||||
|
|
||||||
// Get the month and day
|
// Get the month and day
|
||||||
const month = monthNames[date.getMonth()]; // Month is 0-indexed (January = 0)
|
const month = monthNames[date.getMonth()]; // Month is 0-indexed (January = 0)
|
||||||
const day = date.getDate(); // Get the day of the month
|
const day = date.getDate(); // Get the day of the month
|
||||||
|
|
||||||
return { month, day }; // Return the result
|
return { month, day }; // Return the result
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.chartItemContainer} ${selectedIndex !== -1 ? styles.expanded : ''}`}>
|
<div className={`${styles.chartItemContainer} ${selectedIndex !== -1 ? styles.expanded : ''}`}>
|
||||||
@@ -119,22 +128,22 @@ const DailyCharts = ({ incomeGraph, transactionGraph, materialGraph, colors, typ
|
|||||||
key={indexx}
|
key={indexx}
|
||||||
className={`${styles.dateSelector} ${index === indexx ? styles.dateSelectorActive : styles.dateSelectorInactive
|
className={`${styles.dateSelector} ${index === indexx ? styles.dateSelectorActive : styles.dateSelectorInactive
|
||||||
}`}
|
}`}
|
||||||
style={{position: 'relative' }}
|
style={{ position: 'relative' }}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
type == 'yesterday' && selectedIndex == -1 || type != 'yesterday' && selectedIndex !== index ? setSelectedIndex(index) : setSelectedIndex(-1)
|
type == 'yesterday' && selectedIndex == -1 || type != 'yesterday' && selectedIndex !== index ? setSelectedIndex(index) : setSelectedIndex(-1)
|
||||||
}
|
}
|
||||||
// style={{ backgroundColor: index === indexx ? colors[index % colors.length] : 'transparent' }}
|
// style={{ backgroundColor: index === indexx ? colors[index % colors.length] : 'transparent' }}
|
||||||
>
|
>
|
||||||
<div style={{position: 'absolute', bottom: 0, left: '10%', right: '10%', borderBottom: index == indexx ? `2px solid ${colors[index % colors.length]}` : 'none'}}></div>
|
<div style={{ position: 'absolute', bottom: 0, left: '10%', right: '10%', borderBottom: index == indexx ? `2px solid ${colors[index % colors.length]}` : 'none' }}></div>
|
||||||
<div
|
<div
|
||||||
style={{ color: index === indexx ? 'black' : 'transparent' }}>
|
style={{ color: index === indexx ? 'black' : 'transparent' }}>
|
||||||
{indexx !== chartData.length - 1 ? (
|
{indexx !== chartData.length - 1 ? (
|
||||||
<>
|
<>
|
||||||
{day}{" "}
|
{day}{" "}
|
||||||
{(indexx === 0 || (formatDate(chartData[indexx - 1].date).month !== month && type != 'weekly')) && month}
|
{(indexx === 0 || (formatDate(chartData[indexx - 1].date).month !== month && type != 'weekly')) && month}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
'Kemarin'
|
'Hari ini'
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ const ProfileImage = styled.img`
|
|||||||
width: 60px;
|
width: 60px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
object-fit: contain;
|
object-fit: cover;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
z-index: 199;
|
z-index: 199;
|
||||||
animation: ${(props) => {
|
animation: ${(props) => {
|
||||||
@@ -359,7 +359,7 @@ const Header = ({
|
|||||||
{shopId && user.roleId == 1 && (
|
{shopId && user.roleId == 1 && (
|
||||||
<Child onClick={goToAdminCafes}>Dashboard</Child>)}
|
<Child onClick={goToAdminCafes}>Dashboard</Child>)}
|
||||||
{shopId &&
|
{shopId &&
|
||||||
user.userId == shopOwnerId &&
|
user.user_id == shopOwnerId &&
|
||||||
user.username !== undefined &&
|
user.username !== undefined &&
|
||||||
user.roleId === 1 && (
|
user.roleId === 1 && (
|
||||||
<>
|
<>
|
||||||
@@ -368,7 +368,7 @@ const Header = ({
|
|||||||
{shopName}
|
{shopName}
|
||||||
</Child>
|
</Child>
|
||||||
<Child>
|
<Child>
|
||||||
Mode pengembangan
|
Mode Edit
|
||||||
<Switch
|
<Switch
|
||||||
borderRadius={0}
|
borderRadius={0}
|
||||||
checked={isEditMode}
|
checked={isEditMode}
|
||||||
@@ -377,7 +377,7 @@ const Header = ({
|
|||||||
</Child>
|
</Child>
|
||||||
<Child onClick={() => setModal("reports")}>Lihat laporan</Child>
|
<Child onClick={() => setModal("reports")}>Lihat laporan</Child>
|
||||||
<Child onClick={() => setModal("add_material")}>
|
<Child onClick={() => setModal("add_material")}>
|
||||||
Kelola bahan baku
|
Kelola stok
|
||||||
</Child>
|
</Child>
|
||||||
|
|
||||||
<Child hasChildren>
|
<Child hasChildren>
|
||||||
@@ -423,7 +423,7 @@ const Header = ({
|
|||||||
<Child>{shopName}</Child>
|
<Child>{shopName}</Child>
|
||||||
|
|
||||||
<Child>
|
<Child>
|
||||||
Mode pengembangan
|
Mode Edit
|
||||||
<Switch
|
<Switch
|
||||||
borderRadius={0}
|
borderRadius={0}
|
||||||
checked={isEditMode}
|
checked={isEditMode}
|
||||||
@@ -431,7 +431,7 @@ const Header = ({
|
|||||||
/>
|
/>
|
||||||
</Child>
|
</Child>
|
||||||
<Child onClick={() => setModal("add_material")}>
|
<Child onClick={() => setModal("add_material")}>
|
||||||
Kelola bahan baku
|
Kelola stok
|
||||||
</Child>
|
</Child>
|
||||||
|
|
||||||
<Child hasChildren>
|
<Child hasChildren>
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ const Item = ({
|
|||||||
lineHeight: '1rem',
|
lineHeight: '1rem',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center'
|
||||||
}}>
|
}}>
|
||||||
Promo {(((initialPrice - promoPrice) / initialPrice) * 100).toFixed(0)}%
|
Promo
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ display: 'flex' }}>
|
<div style={{ display: 'flex' }}>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect, useRef } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import styles from "./Modal.module.css";
|
import styles from "./Modal.module.css";
|
||||||
import { getImageUrl } from "../helpers/itemHelper.js";
|
import { ThreeDots } from "react-loader-spinner";
|
||||||
|
|
||||||
|
|
||||||
const ItemConfig = ({
|
const ItemConfig = ({
|
||||||
name: initialName,
|
name: initialName,
|
||||||
@@ -24,11 +25,14 @@ const ItemConfig = ({
|
|||||||
const fileInputRef = useRef(null);
|
const fileInputRef = useRef(null);
|
||||||
const textareaRef = useRef(null);
|
const textareaRef = useRef(null);
|
||||||
|
|
||||||
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
// Prevent scrolling when modal is open
|
// Prevent scrolling when modal is open
|
||||||
document.body.style.overflow = "hidden";
|
document.body.style.overflow = "hidden";
|
||||||
if(selectedImage){
|
if (selectedImage) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onloadend = () => {
|
reader.onloadend = () => {
|
||||||
setPreviewUrl(reader.result);
|
setPreviewUrl(reader.result);
|
||||||
@@ -79,18 +83,27 @@ const ItemConfig = ({
|
|||||||
return () => textarea.removeEventListener("input", handleResize);
|
return () => textarea.removeEventListener("input", handleResize);
|
||||||
}
|
}
|
||||||
}, [textareaRef.current]);
|
}, [textareaRef.current]);
|
||||||
|
const handleCreate = async () => {
|
||||||
|
setIsSaving(true);
|
||||||
|
try {
|
||||||
|
await handleCreateItem(itemName, itemPrice, selectedImage, previewUrl, itemDescription, itemPromoPrice);
|
||||||
|
document.body.style.overflow = "auto";
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleUpdate = async () => {
|
||||||
console.log(itemPromoPrice)
|
setIsSaving(true);
|
||||||
handleCreateItem(itemName, itemPrice, selectedImage, previewUrl, itemDescription, itemPromoPrice);
|
try {
|
||||||
document.body.style.overflow = "auto";
|
await handleUpdateItem(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice);
|
||||||
};
|
document.body.style.overflow = "auto";
|
||||||
const handleUpdate = () => {
|
} finally {
|
||||||
console.log(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice)
|
setIsSaving(false);
|
||||||
handleUpdateItem(itemName, itemPrice, selectedImage, itemDescription, itemPromoPrice);
|
}
|
||||||
document.body.style.overflow = "auto";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={handleOverlayClick} style={{ position: 'fixed', width: '100vw', height: '100vh', left: 0, bottom: 0, display: 'flex', flexDirection: 'column-reverse', zIndex: 301, backgroundColor: '#00000061' }}>
|
<div onClick={handleOverlayClick} style={{ position: 'fixed', width: '100vw', height: '100vh', left: 0, bottom: 0, display: 'flex', flexDirection: 'column-reverse', zIndex: 301, backgroundColor: '#00000061' }}>
|
||||||
<div onClick={handleContentClick} style={{ display: 'flex', flexDirection: 'column', padding: '15px', backgroundColor: 'white', borderRadius: '20px 20px 0 0', overflowY: 'auto' }}>
|
<div onClick={handleContentClick} style={{ display: 'flex', flexDirection: 'column', padding: '15px', backgroundColor: 'white', borderRadius: '20px 20px 0 0', overflowY: 'auto' }}>
|
||||||
@@ -131,7 +144,7 @@ const ItemConfig = ({
|
|||||||
transition: 'all 0.3s ease',
|
transition: 'all 0.3s ease',
|
||||||
boxSizing: 'border-box', // Make sure the padding doesn't cause overflow
|
boxSizing: 'border-box', // Make sure the padding doesn't cause overflow
|
||||||
}}
|
}}
|
||||||
onChange={(e)=>setItemName(e.target.value)}
|
onChange={(e) => setItemName(e.target.value)}
|
||||||
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
||||||
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
||||||
/>
|
/>
|
||||||
@@ -153,7 +166,7 @@ const ItemConfig = ({
|
|||||||
transition: 'all 0.3s ease',
|
transition: 'all 0.3s ease',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
}}
|
}}
|
||||||
onChange={(e)=>setItemPrice(e.target.value)}
|
onChange={(e) => setItemPrice(e.target.value)}
|
||||||
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
||||||
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
||||||
/>
|
/>
|
||||||
@@ -174,7 +187,7 @@ const ItemConfig = ({
|
|||||||
transition: 'all 0.3s ease',
|
transition: 'all 0.3s ease',
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
}}
|
}}
|
||||||
onChange={(e)=>setItemPromoPrice(e.target.value)}
|
onChange={(e) => setItemPromoPrice(e.target.value)}
|
||||||
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
||||||
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
||||||
/>
|
/>
|
||||||
@@ -200,17 +213,40 @@ const ItemConfig = ({
|
|||||||
}}
|
}}
|
||||||
placeholder="Tambah deskripsi..."
|
placeholder="Tambah deskripsi..."
|
||||||
value={itemDescription}
|
value={itemDescription}
|
||||||
onChange={(e)=>setItemDescription(e.target.value)}
|
onChange={(e) => setItemDescription(e.target.value)}
|
||||||
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
onFocus={(e) => e.target.style.borderColor = '#60d37e'}
|
||||||
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
onBlur={(e) => e.target.style.borderColor = '#ccc'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
if (!isSaving) {
|
||||||
|
isBeingEdit ? handleUpdate() : handleCreate();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '40px',
|
||||||
|
alignContent: 'center',
|
||||||
|
textAlign: 'center',
|
||||||
|
borderRadius: '10px',
|
||||||
|
border: '1px solid #60d37e',
|
||||||
|
color: isSaving ? '#aaa' : '#60d37e',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
cursor: isSaving ? 'not-allowed' : 'pointer'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isSaving ? (
|
||||||
|
|
||||||
<div style={{ width: '100%', height: '35px', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
<ThreeDots height={20} width={20} />
|
||||||
<div onClick={() => {isBeingEdit ? handleUpdate() : handleCreate()} } style={{ width: '100%', height: '40px', alignContent: 'center', textAlign: 'center', borderRadius: '10px', border: '1px solid #60d37e', color: '#60d37e', backgroundColor: 'white', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
) : (
|
||||||
{isBeingEdit? 'Simpan' : 'Buat Item'}
|
isBeingEdit ? 'Simpan' : 'Buat Item'
|
||||||
</div>
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -598,7 +598,7 @@ const ItemLister = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{(items.length > 0 ||
|
{(items.length > 0 ||
|
||||||
(user && (user.cafeId == shopId || user.userId == shopOwnerId))) && (
|
(user && (user.cafeId == shopId || user.user_id == shopOwnerId))) && (
|
||||||
<div
|
<div
|
||||||
key={itemTypeId}
|
key={itemTypeId}
|
||||||
className={`${styles["item-lister"]} ${isEdit ? styles["fullscreen"] : ""
|
className={`${styles["item-lister"]} ${isEdit ? styles["fullscreen"] : ""
|
||||||
@@ -713,15 +713,6 @@ const ItemLister = ({
|
|||||||
}
|
}
|
||||||
imageUrl={getImageUrl("uploads/assets/addnew.png")}
|
imageUrl={getImageUrl("uploads/assets/addnew.png")}
|
||||||
/>
|
/>
|
||||||
{/* {typeImage != null && !previewUrl.includes(typeImage) && (
|
|
||||||
<ItemType
|
|
||||||
rectangular={true}
|
|
||||||
onClick={(previewUrl, selectedImage) =>
|
|
||||||
handleImageChange(previewUrl, selectedImage)
|
|
||||||
}
|
|
||||||
imageUrl={getImageUrl(typeImage)}
|
|
||||||
/>
|
|
||||||
)} */}
|
|
||||||
|
|
||||||
<ItemType
|
<ItemType
|
||||||
rectangular={true}
|
rectangular={true}
|
||||||
@@ -857,7 +848,6 @@ const ItemLister = ({
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<button onClick={() => setIsFirstStep(false)} style={{ width: '100%', height: '40px', borderRadius: '20px' }}>selanjutnya</button>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{(isEdit && !isFirstStep || !isEdit) &&
|
{(isEdit && !isFirstStep || !isEdit) &&
|
||||||
@@ -866,7 +856,7 @@ const ItemLister = ({
|
|||||||
<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"]}>
|
||||||
{user && (
|
{user && (
|
||||||
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
user.user_id == shopOwnerId || user.cafeId == shopId) &&
|
||||||
isEditMode && (
|
isEditMode && (
|
||||||
<>
|
<>
|
||||||
{!isAddingNewItem && (
|
{!isAddingNewItem && (
|
||||||
@@ -1113,7 +1103,7 @@ const ItemLister = ({
|
|||||||
|
|
||||||
{user &&
|
{user &&
|
||||||
user.roleId == 1 &&
|
user.roleId == 1 &&
|
||||||
user.userId == shopOwnerId &&
|
user.user_id == shopOwnerId &&
|
||||||
isEdit && (
|
isEdit && (
|
||||||
<>
|
<>
|
||||||
{/* <button
|
{/* <button
|
||||||
|
|||||||
@@ -24,60 +24,8 @@
|
|||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ const ItemTypeLister = ({
|
|||||||
{isEditMode &&
|
{isEditMode &&
|
||||||
!isAddingNewItem &&
|
!isAddingNewItem &&
|
||||||
user && (
|
user && (
|
||||||
user.userId == shopOwnerId || user.cafeId == shopId) && (
|
user.user_id == shopOwnerId || user.cafeId == shopId) && (
|
||||||
<ItemType
|
<ItemType
|
||||||
onClick={toggleAddNewItem}
|
onClick={toggleAddNewItem}
|
||||||
name={"buat baru"}
|
name={"buat baru"}
|
||||||
@@ -111,7 +111,7 @@ const ItemTypeLister = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{user &&(
|
{user &&(
|
||||||
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
user.user_id == shopOwnerId || user.cafeId == shopId) &&
|
||||||
isAddingNewItem && (
|
isAddingNewItem && (
|
||||||
<>
|
<>
|
||||||
<ItemLister
|
<ItemLister
|
||||||
@@ -141,7 +141,7 @@ const ItemTypeLister = ({
|
|||||||
itemTypes.map(
|
itemTypes.map(
|
||||||
(itemType) =>
|
(itemType) =>
|
||||||
(
|
(
|
||||||
itemType.itemList.length > 0 || (user && (user.userId == shopOwnerId || user.cafeId == shopId))) && (
|
itemType.itemList.length > 0 || (user && (user.user_id == shopOwnerId || user.cafeId == shopId))) && (
|
||||||
<ItemType
|
<ItemType
|
||||||
key={itemType.itemTypeId}
|
key={itemType.itemTypeId}
|
||||||
name={itemType.name}
|
name={itemType.name}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ const Modal = ({ user, shop, isOpen, onClose, modalContent, deviceType, setModal
|
|||||||
{modalContent === "create_tenant" && <CreateTenant shopId={shop.cafeId} />}
|
{modalContent === "create_tenant" && <CreateTenant shopId={shop.cafeId} />}
|
||||||
{modalContent === "edit_tables" && <TablesPage shop={shop} />}
|
{modalContent === "edit_tables" && <TablesPage shop={shop} />}
|
||||||
{modalContent === "new_transaction" && (
|
{modalContent === "new_transaction" && (
|
||||||
<Transaction propsShopId={shop.cafeId} handleMoveToTransaction={handleMoveToTransaction} depth={depth} shopImg={shopImg} />
|
<Transaction propsShopId={shop.cafeId} handleMoveToTransaction={handleMoveToTransaction} depth={depth} shopImg={shopImg} setModal={setModal}/>
|
||||||
)}
|
)}
|
||||||
{modalContent === "transaction_canceled" && (
|
{modalContent === "transaction_canceled" && (
|
||||||
<Transaction propsShopId={shop.cafeId} />
|
<Transaction propsShopId={shop.cafeId} />
|
||||||
|
|||||||
@@ -36,3 +36,4 @@
|
|||||||
.closeButton:hover {
|
.closeButton:hover {
|
||||||
color: #f44336; /* Change color on hover for better UX */
|
color: #f44336; /* Change color on hover for better UX */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -479,7 +479,7 @@ export function MusicPlayer({ socket, shopId, user, shopOwnerId, isSpotifyNeedLo
|
|||||||
className={`expandable-container ${expanded ? "expanded" : ""}`}
|
className={`expandable-container ${expanded ? "expanded" : ""}`}
|
||||||
ref={expandableContainerRef}
|
ref={expandableContainerRef}
|
||||||
>
|
>
|
||||||
{user.cafeId == shopId || user.userId == shopOwnerId && (
|
{user.cafeId == shopId || user.user_id == shopOwnerId && (
|
||||||
<>
|
<>
|
||||||
<div className="auth-box">
|
<div className="auth-box">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -106,10 +106,10 @@ export async function getCafeByIdentifier(cafeIdentifyName) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export async function getOwnedCafes(userId) {
|
export async function getOwnedCafes(user_id) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${API_BASE_URL}/cafe/get-cafe-by-ownerId/` + userId,
|
`${API_BASE_URL}/cafe/get-cafe-by-ownerId/` + user_id,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ import { MusicPlayer } from "../components/MusicPlayer";
|
|||||||
import ItemLister from "../components/ItemLister";
|
import ItemLister from "../components/ItemLister";
|
||||||
import Header from "../components/Header";
|
import Header from "../components/Header";
|
||||||
|
|
||||||
|
import Switch from "react-switch";
|
||||||
|
|
||||||
import { ThreeDots } from "react-loader-spinner";
|
import { ThreeDots } from "react-loader-spinner";
|
||||||
|
|
||||||
import { getLocalStorage, updateLocalStorage, removeLocalStorage } from "../helpers/localStorageHelpers";
|
import { getLocalStorage, updateLocalStorage, removeLocalStorage } from "../helpers/localStorageHelpers";
|
||||||
@@ -77,17 +79,28 @@ function CafePage({
|
|||||||
|
|
||||||
const [beingEditedType, setBeingEditedType] = useState(0);
|
const [beingEditedType, setBeingEditedType] = useState(0);
|
||||||
|
|
||||||
const checkWelcomePageConfig = () => {
|
// const checkWelcomePageConfig = () => {
|
||||||
const parsedConfig = JSON.parse(welcomePageConfig);
|
// const parsedConfig = JSON.parse(welcomePageConfig);
|
||||||
if (parsedConfig.isWelcomePageActive == "true") {
|
// if (parsedConfig.isWelcomePageActive == "true") {
|
||||||
const clicked = sessionStorage.getItem("getStartedClicked");
|
// const clicked = sessionStorage.getItem("getStartedClicked");
|
||||||
if (!clicked) {
|
// if (!clicked) {
|
||||||
sessionStorage.setItem("getStartedClicked", true);
|
// sessionStorage.setItem("getStartedClicked", true);
|
||||||
document.body.style.overflow = "hidden";
|
// document.body.style.overflow = "hidden";
|
||||||
setIsStarted(true);
|
// setIsStarted(true);
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (window.gtag && shopIdentifier) {
|
||||||
|
window.gtag('event', 'page_view', {
|
||||||
|
page_title: `Cafe - ${shopIdentifier}`,
|
||||||
|
page_location: window.location.href,
|
||||||
|
page_path: `/` + shopIdentifier,
|
||||||
|
shop_id: shopId || null, // opsional jika kamu mau track ID juga
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
}, [shopIdentifier]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (welcomePageConfig) {
|
if (welcomePageConfig) {
|
||||||
@@ -100,16 +113,16 @@ function CafePage({
|
|||||||
isActive: parsedConfig.isWelcomePageActive === "true",
|
isActive: parsedConfig.isWelcomePageActive === "true",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
checkWelcomePageConfig();
|
// checkWelcomePageConfig();
|
||||||
}, [welcomePageConfig]);
|
}, [welcomePageConfig]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function fetchData() {
|
function fetchData() {
|
||||||
console.log(user.userId == shopOwnerId)
|
console.log(user.user_id == shopOwnerId)
|
||||||
setModal("create_item");
|
setModal("create_item");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(getLocalStorage('auth'))
|
console.log(getLocalStorage('auth'))
|
||||||
if (getLocalStorage("auth") != null) {
|
if (getLocalStorage("auth") != null) {
|
||||||
const executeFetch = async () => {
|
const executeFetch = async () => {
|
||||||
@@ -118,7 +131,7 @@ function CafePage({
|
|||||||
}
|
}
|
||||||
console.log(user)
|
console.log(user)
|
||||||
console.log('open')
|
console.log('open')
|
||||||
if (user.length != 0 && user.userId == shopOwnerId && shopItems.length == 0) fetchData();
|
if (user.length != 0 && user.user_id == shopOwnerId && shopItems.length == 0) fetchData();
|
||||||
};
|
};
|
||||||
executeFetch();
|
executeFetch();
|
||||||
}
|
}
|
||||||
@@ -141,7 +154,7 @@ function CafePage({
|
|||||||
socket.on("joined-room", (response) => {
|
socket.on("joined-room", (response) => {
|
||||||
const { isSpotifyNeedLogin, isExceededDeadline } = response;
|
const { isSpotifyNeedLogin, isExceededDeadline } = response;
|
||||||
setNeedSpotifyLogin(isSpotifyNeedLogin);
|
setNeedSpotifyLogin(isSpotifyNeedLogin);
|
||||||
if (isExceededDeadline) setModal("message",{captMessage:'Kafe sedang tidak tersedia'});
|
if (isExceededDeadline) setModal("message", { captMessage: 'Kafe sedang tidak tersedia' });
|
||||||
setIsExceededDeadline(isExceededDeadline);
|
setIsExceededDeadline(isExceededDeadline);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -211,133 +224,156 @@ function CafePage({
|
|||||||
isFullscreen={true}
|
isFullscreen={true}
|
||||||
/>
|
/>
|
||||||
) : ( */}
|
) : ( */}
|
||||||
<div className={`Cafe ${isExceededDeadline ? 'grayscale' : ''}`}>
|
<div className={`Cafe ${isExceededDeadline ? 'grayscale' : ''}`}>
|
||||||
|
|
||||||
{API_BASE_URL != 'https://dev.api.kedaimaster.com' && API_BASE_URL != 'https://api.kedaimaster.com' &&
|
{API_BASE_URL != 'https://dev.api.kedaimaster.com' && API_BASE_URL != 'https://api.kedaimaster.com' &&
|
||||||
<div className="Watermark"></div>
|
<div className="Watermark"></div>
|
||||||
}
|
}
|
||||||
<div className="App-header">
|
<div className="App-header">
|
||||||
<Header
|
<Header
|
||||||
HeaderText={"Menu"}
|
HeaderText={"Menu"}
|
||||||
showProfile={true}
|
showProfile={true}
|
||||||
setModal={setModal}
|
setModal={setModal}
|
||||||
isLogout={handleLogout}
|
isLogout={handleLogout}
|
||||||
shopId={shopId}
|
shopId={shopId}
|
||||||
shopName={shopName}
|
shopName={shopName}
|
||||||
shopImage={config.image}
|
shopImage={config.image}
|
||||||
shopOwnerId={shopOwnerId}
|
shopOwnerId={shopOwnerId}
|
||||||
shopClerks={shopClerks}
|
shopClerks={shopClerks}
|
||||||
tableCode={table.tableCode}
|
tableCode={table.tableCode}
|
||||||
user={user}
|
user={user}
|
||||||
guestSides={guestSides}
|
guestSides={guestSides}
|
||||||
guestSideOfClerk={guestSideOfClerk}
|
guestSideOfClerk={guestSideOfClerk}
|
||||||
removeConnectedGuestSides={removeConnectedGuestSides}
|
removeConnectedGuestSides={removeConnectedGuestSides}
|
||||||
setIsEditMode={(e) => setIsEditMode(e)}
|
setIsEditMode={(e) => setIsEditMode(e)}
|
||||||
isEditMode={isEditMode}
|
isEditMode={isEditMode}
|
||||||
/>
|
/>
|
||||||
<MusicPlayer
|
<MusicPlayer
|
||||||
socket={socket}
|
socket={socket}
|
||||||
shopId={shopId}
|
shopId={shopId}
|
||||||
user={user}
|
user={user}
|
||||||
shopOwnerId={shopOwnerId}
|
shopOwnerId={shopOwnerId}
|
||||||
isSpotifyNeedLogin={isSpotifyNeedLogin}
|
isSpotifyNeedLogin={isSpotifyNeedLogin}
|
||||||
queue={queue}
|
queue={queue}
|
||||||
setModal={setModal}
|
setModal={setModal}
|
||||||
/>
|
/>{
|
||||||
<div></div>
|
user.username !== undefined &&
|
||||||
<ItemTypeLister
|
(user.cafeId === shopId || user.user_id === shopOwnerId) &&
|
||||||
user={user}
|
(user.roleId === 1 || user.roleId === 2) && (
|
||||||
shopOwnerId={shopOwnerId}
|
<div style={{
|
||||||
shopId={shopId}
|
backgroundColor: '#5c7c5c',
|
||||||
itemTypes={shopItems}
|
padding: '7px 28px',
|
||||||
setShopItems={setShopItems}
|
margin: '0 10px',
|
||||||
isEditMode={isEditMode}
|
borderRadius: '15px',
|
||||||
onFilterChange={(e) => setFilterId(e)}
|
display: 'flex',
|
||||||
filterId={filterId}
|
alignItems: 'center',
|
||||||
beingEditedType={beingEditedType}
|
justifyContent: 'space-between',
|
||||||
setBeingEditedType={setBeingEditedType}
|
textShadow: '2px 2px 4px rgba(0, 0, 0, 0.7)',
|
||||||
/>
|
fontSize: '16px'
|
||||||
{/* <div style={{ marginTop: "15px" }}></div> */}
|
}}>
|
||||||
<div>
|
Mode Edit
|
||||||
{shopItems
|
<Switch
|
||||||
.filter(
|
borderRadius={0}
|
||||||
(itemType) =>
|
checked={isEditMode}
|
||||||
filterId == 0 || itemType.itemTypeId === filterId
|
onChange={() => setIsEditMode(!isEditMode)}
|
||||||
)
|
/>
|
||||||
.map((itemType, index) => (
|
</div>
|
||||||
<ItemLister
|
)
|
||||||
index={index}
|
}
|
||||||
indexTotal={shopItems.length}
|
|
||||||
shopId={shopId}
|
<ItemTypeLister
|
||||||
shopOwnerId={shopOwnerId}
|
user={user}
|
||||||
user={user}
|
shopOwnerId={shopOwnerId}
|
||||||
key={itemType.itemTypeId}
|
shopId={shopId}
|
||||||
itemTypeId={itemType.itemTypeId}
|
itemTypes={shopItems}
|
||||||
typeName={itemType.name}
|
setShopItems={setShopItems}
|
||||||
typeImage={itemType.image}
|
isEditMode={isEditMode}
|
||||||
setShopItems={setShopItems}
|
onFilterChange={(e) => setFilterId(e)}
|
||||||
itemList={itemType.itemList}
|
filterId={filterId}
|
||||||
typeVisibility={itemType.visibility}
|
beingEditedType={beingEditedType}
|
||||||
moveItemTypeUp={(e) => moveItemTypeHandler(e, 'up', index)}
|
setBeingEditedType={setBeingEditedType}
|
||||||
moveItemTypeDown={(e) => moveItemTypeHandler(e, 'down', index)}
|
/>
|
||||||
isEditMode={isEditMode}
|
{/* <div style={{ marginTop: "15px" }}></div> */}
|
||||||
beingEditedType={beingEditedType}
|
<div>
|
||||||
setBeingEditedType={setBeingEditedType}
|
{shopItems
|
||||||
raw={isEditMode || filterId == 0 ? false : true}
|
.filter(
|
||||||
handleCreateItem={(
|
(itemType) =>
|
||||||
itemTypeID,
|
filterId == 0 || itemType.itemTypeId === filterId
|
||||||
name,
|
)
|
||||||
price,
|
.map((itemType, index) => (
|
||||||
selectedImage,
|
<ItemLister
|
||||||
description,
|
index={index}
|
||||||
promoPrice,
|
indexTotal={shopItems.length}
|
||||||
) =>
|
shopId={shopId}
|
||||||
createItem(
|
shopOwnerId={shopOwnerId}
|
||||||
shopId,
|
user={user}
|
||||||
name,
|
key={itemType.itemTypeId}
|
||||||
price,
|
itemTypeId={itemType.itemTypeId}
|
||||||
selectedImage,
|
typeName={itemType.name}
|
||||||
itemTypeID,
|
typeImage={itemType.image}
|
||||||
description,
|
setShopItems={setShopItems}
|
||||||
promoPrice,
|
itemList={itemType.itemList}
|
||||||
)
|
typeVisibility={itemType.visibility}
|
||||||
|
moveItemTypeUp={(e) => moveItemTypeHandler(e, 'up', index)}
|
||||||
|
moveItemTypeDown={(e) => moveItemTypeHandler(e, 'down', index)}
|
||||||
|
isEditMode={isEditMode}
|
||||||
|
beingEditedType={beingEditedType}
|
||||||
|
setBeingEditedType={setBeingEditedType}
|
||||||
|
raw={isEditMode || filterId == 0 ? false : true}
|
||||||
|
handleCreateItem={(
|
||||||
|
itemTypeID,
|
||||||
|
name,
|
||||||
|
price,
|
||||||
|
selectedImage,
|
||||||
|
description,
|
||||||
|
promoPrice,
|
||||||
|
) =>
|
||||||
|
createItem(
|
||||||
|
shopId,
|
||||||
|
name,
|
||||||
|
price,
|
||||||
|
selectedImage,
|
||||||
|
itemTypeID,
|
||||||
|
description,
|
||||||
|
promoPrice,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
handleUpdateItem={(itemId, name, price, selectedImage, description, promoPrice) =>
|
||||||
|
updateItem(itemId, name, price, selectedImage, description, promoPrice)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
{!isEditMode && (user.username || cartItemsLength > 0) &&
|
||||||
|
<div style={{ marginTop: '10px', height: '40px', position: 'sticky', bottom: '40px', display: 'flex', justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>
|
||||||
|
{(lastTransaction != null || 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 style={{ display: 'flex', flexWrap: 'wrap', alignContent: 'center' }}>{lastTransaction != null && '+'}{cartItemsLength} item</div>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', width: '130px' }}>
|
||||||
|
{((lastTransaction == null || lastTransaction?.payment_type != 'paylater')) ?
|
||||||
|
<span style={{ whiteSpace: 'nowrap' }}>Rp{totalPrice}</span>
|
||||||
|
:
|
||||||
|
<span style={{ whiteSpace: 'nowrap' }}>Open bill</span>
|
||||||
}
|
}
|
||||||
handleUpdateItem={(itemId, name, price, selectedImage, description, promoPrice) =>
|
<div style={{ display: 'flex', alignItems: 'center', marginLeft: '5px', width: '20px' }}>
|
||||||
updateItem(itemId, name, price, selectedImage, description, promoPrice)
|
<svg viewBox="0 0 34 34" style={{ fill: 'white', marginTop: '4px' }}>
|
||||||
}
|
<path d="M9.79175 24.75C8.09591 24.75 6.72383 26.1375 6.72383 27.8333C6.72383 29.5292 8.09591 30.9167 9.79175 30.9167C11.4876 30.9167 12.8751 29.5292 12.8751 27.8333C12.8751 26.1375 11.4876 24.75 9.79175 24.75ZM0.541748 0.0833435V3.16668H3.62508L9.17508 14.8679L7.09383 18.645C6.84717 19.0767 6.70842 19.5854 6.70842 20.125C6.70842 21.8208 8.09591 23.2083 9.79175 23.2083H28.2917V20.125H10.4392C10.2234 20.125 10.0538 19.9554 10.0538 19.7396L10.1001 19.5546L11.4876 17.0417H22.973C24.1292 17.0417 25.1467 16.4096 25.6709 15.4538L31.1901 5.44834C31.3134 5.23251 31.3751 4.97043 31.3751 4.70834C31.3751 3.86043 30.6813 3.16668 29.8334 3.16668H7.03217L5.583 0.0833435H0.541748ZM25.2084 24.75C23.5126 24.75 22.1405 26.1375 22.1405 27.8333C22.1405 29.5292 23.5126 30.9167 25.2084 30.9167C26.9042 30.9167 28.2917 29.5292 28.2917 27.8333C28.2917 26.1375 26.9042 24.75 25.2084 24.75Z"></path>
|
||||||
/>
|
</svg>
|
||||||
))}
|
|
||||||
{!isEditMode && (user.username || cartItemsLength > 0) &&
|
|
||||||
<div style={{ marginTop: '10px', height: '40px', position: 'sticky', bottom: '40px', display: 'flex', justifyContent: 'center', alignItems: 'center', textAlign: 'center' }}>
|
|
||||||
{(lastTransaction != null || 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 style={{ display: 'flex', flexWrap: 'wrap', alignContent: 'center' }}>{lastTransaction != null && '+'}{cartItemsLength} item</div>
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', width: '130px' }}>
|
|
||||||
{((lastTransaction == null || lastTransaction?.payment_type != 'paylater')) ?
|
|
||||||
<span style={{ whiteSpace: 'nowrap' }}>Rp{totalPrice}</span>
|
|
||||||
:
|
|
||||||
<span style={{ whiteSpace: 'nowrap' }}>Open bill</span>
|
|
||||||
}
|
|
||||||
<div style={{ display: 'flex', alignItems: 'center', marginLeft: '5px', width: '20px' }}>
|
|
||||||
<svg viewBox="0 0 34 34" style={{ fill: 'white', marginTop: '4px' }}>
|
|
||||||
<path d="M9.79175 24.75C8.09591 24.75 6.72383 26.1375 6.72383 27.8333C6.72383 29.5292 8.09591 30.9167 9.79175 30.9167C11.4876 30.9167 12.8751 29.5292 12.8751 27.8333C12.8751 26.1375 11.4876 24.75 9.79175 24.75ZM0.541748 0.0833435V3.16668H3.62508L9.17508 14.8679L7.09383 18.645C6.84717 19.0767 6.70842 19.5854 6.70842 20.125C6.70842 21.8208 8.09591 23.2083 9.79175 23.2083H28.2917V20.125H10.4392C10.2234 20.125 10.0538 19.9554 10.0538 19.7396L10.1001 19.5546L11.4876 17.0417H22.973C24.1292 17.0417 25.1467 16.4096 25.6709 15.4538L31.1901 5.44834C31.3134 5.23251 31.3751 4.97043 31.3751 4.70834C31.3751 3.86043 30.6813 3.16668 29.8334 3.16668H7.03217L5.583 0.0833435H0.541748ZM25.2084 24.75C23.5126 24.75 22.1405 26.1375 22.1405 27.8333C22.1405 29.5292 23.5126 30.9167 25.2084 30.9167C26.9042 30.9167 28.2917 29.5292 28.2917 27.8333C28.2917 26.1375 26.9042 24.75 25.2084 24.75Z"></path>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
</div>
|
||||||
{user.username &&
|
</div>
|
||||||
<div onClick={goToTransactions} style={{ backgroundColor: '#73a585', width: '15vw', height: '40px', borderRadius: '30px', display: 'flex', justifyContent: 'center', marginLeft: lastTransaction != null || cartItemsLength > 0 ? '6px' : '0px' }}>
|
}
|
||||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '38px', marginRight: '5px' }}>
|
{user.username &&
|
||||||
<div style={{ display: 'flex', alignItems: 'center', marginLeft: '5px', width: '20px' }}>
|
<div onClick={goToTransactions} style={{ backgroundColor: '#73a585', width: '15vw', height: '40px', borderRadius: '30px', display: 'flex', justifyContent: 'center', marginLeft: lastTransaction != null || cartItemsLength > 0 ? '6px' : '0px' }}>
|
||||||
<svg viewBox="0 0 512 512">
|
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', width: '38px', marginRight: '5px' }}>
|
||||||
<g
|
<div style={{ display: 'flex', alignItems: 'center', marginLeft: '5px', width: '20px' }}>
|
||||||
transform="translate(0 460) scale(0.09 -0.09)"
|
<svg viewBox="0 0 512 512">
|
||||||
style={{ fill: 'white', marginTop: '4px' }}
|
<g
|
||||||
stroke="none"
|
transform="translate(0 460) scale(0.09 -0.09)"
|
||||||
>
|
style={{ fill: 'white', marginTop: '4px' }}
|
||||||
<path
|
stroke="none"
|
||||||
d="M1639 5107 c-47 -13 -70 -28 -177 -109 -119 -90 -246 -102 -381 -34
|
>
|
||||||
|
<path
|
||||||
|
d="M1639 5107 c-47 -13 -70 -28 -177 -109 -119 -90 -246 -102 -381 -34
|
||||||
-53 27 -83 36 -121 36 -88 0 -167 -57 -190 -138 -8 -26 -10 -620 -8 -1982 l3
|
-53 27 -83 36 -121 36 -88 0 -167 -57 -190 -138 -8 -26 -10 -620 -8 -1982 l3
|
||||||
-1945 24 -38 c13 -21 42 -50 64 -65 l41 -27 1535 -5 1536 -5 58 -22 c158 -60
|
-1945 24 -38 c13 -21 42 -50 64 -65 l41 -27 1535 -5 1536 -5 58 -22 c158 -60
|
||||||
291 -205 322 -352 10 -45 74 -108 119 -117 78 -14 154 25 182 93 12 27 14 398
|
291 -205 322 -352 10 -45 74 -108 119 -117 78 -14 154 25 182 93 12 27 14 398
|
||||||
@@ -353,24 +389,24 @@ function CafePage({
|
|||||||
20 6 475 9 1183 8 l1150 -2 38 -24z m4 -903 c62 -41 88 -90 88 -168 0 -78 -26
|
20 6 475 9 1183 8 l1150 -2 38 -24z m4 -903 c62 -41 88 -90 88 -168 0 -78 -26
|
||||||
-127 -88 -168 l-41 -27 -665 0 -666 0 -38 24 c-76 47 -111 140 -88 229 14 51
|
-127 -88 -168 l-41 -27 -665 0 -666 0 -38 24 c-76 47 -111 140 -88 229 14 51
|
||||||
76 117 123 131 20 6 291 9 684 8 l650 -2 41 -27z"
|
76 117 123 131 20 6 291 9 684 8 l650 -2 41 -27z"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d="M592 489 c-47 -14 -109 -79 -123 -131 -33 -122 37 -265 159 -325 l57
|
d="M592 489 c-47 -14 -109 -79 -123 -131 -33 -122 37 -265 159 -325 l57
|
||||||
-28 1815 -2 c1736 -2 1813 -2 1765 15 -125 43 -186 126 -205 279 -12 89
|
-28 1815 -2 c1736 -2 1813 -2 1765 15 -125 43 -186 126 -205 279 -12 89
|
||||||
-39 138 -97 174 l-38 24 -1650 2 c-1023 1 -1662 -2 -1683 -8z"
|
-39 138 -97 174 l-38 24 -1650 2 c-1023 1 -1662 -2 -1683 -8z"
|
||||||
/>
|
/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
}
|
||||||
<Watermark/>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<Watermark />
|
||||||
|
</div>
|
||||||
{/* )} */}
|
{/* )} */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -444,6 +444,18 @@ export default function Invoice({ shopId, setModal, table, sendParam, deviceType
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={styles.NoteContainer}>
|
<div className={styles.NoteContainer}>
|
||||||
|
<span>Atas Nama :</span>
|
||||||
|
<span></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.NoteContainer} >
|
||||||
|
<input
|
||||||
|
className={styles.NoteInput}
|
||||||
|
placeholder="Tambahkan catatan..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.NoteContainer}style={{height: '18px'}}>
|
||||||
<span>Catatan :</span>
|
<span>Catatan :</span>
|
||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const CreateClerk = ({ shopId }) => {
|
|||||||
try {
|
try {
|
||||||
const create = await createClerks(shopId || cafeIdParam, username, password);
|
const create = await createClerks(shopId || cafeIdParam, username, password);
|
||||||
|
|
||||||
if (create) setMessage('Clerk created successfully');
|
if (create) {setMessage('Clerk created successfully');}
|
||||||
else setMessage('Failed to create clerk');
|
else setMessage('Failed to create clerk');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setMessage('Error creating clerk');
|
setMessage('Error creating clerk');
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const Dashboard = ({ user, setModal }) => {
|
|||||||
// Create admin functionality
|
// Create admin functionality
|
||||||
createCafeOwner(newItem.email, newItem.username, newItem.password)
|
createCafeOwner(newItem.email, newItem.username, newItem.password)
|
||||||
.then((newitem) => {
|
.then((newitem) => {
|
||||||
setItems([...items, { userId: newitem.userId, name: newitem.username }]);
|
setItems([...items, { user_id: newitem.user_id, name: newitem.username }]);
|
||||||
setIsCreating(false);
|
setIsCreating(false);
|
||||||
setNewItem({ name: "", type: "" });
|
setNewItem({ name: "", type: "" });
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ const LinktreePage = ({ user, setModal }) => {
|
|||||||
|
|
||||||
// Handle manual coupon code check
|
// Handle manual coupon code check
|
||||||
const handleGetkCoupons = async () => {
|
const handleGetkCoupons = async () => {
|
||||||
const result = await getUserCoupons();
|
// const result = await getUserCoupons();
|
||||||
setCoupons(result.coupons);
|
// setCoupons(result.coupons);
|
||||||
console.log(result)
|
// console.log(result)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle user transactions
|
// Handle user transactions
|
||||||
@@ -95,24 +95,20 @@ const LinktreePage = ({ user, setModal }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle login
|
const handleLogin = () => {
|
||||||
const handleLogin = async () => {
|
const baseUrl = "https://kediritechnopark.com/";
|
||||||
try {
|
const modal = "product";
|
||||||
setError(false);
|
const productId = 1;
|
||||||
setLoading(true);
|
|
||||||
const response = await loginUser(username, password);
|
const authorizedUri = "https://kedaimaster.com?token=";
|
||||||
if (response.success) {
|
const unauthorizedUri = `${baseUrl}?modal=${modal}&product_id=${productId}`;
|
||||||
localStorage.setItem('auth', response.token);
|
|
||||||
console.log(response)
|
const url =
|
||||||
window.location.href = response.cafeIdentifyName ? `/${response.cafeIdentifyName}` : '/';
|
`${baseUrl}?modal=${modal}&product_id=${productId}` +
|
||||||
} else {
|
`&authorized_uri=${encodeURIComponent(authorizedUri)}` +
|
||||||
setError(true);
|
`&unauthorized_uri=${encodeURIComponent(unauthorizedUri)}`;
|
||||||
}
|
|
||||||
} catch (error) {
|
window.location.href = url;
|
||||||
setError(true);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle logout
|
// Handle logout
|
||||||
@@ -152,7 +148,7 @@ const LinktreePage = ({ user, setModal }) => {
|
|||||||
try {
|
try {
|
||||||
if (user.roleId < 1) {
|
if (user.roleId < 1) {
|
||||||
const newOwner = await createCafeOwner(newItem.email, newItem.username, newItem.password);
|
const newOwner = await createCafeOwner(newItem.email, newItem.username, newItem.password);
|
||||||
setItems([...items, { userId: newOwner.userId, name: newOwner.username }]);
|
setItems([...items, { user_id: newOwner.user_id, name: newOwner.username }]);
|
||||||
} else {
|
} else {
|
||||||
const newCafe = await createCafe(newItem.name);
|
const newCafe = await createCafe(newItem.name);
|
||||||
setItems([...items, { cafeId: newCafe.cafeId, name: newCafe.name }]);
|
setItems([...items, { cafeId: newCafe.cafeId, name: newCafe.name }]);
|
||||||
@@ -202,7 +198,7 @@ const LinktreePage = ({ user, setModal }) => {
|
|||||||
];
|
];
|
||||||
console.log(items)
|
console.log(items)
|
||||||
|
|
||||||
const selectedItems = items?.items?.find(item => (item.userId || item.cafeId) === selectedItemId);
|
const selectedItems = items?.items?.find(item => (item.user_id || item.cafeId) === selectedItemId);
|
||||||
|
|
||||||
// If the selected tenant is found, extract the cafes
|
// If the selected tenant is found, extract the cafes
|
||||||
const selectedSubItems = selectedItems?.subItems || [];
|
const selectedSubItems = selectedItems?.subItems || [];
|
||||||
@@ -278,7 +274,7 @@ const LinktreePage = ({ user, setModal }) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
gratis 3 bulan pertama
|
gratis 1 bulan pertama
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div className={styles.mainHeading}>
|
<div className={styles.mainHeading}>
|
||||||
@@ -290,57 +286,20 @@ const LinktreePage = ({ user, setModal }) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
Gratis 3 bulan pertama
|
Gratis 1 bulan pertama
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className={styles.subHeading}>
|
<div className={styles.subHeading}>
|
||||||
Solusi berbasis web untuk memudahkan pengelolaan kedai, dengan fitur yang mempermudah pemilik, kasir, dan tamu berinteraksi.
|
Solusi berbasis web untuk memudahkan pengelolaan kedai, dengan fitur yang mempermudah pemilik, kasir, dan tamu berinteraksi.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{getLocalStorage('auth') == null && (
|
|
||||||
<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}>---- Masuk -----------------------------</label>
|
<button onClick={() => handleLogin()} className={styles.claimButton}>
|
||||||
<input
|
<span>Masuk</span>
|
||||||
id="username"
|
|
||||||
placeholder="username"
|
|
||||||
maxLength="30"
|
|
||||||
className={!error ? styles.usernameInput : styles.usernameInputError}
|
|
||||||
value={username}
|
|
||||||
onChange={(e) => setUsername(e.target.value)}
|
|
||||||
/>
|
|
||||||
<button onClick={() => { setInputtingPassword(true); setWasInputtingPassword(true) }} className={styles.claimButton}>
|
|
||||||
<span>➜</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.FormPassword} ${inputtingPassword ? styles.animateForm : wasInputtingPassword ? styles.reverseForm : styles.idleForm}`}>
|
|
||||||
<span>
|
|
||||||
<label onClick={() => setInputtingPassword(false)} htmlFor="password" className={styles.usernameLabel}> <--- <-- Kembali </label>
|
|
||||||
<label htmlFor="password" className={styles.usernameLabel}> ----- </label>
|
|
||||||
<label onClick={() => setModal('reset-password', { username: username })} className={styles.usernameLabel}>
|
|
||||||
lupa password?
|
|
||||||
</label>
|
|
||||||
</span>
|
|
||||||
<input
|
|
||||||
id="password"
|
|
||||||
placeholder="password"
|
|
||||||
type="password"
|
|
||||||
maxLength="30"
|
|
||||||
className={!error ? styles.usernameInput : styles.usernameInputError}
|
|
||||||
value={password}
|
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
onClick={handleLogin}
|
|
||||||
className={`${styles.claimButton} ${loading ? styles.loading : ''}`}
|
|
||||||
disabled={loading}
|
|
||||||
>
|
|
||||||
<span>{loading ? 'Loading...' : 'Masuk'}</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
<div className={styles.footerLinks}>
|
<div className={styles.footerLinks}>
|
||||||
|
|||||||
@@ -191,7 +191,7 @@
|
|||||||
|
|
||||||
.NoteInput {
|
.NoteInput {
|
||||||
width: 78vw;
|
width: 78vw;
|
||||||
height: 12vw;
|
height: 18px;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ const LinktreePage = ({ data, setModal }) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className={styles.linktreeForm}>
|
<div className={styles.linktreeForm}>
|
||||||
<button onClick={()=>window.open("https://api.whatsapp.com/send?phone=6281318894994&text=Saya%20ingin%20coba%20gratis%203%20bulan")} className={styles.claimButton}>
|
<button onClick={()=>window.open("https://api.whatsapp.com/send?phone=6281318894994&text=Saya%20ingin%20coba%20gratis%203%20bulan")} className={styles.claimButton}>
|
||||||
<span>Dapatkan voucher gratis 3 bulan</span>
|
<span>Dapatkan voucher gratis 1 bulan</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.footer}>
|
<div className={styles.footer}>
|
||||||
|
|||||||
@@ -338,7 +338,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footerLinks {
|
.footerLinks {
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ const SetPaymentQr = ({ cafeId }) => {
|
|||||||
<></>
|
<></>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<h3 className={styles.title}>Bahan baku</h3>
|
<h3 className={styles.title}>Stok</h3>
|
||||||
<Carousel items={materials} onSelect={(e) => setSelectedMaterialIndex(e)} selectedIndex={selectedMaterialIndex} />
|
<Carousel items={materials} onSelect={(e) => setSelectedMaterialIndex(e)} selectedIndex={selectedMaterialIndex} />
|
||||||
{selectedMaterialIndex !== -1 ? (
|
{selectedMaterialIndex !== -1 ? (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -13,10 +13,6 @@ import MultiSwitch from "react-multi-switch-toggle";
|
|||||||
import DailyCharts from '../components/DailyCharts.js';
|
import DailyCharts from '../components/DailyCharts.js';
|
||||||
import PeriodCharts from '../components/PeriodCharts.js';
|
import PeriodCharts from '../components/PeriodCharts.js';
|
||||||
|
|
||||||
import Coupon from "../components/Coupon.js";
|
|
||||||
|
|
||||||
import CreateCouponPage from "./CreateCoupon.js";
|
|
||||||
|
|
||||||
const RoundedRectangle = ({
|
const RoundedRectangle = ({
|
||||||
onClick,
|
onClick,
|
||||||
title,
|
title,
|
||||||
@@ -82,7 +78,7 @@ const RoundedRectangle = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const percentageStyle = {
|
const percentageStyle = {
|
||||||
fontSize: "16px",
|
fontSize: "14px",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
@@ -282,11 +278,11 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
if (amount >= 1_000_000_000) {
|
if (amount >= 1_000_000_000) {
|
||||||
// Format for billions
|
// Format for billions
|
||||||
const billions = amount / 1_000_000_000;
|
const billions = amount / 1_000_000_000;
|
||||||
return billions.toFixed(0) + "b"; // No decimal places for billions
|
return billions.toFixed(0) + "m"; // No decimal places for billions
|
||||||
} else if (amount >= 1_000_000) {
|
} else if (amount >= 1_000_000) {
|
||||||
// Format for millions
|
// Format for millions
|
||||||
const millions = amount / 1_000_000;
|
const millions = amount / 1_000_000;
|
||||||
return millions.toFixed(2).replace(/\.00$/, "") + "m"; // Two decimal places, remove trailing '.00'
|
return millions.toFixed(2).replace(/\.00$/, "") + "jt"; // Two decimal places, remove trailing '.00'
|
||||||
} else if (amount >= 1_000) {
|
} else if (amount >= 1_000) {
|
||||||
// Format for thousands
|
// Format for thousands
|
||||||
const thousands = amount / 1_000;
|
const thousands = amount / 1_000;
|
||||||
@@ -312,7 +308,7 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
filterTexts[["yesterday", "weekly", "monthly", "yearly"].indexOf(filter)];
|
filterTexts[["yesterday", "weekly", "monthly", "yearly"].indexOf(filter)];
|
||||||
|
|
||||||
const [resetKey, setResetKey] = useState(0); // A key to force re-render
|
const [resetKey, setResetKey] = useState(0); // A key to force re-render
|
||||||
const [texts, setTexts] = useState(['Buat bisnis']); // initially show only first 3 texts
|
const [texts, setTexts] = useState([]); // initially show only first 3 texts
|
||||||
const [fullTexts, setFullTexts] = useState(null); // initially show only first 3 texts
|
const [fullTexts, setFullTexts] = useState(null); // initially show only first 3 texts
|
||||||
const [fullTextsVisible, setFullTextsVisible] = useState(null); // initially show only first 3 texts
|
const [fullTextsVisible, setFullTextsVisible] = useState(null); // initially show only first 3 texts
|
||||||
|
|
||||||
@@ -322,22 +318,20 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
let updatedFullTexts;
|
let updatedFullTexts;
|
||||||
if (otherCafes.length === 0) {
|
if (otherCafes.length === 0) {
|
||||||
// Only include the role-specific option if user.roleId is 1
|
// Only include the role-specific option if user.roleId is 1
|
||||||
updatedFullTexts = user.roleId == 1 ? [["Buat Bisnis", 0]] : [];
|
updatedFullTexts = user.roleId == 1 ? [[0]] : [];
|
||||||
setSelectedCafeId(-1);
|
setSelectedCafeId(-1);
|
||||||
} else if (otherCafes.length === 1) {
|
} else if (otherCafes.length === 1) {
|
||||||
updatedFullTexts = [
|
updatedFullTexts = [
|
||||||
[otherCafes[0].cafeIdentifyName || otherCafes[0].username, otherCafes[0].cafeId || otherCafes[0].userId],
|
[otherCafes[0].cafeIdentifyName || otherCafes[0].username, otherCafes[0].cafeId || otherCafes[0].user_id],
|
||||||
// Only add the "Buat Bisnis" option for user.roleId == 1
|
|
||||||
...(user.roleId == 1 ? [["Buat Bisnis", -1]] : [])
|
|
||||||
];
|
];
|
||||||
|
|
||||||
setSelectedCafeId(otherCafes[0].cafeId); // Get the cafeId (second part of the pair)
|
setSelectedCafeId(otherCafes[0].cafeId); // Get the cafeId (second part of the pair)
|
||||||
} else {
|
} else {
|
||||||
updatedFullTexts = [
|
updatedFullTexts = [
|
||||||
["semua", 0], // First entry is "semua"
|
["semua", 0], // First entry is "semua"
|
||||||
...otherCafes.map(item => [item.cafeIdentifyName || item.username, item.cafeId || item.userId]), // Map over cafes to get name and cafeId pairs
|
...otherCafes.map(item => [item.cafeIdentifyName || item.username, item.cafeId || item.user_id]), // Map over cafes to get name and cafeId pairs
|
||||||
// Only add "Buat Bisnis +" option for user.roleId == 1
|
|
||||||
...(user.roleId == 1 ? [["Buat Bisnis +", -1]] : [])
|
...(user.roleId == 1 ? [] : [])
|
||||||
];
|
];
|
||||||
|
|
||||||
setSelectedCafeId(0);
|
setSelectedCafeId(0);
|
||||||
@@ -411,21 +405,21 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
|
|
||||||
console.log(analytics)
|
console.log(analytics)
|
||||||
if (user && user.roleId === 0 && analytics) {
|
if (user && user.roleId === 0 && analytics) {
|
||||||
// Filter the analytics items based on userId
|
// Filter the analytics items based on user_id
|
||||||
if(selectedItem[1] != 0 && selectedItem[1] != -1){
|
if (selectedItem[1] != 0 && selectedItem[1] != -1) {
|
||||||
const filteredData = analytics.items.filter(
|
const filteredData = analytics.items.filter(
|
||||||
(data) => data.userId === nextSelectedId
|
(data) => data.user_id === nextSelectedId
|
||||||
);
|
);
|
||||||
|
|
||||||
// Extract coupons from the filtered data
|
// Extract coupons from the filtered data
|
||||||
const couponsToAdd = filteredData.flatMap((data) => data.coupons);
|
const couponsToAdd = filteredData.flatMap((data) => data.coupons);
|
||||||
|
|
||||||
// Log the coupons to be added
|
// Log the coupons to be added
|
||||||
console.log(couponsToAdd);
|
console.log(couponsToAdd);
|
||||||
// Assuming setCouponList is a function that updates the coupon list
|
// Assuming setCouponList is a function that updates the coupon list
|
||||||
setCouponList(couponsToAdd || []);
|
setCouponList(couponsToAdd || []);
|
||||||
}
|
}
|
||||||
else setCouponList([])
|
else setCouponList([])
|
||||||
}
|
}
|
||||||
|
|
||||||
setResetKey((prevKey) => prevKey + 1); // Increase the key to force re-render
|
setResetKey((prevKey) => prevKey + 1); // Increase the key to force re-render
|
||||||
@@ -511,7 +505,7 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
marginTop: '30px'
|
marginTop: '30px'
|
||||||
}}>
|
}}>
|
||||||
<MultiSwitch
|
<MultiSwitch
|
||||||
texts={["Kemarin", "Minggu ini", "Bulan ini", "Tahun ini"]}
|
texts={["Hari ini", "Minggu ini", "Bulan ini", "Tahun ini"]}
|
||||||
selectedSwitch={["yesterday", "weekly", "monthly", "yearly"].indexOf(
|
selectedSwitch={["yesterday", "weekly", "monthly", "yearly"].indexOf(
|
||||||
filter
|
filter
|
||||||
)}
|
)}
|
||||||
@@ -602,7 +596,7 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
{!forCafe && selectedCafeId != -1 && selectedCafeId != 0 && (
|
{!forCafe && selectedCafeId != -1 && selectedCafeId != 0 && (
|
||||||
<RoundedRectangle
|
<RoundedRectangle
|
||||||
title={"Kunjungi bisnis"}
|
title={"Kunjungi bisnis"}
|
||||||
width= {`calc(${'100%'} - 10px)`}
|
width={`calc(${'100%'} - 10px)`}
|
||||||
height='10px'
|
height='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}
|
||||||
marginBottom={'0px'}
|
marginBottom={'0px'}
|
||||||
@@ -615,9 +609,11 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
>
|
>
|
||||||
<div style={{ marginRight: "5px", fontSize: "1.2em" }}>ⓘ</div>
|
<div style={{ marginRight: "5px", fontSize: "1.2em" }}>ⓘ</div>
|
||||||
<h6 style={{ margin: 0, textAlign: "left", fontSize: '10px', fontWeight: 500 }}>
|
<h6 style={{ margin: 0, textAlign: "left", fontSize: '10px', fontWeight: 500 }}>
|
||||||
{(filter == 'yesterday' || filter == 'weekly') ?
|
{(filter == 'weekly') ?
|
||||||
`Data dihitung dengan membandingkan
|
`Data dihitung dengan membandingkan
|
||||||
${comparisonText} hari terakhir dengan ${comparisonText} hari sebelumnya, dengan penghitungan dimulai dari data kemarin.`
|
7 hari terakhir dengan 7 hari sebelumnya, dengan penghitungan dimulai dari data kemarin.`
|
||||||
|
:
|
||||||
|
(filter == 'yesterday') ? `Data dihitung dengan membandingkan antara hari ini dan kemarin.`
|
||||||
:
|
:
|
||||||
(filter == 'monthly') ? `Data dihitung dengan membandingkan antara awal hingga akhir bulan ini dan bulan lalu, dengan penghitungan berakhir pada data kemarin.` : `Data dihitung dengan membandingkan antara awal hingga akhir tahun ini dan tahun lalu, dengan penghitungan berakhir pada data kemarin.`}
|
(filter == 'monthly') ? `Data dihitung dengan membandingkan antara awal hingga akhir bulan ini dan bulan lalu, dengan penghitungan berakhir pada data kemarin.` : `Data dihitung dengan membandingkan antara awal hingga akhir tahun ini dan tahun lalu, dengan penghitungan berakhir pada data kemarin.`}
|
||||||
</h6>
|
</h6>
|
||||||
@@ -632,7 +628,7 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
}
|
}
|
||||||
style={{ color: 'black', position: 'relative' }}
|
style={{ color: 'black', position: 'relative' }}
|
||||||
>
|
>
|
||||||
<div>Item laku</div>
|
<div>Penjualan</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${styles.filterSelector} ${circularFilter == 'material' ? '' : styles.filterSelectorInactive}
|
className={`${styles.filterSelector} ${circularFilter == 'material' ? '' : styles.filterSelectorInactive}
|
||||||
@@ -720,77 +716,6 @@ const App = ({ forCafe = true, cafeId = -1,
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{!forCafe && selectedCafeId == -1 && user.roleId == 1 &&
|
|
||||||
<div style={{
|
|
||||||
textAlign: "center",
|
|
||||||
}}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexWrap: "wrap",
|
|
||||||
justifyContent: "center",
|
|
||||||
padding: "20px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
|
|
||||||
<RoundedRectangle
|
|
||||||
title={"Masukkan nama bisnis"}
|
|
||||||
width="calc(100% - 10px)"
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
value={itemName}
|
|
||||||
onChange={(e) => setItemName(e.target.value)}
|
|
||||||
style={{
|
|
||||||
width: '70%',
|
|
||||||
fontSize: '25px',
|
|
||||||
borderRadius: '7px',
|
|
||||||
border: '1px solid black'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</RoundedRectangle>
|
|
||||||
|
|
||||||
|
|
||||||
<RoundedRectangle
|
|
||||||
title={"Buat Bisnis"}
|
|
||||||
width="calc(100% - 10px)"
|
|
||||||
onClick={handleClick}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{!forCafe &&
|
|
||||||
<>
|
|
||||||
<div className={`${styles.couponContainer}`}>
|
|
||||||
<div>
|
|
||||||
{!forCafe &&
|
|
||||||
<div className={styles.dateSelectorWrapper} style={{ fontSize: '13px' }}>
|
|
||||||
<div
|
|
||||||
className={`${styles.dateSelector} ${styles.dateSelectorActive}`} style={{ position: 'relative', width: 'calc(32vw - 30px)' }}
|
|
||||||
>
|
|
||||||
<div style={{ position: 'absolute', bottom: 0, left: '10%', right: '10%', borderBottom: `1px solid green` }}></div>
|
|
||||||
<div
|
|
||||||
style={{ color: 'black' }}>
|
|
||||||
Voucher
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style={{ padding: '25px', paddingTop: '0', paddingBottom: '0' }}>
|
|
||||||
{/* <h1>{couponList.length}</h1> */}
|
|
||||||
{couponList && couponList.map((coupon) => {
|
|
||||||
return <Coupon
|
|
||||||
code={coupon?.code || null}
|
|
||||||
value={coupon?.discountValue}
|
|
||||||
period={coupon?.discountPeriods}
|
|
||||||
expiration={coupon?.discountEndDate}
|
|
||||||
/>
|
|
||||||
})}
|
|
||||||
<button className={`${styles.addCoupon}`} onClick={() => setModal('claim-coupon')}>Tambahkan Voucher</button>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { getTables } from "../helpers/tableHelper";
|
|||||||
import TableCanvas from "../components/TableCanvas";
|
import TableCanvas from "../components/TableCanvas";
|
||||||
import { useSearchParams } from "react-router-dom";
|
import { useSearchParams } from "react-router-dom";
|
||||||
|
|
||||||
export default function Transactions({ propsShopId, sendParam, deviceType, handleMoveToTransaction, depth, shopImg }) {
|
export default function Transactions({ propsShopId, sendParam, deviceType, handleMoveToTransaction, depth, shopImg, setModal }) {
|
||||||
const { shopId, tableId } = useParams();
|
const { shopId, tableId } = useParams();
|
||||||
if (sendParam) sendParam({ shopId, tableId });
|
if (sendParam) sendParam({ shopId, tableId });
|
||||||
|
|
||||||
@@ -231,13 +231,29 @@ export default function Transactions({ propsShopId, sendParam, deviceType, handl
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{!transaction.is_paid && transaction.confirmed > -1 &&
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
localStorage.setItem('lastTransaction', JSON.stringify(transaction));
|
||||||
|
setModal("message", { captMessage: 'Silahkan tambahkan pesanan', descMessage: 'Pembayaran akan ditambahkan ke transaksi sebelumnya.' }, null, null);
|
||||||
|
|
||||||
|
// Dispatch the custom event
|
||||||
|
window.dispatchEvent(new Event("localStorageUpdated"));
|
||||||
|
}}
|
||||||
|
className={styles["addNewItem"]}
|
||||||
|
>
|
||||||
|
Tambah pesanan
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<h2 className={styles["Transactions-detail"]}>
|
<h2 className={styles["Transactions-detail"]}>
|
||||||
{transaction.serving_type === "pickup"
|
{transaction.serving_type === "pickup"
|
||||||
? "Ambil sendiri"
|
? "Ambil sendiri"
|
||||||
: `Diantar ke ${transaction.Table ? transaction.Table.tableNo : "N/A"
|
: `Diantar ke ${transaction.Table ? transaction.Table.tableNo : "N/A"
|
||||||
}`}
|
}`}
|
||||||
</h2>
|
</h2>
|
||||||
{transaction.notes != null && (
|
{transaction.notes != '' && (
|
||||||
<>
|
<>
|
||||||
<div className={styles.NoteContainer}>
|
<div className={styles.NoteContainer}>
|
||||||
<span>Note :</span>
|
<span>Note :</span>
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ export default function Transactions({
|
|||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{transaction.payment_type != 'paylater/cash' && transaction.payment_type != 'paylater/cashless' &&
|
{(transaction.payment_type != 'paylater/cash' && transaction.payment_type != 'paylater/cashless') &&
|
||||||
<div
|
<div
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
localStorage.setItem('lastTransaction', JSON.stringify(transaction));
|
localStorage.setItem('lastTransaction', JSON.stringify(transaction));
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import ButtonWithReplica from "../components/ButtonWithReplica";
|
|||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
dayjs.extend(timezone);
|
dayjs.extend(timezone);
|
||||||
|
|
||||||
export default function Transactions({ shop, shopId, propsShopId, sendParam, deviceType, paymentUrl }) {
|
export default function Transactions({ shop, shopId, propsShopId, sendParam, deviceType, paymentUrl, setModal, newTransaction }) {
|
||||||
const { shopIdentifier, tableId } = useParams();
|
const { shopIdentifier, tableId } = useParams();
|
||||||
if (sendParam) sendParam({ shopIdentifier, tableId });
|
if (sendParam) sendParam({ shopIdentifier, tableId });
|
||||||
|
|
||||||
@@ -26,20 +26,22 @@ export default function Transactions({ shop, shopId, propsShopId, sendParam, dev
|
|||||||
const [isPaymentLoading, setIsPaymentLoading] = useState(false);
|
const [isPaymentLoading, setIsPaymentLoading] = useState(false);
|
||||||
const [isPaymentOpen, setIsPaymentOpen] = useState(false);
|
const [isPaymentOpen, setIsPaymentOpen] = useState(false);
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
const [matchedItems, setMatchedItems] = useState([]);
|
const [matchedItems, setMatchedItems] = useState([]);
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMatchedItems(searchAndAggregateItems(transactions, searchTerm));
|
setMatchedItems(searchAndAggregateItems(transactions, searchTerm));
|
||||||
}, [searchTerm, transactions]);
|
}, [searchTerm, transactions]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchTransactions = async () => {
|
const fetchTransactions = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// response = await getMyTransactions(shopId || propsShopId, 5);
|
||||||
|
// setMyTransactions(response);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
let response = await getTransactionsFromCafe(shopId || propsShopId, 5, false);
|
let response = await getTransactionsFromCafe(shopId || propsShopId, -1, false);
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
if (response) setTransactions(response);
|
if (response) setTransactions(response);
|
||||||
@@ -47,34 +49,40 @@ useEffect(() => {
|
|||||||
console.error("Error fetching transactions:", error);
|
console.error("Error fetching transactions:", error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
console.log(deviceType)
|
||||||
fetchTransactions();
|
fetchTransactions();
|
||||||
}, [deviceType]);
|
}, [deviceType, newTransaction]);
|
||||||
|
|
||||||
const calculateTotalPrice = (detailedTransactions) => {
|
const calculateTotalPrice = (detailedTransactions) => {
|
||||||
return detailedTransactions.reduce((total, dt) => {
|
return detailedTransactions.reduce((total, dt) => {
|
||||||
return total + dt.qty * (dt.promoPrice ? dt.promoPrice : dt.price);
|
return total + dt.qty * (dt.promoPrice ? dt.promoPrice : dt.price);
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
const calculateAllTransactionsTotal = (transactions) => {
|
||||||
const calculateAllTransactionsTotal = (transactions) => {
|
return transactions
|
||||||
return transactions.reduce((grandTotal, transaction) => {
|
.filter(transaction => transaction.confirmed > 1) // Filter transactions where confirmed > 1
|
||||||
|
.reduce((grandTotal, transaction) => {
|
||||||
return grandTotal + calculateTotalPrice(transaction.DetailedTransactions);
|
return grandTotal + calculateTotalPrice(transaction.DetailedTransactions);
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
const searchAndAggregateItems = (transactions, searchTerm) => {
|
const searchAndAggregateItems = (transactions, searchTerm) => {
|
||||||
if (!searchTerm.trim()) return [];
|
if (!searchTerm.trim()) return [];
|
||||||
|
|
||||||
const normalizedTerm = searchTerm.trim().toLowerCase();
|
const normalizedTerm = searchTerm.trim().toLowerCase();
|
||||||
|
// Map with key = `${itemId}-${confirmedGroup}` to keep confirmed groups separate
|
||||||
const aggregatedItems = new Map();
|
const aggregatedItems = new Map();
|
||||||
|
|
||||||
transactions.forEach(transaction => {
|
transactions.forEach(transaction => {
|
||||||
|
// Determine confirmed group as a string key
|
||||||
|
const confirmedGroup = transaction.confirmed >= 0 && transaction.confirmed > 1 ? 'confirmed_gt_1' : 'confirmed_le_1';
|
||||||
|
|
||||||
transaction.DetailedTransactions.forEach(detail => {
|
transaction.DetailedTransactions.forEach(detail => {
|
||||||
const itemName = detail.Item.name;
|
const itemName = detail.Item.name;
|
||||||
const itemNameLower = itemName.toLowerCase();
|
const itemNameLower = itemName.toLowerCase();
|
||||||
|
|
||||||
if (itemNameLower.includes(normalizedTerm)) {
|
if (itemNameLower.includes(normalizedTerm)) {
|
||||||
const key = detail.itemId;
|
// Combine itemId and confirmedGroup to keep them separated
|
||||||
|
const key = `${detail.itemId}-${confirmedGroup}`;
|
||||||
|
|
||||||
if (!aggregatedItems.has(key)) {
|
if (!aggregatedItems.has(key)) {
|
||||||
aggregatedItems.set(key, {
|
aggregatedItems.set(key, {
|
||||||
@@ -82,6 +90,7 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
name: itemName,
|
name: itemName,
|
||||||
totalQty: 0,
|
totalQty: 0,
|
||||||
totalPrice: 0,
|
totalPrice: 0,
|
||||||
|
confirmedGroup, // Keep track of which group this belongs to
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,11 +100,12 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
console.log(aggregatedItems.values())
|
||||||
return Array.from(aggregatedItems.values());
|
return Array.from(aggregatedItems.values());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleConfirm = async (transactionId) => {
|
const handleConfirm = async (transactionId) => {
|
||||||
setIsPaymentLoading(true);
|
setIsPaymentLoading(true);
|
||||||
try {
|
try {
|
||||||
@@ -103,7 +113,7 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
if (result) {
|
if (result) {
|
||||||
setTransactions(prev =>
|
setTransactions(prev =>
|
||||||
prev.map(t =>
|
prev.map(t =>
|
||||||
t.transactionId === transactionId ? { ...t, confirmed: 1 } : t
|
t.transactionId === transactionId ? result : t
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -144,39 +154,39 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.Transactions}>
|
<div className={styles.Transactions}>
|
||||||
<h2 className={styles["Transactions-title"]}>
|
<h2 className={styles["Transactions-title"]}>
|
||||||
Daftar transaksi Rp {calculateAllTransactionsTotal(transactions)}
|
Transaksi selesai Rp {calculateAllTransactionsTotal(transactions)}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Cari nama item..."
|
placeholder="Cari nama item..."
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
style={{ border:'0px',height: '42px',borderRadius: '15px', margin: '7px auto 10px', width: '88%', paddingLeft: '8px' }}
|
style={{ border: '0px', height: '42px', borderRadius: '15px', margin: '7px auto 10px', width: '88%', paddingLeft: '8px' }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* Existing Transactions List (keep all your JSX below unchanged) */}
|
{/* Existing Transactions List (keep all your JSX below unchanged) */}
|
||||||
<div className={styles.TransactionListContainer} style={{ padding: '0 8px' }}>
|
<div className={styles.TransactionListContainer} style={{ padding: '0 8px' }}>
|
||||||
|
|
||||||
{matchedItems.length > 0 && matchedItems.map(item => (
|
{matchedItems.length > 0 && matchedItems.map(item => (
|
||||||
<div
|
<div
|
||||||
key={item.itemId}
|
key={`${item.itemId}-${item.confirmedGroup}`}
|
||||||
className={styles.RoundedRectangle}
|
className={styles.RoundedRectangle}
|
||||||
style={{ overflow: "hidden" }}
|
style={{ overflow: "hidden" }}
|
||||||
>
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<strong>{item.name}</strong> x {item.totalQty}
|
<strong>{item.name}</strong> x {item.totalQty}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className={styles.TotalContainer}>
|
<div className={styles.TotalContainer}>
|
||||||
<span>Total:</span>
|
<span>Total:</span>
|
||||||
<span>Rp {item.totalPrice}</span>
|
<span>Rp {item.totalPrice}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{transactions &&
|
{transactions &&
|
||||||
transactions.map((transaction) => (
|
transactions.map((transaction) => (
|
||||||
<div
|
<div
|
||||||
@@ -188,7 +198,7 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
<div className={styles['receipt-header']}>
|
<div className={styles['receipt-header']}>
|
||||||
{transaction.confirmed === 1 ? (
|
{transaction.confirmed === 1 ? (
|
||||||
<ColorRing className={styles['receipt-logo']} />
|
<ColorRing className={styles['receipt-logo']} />
|
||||||
) : transaction.confirmed === -1 || transaction.confirmed === -2 ? (
|
) : transaction.confirmed === -1 && !transaction.is_paid || transaction.confirmed === -2 && !transaction.is_paid ? (
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', margin: '16px 0px' }}>
|
<div style={{ display: 'flex', justifyContent: 'center', margin: '16px 0px' }}>
|
||||||
<svg
|
<svg
|
||||||
style={{ width: '60px', transform: 'Rotate(45deg)' }}
|
style={{ width: '60px', transform: 'Rotate(45deg)' }}
|
||||||
@@ -205,9 +215,9 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
) : transaction.confirmed === 2 ? (
|
) : transaction.confirmed === 2 && !transaction.is_paid ? (
|
||||||
<ColorRing className={styles['receipt-logo']} />
|
<ColorRing className={styles['receipt-logo']} />
|
||||||
) : transaction.confirmed === 3 ? (
|
) : transaction.confirmed === 3 || transaction.is_paid ? (
|
||||||
<div>
|
<div>
|
||||||
<svg
|
<svg
|
||||||
height="60px"
|
height="60px"
|
||||||
@@ -242,15 +252,15 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
|
|
||||||
<div className={styles['receipt-info']}>
|
<div className={styles['receipt-info']}>
|
||||||
{deviceType == 'clerk' ?
|
{deviceType == 'clerk' ?
|
||||||
<h3>{transaction.confirmed === 1 ? (
|
<h3>{transaction.confirmed === 1 && !transaction.is_paid ? (
|
||||||
"Silahkan Cek Pembayaran"
|
"Silahkan Cek Pembayaran"
|
||||||
) : transaction.confirmed === -1 ? (
|
) : transaction.confirmed === -1 && !transaction.is_paid ? (
|
||||||
"Dibatalkan Oleh Kasir"
|
"Dibatalkan Oleh Kasir"
|
||||||
) : transaction.confirmed === -2 ? (
|
) : transaction.confirmed === -2 && !transaction.is_paid ? (
|
||||||
"Dibatalkan Oleh Pelanggan"
|
"Dibatalkan Oleh Pelanggan"
|
||||||
) : transaction.confirmed === 2 ? (
|
) : transaction.confirmed === 2 && !transaction.is_paid ? (
|
||||||
"Sedang Diproses"
|
"Sedang Diproses"
|
||||||
) : transaction.confirmed === 3 ? (
|
) : transaction.confirmed === 3 || transaction.is_paid ? (
|
||||||
"Transaksi Sukses"
|
"Transaksi Sukses"
|
||||||
) : (
|
) : (
|
||||||
"Silahkan Cek Ketersediaan"
|
"Silahkan Cek Ketersediaan"
|
||||||
@@ -299,6 +309,20 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
{!transaction.is_paid && transaction.confirmed > -1 &&
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
localStorage.setItem('lastTransaction', JSON.stringify(transaction));
|
||||||
|
setModal("message", { captMessage: 'Silahkan tambahkan pesanan', descMessage: 'Pembayaran akan ditambahkan ke transaksi sebelumnya.' }, null, null);
|
||||||
|
|
||||||
|
// Dispatch the custom event
|
||||||
|
window.dispatchEvent(new Event("localStorageUpdated"));
|
||||||
|
}}
|
||||||
|
className={styles["addNewItem"]}
|
||||||
|
>
|
||||||
|
Tambah pesanan
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<h2 className={styles["Transactions-detail"]}>
|
<h2 className={styles["Transactions-detail"]}>
|
||||||
{transaction.serving_type === "pickup"
|
{transaction.serving_type === "pickup"
|
||||||
? "Self pickup"
|
? "Self pickup"
|
||||||
@@ -331,7 +355,7 @@ const searchAndAggregateItems = (transactions, searchTerm) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.TotalContainer}>
|
<div className={styles.TotalContainer}>
|
||||||
{(deviceType == 'clerk' && (transaction.confirmed == 0 || transaction.confirmed == 1 || transaction.confirmed == 2)) &&
|
{(deviceType == 'clerk' && !transaction.is_paid && (transaction.confirmed == 0 || transaction.confirmed == 1 || transaction.confirmed == 2)) &&
|
||||||
<button
|
<button
|
||||||
className={styles.PayButton}
|
className={styles.PayButton}
|
||||||
onClick={() => handleConfirm(transaction.transactionId)}
|
onClick={() => handleConfirm(transaction.transactionId)}
|
||||||
|
|||||||
Reference in New Issue
Block a user