diff --git a/app/__init__.py b/app/__init__.py index b23450fd49841704df43f06d02e82ca50cadabfc..f5f2f36bb3cd9042159829fc603443bebd7a56fc 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -96,7 +96,6 @@ def create_app(config_class=Config): db_user = os.getenv("DATABASE_USER") db_password = os.getenv("DATABASE_PASSWORD") db_name = os.getenv("DATABASE_NAME") - create_database_if_not_exists(db_host, db_user, db_password, db_name) app.config['SECRET_KEY'] = os.getenv('SECRET_KEY') diff --git a/app/admin/routes.py b/app/admin/routes.py index 4668cfa26e5d93761e02220e541a45ef1cce535b..8d9259b4faf8ddea6e2d201121fd571dd1d22317 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -94,7 +94,9 @@ def manage_users(): @bp.route('/manage_user_bookings') @permission_required(admin_permission) def manage_user_bookings(): - return render_template('admin/index.html') + bookings = Bookings.get_all_bookings_with_user_table() + locations = Listings.get_all_locations(True) + return render_template('admin/manage_user_bookings.html', bookings=bookings, locations=locations) @bp.route('update_booking/<int:id>', methods=['POST']) diff --git a/app/models/bookings.py b/app/models/bookings.py index 7c9665dbb160d5c0cb3d8460ad094d08eba29ae5..ef33b378b804cc2d92c78678fa3d62676f981b57 100644 --- a/app/models/bookings.py +++ b/app/models/bookings.py @@ -3,6 +3,7 @@ from flask_login import UserMixin from app.logger import error_logger from datetime import datetime from sqlalchemy.orm import relationship +from app.models import User class Bookings(UserMixin, db.Model): __tablename__ = 'bookings' @@ -74,4 +75,11 @@ class Bookings(UserMixin, db.Model): @classmethod def get_all_bookings(cls): - return cls.query.all() \ No newline at end of file + return cls.query.all() + + @classmethod + def get_all_bookings_with_user_table(cls): + return cls.query.join(User, cls.user_id == User.id).add_columns( + User.username + ).all() + diff --git a/app/templates/admin/manage_user_bookings.html b/app/templates/admin/manage_user_bookings.html new file mode 100644 index 0000000000000000000000000000000000000000..ca082b0260c81a7589bd8e10e82f1f667fab917f --- /dev/null +++ b/app/templates/admin/manage_user_bookings.html @@ -0,0 +1,110 @@ +{% extends 'base.html' %} +{% block content %} +<div class="container my-4"> + <div class="d-flex justify-content-between mb-3"> + <h2>Manage Bookings</h2> + </div> + + <div class="table-container"> + <table id="manage_bookings" class="table table-striped table-bordered display hover" style="width:100%"> + <thead> + <tr> + <th>Booking ID</th> + <th>User Name</th> + <th>Booking Date</th> + <th>Departure Date</th> + <th>Departure Location</th> + <th>Destination Location</th> + <th>Cancelled</th> + <th>View Booking</th> + </tr> + </thead> + <tbody> + {% for booking in bookings %} + <tr> + <td>{{ booking.Bookings.id }}</td> + <td>{{ booking.username }}</td> + <td>{{ booking.Bookings.booking_date.strftime("%a, %d %b %Y") }}</td> + <td>{{ booking.Bookings.depart_date.strftime("%a, %d %b %Y") }}</td> + <td>{{ booking.Bookings.listing.depart_location }}</td> + <td>{{ booking.Bookings.listing.destination_location }}</td> + <td>{{ 'Yes' if booking.Bookings.cancelled else 'No' }}</td> + <td class="dt-center"> + <a class="btn btn-secondary view-booking-btn" href="manage_bookings/view/{{ booking.Bookings.id }}">View Booking</a> + </td> + </tr> + {% endfor %} + </tbody> + </table> + </div> +</div> +<style> + .table-container { + width: 100%; + overflow-x: auto; + overflow-y: hidden; + } + + @media (max-width: 800px) { + .table-container { + padding: 0 10px; + } + } + + .dataTables_wrapper { + width: 100%; + } + + table.dataTable.no-footer { + margin-bottom: 30px; + } +</style> +<script> + $(document).ready(function() { + $('.select2-multiple').select2({ + placeholder: "Select locations", + width: '100%' + }); + + $('.select2-dropdown').select2({ + placeholder: "Select a date", + width: '100%', + minimumResultsForSearch: Infinity + }); + + const locations = JSON.parse('{{ locations|tojson|safe }}'); + locations.forEach(location => { + $('#depart_location').append(new Option(location, location)); + $('#destination_location').append(new Option(location, location)); + }); + + // Load table + const table = $('#manage_bookings').DataTable({ + pageLength: 10, + lengthChange: false, + columns: [ + { data: 'id', visible: false }, // Hidden id column + { data: 'username' }, + { data: 'booking_date' }, + { data: 'depart_date' }, + { data: 'depart_location' }, + { data: 'destination_location' }, + { data: 'cancelled' }, + { + data: null, + className: "dt-center", + defaultContent: ` + <a class="btn btn-secondary view-booking-btn" href="#">View Booking</a> + ` + } + ], + language: { + emptyTable: "No bookings could be found." + }, + createdRow: function(row, data, dataIndex) { + $(row).find('.view-booking-btn').attr('href', `manage_bookings/view/${data.id}`); + } + }); + }); +</script> +{% endblock %} diff --git a/docker-compose.yml b/docker-compose.yml index 8b59898d9dd3d9bfab2de75e76aaf6fee78ab02e..ee18fba7b9d133dfc86afb8fb09f6f98d3063396 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,7 +3,7 @@ services: image: flask build: context: . - dockerfile: Dockerfile + dockerfile: ./Dockerfile stop_signal: SIGINT ports: - '5000:5000'