Commit 28a2f91f by Manivasagam S

code changed

parent 840f2f6f
import { useState } from "react";
import { useState, useEffect } from "react";
import styles from "./Auth.module.css";
import { ToastContainer, toast } from "react-toastify";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
export const Auth = ({ LoginComponent, SignUpComponent, onLoginSubmit, onSignUpSubmit }) => {
const [isLoginMode, setIsLoginMode] = useState(true);
export const Auth = ({
LoginComponent,
SignUpComponent,
onLoginSubmit,
onSignUpSubmit,
loginLabel = "Login Form",
signupLabel = "SignUp Form",
loginTabLabel = "Login",
signupTabLabel = "Signup",
initialMode = "login",
showForgotPassword = true,
showSwitchPrompt = true,
}) => {
const [isLoginMode, setIsLoginMode] = useState(initialMode === "login");
useEffect(() => {
setIsLoginMode(initialMode === "login");
}, [initialMode]);
return (
<div className={styles.container}>
<div className={styles.formCard}>
<h2 className={styles.header}>{isLoginMode ? "Login Form" : "SignUp Form"}</h2>
<h2 className={styles.header}>
{isLoginMode ? loginLabel : signupLabel}
</h2>
<div className={styles.tabContainer}>
<button
className={`${styles.tabButton} ${isLoginMode ? styles.activeTab : ""}`}
onClick={() => setIsLoginMode(true)}
>
Login
{loginTabLabel}
</button>
<button
className={`${styles.tabButton} ${!isLoginMode ? styles.activeTab : ""}`}
onClick={() => setIsLoginMode(false)}
>
Signup
{signupTabLabel}
</button>
</div>
{isLoginMode ? (
<div className={styles.login}>
<LoginComponent onLogin={onLoginSubmit} />
<a href="#" className={styles.forgotLink}>Forgot password?</a>
{showForgotPassword && (
<a href="#" className={styles.forgotLink}>Forgot password?</a>
)}
</div>
) : (
<div className={styles.signup}>
<SignUpComponent onSubmit={() => {
setIsLoginMode(true);
if (onSignUpSubmit) onSignUpSubmit();
}} />
<SignUpComponent
onSignUpSubmit={async (formData) => {
if (onSignUpSubmit) {
await onSignUpSubmit(formData);
setIsLoginMode(true);
}
}}
/>
</div>
)}
<div className={styles.signupPrompt}>
{isLoginMode ? "Not a member?" : "Already a member?"}{" "}
<a href="#" onClick={() => setIsLoginMode(!isLoginMode)}>
{isLoginMode ? "Signup now" : "Login"}
</a>
</div>
{showSwitchPrompt && (
<div className={styles.signupPrompt}>
{isLoginMode ? "Not a member?" : "Already a member?"}{" "}
<a href="#" onClick={() => setIsLoginMode(!isLoginMode)}>
{isLoginMode ? "Signup now" : "Login"}
</a>
</div>
)}
</div>
<ToastContainer position="top-right" autoClose={3000} />
......
import { Auth } from "./Auth.jsx";
import { Login } from "../Form/Login/Login.jsx";
import { SignUp } from "../Form/SignUp/SignUp.jsx";
import { action } from "@storybook/addon-actions";
export default {
title: "Auth/Auth",
component: Auth,
argTypes: {
loginLabel: { control: "text", name: "Login Title" },
signupLabel: { control: "text", name: "Signup Title" },
loginTabLabel: { control: "text", name: "Login Tab Label" },
signupTabLabel: { control: "text", name: "Signup Tab Label" },
initialMode: {
control: { type: "radio" },
options: ["login", "signup"],
name: "Initial Mode",
},
showForgotPassword: { control: "boolean", name: "Show Forgot Password" },
showSwitchPrompt: { control: "boolean", name: "Show Switch Prompt" },
},
};
const DummyLogin = ({ onLogin }) => (
<div>
<Login onLogin={onLogin} />
</div>
);
const DummySignUp = ({ onSubmit }) => (
<div>
<SignUp onSignUpSubmit={async (formData) => {
action('Sign Up Submitted')(formData); // logs action
return new Promise((resolve) => setTimeout(resolve, 1000)); // simulate async
}} />
</div>
);
export const AuthTabs = (args) => (
<Auth
{...args}
LoginComponent={DummyLogin}
SignUpComponent={DummySignUp}
onLoginSubmit={action("Login Submit")}
onSignUpSubmit={async(formData)=>action("Signup Submit")}
/>
);
AuthTabs.args = {
loginLabel: "Login Form",
signupLabel: "SignUp Form",
loginTabLabel: "Login",
signupTabLabel: "Signup",
initialMode: "login",
showForgotPassword: true,
showSwitchPrompt: true,
};
......@@ -80,7 +80,8 @@
background-color: var(--secondary);
color: black;
border-radius: 15px;
min-width: 12rem;
width: 100%;
/* min-width: 12rem; */
}
.secondary:hover {
......
import { Button } from './Button';
import styles from '../Buttons/Button.module.css';
export default {
title: 'Base/Button',
component: Button,
......
import { Screen } from "./Screen";
export default{
title:'Shared/Screen',
component:Screen,
parameters: {
backgrounds: {
default: 'blue-bg',
values: [{ name: 'blue-bg', value: '#3444c5' }],
},
}
}
export const Default=(args)=><Screen {...args}/>
\ No newline at end of file
......@@ -2,13 +2,12 @@ import React, { useState } from 'react';
import { Input } from '../../Base/Input/Input';
import { Button } from '../../Base/Buttons/Button';
import styles from './SignUp.module.css';
// import signup from '../../../assets/Signup.png';
import { getUserByPhone, postUser } from '../../../Api/userApi';
import { getUserByPhone } from '../../../Api/userApi';
import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
export const SignUp = ({
onSubmit,
onSignUpSubmit,
label = "SignUp",
namePlaceholder = "Name",
emailPlaceholder = "Email",
......@@ -34,8 +33,7 @@ export const SignUp = ({
setErrors((prev) => ({ ...prev, phoneNumber: '' }));
};
const handleSubmit = async (e) => {
e.preventDefault();
const validateForm = () => {
const newErrors = {};
if (!name.trim()) newErrors.name = 'Name is required';
......@@ -61,47 +59,39 @@ export const SignUp = ({
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
if (Object.keys(newErrors).length === 0) {
try {
const res = await getUserByPhone(phoneNumber);
if (res.data.length > 0) {
setErrors((prev) => ({
...prev,
phoneNumber: 'Phone number already registered',
}));
return;
}
const handleSubmit = async (e) => {
e.preventDefault();
const formData = { name, email, phoneNumber, reservedSeats: [] };
const postRes = await postUser(formData);
setName("");
setEmail("");
setPhoneNumber("");
if (postRes.status === 201) {
toast.success("Account created successfully!");
if (onSubmit) onSubmit(formData);
} else {
toast.error("Something went wrong. Please try again.");
}
if (!validateForm()) return;
} catch (err) {
console.error('Error submitting form:', err);
toast.error("Network error or server not available.");
try {
const res = await getUserByPhone(phoneNumber);
if (res.data.length > 0) {
setErrors((prev) => ({
...prev,
phoneNumber: 'Phone number already registered',
}));
return;
}
const formData = { name, email, phoneNumber };
await onSignUpSubmit?.(formData);
setName('');
setEmail('');
setPhoneNumber('');
} catch (error) {
toast.error("Something went wrong. Please try again.");
}
};
return (
<div className={styles.SignUpContainer}>
<div className={styles.wrapper}>
{/* <div
className={styles.leftPane}
style={{ backgroundImage: `url(${signup})` }}
></div> */}
<div className={styles.rightPane}>
{/* <h1 className={styles.text}>Create Account</h1> */}
<form onSubmit={handleSubmit} className={styles.form}>
<Input
type="text"
......
import styles from "../Screen/Screen.module.css"
import styles from "./Screen.module.css";
export const Screen = ({ width = 600, height = 210 }) => (
<div className={styles.shadow}>
<svg width={width} height={height} viewBox="0 0 300 120" xmlns="http://www.w3.org/2000/svg">
......@@ -11,6 +12,6 @@ export const Screen = ({ width = 600, height = 210 }) => (
</defs>
<path d="M30 60 Q150 36 270 60 L285 130 L10 130 Z" fill="url(#lightGradient)" />
<path d="M30 60 Q150 36 270 60" stroke="#fff" strokeWidth="2" fill="none" strokeLinecap="round" />
</svg>
</svg>
</div>
);
import React from "react";
import { Screen } from "./Screen";
export default {
title: "Shared/Screen",
component: Screen,
parameters: {
backgrounds: {
default: "blue-bg",
values: [{ name: "blue-bg", value: "#3444c5" }],
},
},
argTypes: {
width: {
control: { type: "number" },
defaultValue: 600,
},
height: {
control: { type: "number" },
defaultValue: 210,
},
},
};
export const statndardScreen= (args) => <Screen {...args} />;
statndardScreen.args = {
width: 600,
height: 210,
};
......@@ -30,7 +30,7 @@ export const Notification = ({ title, type, msg, button, }) => {
</span>
<h2 className={styles.title}>{title}</h2>
<p className={styles.msg}>{msg}</p>
{button && button}
<div className={styles.button}> {button && button}</div>
</div>
</>
);
......
......@@ -18,7 +18,9 @@ font-size: 2rem;
width: 100%;
height: 100%;
}
.button{
max-width: 12rem;
}
.container:hover {
transform: scale(1.02);
opacity: 0.95;
......
......@@ -3,12 +3,15 @@ import cn from 'classnames';
import styles from './Seat.module.css';
export const Seat = ({ seatNo, status, onClick }) => {
const isMine = status === 'mine' || status === 'mine-unselected';
const className = cn(styles.seat, {
[styles.noSeat]: status === 'none',
[styles.available]: status === 'available',
[styles.reserved]: status === 'reserved',
[styles.selected]: status === 'selected',
[styles.mine]:status === 'mine',
[styles.mine]: isMine,
[styles.unselected]: status === 'mine-unselected',
});
return (
......@@ -16,7 +19,7 @@ export const Seat = ({ seatNo, status, onClick }) => {
className={className}
data-tooltip={seatNo}
role="button"
tabIndex={status === 'available' || status === 'selected' ? 0 : -1}
tabIndex={['available', 'selected', 'mine', 'mine-unselected'].includes(status) ? 0 : -1}
onClick={onClick}
>
{null}
......@@ -26,6 +29,13 @@ export const Seat = ({ seatNo, status, onClick }) => {
Seat.propTypes = {
seatNo: PropTypes.string.isRequired,
status: PropTypes.oneOf(['none', 'available', 'reserved', 'selected']),
status: PropTypes.oneOf([
'none',
'available',
'reserved',
'selected',
'mine',
'mine-unselected'
]),
onClick: PropTypes.func,
};
......@@ -27,7 +27,12 @@
background-color:#5b66cb;
}
.mine{
background-color: white;
background-color: #01fff7;
cursor: pointer;
}
.unselected {
background-color:transparent;
border: 0.5px solid rgba(164, 175, 255, 1);
}
.reserved:hover {
......
......@@ -2,18 +2,24 @@ import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { Seat } from '../Seat/Seat.jsx';
import styles from './SeatLayout.module.css';
import { seatsData } from '../SeatLayout/SeatsData.js';
import { seatsData } from './SeatsData.js';
const populateSeatsArray = (selectedSeats, allReservedSeats) => {
const populateSeatsArray = (selectedSeats, reservedSeats, localSelectedSeats) => {
return seatsData.map(({ row, seats }) =>
seats.map((number) => {
const seatNo = row + number;
if (number === '/') {
return { seatNo, status: 'none' };
} else if (localSelectedSeats.includes(seatNo)) {
if (selectedSeats.includes(seatNo)) {
return { seatNo, status: 'mine' };
} else {
return { seatNo, status: 'mine-unselected' };
}
} else if (reservedSeats.includes(seatNo)) {
return { seatNo, status: 'reserved' };
} else if (selectedSeats.includes(seatNo)) {
return { seatNo, status: 'selected' };
} else if (allReservedSeats.includes(seatNo)) {
return { seatNo, status: 'reserved' };
} else {
return { seatNo, status: 'available' };
}
......@@ -22,67 +28,62 @@ const populateSeatsArray = (selectedSeats, allReservedSeats) => {
};
export const SeatLayout = ({
initialReservedSeats = [],
allReservedSeats = [],
selectedSeats: initialSelected = [],
reservedSeats = [],
currentReservedSeats = [],
limit,
onSelectionChange,
onSubmit,
}) => {
const [selectedSeats, setSelectedSeats] = useState(initialReservedSeats);
const [localSelectedSeats, setLocalSelectedSeats] = useState(currentReservedSeats);
useEffect(() => {
onSelectionChange?.(selectedSeats);
}, [selectedSeats, onSelectionChange]);
// useEffect(() => {
// setSelectedSeats(initialReservedSeats);
// }, [initialReservedSeats]);
setLocalSelectedSeats(currentReservedSeats);
}, [currentReservedSeats]);
const seatClickHandler = (seat) => {
if (seat.status === 'available' || seat.status === 'selected') {
setSelectedSeats((prevSelected) => {
let newSelected;
let actionType;
useEffect(() => {
onSelectionChange?.(localSelectedSeats);
}, [localSelectedSeats, onSelectionChange]);
if (prevSelected.includes(seat.seatNo)) {
newSelected = prevSelected.filter((s) => s !== seat.seatNo);
actionType = 'unclicked';
} else if (prevSelected.length < limit) {
newSelected = [...prevSelected, seat.seatNo];
actionType = 'clicked';
} else {
return prevSelected;
}
const seatClickHandler = (seat) => {
const { seatNo, status } = seat;
if (status === 'reserved') return;
onSubmit?.(actionType);
return newSelected;
});
}
};
const hasExisting = currentReservedSeats.length > 0;
const maxLimit = hasExisting ? Infinity : Number(limit);
setLocalSelectedSeats((prev) => {
if (prev.includes(seatNo)) {
return prev.filter((s) => s !== seatNo);
} else if (prev.length < maxLimit) {
return [...prev, seatNo];
}
return prev;
});
};
const renderedSeats = populateSeatsArray(
localSelectedSeats,
reservedSeats,
currentReservedSeats
);
const renderedSeats = populateSeatsArray(selectedSeats, allReservedSeats);
console.log(selectedSeats);
return (
<div className={styles.container}>
{renderedSeats.map((rowSeats, i) => (
<div key={i} className={styles.seatcontainer}>
{rowSeats.map((seat, j) => (
<Seat key={j} onClick={() => seatClickHandler(seat)} {...seat} />
))}
</div>
))}
{renderedSeats.map((row, i) => (
<div key={i} className={styles.seatcontainer}>
{row.map((seat, j) => (
<Seat key={j} {...seat} onClick={() => seatClickHandler(seat)} />
))}
</div>
))}
</div>
);
};
SeatLayout.propTypes = {
allReservedSeats: PropTypes.arrayOf(PropTypes.string),
initialReservedSeats: PropTypes.arrayOf(PropTypes.string),
limit: PropTypes.number,
onSelectionChange: PropTypes.func,
selectedSeats: PropTypes.arrayOf(PropTypes.string),
reservedSeats: PropTypes.arrayOf(PropTypes.string),
currentReservedSeats: PropTypes.arrayOf(PropTypes.string),
limit: PropTypes.number.isRequired,
onSelectionChange: PropTypes.func.isRequired,
};
......@@ -5,7 +5,7 @@
align-items: center;
margin-bottom: 5rem;
width: 100%;
overflow-x: auto;
/* overflow-x: auto; */
}
.seatcontainer {
......
import { SeatLayout } from "./SeatLayout";
import React from 'react';
import { SeatLayout } from './SeatLayout';
import { action } from '@storybook/addon-actions';
const reservedSeatsSample = ['A1', 'B2', 'C3'];
const currentUserReservedSeats = ['A3', 'B4'];
const logSelectionChange = action('Clicked/Unclicked');
export default {
title: 'Toplevel/SeatLayout',
component: SeatLayout,
parameters:{
backgrounds: {
parameters: {
backgrounds: {
default: 'blue-bg',
values: [
{ name: 'blue-bg', value: '#3444c5' }, // blue background
],
values: [{ name: 'blue-bg', value: '#3444c5' }],
},
layout:"centered"
layout: 'centered',
},
argTypes: {
seatType: {
control: {
type: 'radio',
},
options: ['available', 'reserved', 'selected']
selectedSeats: {
control: { type: 'array' },
description: 'Seats currently selected by the user',
},
reservedSeats: {
control: { type: 'array' },
description: 'Seats reserved by others',
},
limit: {
control: { type: 'number', min: 1, max: 10 },
currentReservedSeats: {
control: { type: 'array' },
description: 'Seats reserved by the logged-in user',
},
onSubmit: { action: 'clicked/unclicked' },
onSelectionChange: { action: 'selectedseats' },
// limit is used internally, not exposed in the controls
},
};
const modeConfig = {
available: {
selectedSeats: [],
reservedSeats: [],
currentReservedSeats: [],
limit: 3,
},
reserved: {
selectedSeats: [],
reservedSeats: reservedSeatsSample,
currentReservedSeats: [],
limit: 2,
},
selected: {
selectedSeats: [],
reservedSeats: [],
currentReservedSeats: currentUserReservedSeats,
limit: 1,
},
};
export const Default= ({ seatType, limit, onSubmit, onSelectionChange }) => {
let allReservedSeats = [];
let initialReservedSeats = [];
export const Default = (args) => {
const config = modeConfig[args.mode] || modeConfig.available;
if (seatType === 'reserved') {
allReservedSeats = ['B1', 'B2', 'B3'];
} else if (seatType === 'selected') {
initialReservedSeats = ['C1', 'C2','C3'];
}
return (
<SeatLayout
key={seatType}
allReservedSeats={allReservedSeats}
initialReservedSeats={initialReservedSeats}
limit={limit}
onSubmit={onSubmit}
onSelectionChange={onSelectionChange}
selectedSeats={args.selectedSeats.length ? args.selectedSeats : config.selectedSeats}
reservedSeats={args.reservedSeats.length ? args.reservedSeats : config.reservedSeats}
currentReservedSeats={
args.currentReservedSeats.length
? args.currentReservedSeats
: config.currentReservedSeats
}
limit={config.limit}
onSelectionChange={logSelectionChange}
/>
);
};
Default.args = {
seats: [
[0, "A1", "A2", "A3", 0, "A4", "A5", "A6", 0],
["B1", "B2", "B3", "B4", 0, "B5", "B6", "B7", "B8"],
["C1", "C2", "C3", "C4", 0, "C5", "C6", "C7", "C8"],
["D1", "D2", "D3", "D4", 0, "D5", "D6", "D7", "D8"],
["E1", "E2", "E3", "E4", 0, "E5", "E6", "E7", "E8"],
["F1", "F2", "F3", "F4", 0, "F5", "F6", "F7", "F8"],
["G1", "G2", "G3", "G4", 0, "G5", "G6", "G7", "G8"],
[0, "H1", "H2", "H3", 0, "H4", "H5", "H7", 0],
],
seatType: 'available',
limit: 3,
mode: 'available',
selectedSeats: [],
reservedSeats: [],
currentReservedSeats: [],
};
......@@ -9,11 +9,13 @@ import "react-toastify/dist/ReactToastify.css";
import { toast, ToastContainer } from "react-toastify";
import { Modal } from "../../Base/Modal/Modal";
import { SeatSelectForm } from "../../Form/SeatSelectForm/SeatSelectForm";
import { Screen } from "../../Base/Screen/Screen";
import { Screen } from "../../Shared/Screen/Screen";
import { AiOutlineLogout } from "react-icons/ai";
export const Selectseat = ({onLogout}) => {
export const Selectseat = ({ onLogout }) => {
const [selectedSeats, setSelectedSeats] = useState([]);
const [allReservedSeats, setAllReservedSeats] = useState([]);
const [selectedData, setselectedData] = useState([]);
const [reservedSeats, setreservedSeats] = useState([]);
const [seatCount, setSeatCount] = useState(1);
const [availableSeats, setAvailableSeats] = useState(0);
const [showSelect, setShowSelect] = useState(true);
......@@ -22,114 +24,124 @@ export const Selectseat = ({onLogout}) => {
getAllUsers()
.then(res => {
const users = res.data;
const reserved = users
.flatMap(u => u.reservedSeats || [])
.filter(seat => seat);
setAllReservedSeats(reserved);
const totalSeats=60;
const totalSeats = 60;
const loggedUser = getCurrentUser();
const allReserved = users.flatMap(u => u.reservedSeats || []);
const currentUser = users.find(u => u.phoneNumber === loggedUser.phoneNumber);
const userSeats = currentUser?.reservedSeats || [];
const othersReserved = allReserved.filter(seat => !userSeats.includes(seat));
setselectedData(userSeats);
setreservedSeats(othersReserved);
const available = totalSeats - allReserved.length;
setAvailableSeats(available);
const available=totalSeats-reserved.length;
setAvailableSeats(available);
})
if (userSeats.length > 0) {
setSeatCount(userSeats.length);
setShowSelect(false); // skip modal for existing users
}
})
.catch(err => {
console.error("Error fetching users", err);
toast.error("Failed to load seat data.");
});
}, []);
const confirmHandler = () => {
const user = getCurrentUser();
const confirmHandler = () => {
const user = getCurrentUser();
if (!user || !user.phoneNumber?.trim()) {
toast.warn("User not logged in");
return;
}
if (!user || !user.phoneNumber?.trim()) {
toast.warn("User not logged in");
return;
}
if (selectedSeats.length < seatCount) {
toast.info(`Please select ${seatCount} seats`);
return;
}
if (selectedData.length === 0 && selectedSeats.length < seatCount) {
toast.info(`Please select ${seatCount} seat(s)`);
return;
}
getAllUsers()
.then(res => {
const users = res.data;
const currentUser = users.find(u => u.phoneNumber === user.phoneNumber);
if (!currentUser) {
toast.error("User not found");
return;
}
getAllUsers()
.then(res => {
const users = res.data;
const currentUser = users.find(u => u.phoneNumber === user.phoneNumber);
const latestReserved = users
.flatMap(u => u.reservedSeats || []);
if (!currentUser) {
toast.error("User not found");
return;
}
const conflictSeats = selectedSeats.filter(seat =>
latestReserved.includes(seat)
);
const latestReserved = users
.flatMap(u => u.reservedSeats || [])
.filter(seat => !currentUser.reservedSeats.includes(seat));
if (conflictSeats.length > 0) {
toast.error(
`The following seat(s) were just taken: ${conflictSeats.join(", ")}`
const conflictSeats = selectedSeats.filter(seat =>
latestReserved.includes(seat)
);
setSelectedSeats([]);
return;
}
const updatedSeats = Array.from(
new Set([...(currentUser.reservedSeats || []), ...selectedSeats])
);
return updateUserReservedSeats(currentUser.id, updatedSeats);
})
.then(res => {
if (res) {
toast.success("Seats confirmed!");
setSelectedSeats([]);
if (conflictSeats.length > 0) {
toast.error(`The following seat(s) were just taken: ${conflictSeats.join(", ")}`);
return;
}
return updateUserReservedSeats(currentUser.id, selectedSeats);
})
.then(res => {
if (res) {
toast.success("Seats updated!");
setSelectedSeats([]);
setTimeout(() => {
window.location.replace("/success");
}, 1000);
}
})
.catch(err => {
console.error("Error confirming seats", err);
toast.error("Failed to confirm seats");
setTimeout(() => {
window.location.replace("/success");
window.location.replace("/error");
}, 1000);
}
})
.catch(err => {
console.error("Error confirming seats", err);
toast.error("Failed to confirm seats");
setTimeout(() => {
window.location.replace("/error");
}, 1000);
});
};
});
};
const handleModal = () => {
setShowSelect(false);
};
const seatOptions = Array.from({ length: availableSeats }).map((_, i) => ({
const seatOptions = Array.from({ length: availableSeats }).map((_, i) => ({
value: i + 1,
label: `${i + 1} ${i + 1 === 1 ? "seat" : "seats"}`
}));
return (
<>
<div className={styles.logoutButton}>
<AiOutlineLogout onClick={onLogout}/>
</div>
<div className={styles.logoutButton}>
<AiOutlineLogout onClick={onLogout} />
</div>
<div className={styles.container}>
{/* <div className={styles.logoutButton}><Button variant="secondary" label="Logout" size="sm" onClick={onLogout}/></div> */}
<h2 className={styles.text}>Choose Seats</h2>
<Screen/>
<h2 className={styles.text}>Choose Seats</h2>
<Screen />
<div className={styles.seatcontainer}>
<SeatLayout
allReservedSeats={allReservedSeats}
onSelectionChange={setSelectedSeats}
selectedSeats={selectedSeats}
reservedSeats={reservedSeats}
currentReservedSeats={selectedData}
limit={seatCount}
onSelectionChange={setSelectedSeats}
/>
</div>
<div className={styles.button}>
<Button variant="secondary" label="Confirm" size='md' onClick={confirmHandler} disabled={selectedSeats.length!=seatCount}/>
<Button
variant="secondary"
label="Confirm"
size="md"
onClick={confirmHandler}
disabled={selectedData.length === 0 && selectedSeats.length !== seatCount}
/>
</div>
<div className={styles.legend}>
......@@ -155,6 +167,6 @@ export const Selectseat = ({onLogout}) => {
)}
<ToastContainer position="top-right" autoClose={3000} />
</>
</>
);
};
......@@ -29,7 +29,8 @@ body {
position: relative;
bottom: 4rem;
padding: 0 1rem;
max-width: 12rem;
margin: 0 auto;
}
/*
.shadow {
......@@ -40,6 +41,10 @@ body {
padding: 0 1rem;
} */
/* labels:{
signUp:'sdfs'
/} */
.seatcontainer {
position: relative;
bottom:4rem;
......
// Auth.stories.jsx
import { Auth } from "../Auth/Auth.jsx";
import {Login} from '../../Components/Form/Login/Login.jsx'
import { SignUp } from "../../Components/Form/SignUp/SignUp.jsx";
export default {
title: "Auth/Auth",
component: Auth,
};
const DummyLogin = ({ onLogin }) => (
<div>
<Login/>
</div>
);
const DummySignUp = ({ onSubmit }) => (
<div>
<SignUp/>
</div>
);
export const Default = () => (
<Auth
LoginComponent={DummyLogin}
SignUpComponent={DummySignUp}
onLoginSubmit={(data) => console.log("Login Submit:", data)}
onSignUpSubmit={() => console.log("SignUp Submit")}
/>
);
import { Login} from "../Components/Form/Login/Login.jsx"
import { SignUp } from "../Components/Form/SignUp/SignUp";
import { toast } from "react-toastify";
import { Auth } from "./Auth/Auth.jsx";
import { Auth } from "../Components/Auth/Auth.jsx";
import { getUserByPhone,postUser } from "../Api/userApi.js";
export const AuthPage = () => {
const handleLogin = async (phoneNumber) => {
try {
......@@ -21,11 +22,40 @@ export const AuthPage = () => {
}
};
const handleSignUp = async (formData) => {
try {
if (!formData || !formData.phoneNumber) {
toast.error("Invalid form data");
return;
}
const response = await getUserByPhone(formData.phoneNumber);
if (response.data.length > 0) {
toast.warn("Phone number already registered.");
return;
}
const newUser = { ...formData, reservedSeats: [] };
const postRes = await postUser(newUser);
if (postRes.status === 201) {
localStorage.setItem("user", JSON.stringify(postRes.data));
toast.success("Account created successfully!");
} else {
toast.error("Failed to create account. Try again.");
}
} catch (error) {
console.error("Sign up error:", error);
toast.error("Network error or server not available.");
}
};
return (
<Auth
LoginComponent={Login}
SignUpComponent={SignUp}
onLoginSubmit={handleLogin}
onSignUpSubmit={handleSignUp}
/>
);
};
......@@ -18,6 +18,9 @@
"phoneNumber": "9361775481",
"name": "mani",
"reservedSeats": [
"B3",
"B2",
"B1",
"C4"
]
},
......@@ -26,6 +29,106 @@
"name": "mani",
"email": "mani@gmail.com",
"phoneNumber": "9934782103",
"reservedSeats": [
"B4",
"D4",
"E3",
"A3",
"A2",
"A1",
"H1",
"H2"
]
},
{
"id": "2c1f",
"name": "mani",
"email": "mani@gmail.com",
"phoneNumber": "9312345678",
"reservedSeats": []
},
{
"id": "845c",
"name": "abinesh",
"email": "abi@gmail.com",
"phoneNumber": "1234587690",
"reservedSeats": []
},
{
"id": "8ebe",
"name": "asdfsa",
"email": "adsasdf@gmail.om",
"phoneNumber": "12341234234",
"reservedSeats": []
},
{
"id": "b80a",
"name": "ganesh",
"email": "ganesh@gmail.com",
"phoneNumber": "9786543219",
"reservedSeats": []
},
{
"id": "9659",
"name": "dinesh",
"email": "din@gmail.com",
"phoneNumber": "7895432173",
"reservedSeats": []
},
{
"id": "d7df",
"name": "janani",
"email": "janani@gmail.com",
"phoneNumber": "9587923467",
"reservedSeats": []
},
{
"id": "29ef",
"name": "viji",
"email": "viji@gmail.com",
"phoneNumber": "7689543218",
"reservedSeats": []
},
{
"id": "a364",
"name": "vijay",
"email": "vijay@gmail.com",
"phoneNumber": "6789543212",
"reservedSeats": []
},
{
"id": "f999",
"name": "kain",
"email": "kain@gmail.com",
"phoneNumber": "7584932105",
"reservedSeats": []
},
{
"id": "5dcd",
"name": "ganesh",
"email": "ganesh@gmail.com",
"phoneNumber": "8790654321",
"reservedSeats": []
},
{
"id": "5306",
"name": "janani",
"email": "janani@gmail.com",
"phoneNumber": "9867543210",
"reservedSeats": []
},
{
"id": "aaff",
"name": "maniv",
"email": "maniv@gmail.com",
"phoneNumber": "9687543721",
"reservedSeats": []
},
{
"id": "8ec3",
"name": "dfgfdg",
"email": "dsbfsdbf@gmail.com",
"phoneNumber": "4782391204",
"reservedSeats": []
}
]
......
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