Commit 83a46bc1 by Madhankumar

storybook seat-limit

parent 19a6eea9
/** @type { import('@storybook/react').Preview } */ import { MemoryRouter } from "react-router-dom";
import "../src/index.css"; import "../src/index.css";
/** @type { import('@storybook/react').Preview } */
const preview = { const preview = {
parameters: { parameters: {
actions: { argTypesRegex: "^on[A-Z].*" }, actions: { argTypesRegex: "^on[A-Z].*" },
...@@ -11,5 +13,11 @@ const preview = { ...@@ -11,5 +13,11 @@ const preview = {
}, },
}, },
}; };
export const decorators = [
(Story) => (
<MemoryRouter initialEntries={["/"]}>
<Story />
</MemoryRouter>
),
];
export default preview; export default preview;
...@@ -7,25 +7,14 @@ ...@@ -7,25 +7,14 @@
{ {
"mobile": "9999999999", "mobile": "9999999999",
"id": 2 "id": 2
}
],
"reservedSeats": [
{
"userId": 1,
"seats": [
"E1",
"E4",
"F3"
],
"id": 1
}, },
{ {
"userId": 2, "mobile": "9999999998",
"seats": [ "id": 3
"C5",
"C6"
],
"id": 2
} }
],
"reservedSeats": [
] ]
} }
\ No newline at end of file
...@@ -28,7 +28,7 @@ function App() { ...@@ -28,7 +28,7 @@ function App() {
element={<AuthGuard component={_seatLimit} />} element={<AuthGuard component={_seatLimit} />}
/> />
<Route <Route
path="/booking/:id" path="/booking/:id/:limit?"
element={<AuthGuard component={_Seatlayout} />} element={<AuthGuard component={_Seatlayout} />}
/> />
<Route <Route
......
...@@ -6,7 +6,6 @@ export const useAppContext = () => useContext(AppContext); ...@@ -6,7 +6,6 @@ export const useAppContext = () => useContext(AppContext);
export function ContextProvider({ children }) { export function ContextProvider({ children }) {
const [userseats, setUserSeats] = useState([]); const [userseats, setUserSeats] = useState([]);
const LoginOrRegister = async ({ mobile }) => { const LoginOrRegister = async ({ mobile }) => {
try { try {
const response = await api.LoginOrRegister({ mobile }); const response = await api.LoginOrRegister({ mobile });
...@@ -16,17 +15,17 @@ export function ContextProvider({ children }) { ...@@ -16,17 +15,17 @@ export function ContextProvider({ children }) {
toast.error(err.message); toast.error(err.message);
} }
}; };
const AddOrUpdateSeats = async ({ userId, seats }) => { const AddOrUpdateSeats = async ({ id, seats }) => {
try { try {
const response = await api.AddOrUpdateSeats({ const response = await api.AddOrUpdateSeats({
userId, id,
seats, seats,
}); });
if (response.isAddSeat) { if (response.isAddSeat) {
setUserSeats([...userseats, response.response]); setUserSeats([...userseats, response.response]);
} else { } else {
const result = userseats.map((e) => const result = userseats.map((e) =>
e.userId === userId ? response.response : e e.id === id ? response.response : e
); );
setUserSeats(result); setUserSeats(result);
} }
......
...@@ -3,7 +3,7 @@ import styles from "./layout.module.css"; ...@@ -3,7 +3,7 @@ import styles from "./layout.module.css";
function Layout({ title, ...props }) { function Layout({ title, ...props }) {
return ( return (
<div className={styles.card}> <div className={styles.card}>
<h2 className={styles.header2}>{title}</h2> <h2 className={styles.header}>{title}</h2>
<div {...props}></div> <div {...props}></div>
</div> </div>
); );
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
padding: 0.3rem; padding: 0.3rem;
} }
h2.header2 { .header {
text-align: center; text-align: center;
margin: 0.6em;
} }
...@@ -28,3 +28,7 @@ h3, ...@@ -28,3 +28,7 @@ h3,
h4 { h4 {
margin: 0.6rem; margin: 0.6rem;
} }
.logout {
margin: 10px;
}
...@@ -3,7 +3,10 @@ import Confirmation from "."; ...@@ -3,7 +3,10 @@ import Confirmation from ".";
export default { export default {
title: "Top-Level/Confirmation", title: "Top-Level/Confirmation",
component: Confirmation, component: Confirmation,
argTypes: { onEdit: { action: "onEdit" } }, argTypes: {
onEdit: { action: "onEdit" },
onLogOut: { action: "logout triggered" },
},
}; };
export const confirmation = { export const confirmation = {
......
...@@ -2,8 +2,9 @@ import Layout from "../../Base/layout"; ...@@ -2,8 +2,9 @@ import Layout from "../../Base/layout";
import Image from "../../../assets/conform.png"; import Image from "../../../assets/conform.png";
import style from "./confirmation.module.css"; import style from "./confirmation.module.css";
import Button from "../../Base/button"; import Button from "../../Base/button";
import { Link } from "react-router-dom";
function Confirmation({ seatCount, seats, onEdit }) { function Confirmation({ seatCount, seats, onLogOut, onEdit }) {
return ( return (
<Layout title="Booking Confirmed"> <Layout title="Booking Confirmed">
<div className={style.confirmation}> <div className={style.confirmation}>
...@@ -17,6 +18,9 @@ function Confirmation({ seatCount, seats, onEdit }) { ...@@ -17,6 +18,9 @@ function Confirmation({ seatCount, seats, onEdit }) {
<h3> {seats.toString()}</h3> <h3> {seats.toString()}</h3>
</span> </span>
<Button onClick={onEdit}>Modify</Button> <Button onClick={onEdit}>Modify</Button>
<div className={style.logout} onClick={onLogOut}>
<Link to="/">LogOut</Link>
</div>
</div> </div>
</Layout> </Layout>
); );
......
...@@ -2,36 +2,42 @@ import { useState } from "react"; ...@@ -2,36 +2,42 @@ import { useState } from "react";
import Button from "../../Base/button"; import Button from "../../Base/button";
import Input from "../../Base/input"; import Input from "../../Base/input";
import Layout from "../../Base/layout"; import Layout from "../../Base/layout";
import styles from "./login.module.css";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import styles from "./login.module.css";
function Login({ onSubmit }) { function Login({ onSubmit }) {
const [mobile, setMobile] = useState(""); const [mobile, setMobile] = useState("");
const [iserror, setIsError] = useState(false);
const handleSubmit = (e) => { const handleSubmit = (e) => {
e.preventDefault(); e.preventDefault();
console.log("mobile", mobile.length);
if (mobile.length < 10) { if (mobile.length < 10) {
setIsError(true);
toast.info("mobile should be 10 digits"); toast.info("mobile should be 10 digits");
} else { } else {
onSubmit({ mobile }); onSubmit({ mobile });
setMobile(""); setMobile("");
setIsError(false);
} }
}; };
const handleChange = (e) => {
setMobile(e.target.value);
};
return ( return (
<Layout title="Login"> <Layout title="Login">
<form onSubmit={handleSubmit}> <form className="form" onSubmit={handleSubmit}>
<label>Mobile:</label> <div>
<label className="label">Mobile:</label>
<Input <Input
placeholder="Enter Mobile" placeholder="Enter Mobile"
type="tel" type="tel"
required required
onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
}
}}
maxLength={10} maxLength={10}
onChange={(e) => setMobile(e.target.value)} onChange={handleChange}
/> />
{iserror && <span>Please enter 10 digits</span>}
</div>
<Button>Submit</Button> <Button>Submit</Button>
</form> </form>
</Layout> </Layout>
......
label { span {
color: #6c6a6a; color: red;
}
form {
padding: 1.5rem;
> * {
inset: 0;
margin: 10px auto;
}
}
input[type="number"]::-webkit-inner-spin-button {
display: none;
}
input[type="number"] {
-moz-appearence: textfield;
} }
...@@ -4,8 +4,9 @@ import Button from "../../Base/button"; ...@@ -4,8 +4,9 @@ import Button from "../../Base/button";
import styles from "./seat-layout.module.css"; import styles from "./seat-layout.module.css";
import Seat from "../seat"; import Seat from "../seat";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useLocation } from "react-router-dom";
function SeatLayout({ function SeatLayout({
userId,
seats, seats,
reservedSeats, reservedSeats,
selectedSeats, selectedSeats,
...@@ -13,18 +14,15 @@ function SeatLayout({ ...@@ -13,18 +14,15 @@ function SeatLayout({
onClick, onClick,
...props ...props
}) { }) {
const location = useLocation();
console.log(seatLimit, location.state.seatLimit);
const _seatLimit = seatLimit ?? location.state.seatLimit;
const [selectedseat, setSelectedSeat] = useState([...selectedSeats]); const [selectedseat, setSelectedSeat] = useState([...selectedSeats]);
const handleSeats = (seat) => { const handleSeats = (seat) => {
if (!selectedseat?.includes(seat) && selectedseat.length < _seatLimit) { if (!selectedseat?.includes(seat) && selectedseat.length < seatLimit) {
setSelectedSeat([...selectedseat, seat]); setSelectedSeat([...selectedseat, seat]);
} else if (selectedseat?.includes(seat)) { } else if (selectedseat?.includes(seat)) {
setSelectedSeat(selectedseat?.filter((e) => e != seat)); setSelectedSeat(selectedseat?.filter((e) => e != seat));
} else { } else {
toast.info(`Cannot select seat more than ${_seatLimit}`); toast.info(`Cannot select seat more than ${seatLimit}`);
} }
}; };
useEffect(() => { useEffect(() => {
...@@ -34,11 +32,11 @@ function SeatLayout({ ...@@ -34,11 +32,11 @@ function SeatLayout({
e.preventDefault(); e.preventDefault();
//check if already have data then update otherwise create, //check if already have data then update otherwise create,
//write code //write code
if (!selectedseat.length || selectedseat.length < _seatLimit) { if (!selectedseat.length || selectedseat.length < seatLimit) {
toast.error(`please select upto ${seatLimit} `); toast.error(`please select upto ${seatLimit} `);
} else { } else {
onClick({ onClick({
userId: parseInt(props.userId), id: parseInt(userId) || 1,
seats: selectedseat, seats: selectedseat,
}); });
} }
......
import { useState } from "react"; import { useState } from "react";
import Button from "../../Base/button"; import Button from "../../Base/button";
import Layout from "../../Base/layout"; import Layout from "../../Base/layout";
import styles from "./seatlimit.module.css";
import Input from "../../Base/input"; import Input from "../../Base/input";
import { toast } from "react-toastify";
function SeatLimit({ onLimit, ...props }) { function SeatLimit({ onLimit, ...props }) {
const [limit, setLimit] = useState(0); const [limit, setLimit] = useState(0);
const handleLimit = () => { const handleLimit = (e) => {
e.preventDefault();
if (limit > 0) {
onLimit({ limit }); onLimit({ limit });
} else {
toast.info("Please enter atleast 1 seat");
}
}; };
return ( return (
<Layout title="How many seats?"> <Layout title="How many seats?">
<form onSubmit={handleLimit} className={styles["form"]}> <form onSubmit={handleLimit} className="form">
<div> <div>
<label>No of seats:</label> <label className="label">No of seats:</label>
<Input <Input
type="number" type="number"
value={limit} value={limit}
onChange={(e) => setLimit(e.target.value)} onChange={(e) => setLimit(e.target.value)}
min="1"
max="10"
/> />
{/* <input {/* <input
className={styles.input} className={styles.input}
......
/* .label {
color: #6c6a6a;
}
.form > *:not(input) {
padding: 17px;
}
input[type="number"]::-webkit-inner-spin-button {
display: none;
}
input[type="number"] {
-moz-appearence: textfield;
} */
import SeatLimit from ".";
export default {
title: "Top-Level/Seat-limit",
component: SeatLimit,
argTypes: { onLimit: { action: "onLimit" } },
};
export const seatlimit = {};
.input {
height: 30px;
width: 100%;
}
.form {
padding: 1rem 3rem;
}
.form > div {
padding: 10px;
}
...@@ -17,3 +17,17 @@ code { ...@@ -17,3 +17,17 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace; monospace;
} }
.label {
color: #6c6a6a;
}
.form > *:not(input) {
padding: 17px;
}
input[type="number"]::-webkit-inner-spin-button {
display: none;
}
input[type="number"] {
-moz-appearence: textfield;
}
...@@ -16,29 +16,30 @@ export async function LoginOrRegister({ mobile }) { ...@@ -16,29 +16,30 @@ export async function LoginOrRegister({ mobile }) {
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ mobile }), body: JSON.stringify({ mobile }),
}); });
let _userData = [{ ...user }];
return _userData; return await user.json();
} else { } else {
// User data found, return JSON // User data found, return JSON
return result; return result?.[0];
} }
} catch (err) { } catch (err) {
toast.error(err.message); toast.error(err.message);
} }
} }
export async function AddOrUpdateSeats({ userId, seats }) { export async function AddOrUpdateSeats({ id, seats }) {
try { try {
const userSeat = await fetch( const userSeat = await fetch(
`http://192.168.1.91:5000/reservedSeats?userId=${userId}` `http://192.168.1.91:5000/reservedSeats/${id}`
); );
const result = await userSeat.json(); const result = await userSeat.json();
if (!result.length) { console.log("oidufuf", result);
if (!Object.keys(result).length) {
//add seat //add seat
const response = await fetch(BASE_URL + "/reservedSeats", { const response = await fetch(BASE_URL + "/reservedSeats", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ userId, seats }), body: JSON.stringify({ id, seats }),
}); });
const res = await response.json(); const res = await response.json();
return { return {
...@@ -47,10 +48,11 @@ export async function AddOrUpdateSeats({ userId, seats }) { ...@@ -47,10 +48,11 @@ export async function AddOrUpdateSeats({ userId, seats }) {
}; };
} else { } else {
//update //update
console.log("patch");
const response = await fetch( const response = await fetch(
`http://192.168.1.91:5000/reservedSeats/${userId}`, `http://192.168.1.91:5000/reservedSeats/${id}`,
{ {
method: "PATCH", method: "PUT",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ seats }), body: JSON.stringify({ seats }),
} }
......
...@@ -6,11 +6,11 @@ export function _Confirmation() { ...@@ -6,11 +6,11 @@ export function _Confirmation() {
const seatCount = location.state.seatCount; const seatCount = location.state.seatCount;
const seats = location.state.seats; const seats = location.state.seats;
const id = location.state.id; const id = location.state.id;
const seatLimit = location.state.seatlimit; const seatLimit = location.state.limit;
const navigate = useNavigate(); const navigate = useNavigate();
const handleModify = (e) => { const handleModify = (e) => {
e.preventDefault(); e.preventDefault();
navigate(`/booking/${id}`, { state: { seatLimit } }); navigate(`/booking/${id}/${seatLimit}`);
}; };
return ( return (
<Confirmation <Confirmation
......
import { useEffect, useState } from "react";
import { useAppContext } from "../_context"; import { useAppContext } from "../_context";
import Login from "../components/top-level/login"; import Login from "../components/top-level/login";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
export function _Login() { export function _Login() {
const navigate = useNavigate(); const navigate = useNavigate();
const { LoginOrRegister } = useAppContext(); const { userseats, LoginOrRegister, GetAllReservedSeats } = useAppContext();
useEffect(() => {
GetAllReservedSeats();
}, []);
const handleLogin = async ({ mobile }) => { const handleLogin = async ({ mobile }) => {
const user = await LoginOrRegister({ mobile }); const users = await LoginOrRegister({ mobile });
if (user?.length) { if (users != null) {
navigate(`/seat-limit/${user[0].id}`); const userstate = userseats.filter((e) =>
//navigate(`/booking/${user[0].id}`); e.id == users.id ? true : false
);
if (userstate.length) {
navigate(`/booking/${userstate[0].id}/${userstate[0].seats.length}`);
} else {
navigate(`/seat-limit/${users.id}`);
}
} }
}; };
return <Login onSubmit={handleLogin} />; return <Login onSubmit={handleLogin} />;
......
...@@ -4,18 +4,14 @@ import { useAppContext } from "../_context"; ...@@ -4,18 +4,14 @@ import { useAppContext } from "../_context";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { bookingSeats } from "./seed"; import { bookingSeats } from "./seed";
import { useLocation } from "react-router-dom";
export function _Seatlayout({ ...props }) { export function _Seatlayout({ ...props }) {
const { userseats, AddOrUpdateSeats, GetAllReservedSeats } = useAppContext(); const { userseats, AddOrUpdateSeats, GetAllReservedSeats } = useAppContext();
const [reservedSeat, setReservedSeat] = useState([]); const [reservedSeat, setReservedSeat] = useState([]);
const [selectedSeat, setSelectedSeat] = useState([]); const [selectedSeat, setSelectedSeat] = useState([]);
const navigate = useNavigate(); const navigate = useNavigate();
const { id } = useParams(); const { id, limit } = useParams();
const location = useLocation();
console.log("seat", bookingSeats);
const seatlimit = location.state.seatLimit;
useLayoutEffect(() => { useLayoutEffect(() => {
GetAllReservedSeats(); GetAllReservedSeats();
}, []); }, []);
...@@ -25,32 +21,34 @@ export function _Seatlayout({ ...props }) { ...@@ -25,32 +21,34 @@ export function _Seatlayout({ ...props }) {
const handleReservedSeats = () => { const handleReservedSeats = () => {
let seatArray = []; let seatArray = [];
const reservedSeats = userseats?.filter((e) => e.userId != id);
const reservedSeats = userseats?.filter((e) => e.id != id);
reservedSeats.forEach((element) => { reservedSeats.forEach((element) => {
element.seats.forEach((e) => { element.seats.forEach((e) => {
seatArray = [...seatArray, e]; seatArray = [...seatArray, e];
setReservedSeat(seatArray); setReservedSeat(seatArray);
}); });
}); });
const selectedSeats = userseats?.find((e) => e.userId == id); const selectedSeats = userseats?.find((e) => e.id == id);
const results = selectedSeats?.seats; const results = selectedSeats?.seats;
setSelectedSeat(results); setSelectedSeat(results);
}; };
const handleConfirmed = async ({ userId, seats }) => { const handleConfirmed = async ({ id, seats }) => {
await AddOrUpdateSeats({ userId, seats }); await AddOrUpdateSeats({ id, seats });
const count = seats?.length; const count = seats?.length;
navigate("/confirmation", { navigate("/confirmation", {
state: { seatCount: count ?? 0, seats: seats, id, seatlimit }, state: { seatCount: count ?? 0, seats: seats, id, limit },
}); });
}; };
return ( return (
<SeatLayout <SeatLayout
userId={id} userId={id}
seatLimit={seatlimit} seatLimit={limit}
seats={bookingSeats} seats={bookingSeats}
selectedSeats={selectedSeat} selectedSeats={selectedSeat}
reservedSeats={reservedSeat} reservedSeats={reservedSeat}
......
import SeatLimit from "../components/top-level/seatlimit"; import SeatLimit from "../components/top-level/seat-limit";
import { useParams, useNavigate } from "react-router-dom"; import { useParams, useNavigate } from "react-router-dom";
export function _seatLimit() { export function _seatLimit() {
...@@ -6,7 +6,7 @@ export function _seatLimit() { ...@@ -6,7 +6,7 @@ export function _seatLimit() {
const navigate = useNavigate(); const navigate = useNavigate();
const handleLimit = (e) => { const handleLimit = (e) => {
navigate(`/booking/${id}`, { state: { seatLimit: e.limit } }); navigate(`/booking/${id}/${e.limit}`);
}; };
return <SeatLimit onLimit={handleLimit} />; return <SeatLimit onLimit={handleLimit} />;
} }
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