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
No related branches found
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'; 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() { function BookingManagement() {
const state = useLocation(); const location = useLocation();
/* Update view based on what booking form is needed const navigate = useNavigate();
if (state.action === "create") {} const [event, setEvent] = useState<Event | null>(null);
else if (state.action === "update") {} const [loading, setLoading] = useState(false);
*/ const [error, setError] = useState<string | null>(null);
return ( const [success, setSuccess] = useState<string | null>(null);
<>
<p>Booking Management</p> // 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 (
<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; export default BookingManagement;
\ No newline at end of file
...@@ -7,25 +7,66 @@ from typing import List, Optional, Dict, Any ...@@ -7,25 +7,66 @@ from typing import List, Optional, Dict, Any
import models, schemas import models, schemas
# Event CRUD operations # Event CRUD operations
def get_events(db: Session, upcoming: bool = False) -> List[models.Event]: def get_events(db: Session, upcoming: bool = False) -> List[dict]:
"""Get all events or only upcoming events""" """Get all events or only upcoming events with spaces left calculation"""
query = db.query(models.Event) query = db.query(models.Event)
if upcoming: if upcoming:
now = datetime.datetime.now() now = datetime.datetime.now()
query = query.filter(models.Event.end > now) query = query.filter(models.Event.end > now)
return query.all()
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[models.Event]: def get_event(db: Session, event_id: str) -> Optional[dict]:
"""Get a specific event by ID""" """Get a specific event by ID with spaces left calculation"""
return db.query(models.Event).filter(models.Event.id == event_id).first() event = db.query(models.Event).filter(models.Event.id == event_id).first()
if not event:
return None
# 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) -> models.Event: def create_event(db: Session, event: schemas.EventCreate) -> dict:
"""Create a new event""" """Create a new event"""
db_event = models.Event(**event.model_dump()) db_event = models.Event(**event.model_dump())
db.add(db_event) db.add(db_event)
db.commit() db.commit()
db.refresh(db_event) 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: def delete_event(db: Session, event_id: str) -> None:
"""Delete an event""" """Delete an event"""
...@@ -125,11 +166,14 @@ def get_booking_stats(db: Session) -> Dict[str, Any]: ...@@ -125,11 +166,14 @@ def get_booking_stats(db: Session) -> Dict[str, Any]:
for event in events: for event in events:
bookings_count = bookings_by_event.get(event.id, 0) bookings_count = bookings_by_event.get(event.id, 0)
capacity = event.capacity capacity = event.capacity
spaces_left = max(0, capacity - bookings_count)
event_capacity[event.id] = { event_capacity[event.id] = {
"name": event.name, "name": event.name,
"bookings": bookings_count, "bookings": bookings_count,
"capacity": capacity, "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 { return {
......
...@@ -90,15 +90,14 @@ async def create_booking(booking: schemas.BookingCreate, db: Session = Depends(g ...@@ -90,15 +90,14 @@ async def create_booking(booking: schemas.BookingCreate, db: Session = Depends(g
raise HTTPException(status_code=404, detail="Event not found") raise HTTPException(status_code=404, detail="Event not found")
# Check if event has already passed # Check if event has already passed
if event.end < datetime.datetime.now(): if event["end"] < datetime.datetime.now(): # Modified to access dict
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot book an event that has already ended" detail="Cannot book an event that has already ended"
) )
# Check if event is at capacity # Check if event has spaces left
event_bookings = crud.get_bookings(db, event_id=booking.event_id) if event["spaces_left"] <= 0: # Using spaces_left instead of counting bookings
if len(event_bookings) >= event.capacity:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
detail="Event is at full capacity" detail="Event is at full capacity"
......
...@@ -16,7 +16,7 @@ class EventCreate(EventBase): ...@@ -16,7 +16,7 @@ class EventCreate(EventBase):
class EventResponse(EventBase): class EventResponse(EventBase):
id: str id: str
spaces_left: int = 0
class Config: class Config:
from_attributes = True from_attributes = True
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment