This commit is contained in:
client perkafean
2024-09-27 09:07:57 +00:00
parent faee9dfd2d
commit 69b3fe4347
33 changed files with 824 additions and 204 deletions

View File

@@ -47,6 +47,7 @@ function CafePage({
const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditMode, setIsEditMode] = useState(false);
const [filterId, setFilterId] = useState(0);
useEffect(() => {
if (user.cafeId != null && user.cafeId != shopId) {
@@ -112,6 +113,7 @@ function CafePage({
guestSideOfClerk={guestSideOfClerk}
removeConnectedGuestSides={removeConnectedGuestSides}
setIsEditMode={(e) => setIsEditMode(e)}
isEditMode={isEditMode}
/>
<div style={{ marginTop: "5px" }}></div>
<SearchInput shopId={shopId} tableCode={table.tableCode} />
@@ -121,28 +123,43 @@ function CafePage({
shopOwnerId={shopOwnerId}
shopId={shopId}
itemTypes={shopItems}
isEditMode={isEditMode}
onFilterChange={(e) => setFilterId(e)}
filterId={filterId}
/>
<div style={{ marginTop: "-13px" }}></div>
<h2 className="title">Music Req.</h2>
<MusicPlayer
socket={socket}
shopId={shopId}
user={user}
isSpotifyNeedLogin={isSpotifyNeedLogin}
/>
{filterId === 0 ? (
<>
<h2 className="title">Music Req.</h2>
<MusicPlayer
socket={socket}
shopId={shopId}
user={user}
isSpotifyNeedLogin={isSpotifyNeedLogin}
/>
</>
) : (
<div style={{ marginTop: "35px" }}></div>
)}
<div style={{ marginTop: "-15px" }}></div>
{shopItems.map((itemType) => (
<ItemLister
shopId={shopId}
shopOwnerId={shopOwnerId}
user={user}
key={itemType.itemTypeId}
itemTypeId={itemType.itemTypeId}
typeName={itemType.name}
itemList={itemType.itemList}
isEditMode={isEditMode}
/>
))}
{shopItems
.filter(
(itemType) => filterId == 0 || itemType.itemTypeId === filterId
)
.map((itemType) => (
<ItemLister
shopId={shopId}
shopOwnerId={shopOwnerId}
user={user}
key={itemType.itemTypeId}
itemTypeId={itemType.itemTypeId}
typeName={itemType.name}
itemList={itemType.itemList}
isEditMode={isEditMode}
raw={isEditMode || filterId == 0 ? false : true}
/>
))}
</body>
{user.username && (
<AccountUpdateModal

View File

@@ -1,6 +1,6 @@
import React, { useRef, useEffect, useState } from "react";
import styles from "./Invoice.module.css";
import { useParams, useLocation } from "react-router-dom"; // Changed from useSearchParams to useLocation
import { useParams } from "react-router-dom"; // Changed from useSearchParams to useLocation
import { ThreeDots, ColorRing } from "react-loader-spinner";
import ItemLister from "../components/ItemLister";
@@ -15,19 +15,12 @@ export default function Invoice({ table, sendParam, deviceType, socket }) {
const { shopId, tableCode } = useParams();
sendParam({ shopId, tableCode });
const location = useLocation(); // Use useLocation hook instead of useSearchParams
const searchParams = new URLSearchParams(location.search); // Pass location.search directly
// const email = searchParams.get("email");
// const orderType = searchParams.get("orderType");
// const tableNumber = searchParams.get("tableNumber");
const [cartItems, setCartItems] = useState([]);
const [totalPrice, setTotalPrice] = useState(0);
const [isPaymentLoading, setIsPaymentLoading] = useState(false); // State for payment button loading animation
const textareaRef = useRef(null);
const [orderType, setOrderType] = useState("serve");
const [orderType, setOrderType] = useState("pickup");
const [tableNumber, setTableNumber] = useState("");
const [email, setEmail] = useState("");
@@ -35,10 +28,41 @@ export default function Invoice({ table, sendParam, deviceType, socket }) {
const fetchCartItems = async () => {
try {
const items = await getCartDetails(shopId);
setCartItems(items);
console.log(items);
// Calculate total price based on fetched cart items
const totalPrice = items.reduce((total, itemType) => {
// Filter out unavailable items
const filteredItems = items
.map((itemType) => ({
...itemType,
itemList: itemType.itemList.filter((item) => item.availability),
}))
.filter((itemType) => itemType.itemList.length > 0); // Remove empty itemTypes
setCartItems(filteredItems);
// Update local storage by removing unavailable items
const updatedLocalStorage =
JSON.parse(localStorage.getItem("cart")) || [];
const newLocalStorage = updatedLocalStorage.map((cafe) => {
if (cafe.cafeId === shopId) {
return {
...cafe,
items: cafe.items.filter((item) =>
filteredItems.some((filtered) =>
filtered.itemList.some(
(i) => i.itemId === item.itemId && i.availability
)
)
),
};
}
return cafe;
});
localStorage.setItem("cart", JSON.stringify(newLocalStorage));
window.dispatchEvent(new Event("localStorageUpdated"));
// Calculate total price based on filtered cart items
const totalPrice = filteredItems.reduce((total, itemType) => {
return (
total +
itemType.itemList.reduce((subtotal, item) => {
@@ -107,6 +131,11 @@ export default function Invoice({ table, sendParam, deviceType, socket }) {
}
}, [textareaRef.current]);
useEffect(() => {
if (table?.tableId != undefined) setOrderType("serve");
console.log(table);
}, [table]);
const handleOrderTypeChange = (event) => {
setOrderType(event.target.value);
};

View File

@@ -0,0 +1,66 @@
// NotificationBlocked.js
import React from "react";
const NotificationBlocked = () => {
return (
<div style={styles.container}>
<h2 style={styles.header}>Notifications Blocked</h2>
<p style={styles.message}>
It looks like notifications are currently blocked in your browser.
Enabling notifications will help you receive important updates, such as
new orders or alerts, directly on your device.
</p>
<h3 style={styles.instructionsHeader}>To enable notifications:</h3>
<ol style={styles.instructions}>
<li>Open Chrome and go to our café's website.</li>
<li>Tap the menu (three dots) in the top-right corner.</li>
<li>
Go to <strong>Settings</strong> &gt; <strong>Site settings</strong>{" "}
&gt; <strong>Notifications</strong>.
</li>
<li>
Find our café's site in the list and change the setting to{" "}
<strong>Allow</strong>.
</li>
</ol>
<p style={styles.footer}>
Once you enable notifications, you'll start receiving updates right
away! If you need help, feel free to ask!
</p>
</div>
);
};
const styles = {
container: {
padding: "20px",
border: "1px solid #ddd",
borderRadius: "5px",
backgroundColor: "#f9f9f9",
boxShadow: "0 2px 5px rgba(0,0,0,0.1)",
maxWidth: "400px",
margin: "20px auto",
textAlign: "center",
},
header: {
color: "#e74c3c",
},
message: {
marginBottom: "20px",
},
instructionsHeader: {
marginTop: "20px",
fontWeight: "bold",
},
instructions: {
listStyleType: "decimal",
paddingLeft: "20px",
textAlign: "left",
},
footer: {
marginTop: "20px",
fontStyle: "italic",
},
};
export default NotificationBlocked;

View File

@@ -1,4 +1,3 @@
// src/CafePage.js
import React, { useState } from "react";
import { useParams, useSearchParams, useNavigate } from "react-router-dom";
@@ -17,7 +16,7 @@ function SearchResult({ user, shopItems, sendParam }) {
sendParam({ shopId, tableCode });
const [searchValue, setSearchValue] = useState(
"dwadawa vvwqd21qb13 4kfawfdwa dhawldhawr dliawbdjawndlks"
"dwakbdawkjhbdaw wadhbakdbaw wadh abkd wba aww wadhbd kablawdloq w"
);
// Function to handle search input change
@@ -69,4 +68,4 @@ function SearchResult({ user, shopItems, sendParam }) {
);
}
export default SearchResult;
export default SearchResult;

View File

@@ -188,7 +188,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
)}
</button>
</div>
{transaction.confirmed == 0 && (
{transaction.confirmed < 2 && (
<h5
className={styles.DeclineButton}
onClick={() => handleDecline(transaction.transactionId)}

View File

@@ -2,6 +2,7 @@ import React, { useRef, useEffect, useState } from "react";
import styles from "./Transactions.module.css";
import { useParams } from "react-router-dom";
import { ColorRing } from "react-loader-spinner";
import ButtonWithReplica from "../components/ButtonWithReplica";
import {
getTransaction,
confirmTransaction,
@@ -156,11 +157,10 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
Rp {calculateTotalPrice(transaction.DetailedTransactions)}
</span>
</div>
<div className={styles.TotalContainer}>
<button
className={styles.PayButton}
<div className={styles.PaymentContainer}>
<ButtonWithReplica
disabled={isPaymentLoading}
onClick={() => handleConfirm(transaction.transactionId)}
disabled={isPaymentLoading} // Disable button if confirmed (1) or declined (-1) or loading
>
{isPaymentLoading ? (
<ColorRing height="50" width="50" color="white" />
@@ -175,7 +175,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
) : (
"Confirm availability" // Display "Confirm availability" if the transaction is not confirmed (0)
)}
</button>
</ButtonWithReplica>
</div>
<h5
className={styles.DeclineButton}

View File

@@ -9,6 +9,7 @@ import {
} from "../helpers/transactionHelpers";
import { getTables } from "../helpers/tableHelper";
import TableCanvas from "../components/TableCanvas";
import ButtonWithReplica from "../components/ButtonWithReplica";
export default function Transactions({ propsShopId, sendParam, deviceType }) {
const { shopId, tableId } = useParams();
@@ -143,6 +144,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
</span>
</div>
<div className={styles.TotalContainer}>
<ButtonWithReplica />
<button
className={styles.PayButton}
onClick={() => handleConfirm(transaction.transactionId)}

View File

@@ -8,6 +8,7 @@
font-size: calc(10px + 2vmin);
color: rgba(88, 55, 50, 1);
background-color: #e9e9e9;
border-radius: 15px;
}
.Transactions-title {
@@ -34,6 +35,8 @@
.TransactionListContainer {
overflow-y: auto; /* Enables vertical scrolling */
background-color: #dbdbdb;
overflow: visible;
}
.TotalContainer {
@@ -50,6 +53,21 @@
margin-bottom: 17px;
}
.PaymentContainer {
display: flex;
justify-content: space-between;
width: 100%; /* Ensures it takes up full width */
margin: 0 auto;
font-family: "Poppins", sans-serif;
font-weight: 600;
font-style: normal;
font-size: 1.5em;
padding: 10px;
box-sizing: border-box; /* Includes padding in width */
margin-bottom: 17px;
justify-content: center;
}
.PayButton {
font-family: "Poppins", sans-serif;
font-weight: 500;