From 589debdbf9d525fd6df7c890e831563b28d9f073 Mon Sep 17 00:00:00 2001
From: Ethan-clay03 <ethanclay2017@gmail.com>
Date: Thu, 13 Feb 2025 17:25:56 +0000
Subject: [PATCH] Fully link seat type to listings and bookings page, complete
 checkout to do

---
 app/bookings/routes.py              |  58 ++++++-
 app/models/listings.py              |  13 ++
 app/templates/bookings/listing.html | 226 +++++++++++++---------------
 3 files changed, 172 insertions(+), 125 deletions(-)

diff --git a/app/bookings/routes.py b/app/bookings/routes.py
index a261b95..a0b36cf 100644
--- a/app/bookings/routes.py
+++ b/app/bookings/routes.py
@@ -50,7 +50,7 @@ def listings():
 
     # Get all locations for dropdowns
     locations = Listings.get_all_locations(True)
-    
+
     return render_template(
         'bookings/listings.html',
         items=paginated_listings,
@@ -66,20 +66,36 @@ def listings():
             'seatType': seat_type
         }
     )
-
-
 @bp.route('/listing/apply_update', methods=['POST'])
 def listing_apply_update(): 
     data = request.get_json()
     selected_date = data.get('date')
+    num_seats = int(data.get('seats'))
+    seat_type = data.get('seatType')
+    
     discount, days_away = calculate_discount(selected_date)
 
+    listing = session['listing']
+    if seat_type == "business":
+        base_price = listing['business_fair_cost']
+    else:
+        base_price = listing['economy_fair_cost']
+    
+    discounted_price = base_price * (1 - discount / 100)
+    total_cost = discounted_price * num_seats
+    total_saved = (base_price * num_seats) - total_cost
+
     response = {
         'discount': discount,
-        'days_away': days_away
+        'days_away': days_away,
+        'base_price': base_price,
+        'discounted_price': discounted_price,
+        'total_cost': total_cost,
+        'total_saved': total_saved
     }
     return jsonify(response)
 
+
 @bp.route('/checkout')
 def checkout(): 
     if not session['checkout_cache']:
@@ -134,14 +150,42 @@ def show_listing_dirty(id):
 @bp.route('/listing/<int:id>', methods=['GET'])
 def listing(id):
     listing = Listings.search_listing(id)
+    
+    if 'listing' not in session:
+        session['listing'] = {}
+
+    session['listing']['economy_fair_cost'] = listing.economy_fair_cost
+    session['listing']['business_fair_cost'] = listing.business_fair_cost
+
     listing.depart_time = pretty_time(listing.depart_time)
     listing.destination_time = pretty_time(listing.destination_time)
     filter_data = session.pop('filter_data', None)
 
     selected_date = filter_data['date'] if filter_data and 'date' in filter_data else None
+    seat_type = filter_data['seatType'] if filter_data and 'seatType' in filter_data else 'economy'
+
     discount, days_away = calculate_discount(selected_date) if selected_date else (0, 0)
 
-    return render_template('bookings/listing.html', listing=listing, selected_date=selected_date, discount=discount, days_away=days_away)
+    if seat_type == "business":
+        base_price = listing.business_fair_cost
+    else:
+        base_price = listing.economy_fair_cost
+
+    discounted_price = base_price * (1 - discount / 100)
+    total_cost = discounted_price
+
+    return render_template(
+        'bookings/listing.html',
+        listing=listing,
+        selected_date=selected_date,
+        seat_type=seat_type,
+        discount=discount,
+        days_away=days_away,
+        base_price=base_price,
+        discounted_price=discounted_price,
+        total_cost=total_cost
+    )
+
 
 @bp.route('/checkout_post', methods=['POST'])
 def checkout_post():
@@ -180,8 +224,8 @@ def filter_bookings():
     depart_location = data.get('depart_location', [])
     destination_location = data.get('destination_location', [])
     depart_date = data.get('date')
-    seat_type = data.get('seatType', 'economy')  # Default to 'economy' if not provided
-    page = int(data.get('page', 1))  # Get the page parameter or default to 1
+    seat_type = data.get('seatType', 'economy')  # Default to economy
+    page = int(data.get('page', 1)) 
     per_page = 10  # How many listings show per page
 
     discount, days_away = calculate_discount(depart_date)
diff --git a/app/models/listings.py b/app/models/listings.py
index dc5fd72..7c00b96 100644
--- a/app/models/listings.py
+++ b/app/models/listings.py
@@ -67,3 +67,16 @@ class Listings(db.Model):
     
         return cls.query.get(listing_id)
 
+    @classmethod
+    def to_dict(self):
+        return {
+            'id': self.id,
+            'depart_location': self.depart_location,
+            'depart_time': self.depart_time,
+            'destination_location': self.destination_location,
+            'destination_time': self.destination_time,
+            'transport_type': self.transport_type,
+            'economy_fair_cost': self.economy_fair_cost,
+            'business_fair_cost': self.business_fair_cost
+        }
+        
diff --git a/app/templates/bookings/listing.html b/app/templates/bookings/listing.html
index 758dc6e..087b326 100644
--- a/app/templates/bookings/listing.html
+++ b/app/templates/bookings/listing.html
@@ -10,15 +10,6 @@
             <div class="col-md-6">
                 <input type="date" class="form-control" id="departDate" name="departDate" required value="{{ selected_date or today }}">
             </div>
-            <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">Seat Type:</label>
-                <div class="col-md-6">
-                    <select class="form-select" id="seatType" name="seatType">
-                        <option value="economy">Economy</option>
-                        <option value="business">Business</option>
-                    </select>
-                </div>
-            </div>
             <button type="button" class="btn btn-warning ms-2" id="resetDate">
                 <i class="fa-solid fa-rotate-right"></i> Reset Date
             </button>
@@ -35,6 +26,15 @@
                 </select>
             </div>
         </div>
+        <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">Seat Type:</label>
+            <div class="col-md-6">
+                <select class="form-select" id="seatType" name="seatType">
+                    <option value="economy" {% if seat_type == 'economy' %}selected{% endif %}>Economy</option>
+                    <option value="business" {% if seat_type == 'business' %}selected{% endif %}>Business</option>
+                </select>
+            </div>
+        </div>        
     </div>
     <h2 class="mb-4" style="text-align: center; margin-top: 40px;">Booking Details</h2>
     <div class="row">
@@ -61,19 +61,17 @@
         <div class="card-body">
             <h2 class="card-title">Transport Information</h2>
             <p><strong>Transport Type:</strong> {{ listing.transport_type }}</p>
-            <p><strong>Price:</strong> £<span id="originalPrice">{{ listing.economy_fair_cost }}</span></p>
-            <p id="discountedPrice" style="display: none;">
-                <strong>Discounted Price:</strong> £<span id="discountedPriceValue"></span>
+            <p><strong>Price:</strong> £<span id="originalPrice">{{ base_price }}</span></p>
+            <p id="discountedPrice" style="display: {% if discount > 0 %}block{% else %}none{% endif %};">
+                <strong>Discounted Price:</strong> £<span id="discountedPriceValue">{{ discounted_price }}</span>
             </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>
-
+            <p><strong>Total Cost:</strong> £<span id="totalCost">{{ total_cost }}</span></p>
+            <p><strong>Total Saved:</strong> £<span id="totalSaved">{{ base_price - discounted_price }}</span></p>
         </div>
     </div>
     <div class="text-center">
@@ -92,111 +90,103 @@
     </div>
 </div>
 <script>
-$(document).ready(function () {
-    const filterDataDepartDate = "{{ selected_date if selected_date else '' }}";
-    const resetDateButton = document.getElementById('resetDate');
-    const today = new Date().toISOString().split('T')[0];
-    const departDateInput = document.getElementById('departDate');
-    const numSeatsInput = document.getElementById('numSeats');
-    const seatTypeInput = document.getElementById('seatType'); // Add this line
-
-    if (!filterDataDepartDate) {
-        departDateInput.value = today;
-    } else {
-        departDateInput.value = filterDataDepartDate;
-    }
-
-    departDateInput.setAttribute('min', today);
-
-    let maxDate = new Date();
-    maxDate.setDate(maxDate.getDate() + 90);
-    departDateInput.setAttribute('max', maxDate.toISOString().split('T')[0]);
-
-    // Reset date to today when the reset button is clicked
-    resetDateButton.addEventListener('click', () => {
-        departDateInput.value = today;
-        departDateInput.dispatchEvent(new Event('change'));
-    });
-
-    // Prevent any dates being changed by the user manually typing
-    departDateInput.addEventListener('keydown', (event) => {
-        event.preventDefault();
-    });
-
-    // Send the updated date, number of seats, and seat type to the server to check for discounts and calculate total cost
-    function updateData() {
-        const newDate = departDateInput.value;
-        const numSeats = numSeatsInput.value;
-        const seatType = seatTypeInput.value; // Add this line
-
-        $.ajax({
-            url: "{{ url_for('bookings.listing_apply_update') }}",
-            type: 'POST',
-            contentType: 'application/json',
-            data: JSON.stringify({ date: newDate, seats: numSeats, seatType: seatType }), // Update this line
-            success: function (data) {
-                const discountBanner = document.getElementById('discountBanner');
-                const originalPrice = document.getElementById('originalPrice');
-                const discountedPrice = document.getElementById('discountedPrice');
-                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');
-                const originalPriceValue = parseFloat(originalPrice.textContent.replace('£', ''));
-
-                let discountValue = originalPriceValue;
-                let finalPrice = originalPriceValue;
-
-                // Calculate the cost based on the seat type
-                if (seatType === "business") {
-                    discountValue = originalPriceValue * 2;
-                }
-
-                if (data.discount) {
-                    discountValue = discountValue * (1 - data.discount / 100);
-                    originalPrice.style.textDecoration = 'line-through';
-                    discountedPriceValue.textContent = `${discountValue.toFixed(2)}`;
-                    discountedPrice.style.display = 'block';
-                    discountBanner.style.display = 'block';
+    $(document).ready(function () {
+        const filterDataDepartDate = "{{ selected_date if selected_date else '' }}";
+        const resetDateButton = document.getElementById('resetDate');
+        const today = new Date().toISOString().split('T')[0];
+        const departDateInput = document.getElementById('departDate');
+        const numSeatsInput = document.getElementById('numSeats');
+        const seatTypeInput = document.getElementById('seatType');
+        const bookButton = document.getElementById('bookButton');
+    
+        if (!filterDataDepartDate) {
+            departDateInput.value = today;
+        } else {
+            departDateInput.value = filterDataDepartDate;
+        }
+    
+        departDateInput.setAttribute('min', today);
+    
+        let maxDate = new Date();
+        maxDate.setDate(maxDate.getDate() + 90);
+        departDateInput.setAttribute('max', maxDate.toISOString().split('T')[0]);
+    
+        // Reset date to today when the reset button is clicked
+        resetDateButton.addEventListener('click', () => {
+            departDateInput.value = today;
+            departDateInput.dispatchEvent(new Event('change'));
+        });
+    
+        // Prevent any dates being changed by the user manually typing
+        departDateInput.addEventListener('keydown', (event) => {
+            event.preventDefault();
+        });
+    
+        // Send the updated date, number of seats, and seat type to the server to check for discounts and calculate total cost
+        function updateData() {
+            const newDate = departDateInput.value;
+            const numSeats = numSeatsInput.value;
+            const seatType = seatTypeInput.value;
+    
+            $.ajax({
+                url: "{{ url_for('bookings.listing_apply_update') }}",
+                type: 'POST',
+                contentType: 'application/json',
+                data: JSON.stringify({ date: newDate, seats: numSeats, seatType: seatType }),
+                success: function (data) {
+                    const discountBanner = document.getElementById('discountBanner');
+                    const originalPrice = document.getElementById('originalPrice');
+                    const discountedPrice = document.getElementById('discountedPrice');
+                    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');
+    
+                    // Update UI with the data received from the server
+                    originalPrice.textContent = `${data.base_price.toFixed(2)}`;
                     discountPercent.textContent = data.discount;
                     daysAway.textContent = data.days_away;
-                } else {
-                    originalPrice.style.textDecoration = 'none';
-                    discountedPrice.style.display = 'none';
-                    discountBanner.style.display = 'none';
+                    discountedPriceValue.textContent = `${data.discounted_price.toFixed(2)}`;
+                    totalCost.textContent = `${data.total_cost.toFixed(2)}`;
+                    totalSaved.textContent = `${data.total_saved.toFixed(2)}`;
+    
+                    // Show or hide discount banner
+                    if (data.discount > 0) {
+                        discountBanner.style.display = 'block';
+                        originalPrice.style.textDecoration = 'line-through';
+                        discountedPrice.style.display = 'block';
+                    } else {
+                        discountBanner.style.display = 'none';
+                        originalPrice.style.textDecoration = 'none';
+                        discountedPrice.style.display = 'none';
+                    }
+                },
+                error: function () {
+                    alert('Error applying discount. Please try again.');
                 }
-
-                // 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);
+        seatTypeInput.addEventListener('change', updateData);
+    
+        // Trigger the change event to apply the initial discount if a date is selected
+        if (filterDataDepartDate) {
+            updateData();
+        }
+    
+        // Handle "Book Now" button click
+        bookButton.addEventListener('click', () => {
+            const departDate = departDateInput.value;
+            const numSeats = numSeatsInput.value;
+            const seatType = seatTypeInput.value;
+            const listingId = "{{listing.id}}";
+    
+            window.location.href = `{{ url_for('bookings.payment') }}?date=${departDate}&seats=${numSeats}&listing_id=${listingId}`;
         });
-    }
-
-    departDateInput.addEventListener('change', updateData);
-    numSeatsInput.addEventListener('change', updateData);
-    seatTypeInput.addEventListener('change', updateData); // Add this line
-
-    // Trigger the change event to apply the initial discount if a date is selected
-    if (filterDataDepartDate) {
-        updateData();
-    }
-
-    // Handle "Book Now" button click
-    bookButton.addEventListener('click', () => {
-        const departDate = departDateInput.value;
-        const numSeats = numSeatsInput.value;
-        const seatType = seatTypeInput.value; // Add this line
-        const listingId = "{{listing.id}}";
-
-        window.location.href = `{{ url_for('bookings.payment') }}?date=${departDate}&seats=${numSeats}&listing_id=${listingId}`;
     });
-});
-
-</script>
+    </script>
+    
 {% endblock %}
-- 
GitLab