Commit 64df307a by Sujeeth AV

Fixed signup page routing issue and updated LoginPage.jsx

parent 0b1fbd2e
......@@ -135,7 +135,11 @@
{
"userId": "9677655288",
"seats": [
"A1"
"A4",
"A5",
"A6",
"E5",
"E6"
],
"status": "booked",
"id": "4271"
......@@ -154,8 +158,10 @@
{
"userId": "9500403346",
"seats": [
"F3",
"F4"
"C5",
"C6",
"C7",
"C8"
],
"status": "booked",
"id": "b4fe"
......@@ -163,8 +169,8 @@
{
"userId": "9976051171",
"seats": [
"F1",
"F2"
"A1",
"A2"
],
"status": "booked",
"id": "40ef"
......
......@@ -7,13 +7,12 @@
body {
background-color: #303fb6;
font-family: "Poppins", sans-serif;
min-height: 50svh;
height: 100svh;
min-height: 100svh;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
margin: 0;
padding: 0;
}
h2 {
font-size: 1.5rem;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -2,24 +2,29 @@
"name": "seat",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
"build-storybook": "storybook build",
"start:server": "json-server --watch db.json --port 3001 --host 0.0.0.0"
},
"dependencies": {
"axios": "^1.9.0",
"classnames": "^2.5.1",
"express": "^5.1.0",
"fireworks-js": "^2.10.8",
"json-server": "^0.17.4",
"json-server-auth": "^2.1.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.6.2",
"react-toastify": "^11.0.5"
"react-toastify": "^11.0.5",
"remark-gfm": "^4.0.1"
},
"devDependencies": {
"@eslint/js": "^9.25.0",
......
const jsonServer = require('json-server');
const server = jsonServer.create();
const router = jsonServer.router('db.json');
const middlewares = jsonServer.defaults();
server.use(middlewares);
server.use(jsonServer.bodyParser);
server.get('/reserved-seats', (req, res) => {
const seats = router.db.get('seats')
.filter({ status: 'booked' })
.map(seat => ({
id: seat.id,
seats: seat.seats
}))
.value();
res.json(seats);
});
server.use(router);
const PORT = 3001;
server.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
});
import axios from "axios";
const BASE_URL = "http://192.168.1.64:3001";
export const loginUser = async (mobile) => {
const res = await axios.get(`${BASE_URL}/users`, {
params: { Mobile: mobile }
......@@ -61,3 +63,8 @@ export const getUserReservedSeats = async (userId) => {
return record || null;
};
export const getReservedSeatOnly=async()=>{
const response=await axios.get(`${BASE_URL}/reserved-seats`);
return response.data;
};
......@@ -11,14 +11,7 @@ function App() {
<ContextProvider>
<Routes>
<Route path="/" element={<LoginPage />} />
<Route
path="/signup"
element={
<ProtectedRoute>
<LoginPage />
</ProtectedRoute>
}
/>
<Route path="/signup" element={<LoginPage />} />
<Route
path="/seat-limit"
element={
......@@ -43,6 +36,8 @@ function App() {
</ProtectedRoute>
}
/>
<Route path="*" element={<Summary success={false} />} />
</Routes>
</ContextProvider>
);
......
src/Assets/Failed.png

261 KB | W: | H:

src/Assets/Failed.png

61.1 KB | W: | H:

src/Assets/Failed.png
src/Assets/Failed.png
src/Assets/Failed.png
src/Assets/Failed.png
  • 2-up
  • Swipe
  • Onion skin
src/Assets/Login.png

240 KB | W: | H:

src/Assets/Login.png

135 KB | W: | H:

src/Assets/Login.png
src/Assets/Login.png
src/Assets/Login.png
src/Assets/Login.png
  • 2-up
  • Swipe
  • Onion skin
import { Input } from "./Input";
export default {
title: 'Base/Input',
title: "Base/Input",
component: Input,
tags: ['autodocs'],
tags: ["autodocs"],
};
export const input={
render:(args)=><Input {...args}/>,
export const input = {
render: (args) => <Input {...args} />,
args:{
placeholder:'Enter the Text',
}
}
export const number={
render:(args)=><Input {...args}/>,
args: {
placeholder: "Enter the Text",
type: "text",
},
};
args:{
placeholder:'Enter Your Number',
}
}
export const number = {
render: (args) => <Input {...args} />,
args: {
placeholder: "Enter Your Number",
type: "number",
},
};
......@@ -3,11 +3,13 @@ import { Header } from "../../Layout/Card/Header";
import { Input } from "../../Form/form/Input";
import { Button } from "../../Form/Button/Button";
import styles from "./Login.module.css";
import { toast, ToastContainer } from "react-toastify";
import Home from "../../../Assets/Login.png";
import { FaPhoneAlt } from "react-icons/fa";
import PropTypes from "prop-types";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
export const Login = ({ onClick, onSwitch }) => {
export const Login = ({ title, onSubmit = () => {}, markdown, labels }) => {
const [value, setValue] = useState("");
const [islesser, setIsLesser] = useState(false);
......@@ -19,43 +21,34 @@ export const Login = ({ onClick, onSwitch }) => {
}
};
const HandleButton = (e) => {
const handleSubmit = (e) => {
e.preventDefault();
if (!value) {
toast.info("Please Enter Your Number");
return;
}
if (!/^[6-9]\d{9}$/.test(value)) {
toast.info("Invalid Number");
return;
}
if (value.length < 10) {
setIsLesser(true);
toast.error("Mobile Number is less than 10");
} else {
console.log("onClick prop:", onClick);
onClick({ mobile: value });
setIsLesser(false);
setValue("");
return;
}
onSubmit({ mobile: value });
setIsLesser(false);
setValue("");
};
const HandleKey = (e) => {
const handleKey = (e) => {
if (e.key === "Enter") {
HandleButton(e);
handleSubmit(e);
}
};
return (
<>
<div className={styles.container}>
<div className={`${styles.back} ${styles.round}`}>
<Header title="Login Page" Color="#000" className={styles.head} />
<img src={Home} className={styles.img} />
<div className={styles.form}>
<div className={`${styles.login} ${styles.round}`}>
<Header title={title} className={styles.head} />
<img src={Home} className={styles.img} alt="Login illustration" />
<div className={styles.form}>
<form onSubmit={handleSubmit}>
<div className={styles.inp}>
<Input
placeholder="Enter Your Mobile Number"
placeholder={labels.mobilePlaceholder}
value={value}
onChange={InputChange}
type="tel"
......@@ -63,32 +56,41 @@ export const Login = ({ onClick, onSwitch }) => {
min="0"
icon={FaPhoneAlt}
required
onKeyDown={HandleKey}
onKeyDown={handleKey}
/>
</div>
{islesser && (
<span className={styles.span}>Please enter 10 digits</span>
<span className={styles.span}>{labels.mobileError}</span>
)}
<div className={styles.btn}>
<Button
children="Submit"
onClick={HandleButton}
// disabled={value.trim().length === 0}
/>
<div className={styles.foot}>
Don't have an account?{" "}
<span
style={{ color: "blue", cursor: "pointer" }}
onClick={onSwitch}
>
Sign Up
</span>
</div>
<Button type="submit">{labels.submitBtnText}</Button>
</div>
</form>
<div className={styles.footer}>
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{markdown}
</ReactMarkdown>
</div>
</div>
<ToastContainer />
</div>
</>
);
};
Login.propTypes = {
onSubmit: PropTypes.func,
onSwitch: PropTypes.func,
markdown: PropTypes.string,
labels: PropTypes.shape({
submitBtnText: PropTypes.string,
mobilePlaceholder: PropTypes.string,
mobileInvalid: PropTypes.string,
mobileError: PropTypes.string,
mobileRequired: PropTypes.string,
title: PropTypes.string,
signUp: PropTypes.string,
accountLabel: PropTypes.string,
}),
};
@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");
.container {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.back {
background-color: #f7fafc;
padding: 2rem;
.login {
background: #ffff;
padding: 1rem;
border-radius: 0.75rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
width: 100%;
max-width: 28rem;
text-align: center;
}
.round {
border-radius: 0.75rem;
}
.head {
font-size: 1.875rem;
font-weight: 700;
color: #2d3748;
margin-bottom: 2rem;
}
.img {
width: 16rem;
img {
height: auto;
margin-bottom: 2rem;
aspect-ratio: 4/3;
object-fit: contain;
max-width: 100%;
display: block;
}
.form {
display: flex;
flex-direction: column;
gap: 0.3rem;
}
.inp {
margin-bottom: 0.3rem;
margin-bottom: 0;
}
.span {
......@@ -56,7 +37,7 @@
.btn {
display: flex;
flex-direction: column;
gap: 0.5rem;
gap: 0.3rem;
}
.foot {
......@@ -64,3 +45,11 @@
color: #4a5568;
margin-top: 1rem;
}
.head {
color: #000;
}
.footer {
margin-top: 1rem;
}
......@@ -5,8 +5,7 @@ export default {
component: Login,
tags: ["autodocs"],
argTypes: {
onClick: { action: "User" },
onChange: { action: "change" },
onSubmit: { action: "Submitted" },
},
parameters: {
layout: "centered",
......@@ -14,11 +13,15 @@ export default {
};
export const login = {
render: (args) => <Login {...args} />,
args: {
value: "",
onLogin: (user) => {
console.log("login", user);
title: "Login",
markdown: `Don't have an account? [SignUp](/sign-up)`,
labels: {
mobilePlaceholder: "Enter Your Number",
submitBtnText: "Submit",
mobileError: "Enter 10 digits",
},
},
render: (args) => <Login {...args} />,
};
......@@ -3,12 +3,13 @@ import { Input } from "../../Form/form/Input";
import { Button } from "../../Form/Button/Button";
import { Header } from "../../Layout/Card/Header";
import style from "./Styles.module.css";
import { ToastContainer } 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 = ({
onSubmit,
onChange,
labels: { mobileplaceholder, nameplaceholder, btnLabel, titleLabel },
}) => {
const [num, setNum] = useState("");
const [name, setName] = useState("");
......@@ -27,70 +28,55 @@ export const Sign = ({ onClick, onChange, onSwitch }) => {
onChange(e);
}
};
const handleNewUser = () => {
const handleNewUser = (e) => {
e.preventDefault();
console.log("signup page worked");
if (!num || !name) {
toast.error("Please enter both Name and Number ");
return;
}
if (!/^[6-9]\d{9}$/.test(num)) {
toast.info("Please enter a valid 10-digit number");
return;
}
const confirmSignUp = window.confirm("Are you sure you want to Sign Up?");
if (!confirmSignUp) return;
console.log("Calling onClick:", { mobile: num, name });
if (onClick) {
onClick({ mobile: num, name });
} else {
console.log("onclick not defined in sign");
}
setName("");
setNum("");
if (onSwitch) {
onSwitch();
if (onSubmit) {
onSubmit({ name, mobile: num });
}
};
return (
<>
<div className={style.container}>
<div className={style.block}>
<div className={style.image}>
<Header title="Sign-Up Page" Color="#000" className={style.head} />
<Header title={titleLabel} className={style.head} />
</div>
<div className={style.signcontainer}>
<div className={style.Inpbtn}>
<Input
placeholder="Enter Your Mobile Number"
value={num}
onChange={Number}
type="text"
pattern="[6-9][0-9]{9}"
min="0"
icon={FaPhoneAlt}
/>
</div>
<div className={style.Inpname}>
<Input
placeholder="Enter Your Name"
value={name}
onChange={Name}
type="text"
maxLength={255}
icon={TiSortAlphabetically}
/>
</div>
<div className={style.signbtn}>
<Button
children="Submit"
size="medium"
primary="true"
onClick={handleNewUser}
/>
</div>
<form onSubmit={handleNewUser}>
<div className={style.Inpbtn}>
<Input
placeholder={mobileplaceholder}
value={num}
onChange={Number}
type="text"
pattern="[6-9][0-9]{9}"
min="0"
icon={FaPhoneAlt}
/>
</div>
<div className={style.Inpname}>
<Input
placeholder={nameplaceholder}
value={name}
onChange={Name}
type="text"
maxLength={255}
icon={TiSortAlphabetically}
/>
</div>
<div className={style.signbtn}>
<Button
children={btnLabel}
size="medium"
primary="true"
type="submit"
/>
</div>
</form>
</div>
</div>
<ToastContainer />
</div>
</>
);
......
......@@ -11,4 +11,14 @@ export default {
},
};
export const signUp = (args) => <Sign {...args} />;
export const signUp = {
render: (args) => <Sign {...args} />,
args: {
labels: {
mobileplaceholder: "Enter Your Number",
nameplaceholder: "Enter Your Name",
btnLabel: "Submit",
titleLabel: "SignUp",
},
},
};
......@@ -12,22 +12,18 @@
background-color: #ffffff;
border-radius: 1rem;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
padding: 1.2rem;
max-width: 600px;
padding: 1rem;
max-width: 37.5rem;
width: 100%;
}
.head {
color: #000;
}
.image {
text-align: center;
margin-bottom: 1rem;
}
.head {
font-size: 2rem;
font-weight: bold;
color: #1f2937;
}
.signcontainer {
display: flex;
flex-direction: column;
......
export const Header = ({ title, Color, className }) => {
import styles from "./Header.module.css";
export const Header = ({ title, fontSize, ...props }) => {
return (
<div className={className}>
<h2 style={{ color: Color }}>{title}</h2>
<div className={styles.head}>
<h2 style={{ fontSize }} {...props}>
{title}
</h2>
</div>
);
};
......@@ -4,7 +4,7 @@ import { MdHome, MdCheckCircle } from "react-icons/md";
import { RiArrowGoBackLine } from "react-icons/ri";
import { Button } from "../Form/Button/Button";
import styles from "./Styles.module.css";
import Success from "../../Assets/Success.png";
import Failed from "../../Assets/Failed.png";
export const Summary = ({ success: propSuccess }) => {
......@@ -30,11 +30,6 @@ export const Summary = ({ success: propSuccess }) => {
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}>Your Seat, Secured in Seconds</p>
</div>
{bookingInfo && (
<div className={styles.info}>
<div className={styles.row}>
......@@ -79,10 +74,6 @@ export const Summary = ({ success: propSuccess }) => {
) : (
<div className={styles.error}>
<img src={Failed} alt="Failed" className={styles.symbol} />
<h2 className={styles.hdError}>Something Went Wrong</h2>
<p className={styles.timeStamp}>
Booked On: {new Date().toLocaleString()}
</p>
<Button onClick={onLogout} className={styles.homeBtn}>
<IoMdLogOut className={styles.icon} />
<span>Back to Home</span>
......
......@@ -3,16 +3,14 @@
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 2rem;
padding: 1rem;
margin: 1rem;
}
.success {
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);
......@@ -20,21 +18,21 @@
.error {
background-color: #fff1f1;
padding: 2rem;
padding: 1.2rem;
border-radius: 1.5rem;
max-width: 500px;
max-width: 50svh;
width: 100%;
text-align: center;
border: 1px solid #fca5a5;
box-shadow: 0 10px 25px rgba(239, 68, 68, 0.1);
}
.symbol {
font-size: 64px;
font-size: 54px;
color: #22c55e;
margin-bottom: 1rem;
}
.error .symbol {
max-width: 100%;
object-fit: contain;
}
.qr {
width: 128px;
height: 128px;
......@@ -50,20 +48,20 @@
}
.qrNote {
font-size: 0.75rem;
font-size: 0.69rem;
color: #6b7280;
margin-top: 0.5rem;
}
.hd {
font-size: 1.5rem;
font-size: 1rem;
font-weight: 600;
color: #1f2937;
margin-bottom: 0.5rem;
}
.hdError {
font-size: 1.25rem;
font-size: 0.9rem;
font-weight: 600;
color: #dc2626;
margin-bottom: 0.5rem;
......@@ -71,12 +69,12 @@
.subtitle {
color: #4b5563;
margin-bottom: 2rem;
font-size: 0.78rem;
}
.info {
margin-bottom: 2rem;
font-size: 0.875rem;
margin-bottom: 1rem;
font-size: 0.775rem;
}
.row {
......@@ -106,8 +104,8 @@
color: #4338ca;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
font-size: 0.6rem;
font-weight: 450;
}
.downloadBtn {
......@@ -125,6 +123,7 @@
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
transition: background-color 0.2s ease;
cursor: pointer;
font-size: 0.78rem;
}
.downloadBtn:hover {
......@@ -146,6 +145,7 @@
gap: 0.5rem;
transition: background-color 0.2s ease;
cursor: pointer;
font-size: 0.78rem;
}
.homeBtn:hover {
......@@ -153,17 +153,58 @@
}
.icon {
font-size: 1.25rem;
font-size: 1rem;
}
.timeStamp {
font-size: 0.875rem;
font-size: 0.675rem;
color: #6b7280;
margin-bottom: 1rem;
}
@media (min-width: 768px) {
.pageContainer {
margin: 0;
margin-top: 4rem;
}
.symbol {
font-size: 64px;
margin-bottom: 1rem;
}
.icon {
font-size: 1.25rem;
}
.timeStamp {
font-size: 0.875rem;
margin-bottom: 1rem;
}
.seatPill {
font-size: 0.75rem;
font-weight: 500;
}
.info {
margin-bottom: 2rem;
font-size: 0.875rem;
}
.qrNote {
font-size: 0.75rem;
}
.hd {
font-size: 1.5rem;
font-weight: 600;
}
.hdError {
font-size: 1.25rem;
font-weight: 600;
}
.subtitle {
font-size: 1rem;
margin-bottom: 2rem;
}
.homeBtn,
.downloadBtn {
font-size: 1rem;
}
}
......@@ -7,10 +7,8 @@ import { toast } from "react-toastify";
const Counter = ({ onSubmit, className, onChange, onClick }) => {
const [count, setCount] = useState(0);
console.log(onSubmit);
const Num = (e) => {
const value = Number(e.target.value);
console.log("number", value);
setCount(value);
if (onChange) {
onChange({ limit: value });
......
......@@ -2,7 +2,7 @@
width: 100%;
max-width: 15rem;
background-color: #ffffff;
padding: 1.5rem;
padding: 1rem;
border-radius: 1rem;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
0 10px 10px -5px rgba(0, 0, 0, 0.04);
......@@ -10,14 +10,14 @@
.hd {
text-align: center;
margin-bottom: 1.5rem;
font-size: 1.125rem;
font-weight: 500;
margin-bottom: 1rem;
font-size: 0.787rem;
font-weight: 250;
color: #000000;
}
.block {
margin-bottom: 1.5rem;
margin-bottom: 0.5rem;
}
.block input[type="number"] {
......@@ -72,6 +72,14 @@
@media (min-width: 768px) {
.container {
max-width: 28rem;
max-width: 18rem;
}
.hd {
margin-bottom: 1.5rem;
font-size: 1.125rem;
font-weight: 500;
}
.block {
margin-bottom: 1rem;
}
}
......@@ -3,6 +3,7 @@ import { Seat } from "../Seat/Seat.jsx";
import styles from "./Styles.module.css";
import { toast, ToastContainer } from "react-toastify";
import { Button } from "../../Form/Button/Button.jsx";
export const SeatSelectionComponent = ({
reservedSeats = [],
selectedSeats = [],
......@@ -26,7 +27,8 @@ export const SeatSelectionComponent = ({
} else if (selectedseats.includes(seat)) {
setSelectedSeats(selectedseats.filter((e) => e !== seat));
} else {
toast.info(`You can't select more than ${seatLimit} seat(s).`);
window.location.href.startsWith("http://192.168.1.64:5173/") &&
toast.info(`You can't select more than ${seatLimit} seat(s).`);
}
};
......@@ -35,14 +37,11 @@ export const SeatSelectionComponent = ({
if (selectedseats.length < seatLimit) {
toast.error(`Please select atleast ${seatLimit} seat(s).`);
} else {
console.log("Triggered onChange with:", { seats: selectedseats });
onClick({
seats: selectedseats,
clearSelection: () => setSelectedSeats([]),
});
}
};
const isSeatDisabled = (seat) =>
reservedSeats.includes(seat) && !selectedSeats.includes(seat);
......@@ -90,7 +89,6 @@ export const SeatSelectionComponent = ({
</div>
);
};
SeatSelectionComponent.defaultProps = {
seats: [],
reservedSeats: [],
......
......@@ -23,23 +23,6 @@
gap: 1px;
}
.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;
}
......@@ -61,13 +44,22 @@
.remove {
visibility: hidden;
}
.btn {
margin-top: 2rem;
}
.btn button {
display: flex;
justify-content: center;
border-radius: 1rem;
max-width: 45%;
max-width: 35%;
margin: 0 auto;
border-radius: 0.9rem;
margin-top: 2rem;
}
@media (min-width: 768px) {
.btn {
margin-top: 2rem;
}
.btn button {
display: flex;
justify-content: center;
border-radius: 1rem;
max-width: 45%;
margin: 0 auto;
}
}
......@@ -16,8 +16,6 @@ export function ContextProvider({ children }) {
);
const navigate = useNavigate();
console.log(reservedSeats);
const loginUser = async ({ mobile }) => {
try {
const user = await api.loginUser(mobile);
......@@ -143,8 +141,6 @@ export function ContextProvider({ children }) {
}
getAllReservedSeats();
}, []);
console.log("state reserved", reservedSeats);
console.log("Selected Seats:", reservedSeats.length);
const value = {
userSeats,
......
......@@ -3,18 +3,36 @@ import { useAppContext } from "../context/Index";
import { Login } from "../components/Forms/Login/Login";
import { Sign } from "../components/Forms/SignUp/Sign";
import styles from "./Styles.module.css";
import { useNavigate } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { toast, ToastContainer } from "react-toastify";
export const LoginPage = () => {
const navigate = useNavigate();
const location = useLocation();
const { loginUser, registerUser } = useAppContext();
const [showLogin, setShowLogin] = useState(true);
useEffect(() => {
sessionStorage.clear();
}, []);
if (location.pathname === "/signup") {
setShowLogin(false);
}
}, [location.pathname]);
const handlelogin = async ({ mobile }) => {
if (!mobile) {
toast.error("please Enter Your Number");
return;
}
if (mobile.length < 10) {
toast.error("Mobile number is less than 10");
return;
}
if (!/^[6-9]\d{9}$/.test(mobile)) {
toast.info("Invalid Number");
return;
}
const res = await loginUser({ mobile });
if (res) {
navigate("/seat-limit");
......@@ -22,18 +40,49 @@ export const LoginPage = () => {
};
const handleSignup = async ({ name, mobile }) => {
if (!name || !mobile) {
toast.error("Please enter both name and number");
return;
}
if (!/^[6-9]\d{9}$/.test(mobile)) {
toast.info("Please enter a valid 10-digit number");
return;
}
const confirmSeat = window.confirm("Are you sure,you want to signUp?");
if (!confirmSeat) return;
const res = await registerUser({ name, mobile });
console.log("registered", res);
setShowLogin(true);
};
return (
<div className={styles.login}>
{showLogin ? (
<Login onClick={handlelogin} onSwitch={() => setShowLogin(false)} />
) : (
<Sign onClick={handleSignup} onSwitch={() => setShowLogin(true)} />
)}
</div>
<>
<div className={styles.login}>
{showLogin ? (
<Login
onSubmit={handlelogin}
onSwitch={() => setShowLogin(false)}
markdown={`Don't have an account? [SignUp](/signup)`}
labels={{
mobilePlaceholder: "Enter Your Number",
submitBtnText: "Submit",
mobileError: "Enter 10 digits",
}}
/>
) : (
<Sign
onSubmit={handleSignup}
onSwitch={() => setShowLogin(true)}
labels={{
mobileplaceholder: "Enter Your Number",
nameplaceholder: "Enter Your Name",
btnLabel: "Submit",
titleLabel: "SignUp",
}}
/>
)}
</div>
<ToastContainer />
</>
);
};
......@@ -4,6 +4,7 @@ import {
getSeatLayout,
getReservedSeats,
getUserReservedSeats,
getReservedSeatOnly,
saveSeat,
updateSeat,
} from "../Api/Api";
......@@ -36,11 +37,13 @@ function SeatBooking() {
setLoading(true);
setError(null);
const [layoutData, allReserved, userRecord] = await Promise.all([
getSeatLayout(),
getReservedSeats(),
userId ? getUserReservedSeats(userId) : Promise.resolve(null),
]);
const [layoutData, allReserved, userRecord, reservedOnly] =
await Promise.all([
getSeatLayout(),
getReservedSeats(),
userId ? getUserReservedSeats(userId) : Promise.resolve(null),
getReservedSeatOnly(),
]);
if (isMounted) {
setSeatLayout(layoutData);
......
import React from "react";
import Counter from "../components/Top-level/Counter/Counter";
import { useAppContext } from "../context/Index";
import styles from "./Styles.module.css";
import { MdEventSeat } from "react-icons/md";
import { Header } from "../components/Layout/Card/Header";
import { useNavigate } from "react-router-dom";
import { useEffect } from "react";
export const SeatLimit = () => {
const navigate = useNavigate();
const totalSeats = 60;
const { reservedSeats } = useAppContext();
const { reservedSeats, getAllReservedSeats } = useAppContext();
const Seat = totalSeats - reservedSeats.length;
useEffect(() => {
const Timer = setInterval(() => {
getAllReservedSeats();
}, 500);
return () => clearTimeout(Timer);
}, [getAllReservedSeats]);
const handleSeat = (seatCount) => {
console.log("handleSeat called with seatCount:", seatCount);
sessionStorage.setItem("seatLimit", seatCount);
window.location.replace("/booking");
navigate("/booking");
};
return (
<>
<div className={styles.seat}>
<MdEventSeat className={styles.icon} />
<Header
title={`Remaining Seats Available:${Seat}`}
Color="#fff"
className={styles.line}
/>
<div className={styles.seatContainer}>
<div className={styles.seat}>
<MdEventSeat className={styles.icon} />
<Header
title={`Remaining Seats Available:${Seat}`}
Color="#fff"
className={styles.line}
/>
</div>
<Counter onSubmit={handleSeat} />
</div>
<Counter onSubmit={handleSeat} />
</>
);
};
......@@ -6,7 +6,7 @@
justify-content: center;
text-align: center;
margin-top: 0;
margin-bottom: 1.2rem;
font-size: 0.8rem;
}
.container {
display: flex;
......@@ -14,9 +14,6 @@
align-items: center;
}
.login {
min-height: 20rem;
}
.logout {
display: flex;
justify-content: end;
......@@ -29,6 +26,8 @@
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 0.8rem;
margin-bottom: 1rem;
}
.screen {
display: flex;
......@@ -37,28 +36,35 @@
position: relative;
min-width: 20rem;
}
.line {
font-size: 1rem;
.line h2 {
font-size: 15px;
color: #c7d2fe;
font-weight: 300;
font-weight: 100;
margin-bottom: 1rem;
display: flex;
justify-content: center;
margin-left: 2.9rem;
flex-wrap: wrap;
}
.line p {
text-align: center;
.seat {
margin-left: 2.3rem;
}
.icon {
color: #fff;
position: absolute;
margin-left: 0;
margin-top: 1rem;
height: 2rem;
width: 2rem;
margin-left: -1.2rem;
margin-top: 0.2rem;
height: 1rem;
width: 1rem;
}
.seatContainer {
display: flex;
flex-direction: column;
box-sizing: border-box;
width: 100%;
max-width: 18rem;
justify-content: center;
align-items: center;
}
.login {
max-width: 20rem;
}
@media (min-width: 768px) {
.container {
display: flex;
......@@ -70,16 +76,27 @@
width: 550;
height: 210;
}
.login {
min-width: 40rem;
}
.icon {
margin-left: 0.5rem;
margin-top: 0.3rem;
height: 1.5rem;
width: 1.5rem;
}
.line {
.line h2 {
margin-left: 2.5rem;
width: unset;
font-size: 1.5rem;
font-weight: 300;
}
.footer {
font-size: 1.2rem;
}
.head {
font-size: 1.5rem;
margin-top: 1rem;
}
.seat {
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