Commit b695a147 by Syed Abdul Rahman

login screen design completed

parent f86b4fe6
/** @type { import('@storybook/react-vite').Preview } */
import '../src/assets/fonts.css'
const preview = {
parameters: {
backgrounds: {
......
......@@ -9,7 +9,8 @@
"version": "0.0.0",
"dependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0"
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.2"
},
"devDependencies": {
"@chromatic-com/storybook": "^4.0.0",
......@@ -2792,6 +2793,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/cookie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
"integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
......@@ -4551,6 +4561,44 @@
"node": ">=0.10.0"
}
},
"node_modules/react-router": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.2.tgz",
"integrity": "sha512-U7Nv3y+bMimgWjhlT5CRdzHPu2/KVmqPwKUCChW8en5P3znxUqwlYFlbmyj8Rgp1SF6zs5X4+77kBVknkg6a0w==",
"license": "MIT",
"dependencies": {
"cookie": "^1.0.1",
"set-cookie-parser": "^2.6.0"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
}
}
},
"node_modules/react-router-dom": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.2.tgz",
"integrity": "sha512-Q8zb6VlTbdYKK5JJBLQEN06oTUa/RAbG/oQS1auK1I0TbJOXktqm+QENEVJU6QvWynlXPRBXI3fiOQcSEA78rA==",
"license": "MIT",
"dependencies": {
"react-router": "7.6.2"
},
"engines": {
"node": ">=20.0.0"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
}
},
"node_modules/recast": {
"version": "0.23.11",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.23.11.tgz",
......@@ -4717,6 +4765,12 @@
"semver": "bin/semver.js"
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
......
......@@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview",
......@@ -13,7 +13,8 @@
},
"dependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0"
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.2"
},
"devDependencies": {
"@chromatic-com/storybook": "^4.0.0",
......
import './App.css'
import Button from './components/Base/Button/Index';
import Login from './components/TopLevel/Login/Index'
import Navigates from './Navigates'
function App() {
return (
<>
<h3> Booking APP</h3>
<Button>Confirm</Button>
<Login />
</>
<div style={{ height: "100%" }}>
<Navigates />
</div>
)
}
......
import { Routes, Route } from "react-router-dom";
import Login from "./components/TopLevel/Login/Index";
import SeatBooking from "./components/TopLevel/SeatBooking/Index";
const Navigates = () => {
return (
<Routes>
<Route path="" element={<Login />} />
<Route path="/seat-booking" element={<SeatBooking />} />
</Routes>
)
}
export default Navigates
\ No newline at end of file
......@@ -11,3 +11,8 @@
font-family: 'Pacifico';
src: url('../assets/fonts/Pacifico-Regular.ttf');
}
@font-face {
font-family: 'Inter-Medium';
src: url('../assets/fonts/Inter_28pt-MediumItalic.ttf');
}
\ No newline at end of file
......@@ -3,29 +3,36 @@
outline: none;
background-color: white;
color: black;
border-radius: 5px;
border-radius: 10px;
font-family: 'Poppins-Bold';
cursor: pointer;
text-overflow: ellipsis;
white-space: wrap;
display: flex;
gap: 1rem;
align-items: center;
justify-content: center;
font-size: clamp(1rem, 2vw, 1.5rem);
}
.sm {
padding: 0.5rem 1.5rem;
font-size: 12px;
font-size: clamp(0.5rem, 2vw, 1rem);
}
.md {
padding: 0.5rem 2rem;
padding: 0.7rem 3rem;
font-size: 16px;
font-size: clamp(1rem, 2vw, 1.5rem);
}
.lg {
padding: 0.9rem 2.5rem;
font-size: 20px;
font-size: clamp(1.5rem, 2vw, 2rem);
}
......
import PropTypes from 'prop-types';
import styles from './styles.module.css';
const Input = ({ ...inputPprops }) => {
const Input = ({
type = 'text',
name,
value,
onChange,
label,
placeholder = '',
disabled = false,
error = '',
...inputPprops
}) => {
return (
<input className={styles.input} {...inputPprops} />
<div className={styles.inputWrapper}>
{label && <label htmlFor={name} className={styles.label}>{label}</label>}
<input
type={type}
name={name}
id={name}
value={value}
placeholder={placeholder}
onChange={onChange}
disabled={disabled}
className={`${styles.input} ${error ? styles.errorInput : ''}`}
{...inputPprops}
/>
{error && <p className={styles.errorText}>{error}</p>}
</div>
// <input className={styles.input} {...inputPprops} />
)
}
export default Input;
Input.propTypes = {
onChange: PropTypes.func.isRequired,
type: PropTypes.string,
value: PropTypes.string,
placeholder: PropTypes.string
}
export default Input;
.input{
border-color: aqua;
.inputWrapper {
display: flex;
flex-direction: column;
gap: 1rem;
}
.label {
font-family: 'Inter-Medium';
font-size: clamp(1rem, 2vw, 1.5rem);
}
.input {
outline: none;
padding: 0.5rem 1rem;
border-radius: 10px;
padding: 3% 5%;
border-radius: 5px;
width: 90%;
font-family: 'Inter-Medium';
color: #000000db;
font-size: clamp(1rem, 2vw, 1.5rem);
}
\ No newline at end of file
import styles from './styles.module.css';
import Seat from './Seat';
const BookingWrapper = ({onSeatClick}) => {
import styles from './styles.module.css';
import Seat from './Seat';
const BookingWrapper = ({ onSeatClick }) => {
const aisleIndex = 5;
const seatData = [
{ id: 1, status: 'available' },
{ id: 2, status: 'reserved' },
{ id: 3, status: 'available' },
{ id: 4, status: 'reserved' },
{ id: 0, status: 'aisle' },
{ id: 1, status: 'reserved' },
{ id: 2, status: 'available' },
{ id: 3, status: 'reserved' },
{ id: 4, status: 'available' },
{ id: 0, status: 'aisle' },
{ id: 5, status: 'available' },
{ id: 6, status: 'selected' },
{ id: 6, status: 'reserved' },
{ id: 7, status: 'available' },
{ id: 8, status: 'reserved' },
{ id: 9, status: 'available' },
{ id: 10, status: 'reserved' },
{ id: 11, status: 'available' }
];
......@@ -21,21 +21,20 @@
const isLeftBlock = (col) => col < aisleIndex;
const isRightBlock = (col) => col > aisleIndex;
// const onSeatClick = (id) => {
// console.log(id, "<<<<=============")
// }
return (
<div>
<div className={styles['theatre']}>
{Array.from({ length: 6 }, (_, row_index) => (
{Array.from({ length: 2 }, (_, row_index) => (
<div className={styles['seat-row']}>
{seatData.map((ele, column_index) => {
const isFirstRow = row_index === 0;
const isLastRow = row_index === 6 - 1;
const isLastRow = row_index === 2 - 1;
if (isLeftBlock(column_index) && column_index === 0 && (isFirstRow || isLastRow)) {
return <div key={`gap-left-${row_index}-${column_index}`} className={styles["seat-gap"]} />;
// return <div key={`gap-left-${row_index}-${column_index}`} className={styles["seat-gap"]} />;
return <div className={styles['aisle']}></div>;
}
if (
......@@ -43,7 +42,8 @@
column_index === seatData.length - 1 &&
(isFirstRow || isLastRow)
) {
return <div key={`gap-right-${row_index}-${row_index}`} className={styles["seat-gap"]} />;
// return <div key={`gap-right-${row_index}-${row_index}`} className={styles["seat-gap"]} />;
return <div className={styles['aisle']}></div>;
}
if (column_index == aisleIndex) {
......@@ -52,8 +52,7 @@
)
}
return (
// <div className={`${styles.seat} ${styles[ele.status]}`}></div>
<Seat status={ele.status} onClick={()=>onSeatClick(ele.id)} />
<Seat status={ele.status} id={ele.id} onClick={() => onSeatClick(ele.id)} />
)
})}
</div>
......@@ -61,7 +60,7 @@
</div>
</div>
)
}
}
export default BookingWrapper;
export default BookingWrapper;
......@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
const Seat = ({ id,status, ...rest }) => {
return (
<div {...rest} className={` ${styles[status]} ${styles.seat} `}></div>
<div {...rest} className={` ${styles[status]} ${styles.seat} `}>{id}</div>
)
}
......
......@@ -54,8 +54,8 @@
@media screen and (min-width: 768px) {
.seat {
width: 30px;
height: 30px;
width: 40px;
height: 40px;
}
.aisle {
......@@ -64,7 +64,7 @@
.seat-gap {
width: 40px;
height: 30px;
height: 40px;
}
......
......@@ -8,16 +8,14 @@ const Header = ({ children }) => {
<div className={styles.title}>
{children}
</div>
<div style={{width: '60%'}}>
<div className={styles.screenWrapper}>
<svg viewBox="0 0 480 260" xmlns="http://www.w3.org/2000/svg">
<path d="M 30 70 Q 240 20 450 70" stroke="white" stroke-width="5" fill="none" />
<defs>
<linearGradient id="glowGradient" x1="0" y1="70" x2="0" y2="180" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#addfff" stop-opacity="0.15" />
<stop offset="100%" stop-color="#addfff" stop-opacity="0" />
</linearGradient>
<clipPath id="glowClip">
<path d="
M 30 70
......@@ -27,7 +25,6 @@ const Header = ({ children }) => {
Z" />
</clipPath>
</defs>
<rect x="0" y="0" width="480" height="260"
fill="url(#glowGradient)"
clip-path="url(#glowClip)" />
......
.title{
.header-wrapper {
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: center; */
width: 100%;
/* outline: 2px solid red; */
}
.title {
font-family: 'Poppins-Bold';
color: white;
font-size: 24px;
}
.header-wrapper{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* gap: 0.5rem; */
.screenWrapper {
width: 50%;
}
\ No newline at end of file
import styles from './styles.module.css'
import img from '../../../assets/images/background.png'
import styles from './styles.module.css';
import Input from '../../Base/Input/Index'
import Button from '../../Base/Button/Index';
import { useNavigate } from 'react-router-dom';
const Login = () => {
const navigate = useNavigate();
const handleSubmit = (e) => {
e.preventDefault();
navigate("/seat-booking")
}
return (
<div className={styles.bg}>
<section className={styles.container}>
<form action="/login" method="POST">
<div className={styles.title}>Login</div>
<label for="username">Username:</label><br />
<input type="text" id="username" name="username" /><br /><br />
<label for="password">Password:</label><br />
<input type="password" id="password" name="password" /><br /><br />
<div className={styles.contentWrapper}>
<div className={styles.title}>Welcome Back!</div>
<div className={styles.desc}>Login with email and passoword to book seats.</div>
</div>
<form className={styles.formWrapper} onSubmit={handleSubmit}>
<button type="submit">Confirm</button>
<Input
label="Email"
name="email"
type="email"
/>
{/* <br /> */}
<Input
label="Password"
name="email"
type="password"
/>
<Button size={"md"}>Confirm</Button>
</form>
</section>
</div>
......
import Login from './Index';
import { MemoryRouter } from 'react-router-dom';
export default {
title: "component/TopLevel/login",
tags: ["autodocs"],
decorators: [
(Story) => (
<MemoryRouter>
<Story />
</MemoryRouter>
),
],
component: Login
}
......
.bg {
position: relative;
width: 100%;
height: 95vh;
overflow: hidden;
height: 100%;
overflow-y: auto;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', sans-serif;
height: 100vh;
background-color: #3444c5;
}
.bg::before {
/* .bg::before {
content: "";
position: absolute;
inset: 0;
background-image: url('/src/assets/images/background.png'); /* Make sure path is correct */
background-image: url('/src/assets/images/background.png');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
filter: blur(3px);
z-index: -1;
}
height: 100%;
height: 100vh;
width: 100%;
} */
.container {
position: relative;
background-color: rgb(4, 3, 57);
background-color: rgba(0, 0, 0, 0.6);
border-radius: 10px;
height: 70vh;
padding: 1rem 3rem;
padding: 3% 5% ;
max-height: 70%;
max-width: 70%;
min-height: max(550px, 30vh);
box-sizing: border-box;
width: 30vw;
z-index: 1;
color: white;
backdrop-filter: blur(10px);
border: 1px solid #3444c5;
box-shadow: 0 0 12px 10px rgba(52, 68, 197, 0.4);
box-sizing: border-box;
}
.contentWrapper{
padding-bottom: 2rem;
}
.formWrapper{
display: flex;
flex-direction: column;
gap: 2rem;
}
.title {
font-family: 'Inter-Medium';
font-size: clamp(1rem,2vw,3rem);
color: #f1f1f1c4;
padding: 1% 0;
}
.desc {
font-family: 'Inter-Medium';
font-size: 16px;
color: #bdbcbc97;
font-size: clamp(0.5rem,3vw,1.5rem);
padding: 1% 0;
}
.title{
font-family: 'Pacifico';
font-size: 26px;
.inputStyle {
width: 90%;
}
\ No newline at end of file
import BookingWrapper from '../../Layout/BookingWrapper/Index';
import Header from '../../Layout/Header/Index'
import styles from './styles.module.css';
import Button from '../../Base/Button/Index'
const SeatBooking = () => {
return (
<div className={styles['seat-booking-wrapper']}>
<Header>Choose Seats</Header>
<BookingWrapper />
<div className={styles['btn-wrapper']}>
<Button size={"md"}>Confirm</Button>
</div>
</div>
)
}
export default SeatBooking
\ No newline at end of file
.seat-booking-wrapper{
background-color: #3444c5;
height: 100%;
width: 100%;
padding: 2rem;
box-sizing: border-box;
/* display: flex; */
flex-direction: column;
align-items: center;
gap: 2rem;
/* overflow-y: auto; */
}
.btn-wrapper{
display: flex;
justify-content: center;
align-items: center;
}
\ No newline at end of file
......@@ -2,9 +2,11 @@ import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
import { BrowserRouter } from 'react-router-dom'
createRoot(document.getElementById('root')).render(
<StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</StrictMode>,
)
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