Commit 1ae88499 by Syed Abdul Rahman

Implemented json server for persisting seats state

parent 7a726c25
{
"users": [
{
"id": 1,
"email": "john@gmail.com"
},
{
"id": 2,
"email": "lucy@gmail.com"
},
{
"id": 3,
"email": "abdul@gmail.com"
}
]
"users": [
{
"id": "1",
"email": "syedabdul.rahman@krds.com"
},
{
"id": "2",
"email": "lucy@gmail.com"
},
{
"id": "3",
"email": "abdul@gmail.com"
},
{
"id": "05cc",
"email": "test@gmail.com"
}
],
"selectedSeats": [
{
"id": "1",
"userid": "1",
"selected": [
{
"row": 8,
"seat": 5
}
]
}
]
}
\ No newline at end of file
File added
import { Routes, Route } from "react-router-dom";
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'
const Navigates = () => {
const isAuthenticated = getItem("user");
const RequireAuth = ({ children }) => {
return isAuthenticated ? children : <Navigate to="/login" replace />;
};
return (
<Routes>
<Route path="" element={<Login />} />
<Route path="/seat-booking" element={<SeatBooking />} />
<Route path="/login" element={<Login />} />
<Route path="/" element={
<RequireAuth>
<SeatBooking />
</RequireAuth>
} />
</Routes>
)
}
......
......@@ -27,7 +27,7 @@
}
.md {
padding: 0.7rem 1.5rem;
padding: 0.4rem 1.5rem;
font-size: 18px;
}
......
import styles from './styles.module.css';
import Seat from './Seat';
import { getItem } from '../../../utils/localStorage';
import styles from './styles.module.css';
const BookingWrapper = ({ onSeatClick, selectedSeats, seatData }) => {
const BookingWrapper = ({ onSeatClick, selectedSeats, seatData, currentSeats }) => {
const aisleIndex = 5;
const currentUser = 2;
let currentUser = getItem("user");
const selectedSeatMap = new Map();
selectedSeats?.forEach(user => {
user.selected.forEach(seat => {
const key = `${seat.row}-${seat.seat}`;
......@@ -23,7 +23,7 @@ const BookingWrapper = ({ onSeatClick, selectedSeats, seatData }) => {
return (
<div>
<div className={styles['booking-wrapper']}>
<div className={styles['theatre']}>
{seatData?.map((row, row_index) => (
<div className={styles['seat-row']}>
......@@ -53,9 +53,15 @@ const BookingWrapper = ({ onSeatClick, selectedSeats, seatData }) => {
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';
seatClass += selectedBy == currentUser ? 'selected-by-me' : 'selected-by-other';
}
console.log(seatClass, "SeatCLaskk")
return (
<Seat status={seatClass} id={column.id} onClick={() => onSeatClick(row.row_id, column.id)} />
)
......
......@@ -2,7 +2,6 @@ import styles from './styles.module.css'
import PropTypes from 'prop-types';
const Seat = ({ id,status, ...rest }) => {
console.log(status, "status")
return (
<div {...rest} className={` ${styles[status]} ${styles.seat} `}></div>
)
......
.seat {
width: 1.5em;
height: 1.7em;
width: 1.2em;
height: 1.2em;
border: .5px solid rgba(255, 255, 255, 0.603);
border-radius: 5px;
cursor: pointer;
}
.seat:hover {
......@@ -36,8 +36,6 @@
gap: 10px;
}
.aisle {
width: 1em;
}
......@@ -50,12 +48,22 @@
}
.selected-by-me {
background-color: aqua !important; /* your color */
border: unset;
background-color: aqua !important;
border: 0.5px aqua;
}
.current-selected{
background-color: aqua !important;
border: 0.5px aqua;
}
.selected-by-other {
background-color: #bec0c26d !important; /* another color */
background-color: #bec0c26d !important;
}
.booking-wrapper{
width: 100%;
overflow: auto;
}
......@@ -63,8 +71,8 @@
@media screen and (min-width: 768px) {
.seat {
width: 2em;
height: 2em;
width: 1.7em;
height: 1.7em;
}
.aisle {
......
......@@ -52,6 +52,9 @@ const Header = ({ children }) => {
fill="url(#glowGradient)"
clip-path="url(#glowClip)" />
</svg>
</div>
</section>
)
......
......@@ -3,7 +3,6 @@
flex-direction: column;
align-items: center;
width: 100%;
}
.title {
......@@ -14,7 +13,7 @@
}
.screenWrapper {
width: 50%;
width: 80%;
}
@media screen and (min-width: 768px) {
......@@ -24,4 +23,8 @@
font-size: 2rem;
}
.screenWrapper {
width: 50%;
}
}
\ No newline at end of file
.LegendWrapper {
display: flex;
background-color: #3444c5;
height: 60px;
height: 50px;
right: 0;
left: 0;
gap: 1rem;
position: fixed;
bottom: 0;
justify-content: center;
justify-content: space-evenly;
}
\ No newline at end of file
import styles from './styles.module.css';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { setItem } from '../../../utils/localStorage'
import Input from '../../Base/Input/Index'
import Button from '../../Base/Button/Index';
import { useNavigate } from 'react-router-dom';
import styles from './styles.module.css';
const Login = () => {
const navigate = useNavigate();
const [email, setEmail] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
navigate("/seat-booking")
login();
}
const login = async () => {
const response = await fetch("http://localhost:3000/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("http://192.168.1.121:3000/users", {
method: "POST",
body: JSON.stringify({
email: email
})
})
}
}
const onEmailChange = (e) => {
setEmail(e.target.value)
}
return (
<div className={styles.bg}>
......@@ -22,6 +50,7 @@ const Login = () => {
name="email"
type="email"
placeholder='Enter email'
onChange={onEmailChange}
/>
<Button size={"md"}>Confirm</Button>
</form>
......
import { useEffect, useState } from 'react';
import BookingWrapper from '../../Layout/BookingWrapper/Index';
import Header from '../../Layout/Header/Index'
import Modal from '../../Shared/Modal/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 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("user");
const navigate = useNavigate();
const [selectedSeats, setSelectedSeats] = useState();
const [showSeatsModal, setShowSeatsModal] = useState(() => getItem("modal"));
const [showSeatsConfirmationModal, setShowSeatsConfirmationModal] = useState(false);
const [onOfSeats, setNoOfSeats] = useState();
const [currentSeats, setCurrentSeats] = useState([]) // currently selecting seats before booking
useEffect(() => {
getSelectedSeats();
}, [])
const data = [
{
"row_id": 1,
......@@ -400,14 +419,164 @@ const SeatBooking = () => {
]
}
]
const getSelectedSeats = async () => {
const response = await fetch(`${appConstants.API_URL_SEATS}`);
const data = await response.json();
setSelectedSeats(data);
}
const editSeatsApi = async (
id,
body,
newRequest
) => {
try {
const row = newRequest.row;
const column = newRequest.seat;
const current = selectedSeats.find((ele) => ele.userid == userId);
const found = current.selected.find((e) => e.row == newRequest.row && e.seat == newRequest.seat);
if (found) {
let newSelected = current.selected.filter((e) => !(e.row === row && e.seat == column));
const res = await fetch(`${appConstants.API_URL_SEATS}/${id}`,
{
method: "PATCH",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ selected: newSelected })
});
getSelectedSeats();
return;
}
await fetch(`${appConstants.API_URL_SEATS}/${id}`, {
method: "PATCH",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ selected: body })
});
getSelectedSeats();
} 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();
}
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]
}
});
let info = {
id: userId,
userid: userId,
selected: [
{
row: rowId,
seat: columnId
}
]
}
const existingUserSeatMap = selectedSeats?.find((ele) => ele.id == userId);
if (existingUserSeatMap) {
// editSeatsApi(
// existingUserSeatMap.userid,
// [...info.selected, ...existingUserSeatMap.selected],
// {
// row: rowId,
// seat: columnId
// }
// );
} else {
// createSeatApi(info);
}
}
const logout = () => {
reset();
navigate("/login");
}
const onModalChange = (value) => {
setNoOfSeats(value);
}
const modalClose = () => {
setItem("modal", false);
setShowSeatsModal(false)
}
const onSeatsConfirm = () => {
setShowSeatsConfirmationModal(true)
}
const seatsFinal = () => {
setShowSeatsConfirmationModal(false)
}
return (
<div className={styles['seat-booking-wrapper']}>
<Header>Choose Seats</Header>
<BookingWrapper seatData={data} />
<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"}>Confirm</Button>
<Button size={"md"} onClick={onSeatsConfirm}>Confirm</Button>
</div>
<LegendWrapper />
<LegendWrapper />
{showSeatsModal
&&
<Modal
onConfirm={modalClose}
onChange={onModalChange}
/>
}
{showSeatsConfirmationModal
&&
<Modal
onConfirm={seatsFinal}
onChange={onModalChange}
/>
}
</div>
)
}
......
.seat-booking-wrapper{
.seat-booking-wrapper {
background-color: #3444c5;
height: 100%;
width: 100%;
box-sizing: border-box;
flex-direction: column;
align-items: center;
gap: 2rem;
overflow-y: auto;
padding-bottom: 65px;
display: flex;
}
.seat-booking-wrapper > div {
flex: 1;
}
.btn-wrapper{
.btn-wrapper {
display: flex;
justify-content: center;
align-items: center;
margin-top: 1rem;
align-items: center;
flex: 1;
padding: 1.5rem 0;
}
.logout{
position: absolute;
right: 10px;
top: 10px;
cursor: pointer;
}
export const appConstants = {
API_URL_SEATS: "http://localhost:3000/selectedSeats",
API_URL_USERS: "http://localhost:3000/users"
}
// 192.168.1.121
\ No newline at end of file
export const setItem = (key, value) => {
localStorage.setItem(key, JSON.stringify(value));
};
export const getItem = (key) => {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : null;
};
export const reset = () => {
localStorage.clear();
}
\ No newline at end of file
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