Commit 3b117683 by Sujeeth AV

Your commit message here

parent 5e7a4928
...@@ -91,127 +91,115 @@ ...@@ -91,127 +91,115 @@
], ],
"users": [ "users": [
{ {
"id": "9500403346", "id": "9677655288",
"Mobile": "9500403346", "Mobile": "9677655288",
"Name": "sujeeth" "Name": "Anitha"
},
{
"id": "7418601450",
"Mobile": "7418601450",
"Name": "ravi"
}, },
{ {
"id": "9087654321", "id": "9597003337",
"Mobile": "9087654321", "Mobile": "9597003337",
"Name": "oggy" "Name": "venkatesh"
}, },
{ {
"id": "7894561230", "id": "9500403346",
"Mobile": "7894561230", "Mobile": "9500403346",
"Name": "khan" "Name": "Sujeeth"
}, },
{ {
"id": "8097654321", "id": "9976051171",
"Mobile": "8097654321", "Mobile": "9976051171",
"Name": "john" "Name": "JK"
}, },
{ {
"id": "9677655288", "id": "7418601450",
"Mobile": "9677655288", "Mobile": "7418601450",
"Name": "anitha" "Name": "Hari"
}, },
{ {
"id": "9597003337", "id": "7890654312",
"Mobile": "9597003337", "Mobile": "7890654312",
"Name": "venkatesh" "Name": "Guru"
}, },
{ {
"id": "6379757115", "id": "6543217890",
"Mobile": "6379757115", "Mobile": "6543217890",
"Name": "Shaganaz " "Name": "praba"
} }
], ],
"seats": [ "seats": [
{ {
"userId": "9087654321", "userId": "9677655288",
"seats": [
"D4"
],
"status": "booked",
"id": "9192"
},
{
"userId": "9500403346",
"seats": [
"A1",
"A2"
],
"status": "booked",
"id": "7685"
},
{
"id": "4d7f",
"userId": "7418601450",
"seats": [ "seats": [
"D1", "D1",
"D2", "D2",
"D3" "D3"
], ],
"status": "booked" "status": "booked",
"id": "4271"
}, },
{ {
"userId": "8097654321", "userId": "9597003337",
"seats": [ "seats": [
"E6", "E1",
"E7" "E2",
"E3",
"E4"
], ],
"status": "booked", "status": "booked",
"id": "164e" "id": "4fcc"
}, },
{ {
"userId": "9677655288", "userId": "9500403346",
"seats": [ "seats": [
"H1" "F3"
], ],
"status": "booked", "status": "booked",
"id": "aa34" "id": "b4fe"
}, },
{ {
"userId": "9597003337", "userId": "9976051171",
"seats": [ "seats": [
"E1", "F1",
"E2" "F2"
], ],
"status": "booked", "status": "booked",
"id": "9213" "id": "40ef"
}, },
{ {
"userId": "6379757115", "userId": "7418601450",
"seats": [ "seats": [
"B1", "G5",
"B2" "G6",
"G7",
"G8"
], ],
"status": "booked", "status": "booked",
"id": "89cd" "id": "a74a"
}, },
{ {
"id": "7ace", "userId": "7890654312",
"userId": null,
"seats": [ "seats": [
"B1",
"B2",
"B3", "B3",
"B4", "B4",
"E5", "B5",
"E8" "B8",
"B6",
"B7",
"C1",
"C2",
"C3",
"C4"
], ],
"status": "booked" "status": "booked",
"id": "cf53"
}, },
{ {
"id": "ab59", "id": "b883",
"userId": null, "userId": "6543217890",
"seats": [ "seats": [
"B3", "E7",
"B4",
"E5",
"E8" "E8"
], ],
"status": "booked" "status": "booked"
......
...@@ -6,12 +6,14 @@ ...@@ -6,12 +6,14 @@
} }
body { body {
background-color: #303fb6; background-color: #303fb6;
font-family: "Times New Roman", Times, serif; font-family: "Poppins", sans-serif;
min-height: 50svh; min-height: 50svh;
height: 100svh; height: 100svh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 1rem;
margin: 0;
} }
h2 { h2 {
font-size: 1.5rem; font-size: 1.5rem;
......
...@@ -9,7 +9,6 @@ export const loginUser = async (mobile) => { ...@@ -9,7 +9,6 @@ export const loginUser = async (mobile) => {
console.log("Login User API response:", res.data); console.log("Login User API response:", res.data);
return res.data.length ? res.data[0] : null; return res.data.length ? res.data[0] : null;
}; };
export const saveSeat=async({userId,seats})=>{ export const saveSeat=async({userId,seats})=>{
const response=await axios.post(`${BASE_URL}/seats`,{ const response=await axios.post(`${BASE_URL}/seats`,{
userId, userId,
......
...@@ -5,15 +5,44 @@ import { SeatLimit } from "./pages/SeatLimit"; ...@@ -5,15 +5,44 @@ import { SeatLimit } from "./pages/SeatLimit";
import { Summary } from "./components/Response/Index"; import { Summary } from "./components/Response/Index";
import { LoginPage } from "./pages/Forms"; import { LoginPage } from "./pages/Forms";
import { ContextProvider } from "./context/Index"; import { ContextProvider } from "./context/Index";
import { ProtectedRoute } from "./ProtectedRoute";
function App() { function App() {
return ( return (
<ContextProvider> <ContextProvider>
<Routes> <Routes>
<Route path="/signup" element={<LoginPage />} />
<Route path="/" element={<LoginPage />} /> <Route path="/" element={<LoginPage />} />
<Route path="/seat-limit" element={<SeatLimit />} /> <Route
<Route path="/booking" element={<SeatBooking />} /> path="/signup"
<Route path="booking-summary" element={<Summary />} /> element={
<ProtectedRoute>
<LoginPage />
</ProtectedRoute>
}
/>
<Route
path="/seat-limit"
element={
<ProtectedRoute>
<SeatLimit />
</ProtectedRoute>
}
/>
<Route
path="/booking"
element={
<ProtectedRoute>
<SeatBooking />
</ProtectedRoute>
}
/>
<Route
path="Ticket"
element={
<ProtectedRoute>
<Summary />
</ProtectedRoute>
}
/>
</Routes> </Routes>
</ContextProvider> </ContextProvider>
); );
......
src/Assets/Success.png

265 KB | W: | H:

src/Assets/Success.png

257 KB | W: | H:

src/Assets/Success.png
src/Assets/Success.png
src/Assets/Success.png
src/Assets/Success.png
  • 2-up
  • Swipe
  • Onion skin
import { Navigate } from "react-router-dom";
export const ProtectedRoute = ({ children }) => {
const isLoggedIn = !!(
localStorage.getItem("userId") || sessionStorage.getItem("userId")
);
return isLoggedIn ? children : <Navigate to="/" replace />;
};
import styles from "./Styles.module.css"; import styles from "./Styles.module.css";
export const Input = ({ value, onChange, placeholder, type, ...props }) => { export const Input = ({
value,
onChange,
placeholder,
type,
icon: Icon,
...props
}) => {
return ( return (
<div className={styles.input}> <div className={styles.input}>
{Icon && (
<span className={styles.icon}>
<Icon />
</span>
)}
<input <input
value={value} value={value}
placeholder={placeholder} placeholder={placeholder}
......
...@@ -6,6 +6,7 @@ input { ...@@ -6,6 +6,7 @@ input {
font-size: 1rem; font-size: 1rem;
width: 100%; width: 100%;
margin-bottom: 1rem; margin-bottom: 1rem;
padding-left: 1.3rem;
} }
input:focus { input:focus {
outline: none; outline: none;
...@@ -15,3 +16,15 @@ input:focus { ...@@ -15,3 +16,15 @@ input:focus {
display: flex; display: flex;
flex-direction: start; flex-direction: start;
} }
.icon {
position: absolute;
display: flex;
justify-content: start;
align-items: end;
margin-top: 17px;
margin-left: 9px;
color: grey;
}
input {
padding-left: 30px;
}
import React, { useState } from "react"; import { useState } from "react";
import { Header } from "../../Layout/Card/Header"; import { Header } from "../../Layout/Card/Header";
import { Input } from "../../Form/form/Input"; import { Input } from "../../Form/form/Input";
import { Button } from "../../Form/Button/Button"; import { Button } from "../../Form/Button/Button";
import styles from "./Login.module.css"; import styles from "./Login.module.css";
import { toast, ToastContainer } from "react-toastify"; import { toast, ToastContainer } from "react-toastify";
import Home from "../../../Assets/Login.png"; import Home from "../../../Assets/Login.png";
import { Link } from "react-router-dom"; import { FaPhoneAlt } from "react-icons/fa";
import { Sign } from "../SignUp/Sign";
export const Login = ({ onClick, onSwitch }) => { export const Login = ({ onClick, onSwitch }) => {
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const [islesser, setIsLesser] = useState(false); const [islesser, setIsLesser] = useState(false);
const InputChange = (e) => { const InputChange = (e) => {
setValue(e.target.value); const updated = e.target.value;
console.log("executed");
if (/^\d{0,10}$/.test(updated)) {
setValue(updated);
}
}; };
const HandleButton = (e) => { const HandleButton = (e) => {
e.preventDefault(); e.preventDefault();
if (!/^[6-9]\d{9}$/.test(value)) {
toast.info("Please enter a valid 10-digit number");
return;
}
if (value.length < 10) { if (value.length < 10) {
setIsLesser(true); setIsLesser(true);
toast.error("Mobile Number is less than 10"); toast.error("Mobile Number is less than 10");
...@@ -39,11 +45,13 @@ export const Login = ({ onClick, onSwitch }) => { ...@@ -39,11 +45,13 @@ export const Login = ({ onClick, onSwitch }) => {
<div className={styles.form}> <div className={styles.form}>
<div className={styles.inp}> <div className={styles.inp}>
<Input <Input
placeholder="Enter Your Number" placeholder="Enter Your Mobile Number"
type="text"
value={value} value={value}
onChange={InputChange} onChange={InputChange}
required type="tel"
pattern="[6-9][0-9]{9}"
min="0"
icon={FaPhoneAlt}
/> />
</div> </div>
{islesser && ( {islesser && (
......
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap");
@import url("https://fonts.googleapis.com/icon?family=Material+Icons"); @import url("https://fonts.googleapis.com/icon?family=Material+Icons");
body {
font-family: "Poppins", sans-serif;
}
.container { .container {
min-height: 100vh; min-height: 100vh;
display: flex; display: flex;
...@@ -42,7 +38,7 @@ body { ...@@ -42,7 +38,7 @@ body {
.form { .form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 1rem; gap: 0.3rem;
} }
.inp { .inp {
......
...@@ -5,6 +5,8 @@ import { Header } from "../../Layout/Card/Header"; ...@@ -5,6 +5,8 @@ import { Header } from "../../Layout/Card/Header";
import style from "./Styles.module.css"; import style from "./Styles.module.css";
import { ToastContainer } from "react-toastify"; import { ToastContainer } from "react-toastify";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { FaPhoneAlt } from "react-icons/fa";
import { TiSortAlphabetically } from "react-icons/ti";
export const Sign = ({ onClick, onChange, onSwitch }) => { export const Sign = ({ onClick, onChange, onSwitch }) => {
const [num, setNum] = useState(""); const [num, setNum] = useState("");
...@@ -65,6 +67,7 @@ export const Sign = ({ onClick, onChange, onSwitch }) => { ...@@ -65,6 +67,7 @@ export const Sign = ({ onClick, onChange, onSwitch }) => {
type="text" type="text"
pattern="[6-9][0-9]{9}" pattern="[6-9][0-9]{9}"
min="0" min="0"
icon={FaPhoneAlt}
/> />
</div> </div>
<div className={style.Inpname}> <div className={style.Inpname}>
...@@ -74,6 +77,7 @@ export const Sign = ({ onClick, onChange, onSwitch }) => { ...@@ -74,6 +77,7 @@ export const Sign = ({ onClick, onChange, onSwitch }) => {
onChange={Name} onChange={Name}
type="text" type="text"
maxLength={255} maxLength={255}
icon={TiSortAlphabetically}
/> />
</div> </div>
<div className={style.signbtn}> <div className={style.signbtn}>
......
import React from "react";
import styles from "./Styles.module.css";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import { Button } from "../Form/Button/Button";
import { IoMdLogOut } from "react-icons/io"; import { IoMdLogOut } from "react-icons/io";
import { MdHome, MdCheckCircle } from "react-icons/md";
import { RiArrowGoBackLine } from "react-icons/ri";
import styles from "./Styles.module.css";
import Success from "../../Assets/Success.png";
import Failed from "../../Assets/Failed.png"; import Failed from "../../Assets/Failed.png";
import QRCode from "../../Assets/QRcode.png";
import Ticket from "../../Assets/Success.png";
export const Summary = ({ success: propSuccess }) => { export const Summary = ({ success: propSuccess }) => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const currentDateTime = new Date().toLocaleString();
const success = propSuccess ?? location.state?.success; const success = propSuccess ?? location.state?.success;
const onLogout = () => { const bookingInfo = location.state?.bookingInfo;
console.log("exit");
navigate("/"); const onLogout = () => navigate("/");
};
const onBack = () => navigate("/seat-limit");
return ( return (
<div> <div className={styles.pageContainer}>
{success === true ? ( {success === true ? (
<div className={styles.success}> <div className={styles.success}>
{console.log("Worked")} <div>
<img src={Ticket} alt="Success" className={styles.symbol} /> <MdCheckCircle className={styles.symbol} />
<h2 className={styles.hd}>🎉 Hooray!!! Successfully Booked</h2>
<img src={QRCode} alt="QR-Code" className={styles.qr} />
<p className={styles.timeStamp}>Booked On: {currentDateTime}</p>
<div className={styles.logout}>
<Button onClick={onLogout}>
<IoMdLogOut className={styles.logoutIcon} />
</Button>
</div> </div>
<h1 className={styles.hd}>Booking Confirmed!</h1>
<p className={styles.subtitle}>
Your tickets are ready. Enjoy the show!
</p>
<div className={styles.qrContainer}>
<img src={Success} alt="QR code" className={styles.qr} />
<p className={styles.qrNote}>Scan this QR code at the entrance</p>
</div>
{bookingInfo && (
<div className={styles.info}>
<div className={styles.row}>
<span className={styles.label}>Movie</span>
<span className={styles.value}>Thug Life</span>
</div>
<div className={styles.row}>
<span className={styles.label}>Seats</span>
<div className={styles.seatWrapper}>
{bookingInfo.seats?.map((seat, i) => (
<span key={i} className={styles.seatPill}>
{seat}
</span>
))}
</div>
</div>
<div className={styles.row}>
<span className={styles.label}>User Number</span>
<span className={styles.value}>{bookingInfo.userId}</span>
</div>
<div className={styles.row}>
<span className={styles.label}>Booked On</span>
<span className={styles.value}>{bookingInfo.time}</span>
</div>
</div>
)}
<button onClick={onBack} className={styles.downloadBtn}>
<RiArrowGoBackLine className={styles.icon} />
<span>Book More Tickets</span>
</button>
<button onClick={onLogout} className={styles.homeBtn}>
<MdHome className={styles.icon} />
<span>Back to Home</span>
</button>
</div> </div>
) : ( ) : (
<div className={styles.error}> <div className={styles.error}>
{console.log("Failed")}
<img src={Failed} alt="Failed" className={styles.symbol} /> <img src={Failed} alt="Failed" className={styles.symbol} />
<h2>Something Went Wrong</h2> <h2 className={styles.hdError}>Something Went Wrong</h2>
<p className={styles.timeStamp}>Booked On: {currentDateTime}</p> <p className={styles.timeStamp}>
<div className={styles.logout}> Booked On: {new Date().toLocaleString()}
<Button onClick={onLogout}> </p>
<IoMdLogOut className={styles.logoutIcon} /> <button onClick={onLogout} className={styles.homeBtn}>
</Button> <IoMdLogOut className={styles.icon} />
</div> <span>Back to Home</span>
</button>
</div> </div>
)} )}
</div> </div>
......
.success, .pageContainer {
.error {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 2rem 1rem; min-height: 100vh;
text-align: center; padding: 1rem;
min-height: 80vh; }
.success {
background-color: #ffffff; background-color: #ffffff;
padding: 2rem;
border-radius: 1.5rem;
max-width: 500px;
width: 100%;
text-align: center;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.error {
background-color: #fff1f1;
padding: 2rem;
border-radius: 1.5rem;
max-width: 500px;
width: 100%;
text-align: center;
border: 1px solid #fca5a5;
box-shadow: 0 10px 25px rgba(239, 68, 68, 0.1);
} }
.symbol { .symbol {
width: 380px; font-size: 64px;
height: 300px; color: #22c55e;
margin-bottom: 1.5rem; margin-bottom: 1rem;
}
.qr {
width: 128px;
height: 128px;
border-radius: 0.5rem;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
}
.qrContainer {
background-color: #f3f4f6;
padding: 1.5rem;
border-radius: 1rem;
margin-bottom: 2rem;
}
.qrNote {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.5rem;
} }
.hd { .hd {
font-size: 1.5rem; font-size: 1.5rem;
font-weight: 700; font-weight: 600;
color: #28a745; /* Success Green */ color: #1f2937;
margin-bottom: 1rem; margin-bottom: 0.5rem;
} }
.error .hd { .hdError {
color: #dc3545; /* Error Red */ font-size: 1.25rem;
font-weight: 600;
color: #dc2626;
margin-bottom: 0.5rem;
} }
.qr { .subtitle {
width: 160px; color: #4b5563;
height: auto; margin-bottom: 2rem;
margin: 1rem 0;
border: 1px solid #e0e0e0;
border-radius: 12px;
padding: 0.5rem;
} }
.timeStamp { .info {
font-size: 0.9rem; margin-bottom: 2rem;
color: #555; font-size: 0.875rem;
margin: 1rem 0; }
.row {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
}
.label {
color: #6b7280;
}
.value {
color: #1f2937;
font-weight: 500;
}
.seatWrapper {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
margin-left: 2rem;
}
.seatPill {
background-color: #e0e7ff;
color: #4338ca;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.downloadBtn {
width: 100%;
background-color: #4f46e5;
color: white;
font-weight: 500;
padding: 0.75rem 1rem;
border-radius: 0.75rem;
border: none;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
transition: background-color 0.2s ease;
cursor: pointer;
}
.downloadBtn:hover {
background-color: #4338ca;
}
.homeBtn {
margin-top: 1rem;
width: 100%;
background-color: #e5e7eb;
color: #374151;
font-weight: 500;
padding: 0.75rem 1rem;
border-radius: 0.75rem;
border: none;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
transition: background-color 0.2s ease;
cursor: pointer;
}
.homeBtn:hover {
background-color: #d1d5db;
} }
.logout { .icon {
margin-top: 1.5rem; font-size: 1.25rem;
} }
.logoutIcon { .timeStamp {
font-size: 1.2rem; font-size: 0.875rem;
color: #000; color: #6b7280;
margin-bottom: 1rem;
} }
body {
font-family: "Poppins", sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 1rem;
margin: 0;
}
.container { .container {
width: 100%; width: 100%;
max-width: 15rem; max-width: 15rem;
......
import React, { useState } from 'react'
import { Header } from '../../Layout/Card/Header'
import {Screen} from '../Screen/Screen';
import { Index } from '../Seatposition/Index';
import styles from './Styles.module.css'
import { Button } from '../../Form/Button/Button';
import { Legend } from '../../Layout/Legend/Legend';
export const Layout = () => {
const[selectedseat,SetSelectedSeat]=useState([]);
const Confirm=()=>{
if(selectedseat.length > 0){
alert('Are You Sure To Book Tickets');
}
else{
alert("Choose Minimun One Ticket To Proceed");
}
}
return (
<>
<Header className={styles.head} title="Choose Your Seats" Color="white"/>
<div className={styles.center}>
<div className={styles.screen}>
<Screen/>
</div>
<div className={styles.seat}>
<Index selectedseat={selectedseat} SetSelectedseat={SetSelectedSeat} className='seats'/>
</div>
</div>
<div className={styles.btn}>
<Button backgroundColor="white"
label="Confirm"
primary={true}
onClick={Confirm}
/>
</div>
<div className='legend'>
<Legend/>
</div>
</>
)
}
* {
margin: 0;
padding: 0;
}
body {
width: 100%;
height: 60svh;
}
.head {
text-align: center;
margin-top: 25rem;
}
.seat {
overflow: visible;
position: relative;
}
.seat::before {
content: attr(data-tooltip);
position: relative;
bottom: 120%;
left: 50%;
transform: translateX(-50%);
color: #fff;
padding: 3px 6px;
font-size: 12px;
white-space: nowrap;
border-radius: 4px;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease-in-out;
z-index: 10;
}
.seat:hover::before {
opacity: 1;
}
.screen {
display: flex;
justify-content: center;
margin-bottom: -5rem;
position: relative;
}
.center {
display: flex;
flex-direction: column;
align-items: center;
gap: 0;
width: 100%;
}
.btn {
margin-top: 4rem;
display: flex;
justify-content: center;
height: 3rem;
}
button {
height: 3rem;
width: 25%;
border-radius: 10px;
cursor: pointer;
font-weight: 700;
}
.legend {
display: flex;
justify-content: center;
align-items: center;
}
.log {
display: flex;
justify-content: end;
}
...@@ -81,6 +81,7 @@ export const SeatSelectionComponent = ({ ...@@ -81,6 +81,7 @@ export const SeatSelectionComponent = ({
children="Confirm" children="Confirm"
backgroundColor="#fff" backgroundColor="#fff"
onClick={ConfirmSeat} onClick={ConfirmSeat}
disabled={selectedseats.length < seatLimit}
/> />
</div> </div>
</div> </div>
......
import { createContext, useContext, useEffect, useState } from "react"; import { createContext, useContext, useEffect, useState } from "react";
import * as api from "../Api/Api"; import * as api from "../Api/Api";
import { toast } from "react-toastify"; import { toast, ToastContainer } from "react-toastify";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
export const AppContext = createContext(); export const AppContext = createContext();
...@@ -18,30 +18,50 @@ export function ContextProvider({ children }) { ...@@ -18,30 +18,50 @@ export function ContextProvider({ children }) {
console.log(reservedSeats); console.log(reservedSeats);
const loginOrRegister = async ({ mobile, name }) => { const loginUser = async ({ mobile }) => {
try { try {
const user = await api.loginUser(mobile); const user = await api.loginUser(mobile);
if (!user) { if (!user) {
console.log("registering:", mobile, name); toast.error("User not found. Sign up now.");
const response = await api.register({ mobile, name }); console.log("New User");
console.log("Registered:", response); return;
sessionStorage.setItem("userId", response?.id); }
await getAllReservedSeats();
navigate("/seat-limit"); sessionStorage.setItem("userId", user.id);
return response;
} else { const response = await api.getSeat();
sessionStorage.setItem("userId", user?.id); const userSelectedSeats = response.find((e) => e.userId == user.id);
const response = await getAllReservedSeats();
const userSelectedSeats = response.find((e) => e.userId == user?.id);
sessionStorage.setItem( sessionStorage.setItem(
"seatLimit", "seatLimit",
userSelectedSeats?.seats?.length || 0 userSelectedSeats?.seats?.length || 0
); );
navigate("/booking");
navigate("/seat-limit");
return user; return user;
} catch (err) {
toast.error(err.message || "Login failed");
}
};
const registerUser = async ({ mobile, name }) => {
try {
const existingUser = await api.loginUser(mobile);
if (existingUser) {
toast.error("Mobile number already registered. Please log in.");
navigate("/");
return;
} }
const newUser = await api.register({ mobile, name });
sessionStorage.setItem("userId", newUser.id);
sessionStorage.setItem("seatLimit", "0");
toast.success("Signup successful!");
navigate("/");
return newUser;
} catch (err) { } catch (err) {
toast.error(err.message); toast.error(err.message || "Signup failed");
} }
}; };
...@@ -83,9 +103,11 @@ export function ContextProvider({ children }) { ...@@ -83,9 +103,11 @@ export function ContextProvider({ children }) {
api.getUserReservedSeats(id), api.getUserReservedSeats(id),
]); ]);
setReservedSeats(allReserved); setReservedSeats(allReserved);
setUserSeats(userReserved); setUserSeats({ userId: id, seats: userReserved });
return true;
} catch (err) { } catch (err) {
toast.error(err.message || "Something went wrong."); toast.error(err.message || "Something went wrong.");
return false;
} }
}; };
...@@ -129,11 +151,17 @@ export function ContextProvider({ children }) { ...@@ -129,11 +151,17 @@ export function ContextProvider({ children }) {
reservedSeats, reservedSeats,
isLoading, isLoading,
seatLayout, seatLayout,
loginOrRegister, loginUser,
registerUser,
addOrUpdateSeats, addOrUpdateSeats,
getAllReservedSeats, getAllReservedSeats,
getSeatLayout, getSeatLayout,
}; };
return <AppContext.Provider value={value}>{children}</AppContext.Provider>; return (
<AppContext.Provider value={value}>
{children}
<ToastContainer position="top-right" autoClose={3000} />
</AppContext.Provider>
);
} }
...@@ -7,7 +7,7 @@ import { useNavigate } from "react-router-dom"; ...@@ -7,7 +7,7 @@ import { useNavigate } from "react-router-dom";
export const LoginPage = () => { export const LoginPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const { loginOrRegister } = useAppContext(); const { loginUser, registerUser } = useAppContext();
const [showLogin, setShowLogin] = useState(true); const [showLogin, setShowLogin] = useState(true);
useEffect(() => { useEffect(() => {
...@@ -15,12 +15,14 @@ export const LoginPage = () => { ...@@ -15,12 +15,14 @@ export const LoginPage = () => {
}, []); }, []);
const handlelogin = async ({ mobile }) => { const handlelogin = async ({ mobile }) => {
await loginOrRegister({ mobile }); const res = await loginUser({ mobile });
if (res) {
navigate("/seat-limit"); navigate("/seat-limit");
}
}; };
const handleSignup = async ({ name, mobile }) => { const handleSignup = async ({ name, mobile }) => {
const res = await loginOrRegister({ name, mobile }); const res = await registerUser({ name, mobile });
console.log("registered", res); console.log("registered", res);
setShowLogin(true); setShowLogin(true);
}; };
......
...@@ -112,7 +112,16 @@ function SeatBooking() { ...@@ -112,7 +112,16 @@ function SeatBooking() {
sessionStorage.setItem("selectedSeats", JSON.stringify(validSeats)); sessionStorage.setItem("selectedSeats", JSON.stringify(validSeats));
if (typeof clearSelection === "function") clearSelection(); if (typeof clearSelection === "function") clearSelection();
navigate("/booking-summary", { state: { success: true } }); navigate("/Ticket", {
state: {
success: true,
bookingInfo: {
userId,
seats: validSeats,
time: new Date().toLocaleString(),
},
},
});
} catch (error) { } catch (error) {
console.error("Error saving seats:", error); console.error("Error saving seats:", error);
toast.error("Failed to reserve seats. Please try again."); toast.error("Failed to reserve seats. Please try again.");
......
...@@ -2,6 +2,7 @@ import React from "react"; ...@@ -2,6 +2,7 @@ import React from "react";
import Counter from "../components/Top-level/Counter/Counter"; import Counter from "../components/Top-level/Counter/Counter";
import { useAppContext } from "../context/Index"; import { useAppContext } from "../context/Index";
import styles from "./Styles.module.css"; import styles from "./Styles.module.css";
import { MdEventSeat } from "react-icons/md";
export const SeatLimit = () => { export const SeatLimit = () => {
const totalSeats = 60; const totalSeats = 60;
const { reservedSeats } = useAppContext(); const { reservedSeats } = useAppContext();
...@@ -14,7 +15,10 @@ export const SeatLimit = () => { ...@@ -14,7 +15,10 @@ export const SeatLimit = () => {
return ( return (
<> <>
<p className={styles.line}>Remaining Seats Available:{Seat}</p> <div className={styles.seat}>
<MdEventSeat className={styles.icon} />
<p className={styles.line}>Remaining Seats Available: {Seat}</p>
</div>
<Counter onSubmit={handleSeat} /> <Counter onSubmit={handleSeat} />
</> </>
); );
......
...@@ -42,12 +42,20 @@ ...@@ -42,12 +42,20 @@
color: #c7d2fe; color: #c7d2fe;
font-weight: 500; font-weight: 500;
margin-bottom: 1rem; margin-bottom: 1rem;
text-align: center; display: flex;
font-family: "Inter", sans-serif; justify-content: center;
margin-left: 1rem;
} }
.line p { .line p {
text-align: center; text-align: center;
} }
.icon {
color: #fff;
position: absolute;
margin-left: 0.5rem;
margin-top: 4px;
}
@media (min-width: 768px) { @media (min-width: 768px) {
.container { .container {
display: flex; display: flex;
...@@ -62,4 +70,10 @@ ...@@ -62,4 +70,10 @@
.login { .login {
min-width: 40rem; min-width: 40rem;
} }
.icon {
margin-left: 3.5rem;
}
.line {
margin-left: 2rem;
}
} }
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