-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FR | image files #2
base: master
Are you sure you want to change the base?
Changes from 22 commits
acabb86
706c384
c89032b
fa94c15
ffc2bba
db82ee9
124d5bc
abbc1bf
102a6ea
d9dfeea
5fa282a
f2aff88
b7f632e
d79be22
d9f6de7
1b69899
8e16b5e
46b0e78
fc7f9a7
051834f
e1e306d
70ba1fd
067098c
099f869
6312008
ef55983
32987fa
79eefde
6d5973a
faffc41
68bb5a4
feb06af
a6f41d3
068f237
cdaabc6
72f9293
ecf9496
baceccf
bcbb92d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,17 @@ | ||
import React from "react"; | ||
import {Routes, Route} from "react-router-dom"; | ||
import HomePage from "../src/components/HomePage"; | ||
import BookingSeat from "../src/components/BookingSeat"; | ||
function App() { | ||
return ( | ||
<> | ||
<Routes> | ||
<Route path="/" element={<HomePage/>}/> | ||
<Route path="/bookingseat/:id/:path" element={<BookingSeat/>}/> | ||
</Routes> | ||
|
||
export default function App() { | ||
return <h1>Hello world!</h1> | ||
} | ||
</> | ||
); | ||
} | ||
|
||
export default App; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import React from 'react' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please rename the file to be more specific may be like |
||
|
||
const SvgImg = ({colorName}) => { | ||
return ( | ||
<svg width="100" height="80" viewBox="0 0 100 80" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
<rect x="29.5" y="12.5" width="41" height="41" fill={colorName} stroke="white"/> | ||
<mask id="path-2-inside-1_324_100" fill="white"> | ||
<path fillRule="evenodd" clipRule="evenodd" d="M28 26H6V71H94V26H72V55H28V26Z"/> | ||
</mask> | ||
<path fillRule="evenodd" clipRule="evenodd" d="M28 26H6V71H94V26H72V55H28V26Z" fill={colorName}/> | ||
<path d="M6 26V25H5V26H6ZM28 26H29V25H28V26ZM6 71H5V72H6V71ZM94 71V72H95V71H94ZM94 26H95V25H94V26ZM72 26V25H71V26H72ZM72 55V56H73V55H72ZM28 55H27V56H28V55ZM6 27H28V25H6V27ZM7 71V26H5V71H7ZM94 70H6V72H94V70ZM93 26V71H95V26H93ZM72 27H94V25H72V27ZM71 26V55H73V26H71ZM72 54H28V56H72V54ZM29 55V26H27V55H29Z" fill="white" mask="url(#path-2-inside-1_324_100)"/> | ||
</svg> | ||
) | ||
} | ||
|
||
export default SvgImg |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import React, { useState } from "react"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor this component to smaller components and separate logic from presentation. |
||
import { useParams } from "react-router-dom"; | ||
import Modal from "./Modal"; | ||
import vector from "../Asset/Vector 1.png"; | ||
import { | ||
BookingStyles, | ||
VectorImg, | ||
ConfirmButton, | ||
} from "../styles/Booking.styled"; | ||
import MovieSeats from "./MovieSeats"; | ||
|
||
function BookingSeat() { | ||
const [modalVisible, setModalVisible] = useState(false); | ||
const [selectedSeats, setSelectedSeats] = useState([]); | ||
|
||
let param = useParams(); | ||
let selected = []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please elaborate the difference between the variable names selectedSeats and selected array. |
||
|
||
if (JSON.stringify(localStorage.getItem(param.id)) !== "null") { | ||
selected = localStorage.getItem(param.id); | ||
} | ||
|
||
const modalHandle = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please refactor this nested switch case to single switch statement. |
||
setModalVisible(true); | ||
switch (selectedSeats.length > 10) { | ||
case true: | ||
setModalVisible(false); | ||
alert(`you can't select more than 10 seats.. | ||
you have selected ${selectedSeats.length} seats. | ||
Please deselect ${selectedSeats.length - 10} seats`); | ||
break; | ||
default: | ||
switch (selectedSeats.length) { | ||
case 0: | ||
setModalVisible(false); | ||
alert(" Please select seats first"); | ||
break; | ||
default: | ||
selected = selected + selectedSeats + ","; | ||
localStorage.setItem(param.id, selected); | ||
selected = localStorage.getItem(param.id) | ||
} | ||
} | ||
}; | ||
|
||
return ( | ||
<BookingStyles> | ||
<VectorImg src={vector} alt="vector" /> | ||
<MovieSeats selectedSeats ={selectedSeats} | ||
selected ={selected} | ||
setSelectedSeats={setSelectedSeats} | ||
/> | ||
<ConfirmButton onClick={modalHandle}>Confirm booking</ConfirmButton> | ||
<article> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove this article tag. |
||
{modalVisible && ( | ||
<Modal | ||
setVisible={setModalVisible} | ||
selectedSeats={selectedSeats} | ||
setSelectedSeats={setSelectedSeats} | ||
/> | ||
)} | ||
</article> | ||
</BookingStyles> | ||
); | ||
} | ||
export default BookingSeat; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import axios from "axios"; | ||
import MovieCard from "./MovieCard"; | ||
|
||
import { Container } from "../styles/Container.styled"; | ||
import GlobalStyles from "../styles/Global.styled"; | ||
import { Cards } from "../styles/Cards.styled" | ||
import PageNotFound from "./PageNotFound"; | ||
import {apiUrl,searchUrl} from "./constants/Global" | ||
|
||
|
||
function HomePage(){ | ||
const [movies, setMovies] = useState([]); | ||
const [searchTerm, setSearchTerm] = useState(""); | ||
|
||
useEffect(() => { | ||
getMovies(apiUrl) | ||
}, | ||
[]) | ||
|
||
async function getMovies(url) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please declare function before calling the function. |
||
const response = await axios.get(url); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add error handling. Always wrap the API calls inside try catch block and handle errors if any. |
||
const result = response.data.results; | ||
|
||
setMovies(result); | ||
} | ||
|
||
const submit = (e) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please be consistent with syntax. either choose function keyword and use it across the app or choose arrow function syntax and use it across the app. Do not mix both. |
||
e.preventDefault(); | ||
if (searchTerm) { | ||
getMovies(`${searchUrl}&query=${searchTerm}`) | ||
} else { | ||
getMovies(apiUrl) | ||
} | ||
} | ||
|
||
return ( | ||
<> | ||
<GlobalStyles /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add global styles in the index.js file instead of using it in a particular component. |
||
<Container> | ||
<h1>Book Tickets</h1> | ||
<form onSubmit={submit}> | ||
<input type="text" placeholder="search" | ||
value={searchTerm} | ||
onChange={(e) => setSearchTerm(e.target.value)} | ||
/> | ||
</form> | ||
</Container> | ||
{movies.length > 0 ? ( | ||
<Cards> | ||
{movies.map((movie) => | ||
<MovieCard movie={movie} key = {movie.id}/> | ||
)} | ||
</Cards> | ||
) : ( | ||
<PageNotFound/> | ||
)} | ||
|
||
|
||
</> | ||
); | ||
} | ||
|
||
export default HomePage; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import React from "react"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adjust the modal styling to always be in the center. |
||
|
||
import { | ||
ModalStyle, | ||
CloseButton, | ||
DataFlex, | ||
MoviePic, | ||
ModalH1, | ||
ModalH3, | ||
ModalH5, | ||
ModalSmall, | ||
ModalDiv, | ||
ModalDivSeat, | ||
ModalSeatH1, | ||
ModalScreen, | ||
} from "../styles/Booking.styled"; | ||
|
||
import close from "../Asset/Xclose.png"; | ||
import { useParams } from "react-router"; | ||
const imgUrl = "https://image.tmdb.org/t/p/w500/"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is already a constant file to maintain all the urls, please move this variable to that file. |
||
export default function Modal({ setVisible, selectedSeats, setSelectedSeats }) { | ||
const modalClose = () => { | ||
setVisible(false); | ||
setSelectedSeats([]); | ||
}; | ||
const param = useParams(); | ||
return ( | ||
<ModalScreen> | ||
<ModalStyle> | ||
<CloseButton onClick={modalClose} src={close} alt="close" /> | ||
<ModalH1>Thank you for booking</ModalH1> | ||
<ModalH3>Order Summary</ModalH3> | ||
<ModalDiv> | ||
<MoviePic src={imgUrl + param.path} alt="movie" /> | ||
|
||
<article> | ||
<h3>Seats:</h3> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The seats text is not as per the design. Please check and update. |
||
<ModalDivSeat> | ||
<ModalSeatH1>{selectedSeats.toString()}</ModalSeatH1> | ||
</ModalDivSeat> | ||
<DataFlex> | ||
<article> | ||
<ModalH5>{selectedSeats.length}*250</ModalH5> | ||
<br /> | ||
<ModalSmall>CGST(12%)</ModalSmall> | ||
<br /> | ||
<ModalSmall>SGST(12%)</ModalSmall> | ||
</article> | ||
<article> | ||
<ModalH5>{selectedSeats.length * 250}</ModalH5> | ||
<br /> | ||
<ModalSmall> | ||
{12 * (1 / 100) * (selectedSeats.length * 250)} | ||
</ModalSmall> | ||
<br /> | ||
<ModalSmall> | ||
{12 * (1 / 100) * (selectedSeats.length * 250)} | ||
</ModalSmall> | ||
</article> | ||
</DataFlex> | ||
<hr /> | ||
<DataFlex> | ||
<ModalH5>Total</ModalH5> | ||
<ModalH5> | ||
{selectedSeats.length * 250 + | ||
12 * (1 / 100) * (selectedSeats.length * 250) * 2} | ||
</ModalH5> | ||
</DataFlex> | ||
</article> | ||
</ModalDiv> | ||
</ModalStyle> | ||
</ModalScreen> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from "react"; | ||
import { NavLink } from "react-router-dom"; | ||
import { Card } from "../styles/MovieCard.styled"; | ||
import {imgUrl,fakeImg} from './constants/Global' | ||
const MovieCard = ({ movie }) => { | ||
|
||
return ( | ||
<Card key={movie.id}> | ||
<h3>{movie.title}</h3> | ||
<img src={movie.poster_path?imgUrl + movie.poster_path:fakeImg} alt={movie.id} /> | ||
<NavLink to={`/bookingseat/${movie.id}${movie.poster_path}`}> | ||
<button>Book now</button> | ||
</NavLink> | ||
</Card> | ||
) | ||
|
||
} | ||
|
||
|
||
export default MovieCard; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import React from "react"; | ||
import { data } from "./constants/Global"; | ||
import { BookingTableSeats, SeatRow } from "../styles/Booking.styled"; | ||
import SvgImg from "../Asset/SvgImg"; | ||
|
||
const MovieSeats = ({ selectedSeats, selected, setSelectedSeats }) => { | ||
function handleSeats(id) { | ||
if (selected.includes(id)) { | ||
alert("already selected"); | ||
let data = selectedSeats.filter((item) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Conflicting variable names. Please fix it. |
||
return selected.includes(id) !== selectedSeats[item]; | ||
}); | ||
setSelectedSeats(data); | ||
} else { | ||
if (selectedSeats.includes(id)) { | ||
const updatedSeats = selectedSeats.filter((seatId) => seatId !== id); | ||
setSelectedSeats(updatedSeats); | ||
} else { | ||
setSelectedSeats((prevSeats) => [...prevSeats, id]); | ||
} | ||
} | ||
} | ||
return ( | ||
<BookingTableSeats> | ||
<thead> | ||
<tr> | ||
<th> </th> | ||
{data.seats.map((seatno) => ( | ||
<th key={seatno}>{seatno}</th> | ||
))} | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{data.id.map((id) => { | ||
return ( | ||
<React.Fragment key={id}> | ||
<tr> | ||
<SeatRow>{id}</SeatRow> | ||
{data.seats.map((_, index) => { | ||
return ( | ||
<React.Fragment key={index}> | ||
<td | ||
key={id + index} | ||
onClick={() => handleSeats(id + (index + 1))} | ||
> | ||
{(() => { | ||
switch (selected.includes(id + (index + 1))) { | ||
case true: | ||
return <SvgImg colorName="#626262" />; | ||
default: | ||
switch ( | ||
selectedSeats.includes(id + (index + 1)) | ||
) { | ||
case true: | ||
return <SvgImg colorName="#724FD8" />; | ||
default: | ||
return <SvgImg colorName="#DADADA" />; | ||
} | ||
} | ||
})()} | ||
</td> | ||
</React.Fragment> | ||
); | ||
})} | ||
</tr> | ||
</React.Fragment> | ||
); | ||
})} | ||
</tbody> | ||
</BookingTableSeats> | ||
); | ||
}; | ||
|
||
export default MovieSeats; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from "react"; | ||
import img from "../Asset/undraw.png"; | ||
import { Empty } from "../styles/Empty.styled"; | ||
const PageNotFound = () => { | ||
return ( | ||
<Empty> | ||
<h2>Sorry, there is no result for keyword you searched.</h2> | ||
<img src={img} alt="no img found" /> | ||
</Empty> | ||
); | ||
}; | ||
|
||
export default PageNotFound; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
export const imgUrl = "https://image.tmdb.org/t/p/w500/"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The global constants should be under src director and should available to access from anywhere in the codebase. |
||
export const fakeImg = "http://via.placeholder.com/1080x1580/"; | ||
export const apiKey = "api_key=" + process.env.REACT_APP_API_KEY; | ||
export const baseUrl = "https://api.themoviedb.org/3"; | ||
export const apiUrl = | ||
baseUrl + "/discover/movie?sort_by=popularity.desc&" + apiKey; | ||
export const searchUrl = baseUrl + "/search/movie?" + apiKey + "&query="; | ||
export const data = { | ||
id: ["A", "B", "C", "D"], | ||
seats: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The redirected url when a movie is clicked -
http://localhost:3000/bookingseat/438148/wKiOkZTN9lUUUNZLmtnwubZYONg.jpg
The url should be -http://localhost:3000/book/438148/minions-the-rise-of-gru