Commit 0978e293 by Syed Abdul Rahman

seat booking functionality implemented

parent afaedd02
{
"users": [
{
"id": "2297",
"email": "syedabdul.rahman@krds.com"
"id": "8329",
"email": "syedabdul.rahman@krds.com",
"selectionCount": "3"
},
{
"id": "aa8d",
"email": "abdul@gmail.com"
"id": "3450",
"email": "abdul@gmail.com",
"selectionCount": "4"
},
{
"id": "6dc7",
"email": "test@krds.com"
"id": "06b5",
"email": "lucy@gmail.com",
"selectionCount": "3"
},
{
"id": "4422",
"email": "test@krds.fr"
},
{
"id": "6c91",
"email": "anas@gmail.com"
},
{
"id": "68fd",
"email": "lucy@gmail.com"
"id": "92dd",
"email": "",
"selectionCount": "3"
}
],
"selectedSeats": [
{
"id": "4422",
"userid": "4422",
"selected": [
{
"row": 5,
"seat": 5
},
{
"row": 5,
"seat": 6
},
{
"row": 4,
"seat": 7
},
{
"row": 4,
"seat": 8
},
{
"row": 6,
"seat": 7
}
]
"id": "8329",
"userid": "8329",
"selected": []
}
]
}
\ No newline at end of file
import { Routes, Route, Navigate } from 'react-router-dom';
import Login from './pages/LoginPage/Index';
// import SeatBooking from './components/TopLevel/SeatBooking/Index';
import BookingPage from './pages/BookingPage/Index';
import { getItem } from '../src/lib/localStorage';
const Navigates = () => {
const isAuthenticated = getItem('user');
const RequireAuth = ({ children }) => {
const isAuthenticated = getItem('user') ? true : false;
return isAuthenticated ? children : <Navigate to="/login" replace />;
};
......@@ -16,8 +16,7 @@ const Navigates = () => {
path="/"
element={
<RequireAuth>
{/* <SeatBooking /> */}
<div>SEAT BOOKING</div>
<BookingPage />
</RequireAuth>
}
/>
......
......@@ -69,13 +69,20 @@ const BookingWrapper = ({
);
if (found) {
seatClass += 'current-selected';
}
} else {
if (selectedBy) {
console.log(
selectedBy == currentUser,
selectedBy,
currentUser,
'FINAL'
);
seatClass +=
selectedBy == currentUser
? 'selected-by-me'
: 'selected-by-other';
}
}
return (
<Seat
......
import styles from './styles.module.css'
import styles from './styles.module.css';
import PropTypes from 'prop-types';
const Seat = ({ id,status, ...rest }) => {
return (
<div {...rest} className={` ${styles[status]} ${styles.seat} `}></div>
)
}
const Seat = ({ id, status, ...rest }) => {
return <div {...rest} className={` ${styles[status]} ${styles.seat} `}></div>;
};
Seat.propTypes = {
onClick: PropTypes.func.isRequired,
onClick: PropTypes.func.isRequired
// status: PropTypes.oneOf(['available', 'reserved', 'selected'])
}
};
export default Seat;
......@@ -45,11 +45,11 @@
}
.selected-by-me {
background-color: aqua !important;
background-color: aqua;
border: 1px solid aqua;
}
.current-selected{
.current-selected {
background-color: aqua !important;
border: 1px solid aqua;
}
......@@ -61,12 +61,11 @@
pointer-events: none;
}
.booking-wrapper{
.booking-wrapper {
width: 100%;
}
@media screen and (min-width: 768px) {
.seat {
width: 1.8em;
height: 1.8em;
......@@ -88,5 +87,4 @@
.theatre {
gap: 15px;
}
}
......@@ -8,7 +8,6 @@ const Login = ({ onSubmit }) => {
e.preventDefault();
const formData = new FormData(e.target);
const data = { ...Object.fromEntries(formData) };
console.log(data?.email);
onSubmit(data?.email);
};
......
......@@ -18,7 +18,7 @@ export const createUser = async (email) => {
return data;
};
export const getSelectedSeats = async () => {
export const getSelectedSeatsApi = async () => {
const response = await fetch(`${appConstants.API_URL_SEATS}`);
const data = await response.json();
return data;
......@@ -47,3 +47,19 @@ export const createSeatApi = async (body) => {
body: JSON.stringify(body)
});
};
export const saveSeatSelectionCountApi = async (id, count) => {
await fetch(`${appConstants.API_URL_USERS}/${id}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ selectionCount: count })
});
};
export const getSeatSelectionCountApi = async (id) => {
const response = await fetch(`${appConstants.API_URL_USERS}/${id}`);
const data = await response.json();
return data ? data : null;
};
......@@ -9,4 +9,4 @@ export const getItem = (key) => {
export const reset = () => {
localStorage.clear();
}
\ No newline at end of file
};
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { getItem, reset, setItem } from '../../lib/localStorage';
import { appConstants } from '../../lib/AppConstants';
import {
getSelectedSeatsApi,
editSeatsApi,
createSeatApi,
saveSeatSelectionCountApi,
getSeatSelectionCountApi
} from '../../lib/api';
import BookingWrapper from '../../components/Layout/BookingWrapper/Index';
import Header from '../../components/Layout/Header/Index';
import Modal from '../../components/Shared/Modal/Index';
import Button from '../../components/Base/Button/Index';
import LegendWrapper from '../../components/TopLevel/LegendWrapper/Index';
import img from '../../assets/images/power-button_12080802.png';
import styles from './styles.module.css';
const BookingPage = () => {
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 [noOfSeats, setNoOfSeats] = useState();
useEffect(() => {
const fetchSelectedSeats = async () => {
const data = await getSelectedSeatsApi();
const currentData = data.find((e) => e.userid == userId);
setSelectedSeats(data);
setCurrentSeats(currentData.selected);
};
const fetchSeatSelectionCount = async () => {
const data = await getSeatSelectionCountApi(userId);
setNoOfSeats(data?.selectionCount);
};
fetchSelectedSeats();
fetchSeatSelectionCount();
setShowSeatsModal(getItem(appConstants.MODAL));
}, []);
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 logout = () => {
reset();
navigate('/login');
};
const onModalChange = (value) => {
setNoOfSeats(value);
};
const modalClose = () => {
setItem('modal', false);
if (userId && noOfSeats) {
saveSeatSelectionCountApi(userId, noOfSeats);
}
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) => {
const currentData = data.find((e) => e.userid == userId);
const currentSelected = currentData.selected;
let totalAllowedCount = currentSelected.length + currentSeats.length;
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 {
if (totalAllowedCount < noOfSeats) {
if (currentSeats.length < noOfSeats) {
let obj = {
row: rowId,
seat: columnId
};
return [...prev, obj];
} else {
return [...prev];
}
}
}
});
};
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);
} else {
if (current) {
setCurrentSeats([...currentSeats, ...current.selected]);
} else {
setCurrentSeats([...currentSeats]);
}
}
setShowSeatsConfirmationModal(true);
};
const seatsFinal = async () => {
const existingUserSeatMap = selectedSeats?.find((ele) => ele.id == userId);
const fetchData = async () => {
let data = await getSelectedSeatsApi();
setSelectedSeats(data);
};
if (existingUserSeatMap) {
await editSeatsApi(userId, currentSeats);
} else {
let info = {
id: userId,
userid: userId,
selected: currentSeats
};
await createSeatApi(info);
}
setCurrentSeats([]);
fetchData();
setShowSeatsConfirmationModal(false);
};
console.log(currentSeats, 'currentSeats');
return (
<div className={styles['seat-booking-wrapper']}>
<img
src={img}
className={styles['logout']}
width={30}
onClick={() => logout()}
/>
<div className={styles['screen-wrapper']}>
<Header>Choose Seats</Header>
<BookingWrapper
seatData={data}
selectedSeats={selectedSeats}
onSeatClick={onSelectSeats}
currentSeats={currentSeats}
/>
</div>
<div className={styles['btn-wrapper']}>
<Button
size={'lg'}
onClick={onSeatsConfirm}
disabled={currentSeats.length > 0 ? false : true}>
Confirm
</Button>
</div>
<LegendWrapper />
{showSeatsModal && (
<Modal
onConfirm={modalClose}
onChange={onModalChange}
variant="input"
value={noOfSeats}
/>
)}
{showSeatsConfirmationModal && (
<Modal
onConfirm={seatsFinal}
onChange={onModalChange}
variant={'confirm'}
onCancel={finalCancel}
/>
)}
</div>
);
};
export default BookingPage;
.seat-booking-wrapper {
box-sizing: border-box;
flex-direction: column;
display: flex;
justify-content: space-evenly;
background-color: #3444c5;
height: 100%;
overflow-y: auto;
width: 100%;
}
.screen-wrapper {
padding: 1em 0;
}
.btn-wrapper {
display: flex;
justify-content: center;
align-items: center;
padding: 1em 0;
}
.logout {
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
}
import { useNavigate } from 'react-router-dom';
import Login from '../../components/TopLevel/Login/Index';
import { login, createUser } from '../../lib/api';
import { login, createUser, getSeatSelectionCountApi } from '../../lib/api';
import { setItem } from '../../lib/localStorage';
import styles from './styles.module.css';
const LoginPage = () => {
const navigate = useNavigate();
const onSubmit = async (email) => {
const userData = await login(email);
if (userData) {
const fetchSeatSelectionCount = async (id) => {
const data = await getSeatSelectionCountApi(id);
if (data.selectionCount) {
setItem('modal', false);
} else {
setItem('modal', true);
}
navigate('/');
};
if (userData) {
setItem('user', userData.id);
setItem('modal', true);
fetchSeatSelectionCount(userData?.id);
} else {
const data = await createUser(email);
navigate('/');
setItem('user', data.id);
setItem('modal', true);
fetchSeatSelectionCount(data?.id);
}
};
return <Login onSubmit={onSubmit} />;
};
......
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