diff --git a/app/bookings/routes.py b/app/bookings/routes.py index 718660be4eeb699a9993c06105221862011d082f..e82754cb9036a6afe32c6b73ed5d9282ee9ac409 100644 --- a/app/bookings/routes.py +++ b/app/bookings/routes.py @@ -49,7 +49,7 @@ def listings(): locations=locations, discount=discount, days_away=days_away, - form_data={ + form_data= { 'departLocation': depart_location, 'destinationLocation': destination_location } @@ -130,6 +130,35 @@ def listing(id): return render_template('bookings/listing.html', listing=listing, selected_date=selected_date, discount=discount, days_away=days_away) +@bp.route('/checkout_post', methods=['POST']) +def checkout_post(): + card_number = request.form['cardNumber'] + card_expiry = request.form['cardExpiry'] + card_cvc = request.form['cardCVC'] + + # Validate and process payment (pseudo-code) + if not validate_payment(card_number, card_expiry, card_cvc): + flash('Payment failed. Please check your card details.') + return redirect(url_for('checkout')) # Redirect to the checkout page on failure + + # Assume that listing_id and user_id are obtained from session or form + listing_id = request.form['listing_id'] + user_id = request.form['user_id'] + num_seats = int(request.form['num_seats']) + + # Create booking + if create_booking(listing_id, user_id, num_seats): + # Update availability after successful booking + update_listing_availability(listing_id, num_seats) + flash('Booking successful!') + else: + flash('Booking failed. Please try again.') + + return redirect(url_for('booking_confirmation')) + +def validate_payment(card_number, card_expiry, card_cvc): + # Implement your payment validation logic here + return @bp.route('/filter_bookings', methods=['POST']) def filter_bookings(): diff --git a/app/models/listings.py b/app/models/listings.py index f23d6f348038c83d1a52315c775aaf77336e0376..dc5fd72f03562a482b90789cc5531dab93dccf3b 100644 --- a/app/models/listings.py +++ b/app/models/listings.py @@ -11,7 +11,8 @@ class Listings(db.Model): depart_time = db.Column(Time, nullable=False) destination_location = db.Column(db.String(255), nullable=False) destination_time = db.Column(Time, nullable=False) - fair_cost = db.Column(db.Float(), nullable=False) + economy_fair_cost = db.Column(db.Float(), nullable=False) + business_fair_cost = db.Column(db.Float(), nullable=False) transport_type = db.Column(db.String(255), nullable=False) listing_images = relationship("ListingImages", back_populates="listing", cascade="all, delete-orphan") diff --git a/app/templates/bookings/checkout.html b/app/templates/bookings/checkout.html index 196d9b14ecba810593007c83b79a3e913a568b89..ec3cff68bf5db242c2cec679e0097416701085f5 100644 --- a/app/templates/bookings/checkout.html +++ b/app/templates/bookings/checkout.html @@ -24,7 +24,7 @@ <div class="card mb-4"> <div class="card-body"> <h2 class="card-title">Payment Information</h2> - <form id="paymentForm"> + <form id="paymentForm" action="{{ url_for('bookings.checkout_post') }}" method="post"> <div class="form-group"> <label for="cardNumber">Credit Card Number</label> <input type="text" class="form-control" id="cardNumber" name="cardNumber" placeholder="Enter your credit card number"> diff --git a/app/templates/bookings/listing.html b/app/templates/bookings/listing.html index 665438b19384ff6e3612e99ac0375f2c57839a4b..758dc6eefdc6a7e7e597624539786280f14de2e4 100644 --- a/app/templates/bookings/listing.html +++ b/app/templates/bookings/listing.html @@ -10,11 +10,19 @@ <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> </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">Number of Seats:</label> <div class="col-md-6"> @@ -53,7 +61,7 @@ <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.fair_cost }}</span></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> @@ -90,6 +98,7 @@ $(document).ready(function () { 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; @@ -98,6 +107,7 @@ $(document).ready(function () { } departDateInput.setAttribute('min', today); + let maxDate = new Date(); maxDate.setDate(maxDate.getDate() + 90); departDateInput.setAttribute('max', maxDate.toISOString().split('T')[0]); @@ -113,16 +123,17 @@ $(document).ready(function () { event.preventDefault(); }); - // Send the updated date and number of seats to the server to check for discounts and calculate total cost + // 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 }), + 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'); @@ -132,14 +143,18 @@ $(document).ready(function () { 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; - // Run calculations on front end, they match backend and simply are for show. This controls the banner at the top for discounts + // Calculate the cost based on the seat type + if (seatType === "business") { + discountValue = originalPriceValue * 2; + } + if (data.discount) { - discountValue = originalPriceValue * (1 - data.discount / 100); + discountValue = discountValue * (1 - data.discount / 100); originalPrice.style.textDecoration = 'line-through'; discountedPriceValue.textContent = `${discountValue.toFixed(2)}`; discountedPrice.style.display = 'block'; @@ -165,6 +180,7 @@ $(document).ready(function () { 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) { @@ -175,6 +191,7 @@ $(document).ready(function () { 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}`; diff --git a/app/templates/index.html b/app/templates/index.html index 8331722dafa9f4359d9b6fbb4ff1cab161ef666d..144f57ffc18799fa81fb300eb3f7aaaf9da5f2a5 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -18,7 +18,6 @@ <label for="departLocation" class="form-label">Departure Location:</label> <select class="form-select select2-multiple" id="departLocation" name="departLocation"> <option value="" disabled selected>Select locations</option> - <!-- Populate options dynamically if needed --> </select> </div> <div class="col-md-6"> @@ -29,7 +28,6 @@ <label for="destinationLocation" class="form-label">Destination Location:</label> <select class="form-select select2-multiple" id="destinationLocation" name="destinationLocation"> <option value="" disabled selected>Select locations</option> - <!-- Populate options dynamically if needed --> </select> </div> <div class="col-md-6"> @@ -42,14 +40,6 @@ <option value="5">5</option> </select> </div> - <div class="col-md-6"> - <label for="seatType" class="form-label">Seat Type:</label> - <select id="seatType" class="form-select" name="seatType"> - <option value="economy">Economy</option> - <option value="business">Business</option> - <option value="firstClass">First Class</option> - </select> - </div> <div class="col-md-6 d-flex align-items-end justify-content-left"> <button type="submit" class="btn btn-primary">Search</button> </div>