working on modal

This commit is contained in:
nospeedlimitindonesia
2024-07-29 23:55:39 +00:00
parent 93df0458e6
commit 1bef19f624
7 changed files with 197 additions and 146 deletions

View File

@@ -1,5 +1,4 @@
// App.js import React, { useState, useEffect } from "react";
import "./App.css"; import "./App.css";
import "./components/Loading.css"; import "./components/Loading.css";
import { import {
@@ -7,8 +6,8 @@ import {
Route, Route,
Routes, Routes,
useNavigate, useNavigate,
useLocation,
} from "react-router-dom"; } from "react-router-dom";
import React, { useState, useEffect } from "react";
import socket from "./services/socketService"; import socket from "./services/socketService";
import Dashboard from "./pages/Dashboard"; import Dashboard from "./pages/Dashboard";
@@ -24,7 +23,6 @@ import GuestSide from "./pages/GuestSide";
import { getItemTypesWithItems } from "./helpers/itemHelper.js"; import { getItemTypesWithItems } from "./helpers/itemHelper.js";
import { import {
// checkToken,
getConnectedGuestSides, getConnectedGuestSides,
removeConnectedGuestSides, removeConnectedGuestSides,
} from "./helpers/userHelpers.js"; } from "./helpers/userHelpers.js";
@@ -33,44 +31,45 @@ import {
removeLocalStorage, removeLocalStorage,
} from "./helpers/localStorageHelpers"; } from "./helpers/localStorageHelpers";
import { calculateTotals } from "./helpers/cartHelpers"; import { calculateTotals } from "./helpers/cartHelpers";
import Modal from "./components/Modal"; // Import your modal component
function App() { function App() {
const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const [user, setUser] = useState([]); const [user, setUser] = useState([]);
const [guestSideOfClerk, setGuestSideOfClerk] = useState(null); const [guestSideOfClerk, setGuestSideOfClerk] = useState(null);
const [guestSides, setGuestSides] = useState([]); const [guestSides, setGuestSides] = useState([]);
const [shopId, setShopId] = useState(""); const [shopId, setShopId] = useState("");
const [tableId, setTableId] = useState("");
const [totalItemsCount, setTotalItemsCount] = useState(0); const [totalItemsCount, setTotalItemsCount] = useState(0);
const [deviceType, setDeviceType] = useState(""); const [deviceType, setDeviceType] = useState("");
const [shopItems, setShopItems] = useState([]); const [shopItems, setShopItems] = useState([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const [modalContent, setModalContent] = useState(null);
useEffect(() => { useEffect(() => {
// Function to calculate totals from localStorage
const calculateTotalsFromLocalStorage = () => { const calculateTotalsFromLocalStorage = () => {
const { totalCount } = calculateTotals(shopId); const { totalCount } = calculateTotals(shopId);
setTotalItemsCount(totalCount); setTotalItemsCount(totalCount);
}; };
// Initial calculation on component mount
calculateTotalsFromLocalStorage(); calculateTotalsFromLocalStorage();
// Function to handle localStorage change event
const handleStorageChange = () => { const handleStorageChange = () => {
calculateTotalsFromLocalStorage(); calculateTotalsFromLocalStorage();
}; };
// Subscribe to custom localStorage change event
window.addEventListener("localStorageUpdated", handleStorageChange); window.addEventListener("localStorageUpdated", handleStorageChange);
return () => { return () => {
// Clean up: Remove event listener on component unmount
window.removeEventListener("localStorageUpdated", handleStorageChange); window.removeEventListener("localStorageUpdated", handleStorageChange);
}; };
}, [shopId]); }, [shopId]);
// Function to handle setting parameters from CafePage const handleSetParam = ({ shopId, tableId }) => {
const handleSetParam = (param) => { console.log(shopId, tableId);
setShopId(param); setShopId(shopId);
setTableId(tableId);
}; };
useEffect(() => { useEffect(() => {
@@ -78,25 +77,18 @@ function App() {
console.log("gettingItems"); console.log("gettingItems");
try { try {
const { response, data } = await getItemTypesWithItems(shopId); const { response, data } = await getItemTypesWithItems(shopId);
console.log(data);
if (response.status === 200) { if (response.status === 200) {
setShopItems(data); setShopItems(data);
console.log(data);
// setLoading(false);
// socket.emit("join-room", { token: getLocalStorage("auth"), shopId });
socket.on("transaction_created", () => { socket.on("transaction_created", () => {
console.log("transaction created"); console.log("transaction created");
}); });
} else {
// setScreenMessage("Kafe tidak tersedia");
} }
} catch (error) { } catch (error) {
console.error("Error fetching shop items:", error); console.error("Error fetching shop items:", error);
} }
} }
if (shopId != "") fetchData(); if (shopId !== "") fetchData();
}, [shopId]); }, [shopId]);
const rmConnectedGuestSides = async (gueseSideSessionId) => { const rmConnectedGuestSides = async (gueseSideSessionId) => {
@@ -104,23 +96,6 @@ function App() {
setGuestSides(sessionLeft.guestSideList); setGuestSides(sessionLeft.guestSideList);
}; };
// useEffect(() => {
// const validateToken = async () => {
// const checkedtoken = await checkToken(socket.id);
// if (checkedtoken.ok) {
// setUser(checkedtoken.user.user);
// if (checkedtoken.user.user.cafeId == shopId) {
// const connectedGuestSides = await getConnectedGuestSides();
// setGuestSides(connectedGuestSides.sessionDatas);
// setDeviceType("clerk");
// } else {
// setDeviceType("guestDevice");
// }
// }
// };
// validateToken();
// }, [navigate, socket, shopId]);
useEffect(() => { useEffect(() => {
if (socket == null) return; if (socket == null) return;
@@ -129,7 +104,6 @@ function App() {
token: getLocalStorage("authGuestSide"), token: getLocalStorage("authGuestSide"),
}); });
} else { } else {
console.log("emitting");
socket.emit("checkUserToken", { socket.emit("checkUserToken", {
token: getLocalStorage("auth"), token: getLocalStorage("auth"),
shopId, shopId,
@@ -138,17 +112,16 @@ function App() {
socket.on("transaction_created", async (data) => { socket.on("transaction_created", async (data) => {
console.log("transaction notification"); console.log("transaction notification");
setModal("new_transaction");
}); });
socket.on("checkUserTokenRes", async (data) => { socket.on("checkUserTokenRes", async (data) => {
if (data.status !== 200) { if (data.status !== 200) {
removeLocalStorage("auth"); removeLocalStorage("auth");
setDeviceType("guestDevice"); setDeviceType("guestDevice");
console.log("guestDevice");
} else { } else {
console.log("auth success");
setUser(data.data.user); setUser(data.data.user);
if (data.data.user.cafeId == shopId) { if (data.data.user.cafeId === shopId) {
const connectedGuestSides = await getConnectedGuestSides(); const connectedGuestSides = await getConnectedGuestSides();
setGuestSides(connectedGuestSides.sessionDatas); setGuestSides(connectedGuestSides.sessionDatas);
setDeviceType("clerk"); setDeviceType("clerk");
@@ -162,9 +135,7 @@ function App() {
if (data.status !== 200) { if (data.status !== 200) {
removeLocalStorage("authGuestSide"); removeLocalStorage("authGuestSide");
navigate("/guest-side"); navigate("/guest-side");
console.log("isntguestside");
} else { } else {
console.log("isguestside");
setGuestSideOfClerk({ setGuestSideOfClerk({
clerkId: data.sessionData.clerkId, clerkId: data.sessionData.clerkId,
clerkUsername: data.sessionData.clerkUsername, clerkUsername: data.sessionData.clerkUsername,
@@ -177,47 +148,66 @@ function App() {
navigate("/guest-side"); navigate("/guest-side");
}); });
// Clean up on component unmount
return () => { return () => {
socket.off("signout-guest-session"); socket.off("signout-guest-session");
}; };
}, [socket, shopId]); }, [socket, shopId]);
const handleModalFromURL = () => {
const queryParams = new URLSearchParams(location.search);
const modal = queryParams.get("modal");
if (modal) setModal(modal);
};
useEffect(() => {
handleModalFromURL();
}, [shopId]);
// Function to open the modal
const setModal = (content) => {
setIsModalOpen(true);
setModalContent(content);
document.body.style.overflow = "hidden";
navigate(`?modal=` + content, { replace: true });
};
// Function to close the modal
const closeModal = () => {
setIsModalOpen(false);
document.body.style.overflow = "auto";
const queryParams = new URLSearchParams(location.search);
// Remove the 'modal' parameter
queryParams.delete("modal");
// Update the URL without the 'modal' parameter
navigate({ search: queryParams.toString() }, { replace: true });
};
return ( return (
<div className="App"> <div className="App">
<header className="App-header"> <header className="App-header">
<Routes> <Routes>
<Route path="/" element={<Dashboard user={user} />} />
<Route path="/login" element={<LoginPage />} />
<Route <Route
path="/" path="/:shopId/:tableId?"
element={
<>
<Dashboard user={user} />
</>
}
/>
<Route
path="/login"
element={
<>
<LoginPage />
</>
}
/>
<Route
path="/:shopId"
element={ element={
<> <>
<CafePage <CafePage
sendParam={handleSetParam} sendParam={handleSetParam}
shopItems={shopItems} shopItems={shopItems}
socket={socket} socket={socket}
user={user} // if logged user={user}
guestSides={guestSides} // if being clerk guestSides={guestSides}
guestSideOfClerk={guestSideOfClerk} // if being guest side guestSideOfClerk={guestSideOfClerk}
removeConnectedGuestSides={(e) => rmConnectedGuestSides(e)} removeConnectedGuestSides={rmConnectedGuestSides}
setModal={setModal} // Pass the function to open modal
/> />
<Footer <Footer
shopId={shopId} shopId={shopId}
tableId={tableId}
cartItemsLength={totalItemsCount} cartItemsLength={totalItemsCount}
selectedPage={0} selectedPage={0}
/> />
@@ -225,19 +215,20 @@ function App() {
} }
/> />
<Route <Route
path="/:shopId/search" path="/:shopId/:tableId?/search"
element={ element={
<> <>
<SearchResult <SearchResult
sendParam={handleSetParam} sendParam={handleSetParam}
user={user} // if logged user={user}
shopItems={shopItems} shopItems={shopItems}
guestSides={guestSides} // if being clerk guestSides={guestSides}
guestSideOfClerk={guestSideOfClerk} // if being guest side guestSideOfClerk={guestSideOfClerk}
removeConnectedGuestSides={(e) => rmConnectedGuestSides(e)} removeConnectedGuestSides={rmConnectedGuestSides}
/> />
<Footer <Footer
shopId={shopId} shopId={shopId}
tableId={tableId}
cartItemsLength={totalItemsCount} cartItemsLength={totalItemsCount}
selectedPage={1} selectedPage={1}
/> />
@@ -245,7 +236,7 @@ function App() {
} }
/> />
<Route <Route
path="/:shopId/cart" path="/:shopId/:tableId?/cart"
element={ element={
<> <>
<Cart <Cart
@@ -255,6 +246,7 @@ function App() {
/> />
<Footer <Footer
shopId={shopId} shopId={shopId}
tableId={tableId}
cartItemsLength={totalItemsCount} cartItemsLength={totalItemsCount}
selectedPage={2} selectedPage={2}
/> />
@@ -262,37 +254,29 @@ function App() {
} }
/> />
<Route <Route
path="/:shopId/invoice" path="/:shopId/:tableId?invoice"
element={ element={
<> <>
<Invoice sendParam={handleSetParam} deviceType={deviceType} /> <Invoice sendParam={handleSetParam} deviceType={deviceType} />
<Footer <Footer
shopId={shopId} shopId={shopId}
tableId={tableId}
cartItemsLength={totalItemsCount} cartItemsLength={totalItemsCount}
selectedPage={2} selectedPage={2}
/> />
</> </>
} }
/> />
<Route <Route
path="/:shopId/guest-side-login" path="/:shopId/guest-side-login"
element={ element={<GuestSideLogin shopId={shopId} socket={socket} />}
<>
<GuestSideLogin shopId={shopId} socket={socket} />
</>
}
/>
<Route
path="/guest-side"
element={
<>
<GuestSide socket={socket} />
</>
}
/> />
<Route path="/guest-side" element={<GuestSide socket={socket} />} />
</Routes> </Routes>
</header> </header>
<Modal isOpen={isModalOpen} onClose={closeModal}>
{modalContent}
</Modal>
</div> </div>
); );
} }

View File

@@ -2,8 +2,16 @@ import React from "react";
import styles from "./Footer.module.css"; // assuming you have a CSS module for Footer import styles from "./Footer.module.css"; // assuming you have a CSS module for Footer
import { useNavigationHelpers } from "../helpers/navigationHelpers"; import { useNavigationHelpers } from "../helpers/navigationHelpers";
export default function Footer({ shopId, cartItemsLength, selectedPage }) { export default function Footer({
const { goToShop, goToSearch, goToCart } = useNavigationHelpers(shopId); shopId,
tableId,
cartItemsLength,
selectedPage,
}) {
const { goToShop, goToSearch, goToCart } = useNavigationHelpers(
shopId,
tableId,
);
return ( return (
<div className={styles.item}> <div className={styles.item}>

View File

@@ -1,5 +1,6 @@
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import styled, { keyframes } from "styled-components"; import styled, { keyframes } from "styled-components";
import { useLocation } from "react-router-dom";
import { useNavigationHelpers } from "../helpers/navigationHelpers"; import { useNavigationHelpers } from "../helpers/navigationHelpers";
const HeaderBar = styled.div` const HeaderBar = styled.div`
@@ -225,6 +226,7 @@ const Header = ({
const [animate, setAnimate] = useState(""); const [animate, setAnimate] = useState("");
const rectangleRef = useRef(null); const rectangleRef = useRef(null);
const [guestSideOf, setGuestSideOf] = useState(null); const [guestSideOf, setGuestSideOf] = useState(null);
const location = useLocation();
const handleImageClick = () => { const handleImageClick = () => {
if (showRectangle) { if (showRectangle) {
@@ -251,7 +253,10 @@ const Header = ({
}; };
useEffect(() => { useEffect(() => {
if (showRectangle) { const queryParams = new URLSearchParams(location.search);
const hasModalParam = queryParams.has("modal");
if (showRectangle && !hasModalParam) {
document.addEventListener("mousedown", handleClickOutside); document.addEventListener("mousedown", handleClickOutside);
window.addEventListener("scroll", handleScroll); window.addEventListener("scroll", handleScroll);
} else { } else {
@@ -263,7 +268,7 @@ const Header = ({
document.removeEventListener("mousedown", handleClickOutside); document.removeEventListener("mousedown", handleClickOutside);
window.removeEventListener("scroll", handleScroll); window.removeEventListener("scroll", handleScroll);
}; };
}, [showRectangle]); }, [showRectangle, location.search]);
useEffect(() => { useEffect(() => {
setGuestSideOf(guestSideOfClerk); setGuestSideOf(guestSideOfClerk);

View File

@@ -1,15 +1,28 @@
// src/components/Modal.js import React from "react";
import React from 'react'; import styles from "./Modal.module.css";
import styles from './Modal.module.css';
const Modal = ({ isOpen, onClose, children }) => { const Modal = ({ isOpen, onClose, children }) => {
if (!isOpen) return null; if (!isOpen) return null;
// Function to handle clicks on the overlay
const handleOverlayClick = (event) => {
// Close the modal only if the overlay is clicked
onClose();
};
// Function to handle clicks on the modal content
const handleContentClick = (event) => {
// Prevent click event from propagating to the overlay
event.stopPropagation();
};
return ( return (
<div className={styles.modalOverlay}> <div onClick={handleOverlayClick} className={styles.modalOverlay}>
<div className={styles.modalContent}> <div className={styles.modalContent} onClick={handleContentClick}>
{children} {children}
<button onClick={onClose} className={styles.closeButton}>Close</button> <button onClick={onClose} className={styles.closeButton}>
Close
</button>
</div> </div>
</div> </div>
); );

View File

@@ -1,34 +1,33 @@
/* src/components/Modal.module.css */ /* src/components/Modal.module.css */
.modalOverlay { .modalOverlay {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
z-index: 1000; z-index: 1000;
} }
.modalContent { .modalContent {
background: white; background: white;
padding: 20px; padding: 20px;
border-radius: 5px; border-radius: 5px;
width: 500px; width: 80%;
max-width: 100%; height: 80%;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
position: relative; position: relative;
} }
.closeButton { .closeButton {
margin-top: 20px; margin-top: 20px;
background: #f44336; background: #f44336;
color: white; color: white;
border: none; border: none;
padding: 10px; padding: 10px;
cursor: pointer; cursor: pointer;
border-radius: 5px; border-radius: 5px;
} }

View File

@@ -2,41 +2,83 @@ import { useNavigate } from "react-router-dom";
/** /**
* Custom hook to provide navigation functions. * Custom hook to provide navigation functions.
* @param {string} params - The shop ID for constructing URLs. * @param {string} shopId - The shop ID for constructing URLs.
* @returns {Object} - Navigation functions. * @returns {Object} - Navigation functions.
*/ */
export const useNavigationHelpers = (params) => { export const useNavigationHelpers = (shopId, tableId) => {
const navigate = useNavigate(); const navigate = useNavigate();
const goToLogin = () => { const goToLogin = () => {
if (params) navigate(`/login?next=${params}`); // Construct the base URL
else navigate(`/login`); let url = "/login";
// Append query parameters conditionally
const queryParams = new URLSearchParams();
if (shopId) queryParams.append("next", shopId);
if (tableId) queryParams.append("table", tableId);
// Set the URL with query parameters
if (queryParams.toString()) {
url += `?${queryParams.toString()}`;
}
// Perform the navigation
navigate(url);
}; };
const goToShop = () => { const goToShop = () => {
navigate(`/${params}/`); // Construct the base URL for the shop
let url = `/${shopId}`;
// Append the tableId if it's provided
if (tableId) {
url += `/${tableId}`;
}
// Perform the navigation
navigate(url);
}; };
const goToSearch = () => { const goToSearch = () => {
navigate(`/${params}/search`); let url = `/${shopId}`;
if (tableId) {
url += `/${tableId}`;
}
url += "/search";
navigate(url);
}; };
const goToCart = () => { const goToCart = () => {
navigate(`/${params}/cart`); let url = `/${shopId}`;
if (tableId) {
url += `/${tableId}`;
}
url += "/cart";
navigate(url);
}; };
const goToInvoice = (orderType, tableNumber, email) => { const goToInvoice = (orderType, tableNumber, email) => {
if (orderType === "serve" && tableNumber) { let url = `/${shopId}`;
navigate( if (tableId) {
`/${params}/invoice?orderType=${orderType}&tableNumber=${tableNumber}&email=${email}`, url += `/${tableId}`;
);
} else {
navigate(`/${params}/invoice?orderType=${orderType}&email=${email}`);
} }
url += `/invoice?orderType=${orderType}`;
if (tableNumber) {
url += `&tableNumber=${tableNumber}`;
}
if (email) {
url += `&email=${email}`;
}
navigate(url);
}; };
const goToGuestSideLogin = () => { const goToGuestSideLogin = () => {
navigate(`/${params}/guest-side-login`); let url = `/${shopId}`;
if (tableId) {
url += `/${tableId}`;
}
url += "/guest-side-login";
navigate(url);
}; };
const goToAdminCafes = () => { const goToAdminCafes = () => {

View File

@@ -27,11 +27,12 @@ function CafePage({
guestSides, guestSides,
guestSideOfClerk, guestSideOfClerk,
removeConnectedGuestSides, removeConnectedGuestSides,
setModal,
}) { }) {
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const token = searchParams.get("token"); const token = searchParams.get("token");
const { shopId } = useParams(); const { shopId, tableId } = useParams();
sendParam(shopId); sendParam({ shopId, tableId });
const navigate = useNavigate(); const navigate = useNavigate();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
@@ -43,7 +44,6 @@ function CafePage({
useEffect(() => { useEffect(() => {
if (user.cafeId != null && user.cafeId != shopId) { if (user.cafeId != null && user.cafeId != shopId) {
navigate("/" + user.cafeId); navigate("/" + user.cafeId);
sendParam(user.cafeId);
} }
if (user.password == "unsetunsetunset") setIsModalOpen(true); if (user.password == "unsetunsetunset") setIsModalOpen(true);
}, [user]); }, [user]);
@@ -94,7 +94,7 @@ function CafePage({
<Header <Header
HeaderText={"Menu"} HeaderText={"Menu"}
showProfile={true} showProfile={true}
isEdit={() => setIsModalOpen(true)} isEdit={() => setModal("edit")}
isLogout={handleLogout} isLogout={handleLogout}
shopId={shopId} shopId={shopId}
user={user} user={user}