From 31ec2a50963cba014965b159b0b7556cda0bd89d Mon Sep 17 00:00:00 2001
From: Ethan-clay03 <ethanclay2017@gmail.com>
Date: Mon, 10 Feb 2025 19:31:06 +0000
Subject: [PATCH] Begin to add book now route

---
 app/bookings/routes.py              | 56 +++++++++++++++++------
 app/templates/bookings/listing.html | 70 +++++++++++++++++++++++------
 2 files changed, 99 insertions(+), 27 deletions(-)

diff --git a/app/bookings/routes.py b/app/bookings/routes.py
index c032fc7..d5ef06a 100644
--- a/app/bookings/routes.py
+++ b/app/bookings/routes.py
@@ -1,4 +1,4 @@
-from flask import render_template, redirect, url_for, request, jsonify, session
+from flask import render_template, redirect, url_for, request, jsonify, session, flash
 from app.bookings import bp
 from app.models import Listings
 from app import db
@@ -56,18 +56,48 @@ def listings():
 @bp.route('/listing/apply_update', methods=['POST'])
 def listing_apply_update(): 
     data = request.get_json()
-    if 'date' not in data:
-        return jsonify({'error': 'Invalid request'}), 400
-
-    depart_date = data['date']
-    try:
-        discount, days_away = calculate_discount(depart_date)
-        return jsonify({'discount': discount, 'days_away': days_away}), 200
-
-    except ValueError:
-        error_logger.error("Invalid date format, the data passed was: " + data)
-        return jsonify({'error': 'Invalid date format'}), 400
-
+    selected_date = data.get('date')
+    discount, days_away = calculate_discount(selected_date)
+
+    response = {
+        'discount': discount,
+        'days_away': days_away
+    }
+    return jsonify(response)
+
+@bp.route('/checkout')
+def checkout(): 
+    if not session['checkout_cache']:
+        flash("Please select a booking", 'error')
+    depart_date = request.args.get('date')
+    num_seats = request.args.get('seats')
+    listing_id = request.args.get('listing_id')
+
+    session['checkout_cache'] = {
+        'depart_date': depart_date,
+        'num_seats': num_seats,
+        'listing_id': listing_id
+    }
+
+    return redirect(url_for('bookings.checkout'))
+
+@bp.route('/payment')
+def payment(): 
+    depart_date = request.args.get('date')
+    num_seats = request.args.get('seats')
+    listing_id = request.args.get('listing_id')
+
+    if not depart_date or not num_seats or not listing_id:
+        flash('Please select a booking in order to checkout.', 'error')
+        return redirect(url_for('bookings.listings'))
+
+    session['checkout_cache'] = {
+        'depart_date': depart_date,
+        'num_seats': num_seats,
+        'listing_id': listing_id
+    }
+
+    return redirect(url_for('bookings.checkout'))
 
 @bp.route('/show_listing/<int:id>', methods=['GET'])
 def show_listing_dirty(id):
diff --git a/app/templates/bookings/listing.html b/app/templates/bookings/listing.html
index e9d27c2..665438b 100644
--- a/app/templates/bookings/listing.html
+++ b/app/templates/bookings/listing.html
@@ -14,12 +14,21 @@
                 <i class="fa-solid fa-rotate-right"></i> Reset Date
             </button>
         </div>
-        <div class="text-end mb-3">
-            <button type="button" class="btn btn-primary me-2" data-bs-toggle="modal" data-bs-target="#filterModal">
-                <i class="fa-solid fa-filter"></i> Filter
-            </button>
+
+        <div class="col-md-6 text-start mb-3 d-flex align-items-center flex-md-nowrap flex-wrap">
+            <label class="form-label me-2">Number of Seats:</label>
+            <div class="col-md-6">
+                <select class="form-select" id="numSeats" name="numSeats">
+                    <option value="1">1</option>
+                    <option value="2">2</option>
+                    <option value="3">3</option>
+                    <option value="4">4</option>
+                    <option value="5">5</option>
+                </select>
+            </div>
         </div>
     </div>
+    <h2 class="mb-4" style="text-align: center; margin-top: 40px;">Booking Details</h2>
     <div class="row">
         <div class="col-md-6">
             <div class="card mb-4">
@@ -50,6 +59,15 @@
             </p>
         </div>
     </div>
+    <div class="card mb-4">
+        <div class="card-body">
+            <h2 class="card-title">Total Cost</h2>
+            <p><strong>Cost Per Person:</strong> {{ listing.transport_type }}</p>
+            <p><strong>Total Cost:</strong> £<span id="totalCost">{{ listing.fair_cost }}</span></p>
+            <p><strong>Total Saved:</strong> £<span id="totalSaved">0.00</span></p>
+
+        </div>
+    </div>
     <div class="text-center">
         <button class="btn btn-secondary btn-lg" id="bookButton" {% if not current_user.is_authenticated %}disabled{% endif %}>
             Book Now
@@ -71,6 +89,7 @@ $(document).ready(function () {
     const resetDateButton = document.getElementById('resetDate');
     const today = new Date().toISOString().split('T')[0];
     const departDateInput = document.getElementById('departDate');
+    const numSeatsInput = document.getElementById('numSeats');
 
     if (!filterDataDepartDate) {
         departDateInput.value = today;
@@ -94,15 +113,16 @@ $(document).ready(function () {
         event.preventDefault();
     });
 
-    // Send the updated date to the server to check for discounts
-    departDateInput.addEventListener('change', (event) => {
-        const newDate = event.target.value;
+    // Send the updated date and number of seats to the server to check for discounts and calculate total cost
+    function updateData() {
+        const newDate = departDateInput.value;
+        const numSeats = numSeatsInput.value;
 
         $.ajax({
             url: "{{ url_for('bookings.listing_apply_update') }}",
             type: 'POST',
             contentType: 'application/json',
-            data: JSON.stringify({ date: newDate }),
+            data: JSON.stringify({ date: newDate, seats: numSeats }),
             success: function (data) {
                 const discountBanner = document.getElementById('discountBanner');
                 const originalPrice = document.getElementById('originalPrice');
@@ -110,15 +130,19 @@ $(document).ready(function () {
                 const discountedPriceValue = document.getElementById('discountedPriceValue');
                 const discountPercent = document.getElementById('discountPercent');
                 const daysAway = document.getElementById('daysAway');
+                const totalCost = document.getElementById('totalCost');
+                const totalSaved = document.getElementById('totalSaved');
 
-                if (data.discount) {
-                    const originalPriceValue = parseFloat(originalPrice.textContent.replace('£', ''));
-                    const discountValue = originalPriceValue * (1 - data.discount / 100);
+                const originalPriceValue = parseFloat(originalPrice.textContent.replace('£', ''));
+                let discountValue = originalPriceValue;
+                let finalPrice = originalPriceValue;
 
+                // Run calculations on front end, they match backend and simply are for show. This controls the banner at the top for discounts
+                if (data.discount) {
+                    discountValue = originalPriceValue * (1 - data.discount / 100);
                     originalPrice.style.textDecoration = 'line-through';
                     discountedPriceValue.textContent = `${discountValue.toFixed(2)}`;
                     discountedPrice.style.display = 'block';
-
                     discountBanner.style.display = 'block';
                     discountPercent.textContent = data.discount;
                     daysAway.textContent = data.days_away;
@@ -127,17 +151,35 @@ $(document).ready(function () {
                     discountedPrice.style.display = 'none';
                     discountBanner.style.display = 'none';
                 }
+
+                // Update total cost div
+                finalPrice = discountValue * numSeats;
+                totalCost.textContent = `${finalPrice.toFixed(2)}`;
+                totalSaved.textContent = `${(originalPriceValue * numSeats - finalPrice).toFixed(2)}`;
             },
             error: function () {
                 alert('Error applying discount. Please try again.');
             }
         });
-    });
+    }
+
+    departDateInput.addEventListener('change', updateData);
+    numSeatsInput.addEventListener('change', updateData);
 
     // Trigger the change event to apply the initial discount if a date is selected
     if (filterDataDepartDate) {
-        departDateInput.dispatchEvent(new Event('change'));
+        updateData();
     }
+
+    // Handle "Book Now" button click
+    bookButton.addEventListener('click', () => {
+        const departDate = departDateInput.value;
+        const numSeats = numSeatsInput.value;
+        const listingId = "{{listing.id}}";
+
+        window.location.href = `{{ url_for('bookings.payment') }}?date=${departDate}&seats=${numSeats}&listing_id=${listingId}`;
+    });
 });
+
 </script>
 {% endblock %}
-- 
GitLab