Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Кольцова А.А. Разработка прототипа системы бронирования велопрокатной организации

.pdf
Скачиваний:
2
Добавлен:
22.08.2024
Размер:
5.83 Mб
Скачать

111

<form method="POST" action="catalog_edit.php" enctype="multipart/form-data"> <input type="hidden" name="action" value="add">

<label for="bike_model">Модель велосипеда:</label> <input type="text" name="bike_model" required> <label for="frame_size_id">Размер рамы:</label> <select name="frame_size_id" required>

<?php while ($frame_size = $frame_sizes_result->fetch_assoc()): ?>

<option value="<?php echo $frame_size['frame_size_id']; ?>"><?php echo htmlspecialchars($frame_size['frame_size'], ENT_QUOTES, 'UTF-8'); ?></option>

<?php endwhile; ?> </select>

<label for="age_limit_id">Возрастное ограничение:</label> <select name="age_limit_id" required>

<?php while ($age_limit = $age_limits_result->fetch_assoc()): ?>

<option value="<?php echo $age_limit['age_limit_id']; ?>"><?php echo htmlspecialchars($age_limit['age_limit'], ENT_QUOTES, 'UTF-8'); ?></option>

<?php endwhile; ?> </select>

<label for="serial_number">Серийный номер:</label> <input type="text" name="serial_number" required> <label for="availability_id">Доступность:</label> <select name="availability_id" required>

<?php while ($availability = $availability_result->fetch_assoc()): ?>

<option value="<?php echo $availability['availability_id']; ?>"><?php echo htmlspecialchars($availability['status'], ENT_QUOTES, 'UTF-8'); ?></option>

<?php endwhile; ?> </select>

<label for="category_id">Категория:</label> <select name="category_id" required>

<?php while ($category = $categories_result->fetch_assoc()): ?>

<option value="<?php echo $category['category_id']; ?>"><?php echo htmlspecialchars($category['category_name'], ENT_QUOTES, 'UTF-8'); ?></option>

<?php endwhile; ?> </select>

<label for="photo">Фото велосипеда:</label> <input type="file" name="photo" accept="image/*">

<button type="submit">Добавить велосипед</button> </form>

<form method="POST" action="download_catalog.php"> <button type="submit">Скачать каталог в Excel</button>

</form>

<h3>Список велосипедов</h3>

<input type="text" id="searchInput" onkeyup="filterTable()" placeholder="Поиск велосипедов по модели..." style="marginbottom: 20px; width: 400px;">

<table id="bikesTable"> <thead>

<tr>

<th>ID</th> <th>Модель</th>

<th>Размер рамы</th> <th>Возрастное ограничение</th> <th>Серийный номер</th> <th>Доступность</th>

<th>Категория</th> <th>Фото</th> <th>Изменить</th> <th>Удалить</th>

</tr>

</thead>

<tbody>

<?php while ($bike = $bikes_result->fetch_assoc()): ?> <tr>

<td><?php echo htmlspecialchars($bike['bike_id'], ENT_QUOTES, 'UTF-8'); ?></td> <td>

<form method="POST" action="catalog_edit.php" enctype="multipart/form-data"> <input type="hidden" name="bike_id" value="<?php echo $bike['bike_id']; ?>">

<input type="text" name="bike_model" value="<?php echo htmlspecialchars($bike['bike_model'], ENT_QUOTES, 'UTF-8'); ?>">

112

</td>

<td>

<select name="frame_size_id"> <?php

$frame_sizes_result->data_seek(0); // Перемотка на начало результата while ($frame_size = $frame_sizes_result->fetch_assoc()): ?>

<option value="<?php echo $frame_size['frame_size_id']; ?>" <?php if ($frame_size['frame_size_id'] == $bike['frame_size_id']) echo 'selected'; ?>>

<?php echo htmlspecialchars($frame_size['frame_size'], ENT_QUOTES, 'UTF-8'); ?> </option>

<?php endwhile; ?> </select>

</td>

<td>

<select name="age_limit_id"> <?php

$age_limits_result->data_seek(0); // Перемотка на начало результата while ($age_limit = $age_limits_result->fetch_assoc()): ?>

<option value="<?php echo $age_limit['age_limit_id']; ?>" <?php if ($age_limit['age_limit_id'] == $bike['age_limit_id']) echo 'selected'; ?>>

<?php echo htmlspecialchars($age_limit['age_limit'], ENT_QUOTES, 'UTF-8'); ?> </option>

<?php endwhile; ?> </select>

</td>

<td><input type="text" name="serial_number" value="<?php echo htmlspecialchars($bike['serial_number'], ENT_QUOTES, 'UTF-8'); ?>"></td>

<td>

<select name="availability_id"> <?php

$availability_result->data_seek(0); // Перемотка на начало результата while ($availability = $availability_result->fetch_assoc()): ?>

<option value="<?php echo $availability['availability_id']; ?>" <?php if ($availability['availability_id'] == $bike['availability_id']) echo 'selected'; ?>>

<?php echo htmlspecialchars($availability['status'], ENT_QUOTES, 'UTF-8'); ?> </option>

<?php endwhile; ?> </select>

</td>

<td>

<select name="category_id"> <?php

$categories_result->data_seek(0); // Перемотка на начало результата while ($category = $categories_result->fetch_assoc()): ?>

<option value="<?php echo $category['category_id']; ?>" <?php if ($category['category_id'] == $bike['category_id']) echo 'selected'; ?>>

<?php echo htmlspecialchars($category['category_name'], ENT_QUOTES, 'UTF-8'); ?> </option>

<?php endwhile; ?> </select>

</td>

<td>

<?php if ($bike['photo']): ?>

<img src="data:image/jpeg;base64,<?php echo base64_encode($bike['photo']); ?>" alt="Фото велосипеда" style="max-width: 100px;">

<?php else: ?>

<span>Нет фото</span> <?php endif; ?>

<input type="file" name="photo" accept="image/*"> </td>

<td>

<button type="submit">Обновить</button> </form>

</td>

<td>

<form method="POST" action="catalog_edit.php" onsubmit="return confirm('Вы уверены, что хотите удалить этот велосипед?');">

<input type="hidden" name="bike_id" value="<?php echo $bike['bike_id']; ?>"> <input type="hidden" name="action" value="delete">

<button type="submit">Удалить</button>

113

</form>

</td>

</tr>

<?php endwhile; ?> </tbody>

</table>

</div>

</body>

</html>

<?php include 'footer.php'; ?>

7.Файл booking.php

Описание: Файл для оформления бронирования велосипедов. Он проверяет куки на наличие выбранных велосипедов, отображает форму для ввода данных бронирования и обрабатывает отправку формы, записывая данные о бронировании в базу данных.

<?php session_start(); include 'header.php';

include 'db.php'; // Подключение к базе данных

// Проверка, есть ли в куки информация о бронировании if (!isset($_COOKIE['bookings'])) {

header('Location: catalog.php'); exit();

}

$bookings = json_decode($_COOKIE['bookings'], true); if (empty($bookings)) {

header('Location: catalog.php'); exit();

}

// Получение информации о выбранных велосипедах из базы данных $bikeIds = implode(',', array_map('intval', $bookings));

$query = "SELECT bike_id, bike_model, serial_number FROM bikes WHERE bike_id IN ($bikeIds)"; $result = $conn->query($query);

$bikes = [];

while ($row = $result->fetch_assoc()) { $bikes[] = $row;

}

if ($_SERVER["REQUEST_METHOD"] == "POST") { // Обработка данных формы

if (!isset($_SESSION['user_id'])) {

header('Location: booking.php?error=Необходимо авторизоваться для оформления бронирования'); exit();

}

$user_id = $_SESSION['user_id'];

$start_date = $conn->real_escape_string($_POST['start_date']); $start_time = $conn->real_escape_string($_POST['start_time']); $end_date = $conn->real_escape_string($_POST['end_date']); $end_time = $conn->real_escape_string($_POST['end_time']);

$start_datetime = $start_date . ' ' . $start_time; $end_datetime = $end_date . ' ' . $end_time;

// Проверка доступности велосипедов из куки $availability_query = "SELECT BD.bike_id, BK.bike_model

FROM bookingdetails BD

JOIN bookings B ON BD.booking_id = B.booking_id JOIN bikes BK ON BD.bike_id = BK.bike_id WHERE BD.bike_id IN ($bikeIds)

AND B.status_id = 1

AND ((B.start_time <= '$start_datetime' AND B.end_time > '$start_datetime') OR (B.start_time < '$end_datetime' AND B.end_time >= '$end_datetime')

114

OR (B.start_time >= '$start_datetime' AND B.end_time <= '$end_datetime'))"; $availability_result = $conn->query($availability_query);

$unavailable_bikes = [];

while ($row = $availability_result->fetch_assoc()) { $unavailable_bikes[] = $row['bike_model'];

}

if (!empty($unavailable_bikes)) {

$error_message = "Следующие велосипеды недоступны на выбранные даты: " . implode(', ', $unavailable_bikes);

}else {

//Вставка данных о бронировании

$booking_query = "INSERT INTO bookings (user_id, start_time, end_time, status_id) VALUES ('$user_id', '$start_datetime', '$end_datetime', 1)";

if ($conn->query($booking_query) === TRUE) { $booking_id = $conn->insert_id;

//Вставка деталей бронирования foreach ($bikes as $bike) {

$bike_id = $bike['bike_id'];

$details_query = "INSERT INTO bookingdetails (booking_id, bike_id) VALUES ('$booking_id', '$bike_id')"; $conn->query($details_query);

}

//Обновление счетчика бронирований пользователя

$update_booking_count_query = "UPDATE users SET booking_count = booking_count + 1 WHERE user_id = '$user_id'"; $conn->query($update_booking_count_query);

// Очистка куки после бронирования setcookie('bookings', '', time() - 3600, '/'); header('Location: confirmation.php'); exit();

} else {

$error_message = "Ошибка при оформлении бронирования: " . $conn->error;

}

}

}

$conn->close(); ?>

<div class="container"> <h1>Оформление бронирования</h1>

<form class="form" action="booking.php" method="POST" id="booking-form"> <h3>Выбранные велосипеды</h3>

<ul id="bike-list">

<?php foreach ($bikes as $bike): ?>

<li class="bike-item" data-bike-id="<?php echo $bike['bike_id']; ?>">

<?php echo htmlspecialchars($bike['bike_model'], ENT_QUOTES, 'UTF-8'); ?> (Серийный номер: <?php echo htmlspecialchars($bike['serial_number'], ENT_QUOTES, 'UTF-8'); ?>)

<span class="remove-bike" onclick="removeBike(<?php echo $bike['bike_id']; ?>)">✖</span> </li>

<?php endforeach; ?> </ul>

<label for="start_date">Дата и время начала:</label>

<input type="date" id="start_date" name="start_date" required> <select id="start_time" name="start_time" required>

<?php for ($hour = 9; $hour <= 20; $hour++): ?>

<option value="<?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':00'; ?>"> <?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':00'; ?>

</option>

<option value="<?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':30'; ?>"> <?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':30'; ?>

</option> <?php endfor; ?>

</select>

<label for="end_date">Дата и время окончания:</label> <input type="date" id="end_date" name="end_date" required>

115

<select id="end_time" name="end_time" required> <?php for ($hour = 9; $hour <= 20; $hour++): ?>

<option value="<?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':00'; ?>"> <?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':00'; ?>

</option>

<option value="<?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':30'; ?>"> <?php echo str_pad($hour, 2, '0', STR_PAD_LEFT) . ':30'; ?>

</option> <?php endfor; ?>

</select>

<button type="submit" id="submit-button">Оформить бронирование</button> </form>

</div>

<script>

// Функция для удаления велосипеда из куки и DOM function removeBike(bikeId) {

let bookings = getCookie('bookings');

bookings = bookings ? JSON.parse(bookings) : []; bookings = bookings.filter(id => id !== bikeId);

//Если куки bookings пустые, удаляем их полностью if (bookings.length === 0) {

setCookie('bookings', '', -1); // Удаление куки } else {

setCookie('bookings', JSON.stringify(bookings), 7); // Сохранение на 7 дней

}

//Удаление элемента из DOM

document.querySelector(`li[data-bike-id="${bikeId}"]`).remove();

// Перезагрузка страницы, если все велосипеды удалены if (bookings.length === 0) {

location.reload();

}

}

//Функция для получения значения куки function getCookie(name) {

let matches = document.cookie.match(new RegExp(

"(?:^|; )" + name.replace(/([.$?*|{}()[]\/+^])/g, '\\$1') + "=([^;]*)"

));

return matches ? decodeURIComponent(matches[1]) : undefined;

}

//Функция для установки куки

function setCookie(name, value, days) { let expires = "";

if (days) {

let date = new Date();

date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = "; expires=" + date.toUTCString();

} else {

expires = "; expires=Thu, 01 Jan 1970 00:00:00 GMT";

}

document.cookie = name + "=" + (value || "") + expires + "; path=/";

}

// Ограничение выбора времени для начала и окончания бронирования function setDateTimeRestrictions() {

const now = new Date();

const tomorrow = new Date(now); tomorrow.setDate(tomorrow.getDate() + 1); const nextWeek = new Date(now); nextWeek.setDate(nextWeek.getDate() + 7);

const formatDate = (date) => {

return date.toISOString().slice(0, 10);

};

116

document.getElementById('start_date').setAttribute('min', formatDate(now)); document.getElementById('start_date').setAttribute('max', formatDate(nextWeek)); document.getElementById('end_date').setAttribute('min', formatDate(now)); document.getElementById('end_date').setAttribute('max', formatDate(nextWeek));

}

// Проверка доступности велосипедов function checkAvailability() {

const startDate = document.getElementById('start_date').value; const startTime = document.getElementById('start_time').value; const endDate = document.getElementById('end_date').value; const endTime = document.getElementById('end_time').value;

if (startDate && startTime && endDate && endTime) { const xhr = new XMLHttpRequest(); xhr.open('POST', 'check_availability.php', true);

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.onreadystatechange = function() {

if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) {

const response = JSON.parse(xhr.responseText);

const errorDiv = document.querySelector('.alert.alert-error'); if (errorDiv) {

errorDiv.remove();

}

if (!response.available) { document.getElementById('submit-button').disabled = true; let newErrorDiv = document.createElement('div'); newErrorDiv.className = 'alert alert-error';

newErrorDiv.textContent = 'Следующие велосипеды недоступны на выбранные даты: ' + response.unavailable_bikes.join(', ');

document.querySelector('.container').insertBefore(newErrorDiv, document.querySelector('form')); } else {

document.getElementById('submit-button').disabled = false;

}

}

}

};

xhr.send(`start_date=${startDate}&start_time=${startTime}&end_date=${endDate}&end_time=${endTime}&bike_ids=${JSON

.stringify(<?php echo json_encode($bookings); ?>)}`);

}

}

// Проверка авторизации и установка ограничений времени document.addEventListener('DOMContentLoaded', function() {

setDateTimeRestrictions();

<?php if (!isset($_SESSION['user_id'])): ?> document.getElementById('submit-button').disabled = true; let errorDiv = document.createElement('div'); errorDiv.className = 'alert alert-error';

errorDiv.textContent = 'Необходимо авторизоваться для оформления бронирования'; document.querySelector('.container').insertBefore(errorDiv, document.querySelector('form'));

<?php endif; ?>

// Добавление обработчиков событий для полей даты и времени document.getElementById('start_date').addEventListener('change', checkAvailability); document.getElementById('start_time').addEventListener('change', checkAvailability); document.getElementById('end_date').addEventListener('change', checkAvailability); document.getElementById('end_time').addEventListener('change', checkAvailability);

});

</script>

</body>

</html>

8. Файл check_availability.php

117

Описание: Этот файл обрабатывает AJAX-запросы для проверки доступности велосипедов на выбранные даты. Он используется в форме бронирования для проверки наличия велосипедов.

<?php

include 'db.php'; // Подключение к базе данных

$start_date = $conn->real_escape_string($_POST['start_date']); $start_time = $conn->real_escape_string($_POST['start_time']); $end_date = $conn->real_escape_string($_POST['end_date']); $end_time = $conn->real_escape_string($_POST['end_time']); $bike_ids = json_decode($_POST['bike_ids'], true);

$start_datetime = $start_date . ' ' . $start_time; $end_datetime = $end_date . ' ' . $end_time;

$bikeIds = implode(',', array_map('intval', $bike_ids));

// Проверка доступности велосипедов из куки, учитывая статус бронирования (status_id = 1) $availability_query = "SELECT BD.bike_id, BK.bike_model

FROM bookingdetails BD

JOIN bookings B ON BD.booking_id = B.booking_id JOIN bikes BK ON BD.bike_id = BK.bike_id WHERE BD.bike_id IN ($bikeIds)

AND B.status_id = 1

AND ((B.start_time <= '$start_datetime' AND B.end_time > '$start_datetime') OR (B.start_time < '$end_datetime' AND B.end_time >= '$end_datetime')

OR (B.start_time >= '$start_datetime' AND B.end_time <= '$end_datetime'))"; $availability_result = $conn->query($availability_query);

$unavailable_bikes = [];

while ($row = $availability_result->fetch_assoc()) { $unavailable_bikes[] = $row['bike_model'];

}

$response = [

'available' => empty($unavailable_bikes), 'unavailable_bikes' => $unavailable_bikes

];

echo json_encode($response);

$conn->close(); ?>

9. Файл login_process.php

Описание: Файл обрабатывает данные формы входа. Он проверяет наличие пользователя в базе данных, сверяет пароль и устанавливает сессию для авторизованного пользователя. В зависимости от роли пользователя, он перенаправляется на соответствующую страницу.

<?php

include 'db.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") { $email = $conn->real_escape_string($_POST['email']);

$password = $conn->real_escape_string($_POST['password']);

$query = "SELECT * FROM Users WHERE email='$email'"; $result = $conn->query($query);

if ($result->num_rows == 1) { $user = $result->fetch_assoc();

if (password_verify($password, $user['password_hash'])) { session_start();

$_SESSION['user_id'] = $user['user_id'];

118

$_SESSION['username'] = $user['username']; $_SESSION['role_id'] = $user['role_id'];

switch ($user['role_id']) { case 1:

header("Location: admin_profile.php?success=Вы успешно вошли в систему."); break;

case 2:

header("Location: profile.php?success=Вы успешно вошли в систему."); break;

case 3:

header("Location: manager_profile.php?success=Вы успешно вошли в систему."); break;

default:

header("Location: login.php?error=Неизвестная роль пользователя.");

}

} else {

header("Location: login.php?error=Неверный пароль.");

}

} else {

header("Location: login.php?error=Пользователь с таким email не найден.");

}

}

$conn->close(); ?>

10.Файл registration.php

Описание: Этот файл отображает форму регистрации нового пользователя. В нем также

показываются оповещения об ошибках или успехах регистрации.

<?php

include 'header.php'; include 'db.php';

// Показ оповещений

if (isset($_GET['error'])) {

echo '<div class="alert alert-error">' . htmlspecialchars($_GET['error']) . '</div>';

}

if (isset($_GET['success'])) {

echo '<div class="alert alert-success">' . htmlspecialchars($_GET['success']) . '</div>';

}

?>

<div class="registration-container"> <h1>Регистрация</h1>

<form action="register_process.php" method="POST" class="form"> <label for="username">Имя пользователя:</label>

<input type="text" id="username" name="username" required>

<label for="email">Электронная почта:</label>

<input type="email" id="email" name="email" required>

<label for="phone_number">Номер телефона:</label>

<input type="text" id="phone_number" name="phone_number">

<label for="password">Пароль:</label>

<input type="password" id="password" name="password" required>

<label for="confirm_password">Подтвердите пароль:</label>

<input type="password" id="confirm_password" name="confirm_password" required>

<button type="submit">Зарегистрироваться</button> </form>

</div>

<?php include 'footer.php'; ?>

119

</body>

</html>

11.Файл register_process.php

Описание: Файл обрабатывает данные формы регистрации. Он проверяет корректность введенных данных, хеширует пароль и записывает данные нового пользователя в базу данных.

<?php

include 'header.php'; include 'db.php';

// Показ оповещений

if (isset($_GET['error'])) {

echo '<div class="alert alert-error">' . htmlspecialchars($_GET['error']) . '</div>';

}

if (isset($_GET['success'])) {

echo '<div class="alert alert-success">' . htmlspecialchars($_GET['success']) . '</div>';

}

?>

<div class="registration-container"> <h1>Регистрация</h1>

<form action="register_process.php" method="POST" class="form"> <label for="username">Имя пользователя:</label>

<input type="text" id="username" name="username" required>

<label for="email">Электронная почта:</label>

<input type="email" id="email" name="email" required>

<label for="phone_number">Номер телефона:</label>

<input type="text" id="phone_number" name="phone_number">

<label for="password">Пароль:</label>

<input type="password" id="password" name="password" required>

<label for="confirm_password">Подтвердите пароль:</label>

<input type="password" id="confirm_password" name="confirm_password" required>

<button type="submit">Зарегистрироваться</button> </form>

</div>

<?php include 'footer.php'; ?> </body>

</html>

12.Файл statistics_manager.php

Описание: Файл предназначен для менеджеров и администраторов. Он позволяет формировать отчеты по бронированиям за выбранный период и, при необходимости,

скачивать эти отчеты в формате Excel.

<?php

include 'header_adm.php'; include 'db.php';

//Проверка роли пользователя if ($_SESSION['role_id'] != 3) { header("Location: login.php");

exit();

}

//Инициализация переменных для сообщений $message = '';

$error = '';

120

// Обработка запроса на формирование отчета $report_data = [];

if ($_SERVER["REQUEST_METHOD"] == "POST" && (isset($_POST['generate_report']) || isset($_POST['download_excel'])))

{

$report_type = $_POST['report_type']; $start_date = $_POST['start_date']; $end_date = $_POST['end_date']; $user_id = $_POST['user_id']; $status_id = $_POST['status_id'];

// Проверка корректности введенных данных if (empty($start_date) || empty($end_date)) {

$error = 'Пожалуйста, укажите оба периода для отчета.';

} elseif ($start_date > $end_date) {

$error = 'Дата начала не может быть позже даты окончания.';

} else { $conditions = [];

$conditions[] = "B.start_time BETWEEN '$start_date' AND '$end_date'"; if ($user_id) {

$conditions[] = "B.user_id = $user_id";

}

if ($status_id) {

$conditions[] = "B.status_id = $status_id";

}

$where_clause = implode(' AND ', $conditions);

if ($report_type == 'bookings') {

$report_query = "SELECT B.booking_id, B.start_time, B.end_time, U.username, BS.status_name, GROUP_CONCAT(DISTINCT BK.bike_model SEPARATOR ', ') AS bike_models

FROM bookings B

LEFT JOIN users U ON B.user_id = U.user_id

LEFT JOIN bookingstatus BS ON B.status_id = BS.status_id LEFT JOIN bookingdetails BD ON B.booking_id = BD.booking_id LEFT JOIN bikes BK ON BD.bike_id = BK.bike_id

WHERE $where_clause GROUP BY B.booking_id";

$result = $conn->query($report_query); while ($row = $result->fetch_assoc()) {

$report_data[] = $row;

}

if (empty($report_data)) {

$message = 'Нет данных о бронированиях за указанный период.';

}elseif (isset($_POST['download_excel'])) {

//Создание Excel документа

header('Content-Type: application/vnd.ms-excel');

header('Content-Disposition: attachment; filename="booking_report_' . date('Ymd') . '.xls"');

echo "ID бронирования\tНачало\tКонец\tПользователь\tСтатус\tВелосипеды\n"; foreach ($report_data as $data) {

echo $data['booking_id'] . "\t" . $data['start_time'] . "\t" . $data['end_time'] . "\t" . $data['username'] . "\t" . $data['status_name'] . "\t" . $data['bike_models'] . "\n";

}

exit();

}

}

}

}

// Получение списка пользователей для фильтра $users_query = "SELECT user_id, username FROM users"; $users_result = $conn->query($users_query);

// Получение списка статусов бронирования для фильтра $status_query = "SELECT status_id, status_name FROM bookingstatus"; $status_result = $conn->query($status_query);

$conn->close(); ?>

<!DOCTYPE html>