Skip to content
This repository has been archived by the owner on May 8, 2024. It is now read-only.

feat: A6 implement #1

Merged
merged 3 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions src/pages/MovieSeatSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@

import PageContainer from 'components/PageContainer';
import { useState } from 'react';
import Form from 'react-bootstrap/Form';
import styles from './style.module.css';

Check failure on line 5 in src/pages/MovieSeatSelect/index.tsx

View workflow job for this annotation

GitHub Actions / build

Cannot find module './style.module.css' or its corresponding type declarations.

interface Seat {
id: string;
row: number;
number: number;
ticketType: TicketType | null;
}

enum TicketType {
Student = 'Student',
Children = 'Children',
Veteran = 'Veteran',
Adult = 'Adult',
Senior = 'Senior',
}

const Index: React.FC = () => {
const [selectedSeats, setSelectedSeats] = useState<Seat[]>([]);
const [selectedTicketType, setSelectedTicketType] = useState<TicketType | null>(null);

const totalSelectedSeats = selectedSeats.length;

const handleSeatClick = (seat: Seat) => {
const seatIndex = selectedSeats.findIndex((selectedSeat) => selectedSeat.id === seat.id);

if (seatIndex === -1) {
setSelectedSeats([...selectedSeats, { ...seat, ticketType: selectedTicketType }]);
} else {
const updatedSeats = [...selectedSeats];
updatedSeats.splice(seatIndex, 1);
setSelectedSeats(updatedSeats);
}
};

const handleTicketTypeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedTicketType(event.target.value as TicketType);
};

const renderSeats = () => {
const rows = 5;
const seatsPerRow = 8;
const seats: Seat[] = [];

for (let row = 1; row <= rows; row++) {
for (let number = 1; number <= seatsPerRow; number++) {
const id = `${row}-${number}`;
seats.push({ id, row, number, ticketType: null });
}
}

return seats.map((seat) => (
<button
key={seat.id}
onClick={() => handleSeatClick(seat)}
className={`${styles.seat} ${selectedSeats.some((selectedSeat) => selectedSeat.id === seat.id) ? styles.selected : ''}`}
>
{seat.row} - {seat.number}
</button>
));
};

return (
<PageContainer>
<div className='text-center'>
<h1>Select Seat</h1>
</div>
<div className={styles.seatContainer}>
{renderSeats()}
</div>
<Form>
<Form.Group controlId="ticketType">
<Form.Label>Select Ticket Type:</Form.Label>
<Form.Control as="select" onChange={handleTicketTypeChange} value={selectedTicketType || ''}>

Check failure on line 78 in src/pages/MovieSeatSelect/index.tsx

View workflow job for this annotation

GitHub Actions / build

Type '(event: React.ChangeEvent<HTMLSelectElement>) => void' is not assignable to type 'ChangeEventHandler<FormControlElement>'.
<option value="" disabled>Select Ticket Type</option>
{Object.values(TicketType).map((type) => (
<option key={type} value={type}>{type}</option>
))}
</Form.Control>
</Form.Group>
</Form>
<div className={styles.messageContainer}>
<p className={styles.message}>
You have selected <strong>{totalSelectedSeats}</strong> seat(s).
</p>
{selectedSeats.map((seat, index) => (
<div key={index}>
{seat.ticketType && (
<p>
{seat.ticketType}
{index < selectedSeats.length - 1 && ', '}
</p>
)}
</div>
))}

</div>
</PageContainer>
);
};

export default Index;
18 changes: 18 additions & 0 deletions src/pages/MovieSeatSelect/style.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.seat-container {
display: flex;
flex-wrap: wrap;
justify-content: center

}

.seat {
margin-right: 20px; /* Adjust the margin as needed */
margin-bottom: 10px; /* Adjust the margin as needed */
}

.selected {
background-color: #3498db; /* Example color for selected seats */
color: #fff; /* Example text color for selected seats */
}


100 changes: 100 additions & 0 deletions src/pages/MovieSelect/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import PageContainer from 'components/PageContainer'
import { useState } from 'react'
import Button from 'react-bootstrap/Button'
import Card from 'react-bootstrap/Card'
import { useNavigate, useParams } from 'react-router-dom'

const Index: React.FC = () => {
const navigate = useNavigate()
const { movieId } = useParams()
const [hoveredMovie, setHoveredMovie] = useState<string | null>(null)

const handleMouseEnter = (title: string) => {
setHoveredMovie(title)
}

const handleMouseLeave = () => {
setHoveredMovie(null)
}

const movies = [
{
title: 'Argylle',
director: 'Matthew Vaughn',
length: '2h 30m',
image:
'https://connect.gtcmovies.com/CDN/Image/Entity/FilmPosterGraphic/HO00003984', // Replace with actual image URL
showTimes: ['10:00 AM', '2:00 PM', '6:00 PM', '9:30 PM']
}
// {
// title: 'Bob Marley One Love',
// director: 'Reinaldus Marcus ',
// length: '2h',
// image: 'https://connect.gtcmovies.com/CDN/Image/Entity/FilmPosterGraphic/HO00004017', // Replace with actual image URL
// showTimes: ['11:00 AM', '3:45 PM', '8:00 PM'],
// },
// {
// title: 'Madame Web',
// director: 'S.J. Clarkson',
// length: '1h 45m',
// image: 'https://connect.gtcmovies.com/CDN/Image/Entity/FilmPosterGraphic/HO00004029', // Replace with actual image URL
// showTimes: ['5:45 PM', '8:00 PM'],
// },
// {
// title: 'Wonka',
// director: 'Paul King',
// length: '2h 15m',
// image: 'https://connect.gtcmovies.com/CDN/Image/Entity/FilmPosterGraphic/HO00003932', // Replace with actual image URL
// showTimes: ['1:30 PM', '6:45 PM', '7:45 PM' ],
// },
]

return (
<PageContainer>
<div className='text-center'>
<h1>Showing</h1>
</div>

<div className='d-flex flex-wrap justify-content-around'>
{movies.map((movie, index) => (
<Card
key={index}
style={{ width: '18rem', margin: '10px' }}
onMouseEnter={() => handleMouseEnter(movie.title)}
onMouseLeave={handleMouseLeave}
>
<Card.Img
variant='top'
src={movie.image}
alt={`${movie.title} poster`}
/>
<Card.Body>
<Card.Title>{movie.title}</Card.Title>
<Card.Text>
<strong>Director:</strong> {movie.director}
<br />
<strong>Length:</strong> {movie.length}
</Card.Text>
{hoveredMovie === movie.title && (
<div>
{movie.showTimes.map((time, timeIndex) => (
<Button
key={timeIndex}
variant='primary'
className='mt-auto'
style={{ marginRight: '8px', marginBottom: '8px' }}
onClick={() => navigate(`/movie/${movieId}/seat`)}
>
{time}
</Button>
))}
</div>
)}
</Card.Body>
</Card>
))}
</div>
</PageContainer>
)
}
export default Index
11 changes: 11 additions & 0 deletions src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Login from 'pages/Login'
import Logout from 'pages/Logout'
import Main from 'pages/Main'
import MovieCreate from 'pages/MovieCreate'
import MovieSeatSelect from 'pages/MovieSeatSelect'
import MovieSelect from 'pages/MovieSelect'
import NotFound from 'pages/NotFound'
import Register from 'pages/Register'
import RegisterConfirm from 'pages/RegisterConfirm'
Expand Down Expand Up @@ -38,6 +40,15 @@ const children: RouteObject[] = [
}
]
},
{
path: '/movie/:movieId/book',
element: <MovieSelect />
},

{
path: '/movie/:movieId/seat',
element: <MovieSeatSelect />
},
{
path: '*',
element: <NotFound />
Expand Down
Loading