ok
This commit is contained in:
16
package-lock.json
generated
16
package-lock.json
generated
@@ -8031,14 +8031,6 @@
|
|||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dotenv": {
|
|
||||||
"version": "10.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
|
||||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dotenv-expand": {
|
"node_modules/dotenv-expand": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
|
||||||
@@ -16193,6 +16185,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-scripts/node_modules/dotenv": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-switch": {
|
"node_modules/react-switch": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz",
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ self.addEventListener("notificationclick", (event) => {
|
|||||||
|
|
||||||
const { cafeId, transactionId } = event.notification.data; // Get the notification data
|
const { cafeId, transactionId } = event.notification.data; // Get the notification data
|
||||||
|
|
||||||
// Open the URL with the cafeId and transactionId
|
// Dynamically detect the domain and construct the URL
|
||||||
event.waitUntil(
|
const domainUrl = self.location.origin;
|
||||||
clients.openWindow(
|
const url = `${domainUrl}/${cafeId}?modal=new_transaction&transactionId=${transactionId}`;
|
||||||
`https://srrk5s-3000.csb.app/${cafeId}?modal=new_transaction&transactionId=${transactionId}`
|
|
||||||
)
|
// Open the constructed URL
|
||||||
);
|
event.waitUntil(clients.openWindow(url));
|
||||||
});
|
});
|
||||||
|
|||||||
15
src/App.js
15
src/App.js
@@ -142,20 +142,6 @@ function App() {
|
|||||||
setGuestSides(sessionLeft.guestSideList);
|
setGuestSides(sessionLeft.guestSideList);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const checkNotifications = async (userId) => {
|
|
||||||
// try {
|
|
||||||
// const permissionGranted =
|
|
||||||
// await NotificationService.requestNotificationPermission(setModal);
|
|
||||||
// if (permissionGranted) {
|
|
||||||
// await SubscriptionService.subscribeUserToNotifications(userId);
|
|
||||||
// } else {
|
|
||||||
// setModal("blocked_notification");
|
|
||||||
// console.log("req notif");
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error("Error handling notifications:", error);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (socket == null) return;
|
if (socket == null) return;
|
||||||
|
|
||||||
@@ -227,6 +213,7 @@ function App() {
|
|||||||
removeLocalStorage("auth");
|
removeLocalStorage("auth");
|
||||||
setDeviceType("guestDevice");
|
setDeviceType("guestDevice");
|
||||||
} else {
|
} else {
|
||||||
|
console.log(data)
|
||||||
setUser(data.data.user);
|
setUser(data.data.user);
|
||||||
if (
|
if (
|
||||||
data.data.user.password == "unsetunsetunset" &&
|
data.data.user.password == "unsetunsetunset" &&
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export default function Footer({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Rounded Rectangle with "Scan Meja" and QR Icon */}
|
{/* Rounded Rectangle with "Scan Meja" and QR Icon */}
|
||||||
{showTable && shopId && (
|
{/* {showTable && shopId && (
|
||||||
<div
|
<div
|
||||||
ref={scanMejaRef}
|
ref={scanMejaRef}
|
||||||
onClick={table.length == 0 ? goToScan : handleScanMejaClick}
|
onClick={table.length == 0 ? goToScan : handleScanMejaClick}
|
||||||
@@ -150,7 +150,7 @@ export default function Footer({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)} */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
.footer-rect {
|
.footer-rect {
|
||||||
height: 75px;
|
height: 75px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.5);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
/* Adjust spacing between SVG icons */
|
/* Adjust spacing between SVG icons */
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ const Header = ({
|
|||||||
<Title>
|
<Title>
|
||||||
{shopName == null
|
{shopName == null
|
||||||
? HeaderText == null
|
? HeaderText == null
|
||||||
? "Groovebrew"
|
? "kedaimaster"
|
||||||
: HeaderText
|
: HeaderText
|
||||||
: generateMenuHeader(shopName)}
|
: generateMenuHeader(shopName)}
|
||||||
</Title>
|
</Title>
|
||||||
@@ -331,12 +331,13 @@ const Header = ({
|
|||||||
Edit profile
|
Edit profile
|
||||||
</Child>
|
</Child>
|
||||||
)}
|
)}
|
||||||
|
{shopId && user.roleId == 1 && (
|
||||||
|
<Child onClick={goToAdminCafes}>see your {user.userId == shopOwnerId ? 'other' : ''} cafes</Child>)}
|
||||||
{shopId &&
|
{shopId &&
|
||||||
user.userId == shopOwnerId &&
|
user.userId == shopOwnerId &&
|
||||||
user.username !== undefined &&
|
user.username !== undefined &&
|
||||||
user.roleId === 1 && (
|
user.roleId === 1 && (
|
||||||
<>
|
<>
|
||||||
<Child onClick={goToAdminCafes}>see your other cafes</Child>
|
|
||||||
|
|
||||||
{/* <Child onClick={() => setModal("update_stock")}>
|
{/* <Child onClick={() => setModal("update_stock")}>
|
||||||
update stock
|
update stock
|
||||||
@@ -365,7 +366,7 @@ const Header = ({
|
|||||||
</Child>
|
</Child>
|
||||||
<Child hasChildren>
|
<Child hasChildren>
|
||||||
clerks
|
clerks
|
||||||
<Child onClick={() => setModal("craete_account_clerk")}>
|
<Child onClick={() => setModal("create_clerk")}>
|
||||||
+ Add clerk
|
+ Add clerk
|
||||||
</Child>
|
</Child>
|
||||||
{shopClerks &&
|
{shopClerks &&
|
||||||
|
|||||||
@@ -205,11 +205,11 @@ const Item = ({
|
|||||||
<div className={styles.itemQty}>
|
<div className={styles.itemQty}>
|
||||||
<button
|
<button
|
||||||
className={styles.addButton}
|
className={styles.addButton}
|
||||||
style={{ backgroundColor: !isAvailable ? "gray" : "#4da94d" }}
|
style={{ backgroundColor: !isAvailable ? "gray" : "inherit" }}
|
||||||
onClick={handlePlusClick}
|
onClick={handlePlusClick}
|
||||||
disabled={!isAvailable} // Optionally disable the button if not available
|
disabled={!isAvailable} // Optionally disable the button if not available
|
||||||
>
|
>
|
||||||
Tambah
|
Pesan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
.itemImage {
|
.itemImage {
|
||||||
width: 139px;
|
width: 139px;
|
||||||
height: 149px;
|
height: 149px;
|
||||||
border-radius: 20px;
|
border-radius: 10px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -167,11 +167,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.addButton {
|
.addButton {
|
||||||
background-color: #04aa6d;
|
background-color: #ffffff;
|
||||||
border: none;
|
border: 2px solid #73a585;
|
||||||
color: white;
|
/* border: none; */
|
||||||
|
color: #73a585;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 95px;
|
width: 95px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ const ItemLister = ({
|
|||||||
const handleImageChange = (previewUrl, selectedImage) => {
|
const handleImageChange = (previewUrl, selectedImage) => {
|
||||||
setSelectedImage(selectedImage);
|
setSelectedImage(selectedImage);
|
||||||
console.log(selectedImage);
|
console.log(selectedImage);
|
||||||
|
console.log(previewUrl);
|
||||||
setPreviewUrl(previewUrl);
|
setPreviewUrl(previewUrl);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -288,10 +289,13 @@ const ItemLister = ({
|
|||||||
handleCreateItem(itemTypeId, name, price, selectedImage);
|
handleCreateItem(itemTypeId, name, price, selectedImage);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.log(selectedImage)
|
||||||
|
console.log(previewUrl)
|
||||||
const itemType = await createItemType(
|
const itemType = await createItemType(
|
||||||
shopId,
|
shopId,
|
||||||
editedTypeName,
|
editedTypeName,
|
||||||
selectedImage
|
selectedImage,
|
||||||
|
previewUrl
|
||||||
);
|
);
|
||||||
console.log(itemType);
|
console.log(itemType);
|
||||||
for (const { name, price, selectedImage } of itemsToCreate) {
|
for (const { name, price, selectedImage } of itemsToCreate) {
|
||||||
@@ -301,6 +305,7 @@ const ItemLister = ({
|
|||||||
// Clear the itemsToUpdate after saving
|
// Clear the itemsToUpdate after saving
|
||||||
setItemsToUpdate([]);
|
setItemsToUpdate([]);
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
|
if (handleUnEdit) handleUnEdit();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to save item type:", error);
|
console.error("Failed to save item type:", error);
|
||||||
}
|
}
|
||||||
@@ -503,9 +508,8 @@ const ItemLister = ({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={styles["item-list"]}>
|
<div className={styles["item-list"]}>
|
||||||
{user &&
|
{user &&(
|
||||||
user.roleId == 1 &&
|
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
||||||
user.userId == shopOwnerId &&
|
|
||||||
isEditMode && (
|
isEditMode && (
|
||||||
<>
|
<>
|
||||||
{!isAddingNewItem && (
|
{!isAddingNewItem && (
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
/* ItemLister.module.css */
|
/* ItemLister.module.css */
|
||||||
|
|
||||||
.item-lister {
|
.item-lister {
|
||||||
|
border-top: 1px solid #888;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px; /* Adjust padding as needed */
|
padding: 10px; /* Adjust padding as needed */
|
||||||
box-sizing: border-box; /* Ensure padding doesn't affect width */
|
box-sizing: border-box; /* Ensure padding doesn't affect width */
|
||||||
white-space: break-spaces;
|
white-space: break-spaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-lister:last-child {
|
|
||||||
margin-bottom: 50px;
|
|
||||||
}
|
|
||||||
.fullscreen {
|
.fullscreen {
|
||||||
position: fixed; /* Keep the container fixed */
|
position: fixed; /* Keep the container fixed */
|
||||||
top: 0; /* Adjust the top position as needed */
|
top: 0; /* Adjust the top position as needed */
|
||||||
@@ -30,6 +28,7 @@
|
|||||||
height: calc(49vw - 20px);
|
height: calc(49vw - 20px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.title-container {
|
.title-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState, useRef, useEffect } from "react";
|
|||||||
import smoothScroll from "smooth-scroll-into-view-if-needed";
|
import smoothScroll from "smooth-scroll-into-view-if-needed";
|
||||||
import "./ItemTypeLister.css";
|
import "./ItemTypeLister.css";
|
||||||
import ItemType from "./ItemType";
|
import ItemType from "./ItemType";
|
||||||
import { createItemType } from "../helpers/itemHelper.js";
|
import { createItem, createItemType } from "../helpers/itemHelper.js";
|
||||||
import { getImageUrl } from "../helpers/itemHelper";
|
import { getImageUrl } from "../helpers/itemHelper";
|
||||||
import ItemLister from "./ItemLister";
|
import ItemLister from "./ItemLister";
|
||||||
const ItemTypeLister = ({
|
const ItemTypeLister = ({
|
||||||
@@ -98,18 +98,16 @@ const ItemTypeLister = ({
|
|||||||
>
|
>
|
||||||
{isEditMode &&
|
{isEditMode &&
|
||||||
!isAddingNewItem &&
|
!isAddingNewItem &&
|
||||||
user &&
|
user && (
|
||||||
user.roleId === 1 &&
|
user.userId == shopOwnerId || user.cafeId == shopId) && (
|
||||||
user.userId === shopOwnerId && (
|
|
||||||
<ItemType
|
<ItemType
|
||||||
onClick={toggleAddNewItem}
|
onClick={toggleAddNewItem}
|
||||||
name={"create"}
|
name={"create"}
|
||||||
imageUrl={getImageUrl("uploads/addnew.png")}
|
imageUrl={getImageUrl("uploads/addnew.png")}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{user &&
|
{user &&(
|
||||||
user.roleId === 1 &&
|
user.userId == shopOwnerId || user.cafeId == shopId) &&
|
||||||
user.userId === shopOwnerId &&
|
|
||||||
isAddingNewItem && (
|
isAddingNewItem && (
|
||||||
<>
|
<>
|
||||||
<ItemLister
|
<ItemLister
|
||||||
@@ -119,7 +117,7 @@ const ItemTypeLister = ({
|
|||||||
typeName={"add new"}
|
typeName={"add new"}
|
||||||
itemList={items}
|
itemList={items}
|
||||||
isEditMode={true}
|
isEditMode={true}
|
||||||
handleCreateItem={handleCreateItem}
|
handleCreateItem={(itemTypeId, name, price, selectedImage) => createItem(shopId, name, price, selectedImage,itemTypeId)}
|
||||||
beingEditedType={beingEditedType}
|
beingEditedType={beingEditedType}
|
||||||
setBeingEditedType={setBeingEditedType}
|
setBeingEditedType={setBeingEditedType}
|
||||||
alwaysEdit={true}
|
alwaysEdit={true}
|
||||||
@@ -137,8 +135,8 @@ const ItemTypeLister = ({
|
|||||||
{itemTypes &&
|
{itemTypes &&
|
||||||
itemTypes.map(
|
itemTypes.map(
|
||||||
(itemType) =>
|
(itemType) =>
|
||||||
((user && user.roleId === 1 && user.userId === shopOwnerId) ||
|
(
|
||||||
itemType.itemList.length > 0) && (
|
itemType.itemList.length > 0 || (user && (user.userId == shopOwnerId || user.cafeId == shopId))) && (
|
||||||
<ItemType
|
<ItemType
|
||||||
key={itemType.itemTypeId}
|
key={itemType.itemTypeId}
|
||||||
name={itemType.name}
|
name={itemType.name}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import styles from "./Modal.module.css";
|
import styles from "./Modal.module.css";
|
||||||
|
import CreateClerk from "../pages/CreateClerk"
|
||||||
import TablesPage from "./TablesPage.js";
|
import TablesPage from "./TablesPage.js";
|
||||||
import PaymentOptions from "./PaymentOptions.js";
|
import PaymentOptions from "./PaymentOptions.js";
|
||||||
import TableMaps from "../components/TableMaps";
|
import TableMaps from "../components/TableMaps";
|
||||||
@@ -37,6 +38,7 @@ const Modal = ({ shop, isOpen, onClose, modalContent }) => {
|
|||||||
</button>
|
</button>
|
||||||
{modalContent === "req_notification" && <NotificationBlocked />}
|
{modalContent === "req_notification" && <NotificationBlocked />}
|
||||||
{modalContent === "blocked_notification" && <NotificationBlocked />}
|
{modalContent === "blocked_notification" && <NotificationBlocked />}
|
||||||
|
{modalContent === "create_clerk" && <CreateClerk 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} />
|
<Transaction propsShopId={shop.cafeId} />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.music-player {
|
.music-player {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 95%;
|
width: 95%;
|
||||||
margin: -10px auto 20px;
|
margin: 7px auto 20px;
|
||||||
/* Added padding for top and bottom */
|
/* Added padding for top and bottom */
|
||||||
color: white;
|
color: white;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
/* Center the background image */
|
/* Center the background image */
|
||||||
filter: blur(1.5px);
|
filter: blur(1.5px);
|
||||||
-webkit-filter: blur(1.5px);
|
-webkit-filter: blur(1.5px);
|
||||||
border-radius: 23px 23px 0 0;
|
border-radius: 13px 13px 0 0;
|
||||||
background-color: rgb(95 121 89);
|
background-color: rgb(95 121 89);
|
||||||
/* Rounded corners at the top */
|
/* Rounded corners at the top */
|
||||||
text-align: right;
|
text-align: right;
|
||||||
@@ -32,6 +32,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.current-name {
|
.current-name {
|
||||||
|
white-space: nowrap;
|
||||||
|
pointer-events: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -41,7 +43,29 @@
|
|||||||
/* Text shadow for readability */
|
/* Text shadow for readability */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* styles.css */
|
||||||
|
@keyframes slideAnimation {
|
||||||
|
0% {
|
||||||
|
margin-left: 100vw;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
margin-left: 30px;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
margin-left: -100vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animated-text {
|
||||||
|
animation: slideAnimation 3s linear infinite; /* 4s duration for the animation */
|
||||||
|
white-space: nowrap; /* Prevent text from wrapping */
|
||||||
|
}
|
||||||
|
|
||||||
.current-artist {
|
.current-artist {
|
||||||
|
pointer-events: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -52,6 +76,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.progress-container {
|
.progress-container {
|
||||||
|
pointer-events: none;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -104,9 +129,10 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
background-color: rgb(29, 185, 84);
|
/* background-color: rgb(29, 185, 84); */
|
||||||
|
background-color: #73a585;
|
||||||
/* background-color: rgb(218 163 99); */
|
/* background-color: rgb(218 163 99); */
|
||||||
border-radius: 0 0 23px 23px;
|
border-radius: 0 0 13px 13px;
|
||||||
/* Rounded corners at the bottom */
|
/* Rounded corners at the bottom */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -134,7 +160,9 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: rgb(29, 185, 84);
|
/* background-color: rgb(29, 185, 84); */
|
||||||
|
|
||||||
|
background-color: #73a585;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-box input[type="text"] {
|
.search-box input[type="text"] {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import MusicComponent from "./MusicComponent";
|
|||||||
export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
||||||
const [currentTime, setCurrentTime] = useState(0);
|
const [currentTime, setCurrentTime] = useState(0);
|
||||||
const [trackLength, setTrackLength] = useState(0);
|
const [trackLength, setTrackLength] = useState(0);
|
||||||
|
const [viewing, setViewing] = useState(false); // State for expansion
|
||||||
const [expanded, setExpanded] = useState(false); // State for expansion
|
const [expanded, setExpanded] = useState(false); // State for expansion
|
||||||
|
|
||||||
const [songName, setSongName] = useState("");
|
const [songName, setSongName] = useState("");
|
||||||
@@ -251,6 +252,9 @@ export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
|||||||
return `${minutes}:${formattedSeconds}`;
|
return `${minutes}:${formattedSeconds}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleView = () => {
|
||||||
|
setViewing(!viewing);
|
||||||
|
};
|
||||||
const toggleExpand = () => {
|
const toggleExpand = () => {
|
||||||
setExpanded(!expanded);
|
setExpanded(!expanded);
|
||||||
};
|
};
|
||||||
@@ -263,9 +267,47 @@ export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
|||||||
}
|
}
|
||||||
}, [expanded]);
|
}, [expanded]);
|
||||||
|
|
||||||
|
|
||||||
|
const [text, setText] = useState("Awaiting the next hit");
|
||||||
|
const textIndex = useRef(0);
|
||||||
|
const [messages, setMessages] = useState(["Awaiting the next hit", "Click to request your fav song"]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update the messages based on currentSong
|
||||||
|
const newMessages = [
|
||||||
|
currentSong != null && currentSong.item != undefined
|
||||||
|
? `${currentSong.item.artists[0].name} - ${currentSong.item.name}`
|
||||||
|
: "Awaiting the next hit",
|
||||||
|
"Click to request your fav song"
|
||||||
|
];
|
||||||
|
|
||||||
|
setMessages(newMessages);
|
||||||
|
setText(newMessages[0]); // Update the text state to the first message
|
||||||
|
|
||||||
|
const element = document.querySelector('.animated-text');
|
||||||
|
|
||||||
|
// Check if the element exists before adding the event listener
|
||||||
|
if (element) {
|
||||||
|
const handleAnimationIteration = () => {
|
||||||
|
// Toggle between the two text values based on the current index
|
||||||
|
textIndex.current = (textIndex.current + 1) % messages.length;
|
||||||
|
setText(messages[textIndex.current]);
|
||||||
|
};
|
||||||
|
|
||||||
|
element.addEventListener('animationiteration', handleAnimationIteration);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
element.removeEventListener('animationiteration', handleAnimationIteration);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, [currentSong]); // Run effect when currentSong changes
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`music-player ${expanded ? "expanded" : ""}`}>
|
<div className={`music-player`} style={{ marginBottom: `${viewing? '-10px' : ''}` }}>
|
||||||
<div
|
<div
|
||||||
|
onClick={toggleView}
|
||||||
className="current-bgr"
|
className="current-bgr"
|
||||||
style={{ backgroundImage: `url(${backgroundImage})` }}
|
style={{ backgroundImage: `url(${backgroundImage})` }}
|
||||||
>
|
>
|
||||||
@@ -287,11 +329,14 @@ export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="current-info" >
|
<div className="current-info" >
|
||||||
<div className="current-name">
|
<div
|
||||||
|
className={`current-name ${viewing? '' : 'animated-text'}`} style={{margin:`${viewing? '35px 30px' : '13px 30px'}`}}>
|
||||||
{currentSong.item && currentSong.item.name
|
{currentSong.item && currentSong.item.name
|
||||||
? currentSong.item.name
|
? (viewing? currentSong.item.name:text)
|
||||||
: "Awaiting the next hit"}
|
:
|
||||||
|
viewing? messages[0]:text}
|
||||||
</div>
|
</div>
|
||||||
|
{viewing && <>
|
||||||
<div className="current-artist">
|
<div className="current-artist">
|
||||||
{currentSong.item &&
|
{currentSong.item &&
|
||||||
currentSong.item.album &&
|
currentSong.item.album &&
|
||||||
@@ -322,8 +367,11 @@ export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
|||||||
>
|
>
|
||||||
{formatTime(trackLength)}
|
{formatTime(trackLength)}
|
||||||
</div>
|
</div>
|
||||||
|
</div></>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{viewing &&
|
||||||
|
<>
|
||||||
<div
|
<div
|
||||||
className={`expandable-container ${expanded ? "expanded" : ""}`}
|
className={`expandable-container ${expanded ? "expanded" : ""}`}
|
||||||
ref={expandableContainerRef}
|
ref={expandableContainerRef}
|
||||||
@@ -390,7 +438,7 @@ export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
|||||||
<div className="expand-button" onClick={toggleExpand}>
|
<div className="expand-button" onClick={toggleExpand}>
|
||||||
<h5>
|
<h5>
|
||||||
{expanded
|
{expanded
|
||||||
? "collapse"
|
? "︿"
|
||||||
: currentSong.item &&
|
: currentSong.item &&
|
||||||
currentSong.item.album &&
|
currentSong.item.album &&
|
||||||
currentSong.item.album.images[0] &&
|
currentSong.item.album.images[0] &&
|
||||||
@@ -398,7 +446,8 @@ export function MusicPlayer({ socket, shopId, user, isSpotifyNeedLogin }) {
|
|||||||
? "expand"
|
? "expand"
|
||||||
: "request your song"}
|
: "request your song"}
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div></>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, {useState} from "react";
|
||||||
import QRCodeWithBackground from "./QR"; // Adjust path as needed
|
import QRCodeWithBackground from "./QR"; // Adjust path as needed
|
||||||
const TableList = ({ shop, tables, onSelectTable, selectedTable }) => {
|
|
||||||
|
const TableList = ({ shop, tables, onSelectTable, selectedTable, handleSetTableNo, handleAddTable }) => {
|
||||||
const [initialPos, setInitialPos] = useState({
|
const [initialPos, setInitialPos] = useState({
|
||||||
left: shop.xposition,
|
left: shop.xposition,
|
||||||
top: shop.yposition,
|
top: shop.yposition,
|
||||||
@@ -21,16 +22,16 @@ const TableList = ({ shop, tables, onSelectTable, selectedTable }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBackgroundUrlChange = (newUrl) => {
|
|
||||||
setBgImageUrl(newUrl);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleQrSave = (qrPosition, qrSize, bgImage) => {
|
const handleQrSave = (qrPosition, qrSize, bgImage) => {
|
||||||
setInitialPos(qrPosition);
|
setInitialPos(qrPosition);
|
||||||
setInitialSize(qrSize);
|
setInitialSize(qrSize);
|
||||||
setBgImageUrl(bgImage);
|
setBgImageUrl(bgImage);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCreateTable = () => {
|
||||||
|
handleAddTable();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -71,6 +72,43 @@ const TableList = ({ shop, tables, onSelectTable, selectedTable }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
|
{/* Add new table input */}
|
||||||
|
<li
|
||||||
|
style={{
|
||||||
|
backgroundColor: "lightgreen",
|
||||||
|
marginBottom: "10px",
|
||||||
|
padding: "10px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
boxShadow: "0 2px 4px rgba(0,0,0,0.1)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter table number"
|
||||||
|
onChange={handleSetTableNo} // Directly using the parent function
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
padding: "8px",
|
||||||
|
marginBottom: "10px",
|
||||||
|
borderRadius: "4px",
|
||||||
|
border: "1px solid #ccc",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleCreateTable}
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
padding: "10px",
|
||||||
|
backgroundColor: "#28a745",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "4px",
|
||||||
|
border: "none",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Table
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
{tables &&
|
{tables &&
|
||||||
tables
|
tables
|
||||||
.filter((table) => table.tableNo !== 0)
|
.filter((table) => table.tableNo !== 0)
|
||||||
|
|||||||
@@ -130,10 +130,10 @@ const TablesPage = ({ shop }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
if (newTable) {
|
// if (newTable) {
|
||||||
try {
|
try {
|
||||||
const createdTable = await createTable(shop.cafeId, {
|
const createdTable = await createTable(shop.cafeId, {
|
||||||
...newTable,
|
// ...newTable,
|
||||||
tableNo,
|
tableNo,
|
||||||
});
|
});
|
||||||
setTables([...tables, createdTable]);
|
setTables([...tables, createdTable]);
|
||||||
@@ -143,28 +143,28 @@ const TablesPage = ({ shop }) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error creating table:", error);
|
console.error("Error creating table:", error);
|
||||||
}
|
}
|
||||||
} else if (selectedTable) {
|
// } else if (selectedTable) {
|
||||||
try {
|
// try {
|
||||||
const updatedTable = await updateTable(shop.cafeId, {
|
// const updatedTable = await updateTable(shop.cafeId, {
|
||||||
...selectedTable,
|
// ...selectedTable,
|
||||||
tableNo,
|
// tableNo,
|
||||||
});
|
// });
|
||||||
setTables(
|
// setTables(
|
||||||
tables.map((table) =>
|
// tables.map((table) =>
|
||||||
table.tableId === updatedTable.tableId ? updatedTable : table
|
// table.tableId === updatedTable.tableId ? updatedTable : table
|
||||||
)
|
// )
|
||||||
);
|
// );
|
||||||
setOriginalTables(
|
// setOriginalTables(
|
||||||
tables.map((table) =>
|
// tables.map((table) =>
|
||||||
table.tableId === updatedTable.tableId ? updatedTable : table
|
// table.tableId === updatedTable.tableId ? updatedTable : table
|
||||||
)
|
// )
|
||||||
);
|
// );
|
||||||
setSelectedTable(null);
|
// setSelectedTable(null);
|
||||||
setTableNo(""); // Reset table name
|
// setTableNo(""); // Reset table name
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error("Error updating table:", error);
|
// console.error("Error updating table:", error);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSetTableNo = (event) => {
|
const handleSetTableNo = (event) => {
|
||||||
@@ -207,6 +207,8 @@ const TablesPage = ({ shop }) => {
|
|||||||
tables={tables}
|
tables={tables}
|
||||||
onSelectTable={handleSelect}
|
onSelectTable={handleSelect}
|
||||||
selectedTable={selectedTable}
|
selectedTable={selectedTable}
|
||||||
|
handleSetTableNo={handleSetTableNo}
|
||||||
|
handleAddTable={handleSave}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// src/config.js
|
// src/config.js
|
||||||
|
|
||||||
const API_BASE_URL = "https://wxf6vz-5000.csb.app"; // Replace with your actual backend URL
|
const API_BASE_URL = 'https://9qc65z-5000.csb.app';
|
||||||
|
|
||||||
export default API_BASE_URL;
|
export default API_BASE_URL;
|
||||||
|
|||||||
@@ -165,12 +165,19 @@ export async function updateItemAvalilability(itemId, isAvailable) {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export async function createItemType(shopId, name, selectedImage, previewUrl) {
|
||||||
export async function createItemType(shopId, name, selectedImage) {
|
|
||||||
try {
|
try {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("name", name);
|
formData.append("name", name);
|
||||||
|
|
||||||
|
// Check if selectedImage is provided
|
||||||
|
if (selectedImage) {
|
||||||
formData.append("image", selectedImage);
|
formData.append("image", selectedImage);
|
||||||
|
} else if (previewUrl) {
|
||||||
|
// Remove the API_BASE_URL and any leading slashes from previewUrl
|
||||||
|
const processedPreviewUrl = previewUrl.replace(API_BASE_URL, "").replace(/^\/+/, "");
|
||||||
|
formData.append("sampleImage", processedPreviewUrl);
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(`${API_BASE_URL}/item/createType/${shopId}`, {
|
const response = await fetch(`${API_BASE_URL}/item/createType/${shopId}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -192,6 +199,7 @@ export async function createItemType(shopId, name, selectedImage) {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateItemType(
|
export async function updateItemType(
|
||||||
shopId,
|
shopId,
|
||||||
itemTypeId,
|
itemTypeId,
|
||||||
|
|||||||
@@ -193,12 +193,12 @@ export const getAllCafeOwner = async (formData) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createCafeOwner = async (shopId, email, username, password) => {
|
export const createCafeOwner = async (email, username, password) => {
|
||||||
const token = getLocalStorage("auth");
|
const token = getLocalStorage("auth");
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
API_BASE_URL + "/user/create-clerk/" + shopId,
|
API_BASE_URL + "/user/create-admin/" ,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@@ -276,6 +276,7 @@ export const createClerks = async (shopId, email, username, password) => {
|
|||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log(data)
|
||||||
return data;
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error getting clerk:", error);
|
console.error("Error getting clerk:", error);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import Header from "../components/Header";
|
|||||||
|
|
||||||
import { ThreeDots } from "react-loader-spinner";
|
import { ThreeDots } from "react-loader-spinner";
|
||||||
|
|
||||||
import { updateLocalStorage } from "../helpers/localStorageHelpers";
|
import { updateLocalStorage, removeLocalStorage } from "../helpers/localStorageHelpers";
|
||||||
import { unsubscribeUser } from "../helpers/subscribeHelpers.js";
|
import { unsubscribeUser } from "../helpers/subscribeHelpers.js";
|
||||||
import WelcomePage from "./WelcomePage.js";
|
import WelcomePage from "./WelcomePage.js";
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@ function CafePage({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
updateLocalStorage("auth", "");
|
removeLocalStorage("auth");
|
||||||
unsubscribeUser();
|
unsubscribeUser();
|
||||||
navigate(0);
|
navigate(0);
|
||||||
};
|
};
|
||||||
@@ -172,9 +172,12 @@ function CafePage({
|
|||||||
setIsEditMode={(e) => setIsEditMode(e)}
|
setIsEditMode={(e) => setIsEditMode(e)}
|
||||||
isEditMode={isEditMode}
|
isEditMode={isEditMode}
|
||||||
/>
|
/>
|
||||||
<div style={{ marginTop: "5px" }}></div>
|
<MusicPlayer
|
||||||
<SearchInput shopId={shopId} tableCode={table.tableCode} />
|
socket={socket}
|
||||||
<div style={{ marginTop: "15px" }}></div>
|
shopId={shopId}
|
||||||
|
user={user}
|
||||||
|
isSpotifyNeedLogin={isSpotifyNeedLogin}
|
||||||
|
/>
|
||||||
<ItemTypeLister
|
<ItemTypeLister
|
||||||
user={user}
|
user={user}
|
||||||
shopOwnerId={shopOwnerId}
|
shopOwnerId={shopOwnerId}
|
||||||
@@ -186,22 +189,8 @@ function CafePage({
|
|||||||
beingEditedType={beingEditedType}
|
beingEditedType={beingEditedType}
|
||||||
setBeingEditedType={setBeingEditedType}
|
setBeingEditedType={setBeingEditedType}
|
||||||
/>
|
/>
|
||||||
<div style={{ marginTop: "-13px" }}></div>
|
|
||||||
{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>
|
{/* <div style={{ marginTop: "15px" }}></div> */}
|
||||||
{shopItems
|
{shopItems
|
||||||
.filter(
|
.filter(
|
||||||
(itemType) =>
|
(itemType) =>
|
||||||
|
|||||||
@@ -163,9 +163,10 @@ export default function Invoice({ table, sendParam, deviceType, socket }) {
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{table.tableNo != null && (
|
||||||
<div className={styles.OrderTypeContainer}>
|
<div className={styles.OrderTypeContainer}>
|
||||||
<span htmlFor="orderType">Order Type:</span>
|
<span htmlFor="orderType">Serve to table {table.tableNo}</span>
|
||||||
<select
|
{/* <select
|
||||||
id="orderType"
|
id="orderType"
|
||||||
value={orderType}
|
value={orderType}
|
||||||
onChange={handleOrderTypeChange}
|
onChange={handleOrderTypeChange}
|
||||||
@@ -175,10 +176,9 @@ export default function Invoice({ table, sendParam, deviceType, socket }) {
|
|||||||
)}
|
)}
|
||||||
<option value="pickup">Pickup</option>
|
<option value="pickup">Pickup</option>
|
||||||
{table == null && <option value="serve">Serve</option>}
|
{table == null && <option value="serve">Serve</option>}
|
||||||
|
</select> */}
|
||||||
{/* tableId harus di check terlebih dahulu untuk mendapatkan tableNo */}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
{orderType === "serve" && table.length < 1 && (
|
{orderType === "serve" && table.length < 1 && (
|
||||||
<div className={styles.OrderTypeContainer}>
|
<div className={styles.OrderTypeContainer}>
|
||||||
<span htmlFor="orderType">Serve to:</span>
|
<span htmlFor="orderType">Serve to:</span>
|
||||||
|
|||||||
111
src/pages/CreateClerk.js
Normal file
111
src/pages/CreateClerk.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { createClerks } from '../helpers/userHelpers'; // Adjust the import path as needed
|
||||||
|
|
||||||
|
const CreateClerk = ({ shopId }) => {
|
||||||
|
const [email, setEmail] = useState('');
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [message, setMessage] = useState('');
|
||||||
|
|
||||||
|
const handleSubmit = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
setLoading(true);
|
||||||
|
setMessage('');
|
||||||
|
|
||||||
|
// Basic validation
|
||||||
|
if (!email || !username || !password) {
|
||||||
|
setMessage('All fields are required');
|
||||||
|
setLoading(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const create = await createClerks(shopId, email, username, password);
|
||||||
|
|
||||||
|
if(create) setMessage('Clerk created successfully');
|
||||||
|
else setMessage('failed')
|
||||||
|
} catch (error) {
|
||||||
|
setMessage('Error creating clerk');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={styles.container}>
|
||||||
|
<h2 style={styles.header}>Create Clerk</h2>
|
||||||
|
<form onSubmit={handleSubmit} style={styles.form}>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
placeholder="Email"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
style={styles.input}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Username"
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
style={styles.input}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder="Password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
style={styles.input}
|
||||||
|
/>
|
||||||
|
<button type="submit" style={styles.button} disabled={loading}>
|
||||||
|
{loading ? 'Creating...' : 'Create Clerk'}
|
||||||
|
</button>
|
||||||
|
{message && <p style={styles.message}>{message}</p>}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Basic styling to make it mobile-friendly
|
||||||
|
const styles = {
|
||||||
|
container: {
|
||||||
|
width: '100%',
|
||||||
|
maxWidth: '400px',
|
||||||
|
margin: '0 auto',
|
||||||
|
padding: '20px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
header: {
|
||||||
|
textAlign: 'center',
|
||||||
|
marginBottom: '20px',
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '15px',
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
padding: '10px',
|
||||||
|
fontSize: '16px',
|
||||||
|
borderRadius: '5px',
|
||||||
|
border: '1px solid #ccc',
|
||||||
|
width: '100%',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
padding: '10px',
|
||||||
|
fontSize: '16px',
|
||||||
|
borderRadius: '5px',
|
||||||
|
border: 'none',
|
||||||
|
backgroundColor: '#28a745',
|
||||||
|
color: 'white',
|
||||||
|
cursor: 'pointer',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'red',
|
||||||
|
marginTop: '10px',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateClerk;
|
||||||
@@ -3,7 +3,7 @@ import styles from "./Dashboard.module.css"; // Import module CSS for styling
|
|||||||
import Header from "../components/Header";
|
import Header from "../components/Header";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import AccountUpdateModal from "../components/AccountUpdateModal";
|
import AccountUpdateModal from "../components/AccountUpdateModal";
|
||||||
import { updateLocalStorage } from "../helpers/localStorageHelpers";
|
import { removeLocalStorage } from "../helpers/localStorageHelpers";
|
||||||
import { getAllCafeOwner, createCafeOwner } from "../helpers/userHelpers";
|
import { getAllCafeOwner, createCafeOwner } from "../helpers/userHelpers";
|
||||||
import { getOwnedCafes, createCafe, updateCafe } from "../helpers/cafeHelpers";
|
import { getOwnedCafes, createCafe, updateCafe } from "../helpers/cafeHelpers";
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ const Dashboard = ({ user, setModal }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
updateLocalStorage("auth", "");
|
removeLocalStorage("auth");
|
||||||
unsubscribeUser();
|
unsubscribeUser();
|
||||||
navigate(0);
|
navigate(0);
|
||||||
};
|
};
|
||||||
@@ -58,9 +58,9 @@ const Dashboard = ({ user, setModal }) => {
|
|||||||
const handleCreateItem = () => {
|
const handleCreateItem = () => {
|
||||||
if (user.roleId < 1) {
|
if (user.roleId < 1) {
|
||||||
// Create admin functionality
|
// Create admin functionality
|
||||||
createCafeOwner(newItem.name)
|
createCafeOwner(newItem.email, newItem.username, newItem.password)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setItems([...items, { name: newItem.name }]);
|
setItems([...items, { name: newItem.username }]);
|
||||||
setIsCreating(false);
|
setIsCreating(false);
|
||||||
setNewItem({ name: "", type: "" });
|
setNewItem({ name: "", type: "" });
|
||||||
})
|
})
|
||||||
@@ -84,7 +84,7 @@ const Dashboard = ({ user, setModal }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header
|
<Header
|
||||||
HeaderText={"GrooveBrew"}
|
HeaderText={"kedaimaster"}
|
||||||
isEdit={() => setIsModalOpen(true)}
|
isEdit={() => setIsModalOpen(true)}
|
||||||
isLogout={handleLogout}
|
isLogout={handleLogout}
|
||||||
user={user}
|
user={user}
|
||||||
@@ -132,12 +132,31 @@ const Dashboard = ({ user, setModal }) => {
|
|||||||
{isCreating && (
|
{isCreating && (
|
||||||
<div className={styles.createModal}>
|
<div className={styles.createModal}>
|
||||||
<h2>Create New {user.roleId < 1 ? "Admin" : "Cafe"}</h2>
|
<h2>Create New {user.roleId < 1 ? "Admin" : "Cafe"}</h2>
|
||||||
|
{user.roleId < 1 ?<>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
value={newItem.email}
|
||||||
|
onChange={(e) => setNewItem({ ...newItem, email: e.target.value })}
|
||||||
|
placeholder="email"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={newItem.username}
|
||||||
|
onChange={(e) => setNewItem({ ...newItem, username: e.target.value })}
|
||||||
|
placeholder="username"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
value={newItem.password}
|
||||||
|
onChange={(e) => setNewItem({ ...newItem, password: e.target.value })}
|
||||||
|
placeholder="Password"
|
||||||
|
/></> :
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
value={newItem.name}
|
value={newItem.name}
|
||||||
onChange={(e) => setNewItem({ ...newItem, name: e.target.value })}
|
onChange={(e) => setNewItem({ ...newItem, name: e.target.value })}
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
/>
|
/>}
|
||||||
<button onClick={handleCreateItem}>Create</button>
|
<button onClick={handleCreateItem}>Create</button>
|
||||||
<button onClick={() => setIsCreating(false)}>Cancel</button>
|
<button onClick={() => setIsCreating(false)}>Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user