Skip to content
Snippets Groups Projects
Commit 1ff1538d authored by Grzywocz, Dawid (UG - Comp Sci & Elec Eng)'s avatar Grzywocz, Dawid (UG - Comp Sci & Elec Eng)
Browse files

Event booking addded

parent 555c9711
Branches Events
No related tags found
No related merge requests found
import { useLocation } from 'react-router-dom';
import { useEffect, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import styles from './BookingManagement.module.scss';
// Define interfaces for type safety
interface Event {
id: string;
name: string;
start: Date;
end: Date;
venue: string;
capacity: number;
}
interface BookingCreate {
user_id: string;
event_id: string;
booking_date: Date;
}
interface BookingResponse extends BookingCreate {
id: string;
}
function BookingManagement() {
const state = useLocation();
/* Update view based on what booking form is needed
if (state.action === "create") {}
else if (state.action === "update") {}
*/
const location = useLocation();
const navigate = useNavigate();
const [event, setEvent] = useState<Event | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
// Get the current user ID - this would typically come from authentication
const userId = "current-user-id"; // Replace with actual user ID from auth
useEffect(() => {
// If there's an event in the location state, use it
if (location.state && location.state.event) {
setEvent({
...location.state.event,
start: new Date(location.state.event.start),
end: new Date(location.state.event.end)
});
}
}, [location]);
const handleCreateBooking = async () => {
if (!event) return;
try {
setLoading(true);
setError(null);
const bookingData: BookingCreate = {
user_id: userId,
event_id: event.id,
booking_date: new Date()
};
const response = await fetch('http://localhost:8000/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(bookingData),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.detail || 'Failed to create booking');
}
const data = await response.json();
setSuccess('Booking created successfully!');
// Redirect to a confirmation page or back to events
setTimeout(() => {
navigate('/my-bookings');
}, 2000);
} catch (err) {
if (err instanceof Error) {
setError(err.message);
} else {
setError('An unknown error occurred');
}
console.error('Error creating booking:', err);
} finally {
setLoading(false);
}
};
// Handle other actions (update, cancel) as needed
const handleUpdateBooking = () => {
// Implementation for updating a booking
console.log("Update booking functionality to be implemented");
};
return (
<>
<p>Booking Management</p>
</>
)
<div className={styles.bookingManagement}>
<h2>Booking Management</h2>
{loading && <p className={styles.loading}>Processing your request...</p>}
{error && <p className={styles.error}>{error}</p>}
{success && <p className={styles.success}>{success}</p>}
{event && (
<div className={styles.eventDetails}>
<h3>Event Details</h3>
<p><strong>Name:</strong> {event.name}</p>
<p><strong>Start:</strong> {event.start.toLocaleString()}</p>
<p><strong>End:</strong> {event.end.toLocaleString()}</p>
<p><strong>Venue:</strong> {event.venue}</p>
<p><strong>Capacity:</strong> {event.capacity}</p>
</div>
)}
{/* Update view based on what booking form is needed */}
{location.state && location.state.action === "create" && (
<div className={styles.bookingActions}>
<button
onClick={handleCreateBooking}
disabled={loading || !event}
className={styles.actionButton}
>
Confirm Booking
</button>
</div>
)}
{location.state && location.state.action === "update" && (
<div className={styles.bookingActions}>
<button
onClick={handleUpdateBooking}
disabled={loading || !event}
className={styles.actionButton}
>
Update Booking
</button>
</div>
)}
<button
onClick={() => navigate('/events')}
className={styles.backButton}
>
Back to Events
</button>
</div>
);
}
export default BookingManagement;
\ No newline at end of file
......@@ -7,25 +7,66 @@ from typing import List, Optional, Dict, Any
import models, schemas
# Event CRUD operations
def get_events(db: Session, upcoming: bool = False) -> List[models.Event]:
"""Get all events or only upcoming events"""
def get_events(db: Session, upcoming: bool = False) -> List[dict]:
"""Get all events or only upcoming events with spaces left calculation"""
query = db.query(models.Event)
if upcoming:
now = datetime.datetime.now()
query = query.filter(models.Event.end > now)
return query.all()
def get_event(db: Session, event_id: str) -> Optional[models.Event]:
"""Get a specific event by ID"""
return db.query(models.Event).filter(models.Event.id == event_id).first()
events = query.all()
result = []
for event in events:
# Count bookings for this event
booking_count = db.query(models.Booking).filter(
models.Booking.event_id == event.id
).count()
# Calculate spaces left
spaces_left = max(0, event.capacity - booking_count)
# Convert to dict and add spaces_left
event_dict = {c.name: getattr(event, c.name) for c in event.__table__.columns}
event_dict['spaces_left'] = spaces_left
result.append(event_dict)
return result
def get_event(db: Session, event_id: str) -> Optional[dict]:
"""Get a specific event by ID with spaces left calculation"""
event = db.query(models.Event).filter(models.Event.id == event_id).first()
if not event:
return None
def create_event(db: Session, event: schemas.EventCreate) -> models.Event:
# Count bookings for this event
booking_count = db.query(models.Booking).filter(
models.Booking.event_id == event_id
).count()
# Calculate spaces left
spaces_left = max(0, event.capacity - booking_count)
# Convert to dict and add spaces_left
event_dict = {c.name: getattr(event, c.name) for c in event.__table__.columns}
event_dict['spaces_left'] = spaces_left
return event_dict
def create_event(db: Session, event: schemas.EventCreate) -> dict:
"""Create a new event"""
db_event = models.Event(**event.model_dump())
db.add(db_event)
db.commit()
db.refresh(db_event)
return db_event
# New event has no bookings, so spaces_left equals capacity
event_dict = {c.name: getattr(db_event, c.name) for c in db_event.__table__.columns}
event_dict['spaces_left'] = db_event.capacity
return event_dict
def delete_event(db: Session, event_id: str) -> None:
"""Delete an event"""
......@@ -125,11 +166,14 @@ def get_booking_stats(db: Session) -> Dict[str, Any]:
for event in events:
bookings_count = bookings_by_event.get(event.id, 0)
capacity = event.capacity
spaces_left = max(0, capacity - bookings_count)
event_capacity[event.id] = {
"name": event.name,
"bookings": bookings_count,
"capacity": capacity,
"fill_percentage": round((bookings_count / capacity) * 100, 2) if capacity > 0 else 0
"fill_percentage": round((bookings_count / capacity) * 100, 2) if capacity > 0 else 0,
"spaces_left": spaces_left # Added spaces_left to stats
}
return {
......
......
......@@ -90,15 +90,14 @@ async def create_booking(booking: schemas.BookingCreate, db: Session = Depends(g
raise HTTPException(status_code=404, detail="Event not found")
# Check if event has already passed
if event.end < datetime.datetime.now():
if event["end"] < datetime.datetime.now(): # Modified to access dict
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot book an event that has already ended"
)
# Check if event is at capacity
event_bookings = crud.get_bookings(db, event_id=booking.event_id)
if len(event_bookings) >= event.capacity:
# Check if event has spaces left
if event["spaces_left"] <= 0: # Using spaces_left instead of counting bookings
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Event is at full capacity"
......
......
......@@ -16,7 +16,7 @@ class EventCreate(EventBase):
class EventResponse(EventBase):
id: str
spaces_left: int = 0
class Config:
from_attributes = True
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment