diff --git a/assets/css/style.css b/assets/css/style.css
new file mode 100644
index 0000000..c123df5
--- /dev/null
+++ b/assets/css/style.css
@@ -0,0 +1,186 @@
+/* Basic Reset & Body Styling */
+body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+ line-height: 1.6;
+ margin: 0;
+ background-color: #f4f7f6;
+ color: #333;
+}
+
+main {
+ padding: 20px;
+ max-width: 1200px;
+ margin: 0 auto;
+}
+
+/* Header & Navigation */
+header {
+ background-color: #fff;
+ padding: 1rem 2rem;
+ border-bottom: 1px solid #e0e0e0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+header nav a {
+ text-decoration: none;
+ color: #007bff;
+ font-weight: 500;
+ margin-left: 15px;
+}
+
+header nav a:hover {
+ text-decoration: underline;
+}
+
+/* Footer */
+footer {
+ text-align: center;
+ padding: 20px;
+ margin-top: 40px;
+ background-color: #fff;
+ border-top: 1px solid #e0e0e0;
+ color: #777;
+}
+
+/* Forms */
+.booking-form {
+ background: #fff;
+ padding: 30px;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px rgba(0,0,0,0.1);
+ max-width: 500px;
+ margin: 40px auto;
+}
+
+.booking-form h2 {
+ margin-top: 0;
+ margin-bottom: 20px;
+ color: #333;
+}
+
+.form-group {
+ margin-bottom: 20px;
+}
+
+.form-group label {
+ display: block;
+ margin-bottom: 8px;
+ font-weight: 500;
+ color: #555;
+}
+
+.form-group input,
+.form-group select {
+ width: 100%;
+ padding: 12px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ box-sizing: border-box; /* Important */
+}
+
+.form-group input:focus,
+.form-group select:focus {
+ outline: none;
+ border-color: #007bff;
+ box-shadow: 0 0 0 2px rgba(0,123,255,0.25);
+}
+
+button {
+ display: inline-block;
+ background-color: #007bff;
+ color: #fff;
+ padding: 12px 20px;
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 16px;
+ width: 100%;
+ transition: background-color 0.2s;
+}
+
+button:hover {
+ background-color: #0056b3;
+}
+
+/* Container for the main content */
+.container {
+ padding: 2rem;
+}
+
+/* Calendar Styling */
+.calendar-container {
+ background: #fff;
+ padding: 30px;
+ border-radius: 8px;
+ box-shadow: 0 4px 10px rgba(0,0,0,0.1);
+ margin: 40px auto;
+}
+
+.calendar-container h2 {
+ margin-top: 0;
+ margin-bottom: 20px;
+ color: #333;
+}
+
+#calendar {
+ max-width: 1100px;
+ margin: 0 auto;
+}
+
+/* Responsive container */
+.container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20px;
+}
+
+.booking-form {
+ flex: 1 1 400px; /* Flex-grow, flex-shrink, flex-basis */
+}
+
+.calendar-container {
+ flex: 2 1 600px; /* Takes up more space */
+}
+
+/* Modal Styling */
+.modal {
+ display: none; /* Hidden by default */
+ position: fixed; /* Stay in place */
+ z-index: 1000; /* Sit on top */
+ left: 0;
+ top: 0;
+ width: 100%; /* Full width */
+ height: 100%; /* Full height */
+ overflow: auto; /* Enable scroll if needed */
+ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
+}
+
+.modal-content {
+ background-color: #fefefe;
+ margin: 15% auto; /* 15% from the top and centered */
+ padding: 20px;
+ border: 1px solid #888;
+ width: 80%; /* Could be more or less, depending on screen size */
+ max-width: 500px;
+ border-radius: 8px;
+ position: relative;
+}
+
+.close-button {
+ color: #aaa;
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+ position: absolute;
+ top: 10px;
+ right: 20px;
+}
+
+.close-button:hover,
+.close-button:focus {
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+}
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..a8c440a
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,111 @@
+document.addEventListener('DOMContentLoaded', function() {
+ var calendarEl = document.getElementById('calendar');
+ var modal = document.getElementById('booking-modal');
+ var closeButton = document.querySelector('.close-button');
+ var bookingForm = document.getElementById('modal-booking-form');
+ var calendar;
+ var currentSelectionInfo;
+
+ if (calendarEl) {
+ calendar = new FullCalendar.Calendar(calendarEl, {
+ initialView: 'timeGridWeek',
+ headerToolbar: {
+ left: 'prev,next today',
+ center: 'title',
+ right: 'dayGridMonth,timeGridWeek,timeGridDay'
+ },
+ events: 'get_bookings.php',
+ slotMinTime: '08:00:00',
+ slotMaxTime: '22:00:00',
+ allDaySlot: false,
+ slotDuration: '00:15:00',
+ selectable: true,
+ editable: true,
+ select: function(info) {
+ currentSelectionInfo = info;
+ modal.style.display = 'block';
+ document.getElementById('organizer-name').focus();
+ },
+ eventDrop: function(info) {
+ updateBooking(info.event);
+ },
+ eventResize: function(info) {
+ updateBooking(info.event);
+ }
+ });
+ calendar.render();
+ }
+
+ if (closeButton) {
+ closeButton.onclick = function() {
+ modal.style.display = 'none';
+ }
+ }
+
+ window.onclick = function(event) {
+ if (event.target == modal) {
+ modal.style.display = 'none';
+ }
+ }
+
+ if (bookingForm) {
+ bookingForm.onsubmit = function(e) {
+ e.preventDefault();
+ var title = document.getElementById('organizer-name').value;
+ var sport = document.getElementById('modal-sport').value;
+
+ if (title && sport && currentSelectionInfo) {
+ var newEvent = {
+ title: title,
+ sport: sport,
+ start: currentSelectionInfo.startStr,
+ end: currentSelectionInfo.endStr
+ };
+
+ fetch('create_booking.php', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(newEvent),
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.status === 'success') {
+ modal.style.display = 'none';
+ bookingForm.reset();
+ calendar.refetchEvents();
+ } else {
+ alert('Error creating booking: ' + data.message);
+ }
+ });
+ }
+ calendar.unselect();
+ }
+ }
+
+ function updateBooking(event) {
+ var eventData = {
+ id: event.id,
+ start: event.startStr,
+ end: event.endStr
+ };
+ fetch('update_booking.php', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(eventData),
+ })
+ .then(response => response.json())
+ .then(data => {
+ if (data.status !== 'success') {
+ alert('Error updating booking: ' + data.message);
+ // Revert the event's position
+ // Note: The `revert()` function is not available on the `event` object directly in v5.
+ // Instead, you would refetch events or handle this state differently.
+ calendar.refetchEvents();
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/create_booking.php b/create_booking.php
new file mode 100644
index 0000000..9cce516
--- /dev/null
+++ b/create_booking.php
@@ -0,0 +1,27 @@
+ 'error', 'message' => 'Invalid request'];
+
+$data = json_decode(file_get_contents('php://input'), true);
+
+if ($data) {
+ try {
+ $pdo = db();
+ $stmt = $pdo->prepare("INSERT INTO bookings (title, sport, start_time, end_time) VALUES (?, ?, ?, ?)");
+ $stmt->execute([
+ $data['title'],
+ $data['sport'],
+ $data['start'],
+ $data['end']
+ ]);
+ $response['status'] = 'success';
+ $response['message'] = 'Booking created successfully';
+ } catch (PDOException $e) {
+ $response['message'] = 'Database error: ' . $e->getMessage();
+ }
+}
+
+echo json_encode($response);
+?>
\ No newline at end of file
diff --git a/db/migrations/001_create_bookings_table.sql b/db/migrations/001_create_bookings_table.sql
new file mode 100644
index 0000000..66eb6ab
--- /dev/null
+++ b/db/migrations/001_create_bookings_table.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS bookings (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ title VARCHAR(255) NOT NULL,
+ start_time DATETIME NOT NULL,
+ end_time DATETIME NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
diff --git a/get_bookings.php b/get_bookings.php
new file mode 100644
index 0000000..8b7d8d0
--- /dev/null
+++ b/get_bookings.php
@@ -0,0 +1,23 @@
+query('SELECT COUNT(*) FROM bookings');
+ if ($stmt->fetchColumn() == 0) {
+ $pdo->exec("INSERT INTO bookings (title, start_time, end_time) VALUES ('Booking 1', '2025-10-02 10:00:00', '2025-10-02 11:00:00')");
+ $pdo->exec("INSERT INTO bookings (title, start_time, end_time) VALUES ('Booking 2', '2025-10-02 14:00:00', '2025-10-02 15:00:00')");
+ }
+
+ $stmt = $pdo->query('SELECT title, start_time AS start, end_time AS end FROM bookings');
+ $bookings = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+ header('Content-Type: application/json');
+ echo json_encode($bookings);
+
+} catch (PDOException $e) {
+ http_response_code(500);
+ echo json_encode(['error' => $e->getMessage()]);
+}
diff --git a/includes/footer.php b/includes/footer.php
new file mode 100644
index 0000000..0441230
--- /dev/null
+++ b/includes/footer.php
@@ -0,0 +1,8 @@
+
+
+
+
+