Commit 2beef710 by Syed Abdul Rahman

implemented toast message and api call fixes

parent 4505dda8
VITE_API_URL=http://192.168.1.73:3000 VITE_API_URL=http://localhost:3000
\ No newline at end of file \ No newline at end of file
{ {
"users": [ "users": [
{ {
"id": "0b2d", "id": "7e7e",
"email": "syedabdul.rahman@krds.com" "email": "syedabdul.rahman@krds.com"
}, },
{ {
"id": "1d58", "id": "6e20",
"email": "abdul@gmail.com" "email": "abdul@gmail.com"
},
{
"id": "42f0",
"email": "lucy@gmail.com"
},
{
"id": "e770",
"email": "new@gmail.com"
},
{
"id": "5f85",
"email": "test@krds.fr"
},
{
"id": "5647",
"email": "anas@krds.fr"
},
{
"id": "ad86",
"email": "test@gmail.com"
} }
], ],
"selectedSeats": [ "selectedSeats": [
{ {
"id": "0b2d", "id": "7e7e",
"userid": "0b2d", "userid": "7e7e",
"selected": [ "selected": [
{ {
"row": 7,
"seat": 5
},
{
"row": 6,
"seat": 5
},
{
"row": 8, "row": 8,
"seat": 4 "seat": "H4"
}
]
},
{
"id": "1d58",
"userid": "1d58",
"selected": [
{
"row": 8,
"seat": 5
}, },
{ {
"row": 8, "row": 8,
"seat": 6 "seat": "H5"
},
{
"row": 7,
"seat": 7
}
]
},
{
"id": "42f0",
"userid": "42f0",
"selected": [
{
"row": 6,
"seat": 1
}, },
{ {
"row": 6, "row": 8,
"seat": 2 "seat": "H6"
},
{
"row": 6,
"seat": 3
},
{
"row": 6,
"seat": 4
}
]
},
{
"id": "5f85",
"userid": "5f85",
"selected": [
{
"row": 4,
"seat": 3
},
{
"row": 6,
"seat": 6
},
{
"row": 5,
"seat": 1
},
{
"row": 5,
"seat": 7
} }
] ]
}, },
{ {
"id": "5647", "id": "6e20",
"userid": "5647", "userid": "6e20",
"selected": [ "selected": [
{ {
"row": 7, "row": 7,
"seat": 8 "seat": "G1"
}, },
{ {
"row": 7, "row": 7,
"seat": 6 "seat": "G3"
}
]
},
{
"id": "e770",
"userid": "e770",
"selected": [
{
"row": 7,
"seat": 2
}, },
{ {
"row": 7, "row": 7,
"seat": 3 "seat": "G2"
}
]
},
{
"id": "ad86",
"userid": "ad86",
"selected": [
{
"row": 4,
"seat": 7
}, },
{ {
"row": 4, "row": 7,
"seat": 8 "seat": "G4"
} }
] ]
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
{ {
"name": "seat-booking", "name": "seat-booking",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "scripts": {
"scripts": { "dev": "vite --host",
"dev": "vite --host", "build": "vite build",
"build": "vite build", "lint": "eslint .",
"lint": "eslint .", "preview": "vite preview",
"preview": "vite preview", "storybook": "storybook dev -p 6006",
"storybook": "storybook dev -p 6006", "build-storybook": "storybook build",
"build-storybook": "storybook build" "server": "node server.cjs"
}, },
"dependencies": { "dependencies": {
"lottie-react": "^2.4.1", "lottie-react": "^2.4.1",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
"react-router-dom": "^7.6.2" "react-router-dom": "^7.6.2"
}, },
"devDependencies": { "devDependencies": {
"@chromatic-com/storybook": "^4.0.0", "@chromatic-com/storybook": "^4.0.0",
"@eslint/js": "^9.25.0", "@eslint/js": "^9.25.0",
"@storybook/addon-a11y": "^9.0.4", "@storybook/addon-a11y": "^9.0.4",
"@storybook/addon-docs": "^9.0.4", "@storybook/addon-docs": "^9.0.4",
"@storybook/addon-onboarding": "^9.0.4", "@storybook/addon-onboarding": "^9.0.4",
"@storybook/addon-vitest": "^9.0.4", "@storybook/addon-vitest": "^9.0.4",
"@storybook/react-vite": "^9.0.4", "@storybook/react-vite": "^9.0.4",
"@types/react": "^19.1.2", "@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2", "@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^4.4.1", "@vitejs/plugin-react": "^4.4.1",
"@vitest/browser": "^3.2.0", "@vitest/browser": "^3.2.0",
"@vitest/coverage-v8": "^3.2.0", "@vitest/coverage-v8": "^3.2.0",
"eslint": "^9.25.0", "eslint": "^9.25.0",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19", "eslint-plugin-react-refresh": "^0.4.19",
"eslint-plugin-storybook": "^9.0.4", "eslint-plugin-storybook": "^9.0.4",
"globals": "^16.0.0", "globals": "^16.0.0",
"playwright": "^1.52.0", "json-server": "^1.0.0-beta.3",
"prop-types": "^15.8.1", "playwright": "^1.52.0",
"storybook": "^9.0.4", "prop-types": "^15.8.1",
"vite": "^6.3.5", "storybook": "^9.0.4",
"vitest": "^3.2.0" "vite": "^6.3.5",
} "vitest": "^3.2.0"
}
} }
...@@ -2,7 +2,12 @@ import PropTypes from 'prop-types'; ...@@ -2,7 +2,12 @@ import PropTypes from 'prop-types';
import styles from './styles.module.css'; import styles from './styles.module.css';
const Seat = ({ id, status, ...rest }) => { const Seat = ({ id, status, ...rest }) => {
return <div {...rest} className={` ${styles[status]} ${styles.seat} `}></div>; return (
<div
{...rest}
title={id}
className={` ${styles[status]} ${styles.seat} `}></div>
);
}; };
Seat.propTypes = { Seat.propTypes = {
......
import styles from './/styles.module.css';
const Toast = ({ message, type = 'info', onClose }) => {
return (
<div className={`${styles.toast} ${styles[type]}`}>
<span>{message}</span>
<button onClick={onClose}>&times;</button>
</div>
);
};
export default Toast;
/* toast.css */
.toast {
position: fixed;
bottom: 20px;
right: 20px;
background-color: #333;
color: white;
padding: 12px 16px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
gap: 10px;
z-index: 9999;
animation: slideIn 0.3s ease-out;
}
.toast.success {
background-color: #28a745;
}
.toast.error {
background-color: #dc3545;
}
.toast.info {
background-color: #007bff;
}
.toast button {
background: transparent;
border: none;
color: white;
font-size: 16px;
cursor: pointer;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
export const login = async (email) => { export const login = async (email) => {
try { try {
const response = await fetch(`${import.meta.env.VITE_API_URL}/users`); const response = await fetch(
`${import.meta.env.VITE_API_URL}/users?email=${email}`
);
const data = await response.json(); const data = await response.json();
const user = data.find((e) => e.email === email); // const user = data.find((e) => e.email === email);
return user; return data;
} catch (error) { } catch (error) {
console.error('Login error:', error); console.error('Login error:', error);
throw error; throw error;
......
import { StrictMode } from 'react' import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client';
import './index.css' import './index.css';
import App from './App.jsx' import App from './App.jsx';
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom';
createRoot(document.getElementById('root')).render( createRoot(document.getElementById('root')).render(
// <StrictMode> // <StrictMode>
<BrowserRouter> <BrowserRouter>
<App /> <App />
</BrowserRouter> </BrowserRouter>
// </StrictMode>, // </StrictMode>
) );
...@@ -12,16 +12,17 @@ import LogoutButton from '@components/Shared/LogoutButton/Index'; ...@@ -12,16 +12,17 @@ import LogoutButton from '@components/Shared/LogoutButton/Index';
import { getItem, reset, setItem } from '../../lib/sessionStorage'; import { getItem, reset, setItem } from '../../lib/sessionStorage';
import { appConstants } from '@lib/AppConstants'; import { appConstants } from '@lib/AppConstants';
import { getSelectedSeatsApi, editSeatsApi, createSeatApi } from '@lib/api'; import { getSelectedSeatsApi, editSeatsApi, createSeatApi } from '@lib/api';
import Toast from '@components/Shared/Toast/Index';
const data = [ const data = [
['*', 1, 2, 3, '*', 4, 5, 6, '*'], ['*', 'A1', 'A2', 'A3', '*', 'A4', 'A5', 'A6', '*'],
[1, 2, 3, 4, '*', 5, 6, 7, 8], ['B1', 'B2', 'B3', 'B4', '*', 'B5', 'B6', 'B7', 'B8'],
[1, 2, 3, 4, '*', 5, 6, 7, 8], ['C1', 'C2', 'C3', 'C4', '*', 'C5', 'C6', 'C7', 'C8'],
[1, 2, 3, 4, '*', 5, 6, 7, 8], ['D1', 'D2', 'D3', 'D4', '*', 'D5', 'D6', 'D7', 'D8'],
[1, 2, 3, 4, '*', 5, 6, 7, 8], ['E1', 'E2', 'E3', 'E4', '*', 'E5', 'E6', 'E7', 'E8'],
[1, 2, 3, 4, '*', 5, 6, 7, 8], ['F1', 'F2', 'F3', 'F4', '*', 'F5', 'F6', 'F7', 'F8'],
[1, 2, 3, 4, '*', 5, 6, 7, 8], ['G1', 'G2', 'G3', 'G4', '*', 'G5', 'G6', 'G7', 'G8'],
['*', 1, 2, 3, '*', 4, 5, 6, '*'] ['*', 'H1', 'H2', 'H3', '*', 'H4', 'H5', 'H6', '*']
]; ];
const BookingPage = () => { const BookingPage = () => {
...@@ -39,15 +40,26 @@ const BookingPage = () => { ...@@ -39,15 +40,26 @@ const BookingPage = () => {
const [buttonState, setButtonState] = useState(true); const [buttonState, setButtonState] = useState(true);
const [modalButtonState, setModalButtonState] = useState(true); const [modalButtonState, setModalButtonState] = useState(true);
const [showSuccessModal, setShowSuccessModal] = useState(false); const [showSuccessModal, setShowSuccessModal] = useState(false);
const [toast, setToast] = useState(null);
useEffect(() => { useEffect(() => {
fetchSelectedSeats(); const initializeSeatsData = async () => {
setShowSeatsModal(getItem(appConstants.MODAL)); await fetchSelectedSeats();
setShowSeatsModal(getItem(appConstants.MODAL));
};
initializeSeatsData();
}, []); }, []);
const fetchSelectedSeats = async () => { const fetchSelectedSeats = async () => {
try { try {
const data = await getSelectedSeatsApi(); const data = await getSelectedSeatsApi();
const currentData = data?.find((e) => e.userid == userId); const currentData = data?.find((e) => e.userid == userId);
if (currentData?.selected?.length > 0) {
setItem('modal', false);
} else {
setItem('modal', true);
}
const structuredData = data.flatMap((user) => user.selected); const structuredData = data.flatMap((user) => user.selected);
const temp = structuredData?.filter( const temp = structuredData?.filter(
...@@ -128,6 +140,7 @@ const BookingPage = () => { ...@@ -128,6 +140,7 @@ const BookingPage = () => {
} }
} else { } else {
updatedSeats = prev ? [...prev] : []; updatedSeats = prev ? [...prev] : [];
showToast('Seat Count Exeeded', 'info');
} }
return updatedSeats; return updatedSeats;
}); });
...@@ -164,6 +177,11 @@ const BookingPage = () => { ...@@ -164,6 +177,11 @@ const BookingPage = () => {
setButtonState(true); setButtonState(true);
}; };
const showToast = (message, type = 'info') => {
setToast({ message, type });
setTimeout(() => setToast(null), 3000);
};
return ( return (
<> <>
<LogoutButton onLogout={logout} /> <LogoutButton onLogout={logout} />
...@@ -194,6 +212,14 @@ const BookingPage = () => { ...@@ -194,6 +212,14 @@ const BookingPage = () => {
{showSuccessModal && ( {showSuccessModal && (
<SuccessModal onConfirm={handleSuccessModalConfirm} /> <SuccessModal onConfirm={handleSuccessModalConfirm} />
)} )}
{toast && (
<Toast
message={toast.message}
type={toast.type}
onClose={() => setToast(null)}
/>
)}
</> </>
); );
}; };
......
...@@ -9,32 +9,13 @@ const LoginPage = () => { ...@@ -9,32 +9,13 @@ const LoginPage = () => {
const onSubmit = async (email) => { const onSubmit = async (email) => {
try { try {
const userData = await login(email); const userData = await login(email);
if (userData?.length > 0) {
const fetchSeatSelectionCount = async (id) => { setItem('user', userData[0].id);
try {
const data = await getSelectedSeatsApi();
const currentData = data?.find((e) => e.userid == id);
if (currentData?.selected?.length > 0) {
setItem('modal', false);
} else {
setItem('modal', true);
}
navigate('/');
} catch (error) {
console.error('Error fetching seat selection count:', error);
}
};
if (userData) {
setItem('user', userData.id);
fetchSeatSelectionCount(userData?.id);
} else { } else {
const data = await createUser(email); const data = await createUser(email);
setItem('user', data.id); setItem('user', data.id);
fetchSeatSelectionCount(data?.id);
} }
navigate('/');
} catch (error) { } catch (error) {
console.error('Error during login or user creation:', error); console.error('Error during login or user creation:', error);
} }
......
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