This commit is contained in:
frontend perkafean
2024-09-18 08:40:55 +00:00
parent f46639e05c
commit dbc43d18fa
18 changed files with 310 additions and 166 deletions

13
package-lock.json generated
View File

@@ -25,6 +25,7 @@
"react-qr-reader": "^3.0.0-beta-1",
"react-router-dom": "^6.24.0",
"react-scripts": "5.0.1",
"react-switch": "^7.0.0",
"socket.io-client": "^4.7.5",
"styled-components": "^6.1.11",
"web-vitals": "^2.1.4"
@@ -16186,6 +16187,18 @@
}
}
},
"node_modules/react-switch": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/react-switch/-/react-switch-7.0.0.tgz",
"integrity": "sha512-KkDeW+cozZXI6knDPyUt3KBN1rmhoVYgAdCJqAh7st7tk8YE6N0iR89zjCWO8T8dUTeJGTR0KU+5CHCRMRffiA==",
"dependencies": {
"prop-types": "^15.7.2"
},
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",

View File

@@ -20,6 +20,7 @@
"react-qr-reader": "^3.0.0-beta-1",
"react-router-dom": "^6.24.0",
"react-scripts": "5.0.1",
"react-switch": "^7.0.0",
"socket.io-client": "^4.7.5",
"styled-components": "^6.1.11",
"web-vitals": "^2.1.4"

View File

@@ -87,11 +87,36 @@ export default function Footer({
{/* Profile Icon */}
<div onClick={goToTransactions} className={styles["footer-icon"]}>
<svg
viewBox="0 0 34 34"
style={{ fill: selectedPage === 3 ? "black" : "#8F8787" }}
>
<path d="M15.9842 0.166656C7.24421 0.166656 0.150879 7.25999 0.150879 16C0.150879 24.74 7.24421 31.8333 15.9842 31.8333C24.7242 31.8333 31.8175 24.74 31.8175 16C31.8175 7.25999 24.7242 0.166656 15.9842 0.166656ZM21.7 10.205C23.3942 10.205 24.7559 11.5667 24.7559 13.2608C24.7559 14.955 23.3942 16.3167 21.7 16.3167C20.0059 16.3167 18.6442 14.955 18.6442 13.2608C18.6284 11.5667 20.0059 10.205 21.7 10.205ZM12.2 7.70332C14.2584 7.70332 15.9367 9.38166 15.9367 11.44C15.9367 13.4983 14.2584 15.1767 12.2 15.1767C10.1417 15.1767 8.46338 13.4983 8.46338 11.44C8.46338 9.36582 10.1259 7.70332 12.2 7.70332ZM12.2 22.1592V28.0967C8.40005 26.9092 5.39171 23.98 4.06171 20.2433C5.72421 18.47 9.87255 17.5675 12.2 17.5675C13.0392 17.5675 14.1 17.6942 15.2084 17.9158C12.6117 19.2933 12.2 21.1142 12.2 22.1592ZM15.9842 28.6667C15.5567 28.6667 15.145 28.6508 14.7334 28.6033V22.1592C14.7334 19.9108 19.3884 18.7867 21.7 18.7867C23.3942 18.7867 26.3234 19.4042 27.78 20.6075C25.9275 25.31 21.3517 28.6667 15.9842 28.6667Z" />
<svg viewBox="0 0 512 512">
<g
transform="translate(0 512) scale(0.1 -0.1)"
style={{ fill: selectedPage === 3 ? "black" : "#8F8787" }}
stroke="none"
>
<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
-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
14 2238 0 2400 4 2243 -53 2303 -67 72 -160 81 -268 26 -52 -26 -89 -37 -138
-41 -99 -8 -161 13 -268 93 -119 89 -140 97 -248 98 -108 0 -129 -8 -249 -98
-107 -80 -168 -101 -267 -93 -79 7 -121 26 -231 108 -165 122 -309 119 -471
-9 -87 -69 -138 -92 -216 -99 -99 -8 -161 13 -268 93 -48 36 -104 73 -123 81
-49 20 -165 26 -221 10z m2274 -1226 c21 -13 50 -42 65 -64 22 -34 27 -52 27
-106 0 -79 -25 -128 -88 -169 l-41 -27 -1165 0 -1166 0 -38 24 c-76 47 -111
140 -88 229 14 52 76 117 123 131 20 6 475 9 1183 8 l1150 -2 38 -24z m0 -900
c21 -13 50 -42 65 -64 22 -34 27 -52 27 -106 0 -79 -25 -128 -88 -169 l-41
-27 -1165 0 -1166 0 -38 24 c-76 47 -111 140 -88 229 14 52 76 117 123 131
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
76 117 123 131 20 6 291 9 684 8 l650 -2 41 -27z"
/>
<path
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
-39 138 -97 174 l-38 24 -1650 2 c-1023 1 -1662 -2 -1683 -8z"
/>
</g>
</svg>
</div>
</div>

View File

@@ -1,5 +1,4 @@
.footerContainer {
margin-top: 40px;
}
.footer-rect {
height: 75px;
@@ -22,8 +21,6 @@
width: calc(100vw);
/* Adjust size as needed, subtracting margin */
height: 75px;
/* Adjust size as needed */
margin-top: 10px;
}
.footer-icon {

View File

@@ -222,6 +222,7 @@ const Header = ({
guestSides,
guestSideOfClerk,
removeConnectedGuestSides,
setIsEditMode,
}) => {
const { goToLogin, goToGuestSideLogin, goToAdminCafes } =
useNavigationHelpers(shopId, tableCode);
@@ -320,6 +321,17 @@ const Header = ({
</Child> */}
<Child hasChildren>
{shopName}
<div class="toggle-switch">
<input
type="checkbox"
className="toggle-switch-checkbox"
// checked={isChecked}
onChange={(e) => setIsEditMode(e.target.checked)}
/>
<label class="toggle-switch-label" for="toggleSwitch">
Edit Mode
</label>
</div>
<Child onClick={() => setModal("add_material")}>
stock
</Child>
@@ -360,6 +372,17 @@ const Header = ({
user.roleId === 2 && (
<Child hasChildren>
{shopName}
<div class="toggle-switch">
<input
type="checkbox"
className="toggle-switch-checkbox"
// checked={isChecked}
onChange={(e) => setIsEditMode(e.target.checked)}
/>
<label class="toggle-switch-label" for="toggleSwitch">
Edit Mode
</label>
</div>
<Child onClick={() => setModal("add_material")}>
stock
</Child>

View File

@@ -111,7 +111,9 @@ const Item = ({
)}
<div className={styles.itemDetails}>
<input
className={`${forInvoice ? styles.itemInvoiceName : styles.itemName} ${blank ? styles.blank : styles.notblank}`}
className={`${
forInvoice ? styles.itemInvoiceName : styles.itemName
} ${blank ? styles.blank : styles.notblank}`}
value={itemName}
onChange={handleNameChange}
disabled={!blank}
@@ -125,7 +127,9 @@ const Item = ({
)}
{!forInvoice && (
<input
className={`${styles.itemPrice} ${blank ? styles.blank : styles.notblank}`}
className={`${styles.itemPrice} ${
blank ? styles.blank : styles.notblank
}`}
value={itemPrice}
onChange={handlePriceChange}
disabled={!blank}

View File

@@ -1,205 +1,206 @@
.itemContainer {
display: flex;
flex-direction: column;
gap: 10px;
display: flex;
flex-direction: column;
/* gap: 10px; */
}
.item {
display: flex;
align-items: stretch;
justify-content: space-between;
padding-left: 5px;
margin-bottom: 10px;
color: rgba(88, 55, 50, 1);
font-size: 32px;
box-sizing: border-box; /* Include padding and border in the element's total width */
width: 100%; /* Ensure the item does not exceed the parent's width */
overflow: hidden; /* Prevent internal overflow */
display: flex;
align-items: stretch;
justify-content: space-between;
padding-left: 5px;
margin-top: 5px;
margin-bottom: 5px;
color: rgba(88, 55, 50, 1);
font-size: 32px;
box-sizing: border-box; /* Include padding and border in the element's total width */
width: 100%; /* Ensure the item does not exceed the parent's width */
overflow: hidden; /* Prevent internal overflow */
}
.itemInvoice {
flex-direction: row;
align-items: center;
justify-content: space-around;
font-size: 18px;
margin-bottom: 45px;
flex-direction: row;
align-items: center;
justify-content: space-around;
font-size: 18px;
margin-bottom: 45px;
}
.itemInvoice:last-child {
margin-bottom: 0; /* Remove margin-bottom for the last child */
margin-bottom: 0; /* Remove margin-bottom for the last child */
}
.itemImage {
width: 139px;
height: 149px;
border-radius: 20px;
margin-right: 10px;
object-fit: cover;
position: relative;
width: 139px;
height: 149px;
border-radius: 20px;
margin-right: 10px;
object-fit: cover;
position: relative;
}
.imageContainer {
position: relative;
width: 139px;
height: 149px;
position: relative;
width: 139px;
height: 149px;
}
.overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
color: white;
display: flex;
justify-content: center;
align-items: center;
border-radius: 20px;
cursor: pointer;
transition: background-color 0.3s ease;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
color: white;
display: flex;
justify-content: center;
align-items: center;
border-radius: 20px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.overlay:hover {
background-color: rgba(0, 0, 0, 0.7);
background-color: rgba(0, 0, 0, 0.7);
}
.fileInput {
display: none;
display: none;
}
.itemDetails {
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
flex-grow: 1;
}
.itemInvoiceDetails {
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
margin-top: -15px;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
margin-top: -15px;
flex-grow: 1;
}
.itemName {
font-family: "Poppins", sans-serif;
font-style: normal;
width: calc(100% - 15px); /* Adjust the width to prevent overflow */
font-size: 1.5rem;
font-weight: 500;
margin-top: 0;
margin: 0 5px;
color: rgba(88, 55, 50, 1);
background-color: transparent;
text-transform: capitalize;
font-family: "Poppins", sans-serif;
font-style: normal;
width: calc(100% - 15px); /* Adjust the width to prevent overflow */
font-size: 1.5rem;
font-weight: 500;
margin-top: 0;
margin: 0 5px;
color: rgba(88, 55, 50, 1);
background-color: transparent;
text-transform: capitalize;
}
.itemInvoiceName {
width: calc(260% - 15px);
background-color: transparent;
font-size: 1.5rem;
font-weight: 500;
width: calc(260% - 15px);
background-color: transparent;
font-size: 1.5rem;
font-weight: 500;
}
.multiplySymbol {
font-weight: 600;
font-weight: 600;
}
.qtyInvoice {
font-weight: 500;
font-weight: 500;
}
.itemPrice {
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
width: calc(100% - 15px); /* Adjust the width to prevent overflow */
font-size: 0.9rem;
margin-bottom: 35px;
margin-left: 5px;
color: #D9C61C;
background-color: transparent;
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
width: calc(100% - 15px); /* Adjust the width to prevent overflow */
font-size: 0.9rem;
margin-bottom: 35px;
margin-left: 5px;
color: #d9c61c;
background-color: transparent;
}
.itemPriceInvoice {
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
width: calc(100% - 15px); /* Adjust the width to prevent overflow */
font-size: 0.9rem;
margin-left: 5px;
color: #D9C61C;
text-align: right;
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
width: calc(100% - 15px); /* Adjust the width to prevent overflow */
font-size: 0.9rem;
margin-left: 5px;
color: #d9c61c;
text-align: right;
}
.itemQty {
display: flex;
align-items: center;
font-size: 0.9rem;
margin-left: 5px;
display: flex;
align-items: center;
font-size: 0.9rem;
margin-left: 5px;
}
.itemQtyValue {
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
margin-top: 5px;
margin-left: 5px;
margin-right: 5px;
width: 25px;
text-align: center;
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
margin-top: 5px;
margin-left: 5px;
margin-right: 5px;
width: 25px;
text-align: center;
}
.itemQtyInput {
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
width: 30px; /* Adjust the width to prevent overflow */
font-size: 0.9rem;
margin-bottom: 10px;
text-align: center;
background-color: transparent;
font-family: "Poppins", sans-serif;
font-style: normal;
font-weight: 600;
width: 30px; /* Adjust the width to prevent overflow */
font-size: 0.9rem;
margin-bottom: 10px;
text-align: center;
background-color: transparent;
}
.plusNegative {
width: 35px;
height: 35px;
margin-top: -10px;
width: 35px;
height: 35px;
margin-top: -10px;
}
.remove {
width: 25px;
height: 25px;
margin-top: -10px;
margin-right: 10px;
width: 25px;
height: 25px;
margin-top: -10px;
margin-right: 10px;
}
.itemInvoice .itemDetails {
flex-direction: row;
justify-content: space-between;
align-items: center;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.itemInvoice .itemName, .itemInvoice .itemPrice, .itemInvoice .itemQty .qtyInvoice .multiplySymbol {
font-size: 0.9rem;
.itemInvoice .itemName,
.itemInvoice .itemPrice,
.itemInvoice .itemQty .qtyInvoice .multiplySymbol {
font-size: 0.9rem;
}
.blank {
border: 1px solid #000000;
border: 1px solid #000000;
}
.notblank {
border: 1px solid #ffffff00;
border: 1px solid #ffffff00;
}
.createItem {
position: absolute;
left: 15px;
right: 15px;
position: absolute;
left: 15px;
right: 15px;
}

View File

@@ -1,6 +1,7 @@
import React, { useState, useRef } from "react";
import styles from "./ItemLister.module.css";
import Item from "./Item";
import Switch from "react-switch";
import {
getItemQtyFromCart,
updateItemQtyInCart,
@@ -23,6 +24,7 @@ const ItemLister = ({
itemList,
forCart,
forInvoice,
isEditMode,
}) => {
const [items, setItems] = useState(
itemList.map((item) => ({
@@ -177,18 +179,27 @@ const ItemLister = ({
)}
{items.map((item) => {
return !forCart || (forCart && item.qty > 0) ? (
<Item
key={item.itemId}
forCart={forCart}
forInvoice={forInvoice}
name={item.name}
price={item.price}
qty={item.qty}
imageUrl={getImageUrl(item.image)}
onPlusClick={() => handlePlusClick(item.itemId)}
onNegativeClick={() => handleNegativeClick(item.itemId)}
onRemoveClick={() => handleRemoveClick(item.itemId)}
/>
<div className={styles["itemWrapper"]}>
{isEditMode && (
<div className={styles["editModeLayout"]}>
<Switch />
<h3>out of stock</h3>
</div>
)}
<Item
key={item.itemId}
forCart={forCart}
forInvoice={forInvoice}
name={item.name}
price={item.price}
qty={item.qty}
imageUrl={getImageUrl(item.image)}
onPlusClick={() => handlePlusClick(item.itemId)}
onNegativeClick={() => handleNegativeClick(item.itemId)}
onRemoveClick={() => handleRemoveClick(item.itemId)}
isEditMode={isEditMode}
/>
</div>
) : null;
})}

View File

@@ -6,6 +6,9 @@
box-sizing: border-box; /* Ensure padding doesn't affect width */
}
.item-lister:last-child {
margin-bottom: 50px;
}
.title-container {
display: flex;
align-items: center;
@@ -59,3 +62,17 @@
.noborder {
border: 1px solid #ffffff00;
}
.itemWrapper {
position: relative;
}
.editModeLayout {
position: absolute;
z-index: 100;
background-color: #0000008c;
width: 100%;
top: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
}

View File

@@ -1,19 +1,19 @@
.item-type-lister {
width: 100vw;
overflow-x: auto;
white-space: nowrap;
padding: 3px 0px;
width: 100vw;
overflow-x: auto;
white-space: nowrap;
padding: 3px 0px;
}
.item-type-list {
display: inline-flex;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
overflow-y: hidden;
display: inline-flex;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
overflow-y: hidden;
}
.item-type {
display: inline-block;
margin-right: 20px;
/* Space between items */
}
display: inline-block;
margin-right: 20px;
/* Space between items */
}

View File

@@ -38,7 +38,10 @@ const Modal = ({ shop, isOpen, onClose, modalContent }) => {
{modalContent === "edit_tables" && <TablesPage shop={shop} />}
{modalContent === "new_transaction" && (
<Transaction propsShopId={shop.cafeId} />
)}{" "}
)}
{modalContent === "transaction_canceled" && (
<Transaction propsShopId={shop.cafeId} />
)}
{modalContent === "transaction_pending" && <Transaction_pending />}
{modalContent === "transaction_confirmed" && (
<Transaction_confirmed paymentUrl={shop.qrPayment} />

View File

@@ -55,7 +55,7 @@ export async function cancelTransaction(transactionId) {
console.log(transactionId);
const token = getLocalStorage("auth");
const response = await fetch(
`${API_BASE_URL}/transaction/claim-transaction/${transactionId}`,
`${API_BASE_URL}/transaction/cancel-transaction/${transactionId}`,
{
method: "POST",
headers: {

View File

@@ -46,6 +46,8 @@ function CafePage({
const [isSpotifyNeedLogin, setNeedSpotifyLogin] = useState(true);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isEditMode, setIsEditMode] = useState(false);
useEffect(() => {
if (user.cafeId != null && user.cafeId != shopId) {
navigate("/" + user.cafeId);
@@ -109,6 +111,7 @@ function CafePage({
guestSides={guestSides}
guestSideOfClerk={guestSideOfClerk}
removeConnectedGuestSides={removeConnectedGuestSides}
setIsEditMode={(e) => setIsEditMode(e)}
/>
<div style={{ marginTop: "5px" }}></div>
<SearchInput shopId={shopId} tableCode={table.tableCode} />
@@ -137,6 +140,7 @@ function CafePage({
itemTypeId={itemType.itemTypeId}
typeName={itemType.name}
itemList={itemType.itemList}
isEditMode={isEditMode}
/>
))}
</body>

View File

@@ -120,6 +120,7 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
setSelectedTable(transaction.Table || { tableId: 0 })
}
>
<div className={styles.RibbonBanner}></div>
<h2 className={styles["Transactions-detail"]}>
Transaction ID: {transaction.transactionId}
</h2>
@@ -176,6 +177,8 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
"Confirm has paid" // Display "Confirm has paid" if the transaction is confirmed (1)
) : transaction.confirmed === -1 ? (
"Declined" // Display "Declined" if the transaction is declined (-1)
) : transaction.confirmed === -2 ? (
"Canceled" // Display "Declined" if the transaction is declined (-1)
) : transaction.confirmed === 2 ? (
"Confirm item has ready" // Display "Item ready" if the transaction is ready (2)
) : transaction.confirmed === 3 ? (

View File

@@ -5,6 +5,7 @@ import { ColorRing } from "react-loader-spinner";
import {
getTransaction,
confirmTransaction,
handleClaimHasPaid,
declineTransaction,
cancelTransaction,
} from "../helpers/transactionHelpers";

View File

@@ -109,6 +109,12 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
setSelectedTable(transaction.Table || { tableId: 0 })
}
>
{transaction.paymentClaimed && (
<div className={styles.RibbonBanner}>
<img src={"https://i.imgur.com/yt6osgL.png"}></img>
<h1>payment claimed</h1>
</div>
)}
<h2 className={styles["Transactions-detail"]}>
Transaction ID: {transaction.transactionId}
</h2>
@@ -148,6 +154,8 @@ export default function Transactions({ propsShopId, sendParam, deviceType }) {
"Confirm has paid" // Display "Confirm has paid" if the transaction is confirmed (1)
) : transaction.confirmed === -1 ? (
"Declined" // Display "Declined" if the transaction is declined (-1)
) : transaction.confirmed === -2 ? (
"Canceled" // Display "Declined" if the transaction is declined (-1)
) : transaction.confirmed === 2 ? (
"Confirm item has ready" // Display "Item ready" if the transaction is ready (2)
) : transaction.confirmed === 3 ? (

View File

@@ -54,7 +54,7 @@
font-family: "Poppins", sans-serif;
font-weight: 500;
font-style: normal;
font-size: 24px; /* Adjusted for better readability */
font-size: 70%; /* Adjusted for better readability */
padding: 12px 24px; /* Added padding for a better look */
border-radius: 50px;
background-color: rgba(88, 55, 50, 1);
@@ -81,6 +81,7 @@
margin-bottom: 23px; /* Space at the bottom to match the PayButton */
}
.RoundedRectangle {
position: relative;
border-radius: 20px;
padding: 15px; /* Adjusted for better spacing */
margin: 26px;
@@ -116,3 +117,28 @@
resize: none; /* Prevent resizing */
overflow-wrap: break-word; /* Ensure text wraps */
}
.RibbonBanner {
position: absolute;
top: 0;
width: 200px;
height: 200px;
left: -18px;
}
.RibbonBanner img {
object-fit: contain;
width: 100%;
height: auto;
}
.RibbonBanner h1 {
margin: 0; /* Remove default margin */
font-size: 20px; /* Adjust font size as needed */
transform: rotate(-44.7deg); /* Rotate the text */
transform-origin: center; /* Rotate around its center */
white-space: nowrap; /* Prevent text wrapping */
position: absolute;
top: 60px;
left: -15px;
}

View File

@@ -1,6 +1,13 @@
import socketIOClient from 'socket.io-client';
import API_BASE_URL from '../config.js';
import socketIOClient from "socket.io-client";
import API_BASE_URL from "../config.js";
const socket = socketIOClient(API_BASE_URL);
const socket = socketIOClient(API_BASE_URL, {
transports: ["websocket"], // Use WebSocket for better performance
reconnection: true, // Enable automatic reconnection
reconnectionAttempts: Infinity, // Set to Infinity to keep trying
reconnectionDelay: 1000, // Time in ms to wait before attempting reconnection
reconnectionDelayMax: 5000, // Max delay in ms for reconnection attempts
timeout: 20000, // Connection timeout
});
export default socket;