Commit dc0416e8 by Syed Abdul Rahman

storybook implementation changes

parent 0b74e4ee
node_modules
build
dist
{
"jsxBracketSameLine": true,
"singleQuote": true,
"jsxSingleQuote": false,
"trailingComma": "none"
}
\ No newline at end of file
{
"users": [
{
"id": "1ad9",
"id": "2297",
"email": "syedabdul.rahman@krds.com"
},
{
"id": "06dd",
"id": "aa8d",
"email": "abdul@gmail.com"
},
{
"id": "b31d",
"email": "lucy@gmail.com"
"id": "6dc7",
"email": "test@krds.com"
},
{
"id": "62fd",
"email": ""
},
{
"id": "08da",
"email": "xyz@gmail.com"
},
{
"id": "a6af",
"email": "testing@gmail.com"
},
{
"id": "7fdf",
"email": "test@gmail.com"
},
{
"id": "a9b6",
"email": "new@gmail.com"
"id": "4422",
"email": "test@krds.fr"
}
],
"selectedSeats": [
{
"id": "1ad9",
"userid": "1ad9",
"id": "4422",
"userid": "4422",
"selected": [
{
"row": 7,
"seat": 4
},
{
"row": 2,
"seat": 5
},
{
"row": 4,
"seat": 4
},
{
"row": 2,
"seat": 1
},
{
"row": 1,
"seat": 1
},
{
"row": 1,
"seat": 2
},
{
"row": 1,
"seat": 3
},
{
"row": 1,
"seat": 4
},
{
"row": 8,
"row": 5,
"seat": 5
},
{
"row": 8,
"seat": 6
},
{
"row": 8,
"seat": 7
},
{
"row": 8,
"seat": 8
}
]
},
{
"id": "b31d",
"userid": "b31d",
"selected": [
{
"row": 7,
"row": 5,
"seat": 6
},
{
"row": 7,
"row": 4,
"seat": 7
},
{
"row": 7,
"row": 4,
"seat": 8
},
{
"row": 7,
"seat": 10
},
{
"row": 7,
"seat": 9
}
]
},
{
"id": "7fdf",
"userid": "7fdf",
"selected": []
},
{
"id": "06dd",
"userid": "06dd",
"selected": [
{
"row": 1,
"seat": 5
},
{
"row": 1,
"seat": 6
},
{
"row": 1,
"row": 6,
"seat": 7
},
{
"row": 1,
"seat": 8
}
]
}
......
import './App.css'
import Navigates from './Navigates'
import "./App.css";
import Navigates from "./Navigates";
function App() {
return (
<div style={{ height: "100%" }}>
<Navigates />
</div>
)
<Navigates />
);
}
export default App
export default App;
import { Routes, Route, Navigate } from "react-router-dom";
import Login from "./components/TopLevel/Login/Index";
import SeatBooking from "./components/TopLevel/SeatBooking/Index";
import { getItem } from '../src/utils/localStorage'
import { Routes, Route, Navigate } from 'react-router-dom';
import Login from './components/TopLevel/Login/Index';
import SeatBooking from './components/TopLevel/SeatBooking/Index';
import { getItem } from '../src/lib/localStorage';
const Navigates = () => {
const isAuthenticated = getItem("user");
const RequireAuth = ({ children }) => {
return isAuthenticated ? children : <Navigate to="/login" replace />;
};
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/" element={
<RequireAuth>
<SeatBooking />
</RequireAuth>
} />
</Routes>
)
}
const isAuthenticated = getItem('user');
const RequireAuth = ({ children }) => {
return isAuthenticated ? children : <Navigate to="/login" replace />;
};
return (
<Routes>
<Route path="/login" element={<Login />} />
<Route
path="/"
element={
<RequireAuth>
<SeatBooking />
</RequireAuth>
}
/>
</Routes>
);
};
export default Navigates
\ No newline at end of file
export default Navigates;
.button {
border: none;
outline: none;
background-color: white;
color: black;
border-radius: 10px;
font-family: 'Poppins-Medium';
font-weight: 500;
cursor: pointer;
display: flex;
gap: 1rem;
align-items: center;
justify-content: center;
font-size: 1rem;
box-sizing: border-box;
border: none;
outline: none;
background-color: white;
color: black;
border-radius: 10px;
font-family: 'Poppins-Medium';
font-weight: 500;
cursor: pointer;
display: flex;
gap: 1rem;
align-items: center;
justify-content: center;
font-size: 1rem;
box-sizing: border-box;
}
.button:hover{
background-color: rgba(161, 161, 245, 0.358);
color: white;
.button:hover {
background-color: rgba(161, 161, 245, 0.358);
color: white;
}
.sm {
padding: 0.5rem 1.5rem;
font-size: 15px;
padding: 0.3rem 1.5rem;
font-size: 15px;
}
.md {
padding: 0.4rem 2rem;
font-size: 18px;
padding: 0.6rem 2rem;
font-size: 18px;
}
.lg {
padding: 0.9rem 2.5rem;
font-size: 22px;
padding: 0.7rem 3rem;
font-size: 22px;
}
.loader {
width: 20px;
height: 20px;
display: inline-block;
border: 2px solid rgba(159, 159, 159, 0.582);
border-radius: 50%;
border-top: 2px solid rgb(51, 51, 221);
animation: rotate 0.5s linear infinite;
width: 20px;
height: 20px;
display: inline-block;
border: 2px solid rgba(159, 159, 159, 0.582);
border-radius: 50%;
border-top: 2px solid rgb(51, 51, 221);
animation: rotate 0.5s linear infinite;
}
.loader-sm {
width: 10px;
height: 10px;
width: 10px;
height: 10px;
}
.loader-md {
width: 15px;
height: 15px;
width: 15px;
height: 15px;
}
.loader-lg {
width: 20px;
height: 20px;
width: 20px;
height: 20px;
}
.disabled {
background-color: rgb(168, 166, 166);
opacity: 0.5;
color: white;
cursor: not-allowed;
background-color: rgb(168, 166, 166);
opacity: 0.5;
color: white;
cursor: not-allowed;
}
.disabled:hover{
background-color: rgba(168, 166, 166, 0.214);
.disabled:hover {
background-color: rgba(168, 166, 166, 0.214);
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
\ No newline at end of file
100% {
transform: rotate(360deg);
}
}
.selected {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: aqua;
width: 15px;
height: 15px;
border-radius: 50%;
background-color: aqua;
}
.reserved {
width: 15px;
height: 15px;
border-radius: 50%;
background-color: rgb(151, 155, 155);
width: 15px;
height: 15px;
border-radius: 50%;
background-color: rgb(151, 155, 155);
}
.available {
width: 15px;
height: 15px;
border-radius: 50%;
border: 1px solid white;
width: 15px;
height: 15px;
border-radius: 50%;
border: 1px solid white;
}
.legend-wrapper {
display: flex;
gap: 10px;
align-items: center;
display: flex;
gap: 10px;
align-items: center;
}
.title {
color: white;
font-family: 'Poppins-Medium';
}
\ No newline at end of file
color: white;
font-family: "Poppins-Medium";
font-size: 14px;
}
@media screen and (min-width: 768px) {
.title {
font-size: 22px;
}
}
import Seat from './Seat';
import { getItem } from '../../../utils/localStorage';
import { getItem } from '../../../lib/localStorage';
import styles from './styles.module.css';
const BookingWrapper = ({ onSeatClick, selectedSeats, seatData, currentSeats }) => {
const aisleIndex = 4;
let currentUser = getItem("user");
const selectedSeatMap = new Map();
selectedSeats?.forEach(user => {
user.selected?.forEach(seat => {
const key = `${seat.row}-${seat.seat}`;
selectedSeatMap.set(key, user.userid);
});
const BookingWrapper = ({
onSeatClick,
selectedSeats,
seatData,
currentSeats
}) => {
const aisleIndex = 4;
let currentUser = getItem('user');
const selectedSeatMap = new Map();
selectedSeats?.forEach((user) => {
user.selected?.forEach((seat) => {
const key = `${seat.row}-${seat.seat}`;
selectedSeatMap.set(key, user.userid);
});
const isLeftBlock = (col) => col < aisleIndex;
const isRightBlock = (col) => col > aisleIndex;
return (
<div className={styles['booking-wrapper']}>
<div className={styles['theatre']}>
{seatData?.map((row, row_index) => (
<div className={styles['seat-row']}>
{row.columnData?.map((column, column_index) => {
const isFirstRow = row_index === 0;
const isLastRow = row_index === seatData.length - 1;
if (isLeftBlock(column_index) && column_index === 0 && (isFirstRow || isLastRow)) {
return <div key={`gap-left-${row_index}-${column_index}`} className={styles["seat-gap"]} />;
}
if (
isRightBlock(column_index) &&
column_index === row.columnData.length - 1 &&
(isFirstRow || isLastRow)
) {
return <div key={`gap-right-${row_index}-${row_index}`} className={styles["seat-gap"]} />;
}
if (column_index == aisleIndex) {
return (
<div className={styles['aisle']}></div>
)
}
const seatKey = `${row.row_id}-${column.id}`;
const selectedBy = selectedSeatMap.get(seatKey);
let seatClass = ``;
const found = currentSeats?.find(e => e.row == row.row_id && e.seat == column.id);
if (found) {
seatClass += 'current-selected'
}
if (selectedBy) {
seatClass += selectedBy == currentUser ? 'selected-by-me' : 'selected-by-other';
}
return (
<Seat status={seatClass} id={column.id} onClick={() => onSeatClick(row.row_id, column.id)} />
)
})}
</div>
))}
</div>
</div>
)
}
});
const isLeftBlock = (col) => col < aisleIndex;
const isRightBlock = (col) => col > aisleIndex;
return (
<div className={styles['booking-wrapper']}>
<div className={styles['theatre']}>
{seatData?.map((row, row_index) => (
<div className={styles['seat-row']}>
{row.columnData?.map((column, column_index) => {
const isFirstRow = row_index === 0;
const isLastRow = row_index === seatData.length - 1;
if (
isLeftBlock(column_index) &&
column_index === 0 &&
(isFirstRow || isLastRow)
) {
return (
<div
key={`gap-left-${row_index}-${column_index}`}
className={styles['seat-gap']}
/>
);
}
if (
isRightBlock(column_index) &&
column_index === row.columnData.length - 1 &&
(isFirstRow || isLastRow)
) {
return (
<div
key={`gap-right-${row_index}-${row_index}`}
className={styles['seat-gap']}
/>
);
}
if (column_index == aisleIndex) {
return <div className={styles['aisle']}></div>;
}
const seatKey = `${row.row_id}-${column.id}`;
const selectedBy = selectedSeatMap.get(seatKey);
let seatClass = ``;
const found = currentSeats?.find(
(e) => e.row == row.row_id && e.seat == column.id
);
if (found) {
seatClass += 'current-selected';
}
if (selectedBy) {
seatClass +=
selectedBy == currentUser
? 'selected-by-me'
: 'selected-by-other';
}
return (
<Seat
status={seatClass}
id={column.id}
onClick={() => onSeatClick(row.row_id, column.id)}
/>
);
})}
</div>
))}
</div>
</div>
);
};
export default BookingWrapper;
.seat {
width: 1.2em;
height: 1.2em;
width: 1.5em;
height: 1.5em;
border: 1.5px solid rgba(255, 255, 255, 0.825);
border-radius: 5px;
cursor: pointer;
......@@ -63,14 +63,13 @@
.booking-wrapper{
width: 100%;
overflow: auto;
}
@media screen and (min-width: 768px) {
.seat {
width: 1.7em;
height: 1.7em;
width: 1.8em;
height: 1.8em;
}
.aisle {
......
......@@ -6,10 +6,7 @@ const Header = ({ children }) => {
<section className={styles["header-wrapper"]}>
<div className={styles.title}>{children}</div>
<div className={styles.screenWrapper}>
<svg
viewBox="0 20 480 100"
xmlns="http://www.w3.org/2000/svg"
>
{/* <svg viewBox="0 20 480 100" xmlns="http://www.w3.org/2000/svg">
<path
d="M 30 70 Q 240 20 450 70"
stroke="white"
......@@ -38,11 +35,11 @@ const Header = ({ children }) => {
<clipPath id="glowClip">
<path
d="
M 30 70
Q 240 20 450 70
L 470 130
L 10 130
Z"
M 30 70
Q 240 20 450 70
L 470 130
L 10 130
Z"
/>
</clipPath>
</defs>
......@@ -51,10 +48,67 @@ const Header = ({ children }) => {
x="0"
y="0"
width="480"
height="600"
height="900"
fill="url(#glowGradient)"
clip-path="url(#glowClip)"
/>
</svg> */}
<svg viewBox="0 20 480 130" xmlns="http://www.w3.org/2000/svg">
<path
d="M 30 70 Q 240 20 450 70"
stroke="white"
stroke-width="3"
fill="none"
/>
<defs>
<mask id="glowMask">
<linearGradient
id="fadeGradient"
x1="0"
y1="70"
x2="0"
y2="150"
gradientUnits="userSpaceOnUse"
>
<stop offset="0%" stop-color="#9c6ad5" stop-opacity="1" />
<stop offset="60%" stop-color="#9c6ad5" stop-opacity="1" />
<stop offset="100%" stop-color="#9c6ad5" stop-opacity="1" />
<stop offset="100%" stop-color="#9c6ad5" stop-opacity="1" />
<stop offset="100%" stop-color="#9c6ad5" stop-opacity="1" />
</linearGradient>
<path
d="
M 30 70
Q 240 20 450 70
L 500 150
L -20 150
Z"
fill="url(#fadeGradient)"
/>
</mask>
<linearGradient
id="glowColor"
x1="0"
y1="100"
x2="0"
y2="150"
gradientUnits="userSpaceOnUse"
>
<stop offset="0%" stop-color="#9c6ad5" stop-opacity="0.4" />
<stop offset="50%" stop-color="#9c6ad5" stop-opacity="0.2" />
<stop offset="100%" stop-color="#9c6ad5" stop-opacity="0" />
<stop offset="100%" stop-color="#9c6ad5" stop-opacity="0" />
<stop offset="100%" stop-color="#9c6ad5" stop-opacity="0" />
</linearGradient>
</defs>
<path
d="M 30 70 Q 240 20 450 70 L 500 150 L -20 150 Z"
fill="url(#glowColor)"
mask="url(#glowMask)"
/>
</svg>
</div>
</section>
......
.header-wrapper {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
gap: 1rem;
}
.title {
font-family: 'Poppins-Bold';
color: white;
font-size: 1rem;
padding-top: 2rem;
/* background-color: #9c6ad5d4; */
font-family: "Poppins-Bold";
color: white;
font-size: 2rem;
}
.screenWrapper {
width:70%;
width: 80%;
}
@media screen and (min-width: 768px) {
.title {
font-family: 'Poppins-Bold';
color: white;
font-size: 2rem;
.title {
font-family: "Poppins-Bold";
color: white;
font-size: 2rem;
}
}
.screenWrapper {
width: 30%;
}
.screenWrapper {
width: 25%;
}
}
\ No newline at end of file
.title {
font-family: "Poppins-Bold";
color: white;
font-size: 2rem;
}
}
import Modal from './Index';
export default {
tags: ["autodocs"],
title: "component/Shared/Modal",
component: Modal,
argTypes: {
onConfirm: {action: "On Modal confirm"},
onChange: {action: "On No of seats value change"}
}
}
tags: ['autodocs'],
title: 'component/Shared/Modal',
component: Modal,
argTypes: {
onConfirm: { action: 'On Modal confirm' },
onChange: { action: 'On No of seats value change' },
variant: {
control: { type: 'select' },
options: ['confirm', 'input']
},
onChange: {
action: 'onchange'
},
onConfirm: {
action: 'onconfirmm'
}
}
};
export const Default = {
}
\ No newline at end of file
args: {
variant: 'input'
}
};
.LegendWrapper {
display: flex;
background-color: #3444c5;
height: 70px;
right: 0;
left: 0;
gap: 1rem;
position: fixed;
bottom: 0;
justify-content: center;
display: flex;
background-color: #3444c5;
/* height: 70px; */
/* position: fixed; */
right: 0;
left: 0;
bottom: 0;
gap: 1rem;
justify-content: center;
padding: 1em 0;
/* border: 2px solid red */
}
@media screen and (min-width: 768px) {
.LegendWrapper {
.LegendWrapper {
gap: 4rem;
}
}
}
\ No newline at end of file
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { setItem } from '../../../utils/localStorage'
import { appConstants } from '../../../utils/AppConstants';
import Input from '../../Base/Input/Index'
import PropTypes from 'prop-types';
import Input from '../../Base/Input/Index';
import Button from '../../Base/Button/Index';
import styles from './styles.module.css';
const Login = () => {
const navigate = useNavigate();
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
login();
}
const login = async () => {
const response = await fetch(`${appConstants.API_URL_USERS}`)
const data = await response.json();
const user = data.find((e) => e.email == email);
if (user) {
setItem("user", user.id)
setItem("modal", true)
navigate("/")
} else {
const response = await fetch(`${appConstants.API_URL_USERS}`, {
method: "POST",
body: JSON.stringify({
email: email
})
})
const data = await response.json();
navigate("/")
setItem("user", data.id)
setItem("modal", true)
}
}
const onEmailChange = (e) => {
setEmail(e.target.value)
}
return (
<div className={styles.bg}>
<section className={styles.container}>
<div className={styles.contentWrapper}>
<div className={styles.title}>Welcome Back!</div>
<div className={styles.desc}>Login with email and passoword to book seats.</div>
</div>
<form className={styles.formWrapper} onSubmit={handleSubmit}>
<Input
label="Email"
name="email"
type="email"
placeholder='Enter email'
onChange={onEmailChange}
/>
<Button size={"md"}>Confirm</Button>
</form>
</section>
const Login = ({ handleSubmit }) => {
const [inputValue, setInputValue] = useState();
const onValueChange = (e) => {
setInputValue(e);
};
return (
<div className={styles.bg}>
<section className={styles.container}>
<div className={styles.contentWrapper}>
<div className={styles.title}>Welcome Back!</div>
<div className={styles.desc}>
Login with email and passoword to book seats.
</div>
</div>
<div className={styles.formWrapper}>
<Input
label="Email"
name="email"
type="email"
placeholder="Enter email"
value={inputValue}
onChange={(e) => onValueChange(e.target.value)}
/>
<Button size={'md'} onClick={() => handleSubmit(inputValue)}>
Confirm
</Button>
</div>
</section>
</div>
);
};
export default Login;
)
}
export default Login
\ No newline at end of file
Login.propTypes = {
handleSubmit: PropTypes.func.isRequired
};
import Login from './Index';
import { MemoryRouter } from 'react-router-dom';
export default {
title: "component/TopLevel/login",
tags: ["autodocs"],
decorators: [
(Story) => (
<MemoryRouter>
<Story />
</MemoryRouter>
),
],
component: Login
}
export const Screen = {
export default {
title: 'component/TopLevel/Login',
component: Login,
argTypes: {
handleSubmit: { action: 'Form Value' }
}
};
}
\ No newline at end of file
export const Screen = {};
......@@ -52,19 +52,18 @@
.title {
font-family: 'Inter-Medium';
font-size: 1.5rem;
color: #f1f1f1e4;
color: white;
padding: 1% 0;
}
.desc {
font-family: 'Inter-Medium';
font-size: 16px;
color: #ece8e8f1;
color: white;
font-size: 1rem;
padding: 1% 0;
}
.inputStyle {
width: 90%;
}
\ No newline at end of file
}
import { useEffect, useState } from "react";
import BookingWrapper from "../../Layout/BookingWrapper/Index";
import Header from "../../Layout/Header/Index";
import Modal from "../../Shared/Modal/Index";
import img from "../../../assets/images/power-button_12080802.png";
import Button from "../../Base/Button/Index";
import LegendWrapper from "../LegendWrapper/Index";
import { getItem, reset, setItem } from "../../../utils/localStorage";
import styles from "./styles.module.css";
import { useNavigate } from "react-router-dom";
import { appConstants } from "../../../utils/AppConstants";
const SeatBooking = () => {
let userId = getItem(appConstants.USER);
const navigate = useNavigate();
const [selectedSeats, setSelectedSeats] = useState(); //persisted seats state
const [currentSeats, setCurrentSeats] = useState([]); // currently selecting seats before booking(local)
const [showSeatsModal, setShowSeatsModal] = useState(() =>
getItem(appConstants.MODAL)
);
const [showSeatsConfirmationModal, setShowSeatsConfirmationModal] =
useState(false);
const [onOfSeats, setNoOfSeats] = useState();
useEffect(() => {
getSelectedSeats();
}, []);
const data = [
{
row_id: 1,
columnData: [
{
id: 0,
status: "aisle",
},
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 0,
},
{
id: 4,
},
{
id: 5,
},
{
id: 6,
},
{
id: 0,
status: "aisle",
},
],
},
{
row_id: 2,
columnData: [
{
id: 1,
status: "available",
},
{
id: 2,
status: "available",
},
{
id: 3,
status: "available",
},
{
id: 4,
status: "available",
},
{
id: 0,
status: "aisle",
},
{
id: 5,
status: "available",
},
{
id: 6,
status: "available",
},
{
id: 7,
status: "available",
},
{
id: 8,
status: "available",
},
],
},
{
row_id: 3,
columnData: [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 4,
},
{
id: 0,
},
{
id: 5,
},
{
id: 6,
},
{
id: 7,
},
{
id: 8,
},
],
},
{
row_id: 4,
columnData: [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 4,
},
{
id: 0,
},
{
id: 5,
},
{
id: 6,
},
{
id: 7,
},
{
id: 8,
},
],
},
{
row_id: 5,
columnData: [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 4,
},
{
id: 0,
},
{
id: 5,
},
{
id: 6,
},
{
id: 7,
},
{
id: 8,
},
],
},
{
row_id: 6,
columnData: [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 4,
},
{
id: 0,
},
{
id: 5,
},
{
id: 6,
},
{
id: 7,
},
{
id: 8,
},
],
},
{
row_id: 7,
columnData: [
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 4,
},
{
id: 0,
},
{
id: 5,
},
{
id: 6,
},
{
id: 7,
},
{
id: 8,
},
],
},
{
row_id: 8,
columnData: [
{
id: 0,
status: "aisle",
},
{
id: 1,
},
{
id: 2,
},
{
id: 3,
},
{
id: 0,
},
{
id: 4,
},
{
id: 5,
},
{
id: 6,
},
{
id: 0,
status: "aisle",
},
],
},
];
const getSelectedSeats = async () => {
const response = await fetch(`${appConstants.API_URL_SEATS}`);
const data = await response.json();
setSelectedSeats(data);
};
const editSeatsApi = async (id, body) => {
try {
await fetch(`${appConstants.API_URL_SEATS}/${id}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ selected: body }),
});
getSelectedSeats();
setCurrentSeats([]);
} catch (error) {
console.log(error, "error");
}
};
const createSeatApi = async (body) => {
await fetch(`${appConstants.API_URL_SEATS}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
getSelectedSeats();
setCurrentSeats([]);
};
const logout = () => {
reset();
navigate("/login");
};
const onModalChange = (value) => {
setNoOfSeats(value);
};
const modalClose = () => {
setItem("modal", false);
setShowSeatsModal(false);
};
const finalCancel = () => {
const current = selectedSeats?.find((ele) => ele.userid == userId);
const mergedSeats = [
...currentSeats.filter(
(cs) =>
!current?.selected.some(
(ss) => ss.row === cs.row && ss.seat === cs.seat
)
),
...current?.selected.filter(
(ss) =>
!currentSeats.some((cs) => cs.row === ss.row && cs.seat === ss.seat)
),
];
setCurrentSeats(mergedSeats)
setShowSeatsConfirmationModal(false);
};
const onSelectSeats = (rowId, columnId) => {
setCurrentSeats((prev) => {
const found = prev.find((e) => e.row == rowId && e.seat == columnId);
if (found) {
return currentSeats.filter(
(e) => !(e.row == rowId && e.seat == columnId)
);
} else {
let obj = {
row: rowId,
seat: columnId,
};
return [...prev, obj];
}
});
};
const onSeatsConfirm = () => {
const current = selectedSeats?.find((ele) => ele.userid == userId);
const found = current?.selected.some((e) =>
currentSeats.some((e2) => e2.row == e.row && e2.seat == e.seat)
);
if (found) {
const mergedSeats = [
...currentSeats.filter(
(cs) =>
!current?.selected.some(
(ss) => ss.row === cs.row && ss.seat === cs.seat
)
),
...current?.selected.filter(
(ss) =>
!currentSeats.some((cs) => cs.row === ss.row && cs.seat === ss.seat)
),
];
setCurrentSeats(mergedSeats);
console.log("CULPRIT")
} else {
if (current) {
setCurrentSeats([...currentSeats, ...current.selected]);
} else {
setCurrentSeats([...currentSeats]);
}
}
setShowSeatsConfirmationModal(true);
};
const seatsFinal = async () => {
const existingUserSeatMap = selectedSeats?.find((ele) => ele.id == userId);
if (existingUserSeatMap) {
await editSeatsApi(userId, currentSeats);
} else {
let info = {
id: userId,
userid: userId,
selected: currentSeats,
};
await createSeatApi(info);
}
setShowSeatsConfirmationModal(false);
};
return (
<div className={styles["seat-booking-wrapper"]}>
<img
src={img}
className={styles["logout"]}
width={30}
onClick={() => logout()}
/>
<div>
<Header>Choose Seats</Header>
</div>
<div>
<BookingWrapper
seatData={data}
selectedSeats={selectedSeats}
onSeatClick={onSelectSeats}
currentSeats={currentSeats}
/>
</div>
<div className={styles["btn-wrapper"]}>
<Button size={"md"} onClick={onSeatsConfirm} disabled={currentSeats.length > 0 ? false : true }>
Confirm
</Button>
</div>
<LegendWrapper />
{showSeatsModal && (
<Modal
onConfirm={modalClose}
onChange={onModalChange}
variant="input"
/>
)}
{showSeatsConfirmationModal && (
<Modal
onConfirm={seatsFinal}
onChange={onModalChange}
variant={"confirm"}
// onOfSeats={currentSeats.length}
onCancel={finalCancel}
/>
)}
</div>
);
};
export default SeatBooking;
.seat-booking-wrapper {
background-color: #3444c5;
height: 100%;
width: 100%;
box-sizing: border-box;
flex-direction: column;
overflow-y: auto;
padding-bottom: 65px;
display: flex;
}
.seat-booking-wrapper > div {
flex: 1;
}
.btn-wrapper {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding: 1.5rem 0;
}
.logout{
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
}
\ No newline at end of file
export const appConstants = {
API_URL_SEATS: "http://localhost:3000/selectedSeats",
API_URL_USERS: "http://localhost:3000/users",
API_URL_SEATS: "http://192.168.1.73:3000/selectedSeats",
API_URL_USERS: "http://192.168.1.73:3000/users",
USER: "user",
MODAL: "modal"
}
......
export const login = async () => {
const response = await fetch(`${appConstants.API_URL_USERS}`);
const data = await response.json();
const user = data.find((e) => e.email == email);
return user;
};
export const getSelectedSeats = async () => {
const response = await fetch(`${appConstants.API_URL_SEATS}`);
const data = await response.json();
return data;
};
export const editSeatsApi = async (id, body) => {
try {
await fetch(`${appConstants.API_URL_SEATS}/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ selected: body })
});
} catch (error) {
console.log(error, 'error');
}
};
export const createSeatApi = async (body) => {
await fetch(`${appConstants.API_URL_SEATS}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(body)
});
};
......@@ -4,9 +4,9 @@ import './index.css'
import App from './App.jsx'
import { BrowserRouter } from 'react-router-dom'
createRoot(document.getElementById('root')).render(
<StrictMode>
// <StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>,
// </StrictMode>,
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment