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

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

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

121

<html lang="ru"> <head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Формирование отчетности</title>

<link rel="stylesheet" href="css/styles.css"> </head>

<body>

<div class="manager-container">

<h2>Формирование отчетности</h2>

<?php if (!empty($message)): ?>

<div class="alert alert-success"><?php echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'); ?></div> <?php endif; ?>

<?php if (!empty($error)): ?>

<div class="alert alert-error"><?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8'); ?></div> <?php endif; ?>

<form method="POST" action="statistics_manager.php"> <label for="report_type">Тип отчета:</label>

<select name="report_type" id="report_type" required>

<option value="bookings">Отчет по бронированиям</option> <!-- Добавить другие типы отчетов при необходимости -->

</select>

<label for="start_date">Дата начала:</label>

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

<input type="date" name="end_date" id="end_date" required> <label for="user_id">Пользователь:</label>

<select name="user_id" id="user_id">

<option value="">Все пользователи</option>

<?php while ($user = $users_result->fetch_assoc()): ?>

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

<?php endwhile; ?> </select>

<label for="status_id">Статус бронирования:</label> <select name="status_id" id="status_id">

<option value="">Все статусы</option>

<?php while ($status = $status_result->fetch_assoc()): ?>

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

<?php endwhile; ?> </select>

<button type="submit" name="generate_report">Сформировать отчет</button>

<button type="submit" name="download_excel" style="margin-top: 10px;">Скачать отчет в Excel</button> </form>

<?php if (!empty($report_data) && !isset($_POST['download_excel'])): ?>

<h3>Результаты отчета</h3>

<table>

<thead>

<tr>

<th>ID бронирования</th> <th>Начало</th> <th>Конец</th> <th>Пользователь</th> <th>Статус</th> <th>Велосипеды</th>

</tr>

</thead>

<tbody>

<?php foreach ($report_data as $data): ?> <tr>

<td><?php echo htmlspecialchars($data['booking_id'], ENT_QUOTES, 'UTF-8'); ?></td> <td><?php echo htmlspecialchars($data['start_time'], ENT_QUOTES, 'UTF-8'); ?></td> <td><?php echo htmlspecialchars($data['end_time'], ENT_QUOTES, 'UTF-8'); ?></td> <td><?php echo htmlspecialchars($data['username'], ENT_QUOTES, 'UTF-8'); ?></td> <td><?php echo htmlspecialchars($data['status_name'], ENT_QUOTES, 'UTF-8'); ?></td> <td><?php echo htmlspecialchars($data['bike_models'], ENT_QUOTES, 'UTF-8'); ?></td>

</tr>

<?php endforeach; ?>

122

</tbody>

</table> <?php endif; ?>

</div>

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

</html>

13.Файл profile.php

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

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

// Проверка, что пользователь авторизован if (!isset($_SESSION['user_id'])) {

header("Location: login.php?error=Пожалуйста, войдите в систему."); exit();

}

$user_id = $_SESSION['user_id'];

// Обработка отмены бронирования

if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['cancel_booking_id'])) { $cancel_booking_id = (int)$_POST['cancel_booking_id'];

$cancel_query = "UPDATE bookings SET status_id = 2 WHERE booking_id = $cancel_booking_id AND user_id = $user_id"; $conn->query($cancel_query);

}

// Обработка обратной связи

if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['feedback_booking_id'])) { $feedback_booking_id = (int)$_POST['feedback_booking_id'];

$rating = (int)$_POST['rating'];

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

$feedback_query = "INSERT INTO feedback (user_id, booking_id, rating, comment) VALUES ($user_id, $feedback_booking_id, $rating, '$comment')";

$conn->query($feedback_query); header("Location: profile.php"); exit();

}

// Отложить отзыв

if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['postpone_feedback'])) { $_SESSION['postpone_feedback'] = true;

header("Location: profile.php"); exit();

}

// Получение информации о пользователе

$user_query = "SELECT username, email, phone_number, booking_count FROM users WHERE user_id = $user_id"; $user_result = $conn->query($user_query);

$user = $user_result->fetch_assoc();

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

$bookings_query = "SELECT B.booking_id, B.start_time, B.end_time, BS.status_name FROM bookings B

LEFT JOIN bookingstatus BS ON B.status_id = BS.status_id WHERE B.user_id = $user_id";

$bookings_result = $conn->query($bookings_query);

// Проверка наличия завершенных бронирований

$completed_booking_query = "SELECT booking_id FROM bookings WHERE user_id = $user_id AND status_id = 3"; $completed_booking_result = $conn->query($completed_booking_query);

123

$completed_booking = $completed_booking_result->fetch_assoc();

// Проверка наличия уже существующего отзыва

$existing_feedback_query = "SELECT feedback_id FROM feedback WHERE user_id = $user_id AND booking_id = " . (isset($completed_booking['booking_id']) ? $completed_booking['booking_id'] : 'NULL');

$existing_feedback_result = $conn->query($existing_feedback_query); $existing_feedback = $existing_feedback_result->fetch_assoc();

?>

<div class="profile-container"> <h1>Личный кабинет</h1> <div class="user-info">

<h2>Информация о пользователе</h2>

<p><strong>Имя пользователя:</strong> <?php echo htmlspecialchars($user['username'], ENT_QUOTES, 'UTF-8'); ?></p> <p><strong>Электронная почта:</strong> <?php echo htmlspecialchars($user['email'], ENT_QUOTES, 'UTF-8'); ?></p> <p><strong>Номер телефона:</strong> <?php echo htmlspecialchars($user['phone_number'], ENT_QUOTES, 'UTF-8');

?></p>

<p><strong>Количество бронирований:</strong> <?php echo htmlspecialchars($user['booking_count'], ENT_QUOTES, 'UTF-8'); ?></p>

</div>

<div class="user-bookings"> <h2>Мои бронирования</h2>

<?php if ($bookings_result->num_rows > 0): ?> <ul>

<?php while($booking = $bookings_result->fetch_assoc()): ?> <li>

<p><strong>ID бронирования:</strong> <?php echo htmlspecialchars($booking['booking_id'], ENT_QUOTES, 'UTF-8'); ?></p>

<p><strong>Начало:</strong> <?php echo htmlspecialchars($booking['start_time'], ENT_QUOTES, 'UTF-8');

?></p>

<p><strong>Конец:</strong> <?php echo htmlspecialchars($booking['end_time'], ENT_QUOTES, 'UTF-8');

?></p>

<p><strong>Статус:</strong> <?php echo htmlspecialchars($booking['status_name'], ENT_QUOTES, 'UTF-8');

?></p>

<p><strong>Велосипеды:</strong></p> <ul>

<?php

$bike_query = "SELECT BK.bike_model, BK.serial_number, BK.photo FROM bookingdetails BD

JOIN bikes BK ON BD.bike_id = BK.bike_id WHERE BD.booking_id = " . $booking['booking_id'];

$bike_result = $conn->query($bike_query); while($bike = $bike_result->fetch_assoc()): ?>

<li style="width: 300px; display: inline-block;">

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

?></p>

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

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

<?php endif; ?> </li>

<?php endwhile; ?> </ul>

<?php if ($booking['status_name'] != 'Отменено'): ?> <form method="POST" action="profile.php">

<input type="hidden" name="cancel_booking_id" value="<?php echo $booking['booking_id']; ?>"> <button type="submit">Отменить</button>

</form> <?php endif; ?>

</li>

<?php endwhile; ?> </ul>

<?php else: ?>

<p>У вас нет активных бронирований.</p>

<?php endif; ?> </div>

</div>

124

<?php if ($completed_booking && !isset($_SESSION['postpone_feedback']) && !$existing_feedback): ?> <div id="feedback-notification" class="feedback-notification">

<div class="feedback-content">

<span class="close-btn" onclick="closeFeedback()">×</span>

<p>У вас есть завершенное бронирование. Пожалуйста, оставьте отзыв!</p> <form method="POST" action="profile.php">

<input type="hidden" name="feedback_booking_id" value="<?php echo $completed_booking['booking_id']; ?>"> <label for="rating">Оценка:</label>

<div class="stars">

<input type="radio" name="rating" class="star-1" id="star-1" value="1"> <label class="star" for="star-1"> </label>

<input type="radio" name="rating" class="star-2" id="star-2" value="2"> <label class="star" for="star-2"> </label>

<input type="radio" name="rating" class="star-3" id="star-3" value="3"> <label class="star" for="star-3"> </label>

<input type="radio" name="rating" class="star-4" id="star-4" value="4"> <label class="star" for="star-4"> </label>

<input type="radio" name="rating" class="star-5" id="star-5" value="5"> <label class="star" for="star-5"> </label>

</div>

<br>

<label for="comment" style="margin-top: 0px;">Комментарий:</label>

<textarea id="comment" name="comment" required style="height: 100px;"></textarea> <br>

<button type="submit">Отправить отзыв</button> </form>

</div>

</div>

<script>

function closeFeedback() { document.getElementById('feedback-notification').style.display = 'none';

}

window.onload = function() {

var notification = document.getElementById('feedback-notification'); notification.style.display = 'block';

}

document.querySelectorAll('.stars input').forEach((input) => { input.addEventListener('change', (e) => {

let value = e.target.value;

document.querySelectorAll('.stars label').forEach((label, index) => { if (index < value) {

label.style.color = 'gold'; } else {

label.style.color = 'gray';

}

});

});

});

</script> <?php endif; ?>

<style>

.feedback-notification { display: none; position: fixed;

top: 50%; left: 50%;

transform: translate(-50%, -50%); background: #f9f9f9;

padding: 20px;

box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); z-index: 1000;

}

.feedback-content { position: relative; max-width: 400px; text-align: center;

}

125

.close-btn { position: absolute; top: 10px;

right: 10px; font-size: 24px; cursor: pointer;

}

.feedback-notification form { display: flex; flex-direction: column; gap: 10px;

}

.stars { display: flex;

justify-content: center; gap: 5px;

}

.stars input[type="radio"] { display: none;

}

.stars label { font-size: 30px; color: gray; cursor: pointer;

}

</style>

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

</html>

126

Приложение Е

Руководство пользователя

Содержание:

1.Введение

2.Регистрация и вход

3.Использование системы

a.Главная страница

b.Просмотр каталога

c.Бронирование велосипедов

d.Личный кабинет

4.Административные функции

a.Панель администратора

b.Панель менеджера

5.Отчеты и статистика

1.Введение

Добро пожаловать в систему RIDE-RENT! Эта система предназначена для управления арендой велосипедов, позволяя пользователям бронировать велосипеды, а администраторам и менеджерам — управлять каталогом велосипедов и отслеживать бронирования.

2. Регистрация и вход

Регистрация

Перейдите на страницу регистрации, кликнув по ссылке "Регистрация" в верхней навигации (рис. 1).

Рисунок 1 – Ссылка на Регистрацию

127

Заполните форму, указав имя пользователя, адрес электронной почты, номер телефона

(необязательно) и пароль.

Нажмите кнопку "Зарегистрироваться"(рис. 2).

Рисунок 2 – Кнопка «Зарегистрироваться» Если все данные введены корректно, вы увидите сообщение об успешной регистрации.

Теперь вы можете войти в систему.

Вход

Перейдите на страницу входа, кликнув по ссылке "Вход" в верхней навигации (рис. 3).

Рисунок 3 – Ссылка на Вход Введите ваш адрес электронной почты и пароль.

Нажмите кнопку "Войти" (рис. 4).

Рисунок 4 – Кнопка «Войти»

128

После успешного входа вы будете перенаправлены на главную страницу или в личный кабинет, в зависимости от вашей роли.

3. Использование системы

Главная страница

На главной странице вы можете найти основную информацию о сервисе RIDE-RENT.

Здесь также можно быстро перейти к каталогу велосипедов или в личный кабинет.

Просмотр каталога

Перейдите на страницу каталога, кликнув по ссылке "Каталог" в верхней навигации

(рис. 5).

Рисунок 5 – Ссылка на Каталог Используйте фильтры, чтобы отфильтровать велосипеды по размеру рамы,

возрастному ограничению, доступности и категории.

Нажмите кнопку "Фильтровать", чтобы применить фильтры (рис. 6).

Рисунок 6 – Кнопка «Фильтровать» в каталоге В каталоге будут отображены доступные велосипеды с информацией о модели,

категории, статусе и других параметрах.

Для бронирования велосипеда нажмите кнопку "Бронировать" рядом с нужным велосипедом (рис. 7).

129

Рисунок 7 – Кнопка «Бронировать» в каталоге

Бронирование велосипедов

Добавьте велосипеды в бронирование, нажимая кнопку "Бронировать" в каталоге.

Перейдите на страницу бронирования, кликнув по ссылке "Перейти к бронированию"

в верхней навигации (рис. 8).

Рисунок 8 – Ссылка на переход к Бронированию Убедитесь, что выбранные велосипеды отображаются в списке.

Укажите дату и время начала и окончания аренды (рис. 9, 10).

130

Рисунок 9 – Выбор начала бронирования

Рисунок 10 – Выбор времени бронирования

Нажмите кнопку "Оформить бронирование".

После успешного оформления бронирования вы увидите сообщение о подтверждении.

Личный кабинет

Перейдите в личный кабинет, кликнув по ссылке "Личный кабинет" в верхней навигации (рис. 11).