Skip to the content.

Feature Overview of Fair Fares | Rohan Bojja

Introduction:

Fair Fares is a feature of this CPT Project that allows for users to efficneltey view travel method options, specifccly with aviable flights.

Our project takes in the users input as their Depatrure IATA code (e.g. LAX), and their Arrival IATA code. The output consists of the various avialble flights with time avilabilties, airlines, and a note feature.

Purpose of Program:

CRUD (Create, Read, Update, Delete), is used so the user will be able to make a post of information (consiting of origin, destination, and note) to the database, and will be able to, through the frotnend itself, replace notes, delete entries, and add more posts.

Input/Output Demo

Input/Output in the Full Stack Feature

Frontend API Request and Response:

<script type="module">
    import { pythonURI, fetchOptions } from '/rohan_2025/assets/js/api/config.js';

    document.getElementById('flightForm').addEventListener('submit', async function(event) {
        event.preventDefault();
        await fetchFlightData();
    });

    async function fetchFlightData() {
        const origin = document.getElementById('origin').value;
        const destination = document.getElementById('destination').value;
        const flightResults = document.getElementById('flightResults');
        const noteSection = document.getElementById('noteSection');
        const noteInput = document.getElementById('noteInput');
        const saveNoteButton = document.getElementById('saveNoteButton');

        flightResults.innerHTML = '<p>Loading...</p>';

        try {
            const response = await fetch(`http://127.0.0.1:8887/api/flight-api?origin=${origin}&destination=${destination}`);
            
            if (!response.ok) {
                throw new Error(`HTTP error! Status: ${response.status}`);
            }

            const data = await response.json();
            if (data && data.data && data.data.length > 0) {
                flightResults.innerHTML = data.data.map(flight =>
                    `<div class="flight-card">
                        <p>Flight ${flight.flight.iata}: ${flight.airline.name} - Departure: ${flight.departure.scheduled}, Arrival: ${flight.arrival.scheduled}</p>
                        <button class="note-button">Add Note</button>
                        <div class="note-input" style="display:none;">
                            <input type="text" class="note-text" placeholder="Type your note here">
                            <button class="save-note">Save Note</button>
                        </div>
                    </div>`
                ).join('');

                const noteButtons = document.querySelectorAll('.note-button');
                noteButtons.forEach((button, index) => {
                    button.addEventListener('click', () => {
                        const noteInputSection = button.closest('.flight-card').querySelector('.note-input');
                        noteInputSection.style.display = 'block';
                    });
                });

                const saveNoteButtons = document.querySelectorAll('.save-note');
                saveNoteButtons.forEach((button, index) => {
                    button.addEventListener('click', async () => {
                        const noteText = button.closest('.flight-card').querySelector('.note-text').value;
                        if (noteText) {
                            await postFlightData(origin, destination, noteText);
                            showNotesTable(); // Refresh the notes table after saving
                        }
                    });
                });
            } else {
                flightResults.innerHTML = `<p>No flights found for the provided details.</p>`;
            }
        } catch (error) {
            flightResults.innerHTML = `<p>Error: ${error.message}</p>`;
        }
    }
</script>

Big Idea 1.4 Debugging Code and Fixing Errors

I used Postman to debug the backend code and find the source of the error, adn then the frontend code was resolved through inspection of the main pages. Adding test data such as this below allowed for the seamless connection testing ebtween the frontend and backend:

Using Postman for Raw API Testing

URL: http://192.168.1.10:8887/api/flight

  • Request: Example of a POST request to create new data:
      {
        "origin": "LAX",
        "destination": "DEN",
        "note": "Buisness Trip"
      }
    
  • Response:
      {
          "destination": "DEN",
          "id": 4,
          "notes": "Buisness Trip",
          "origin": "LAX"
      }
    
  • Request: Example of a PUT request to update data:
      {
        "id": 4,
        "origin": "LAX",
        "destination": "DEN",
        "note": "Buisness Trip"
      }
    
  • Response:
      {
          "destination": "DEN",
          "id": 4,
          "notes": "UPDATED NOTE",
          "origin": "LAX"
      }
    
  • Request: Example of a DELETE request to delete data:
      {
        "id": 4
      }
    
  • Response:
      {
          "message": "Flight deleted successfully"
      }
    
  • Error Responses:
    • 400 Bad Request: If required fields are missing.
    • 404 Not Found: If the endpoint is incorrect.
# INIT
db.create_all()


# Test data
flights = [
    Flight(origin='LAX', destination='JFK', note='Flight from Los Angeles to New York'),
    Flight(origin='SFO', destination='ATL', note='Flight from San Francisco to Atlanta'),
    Flight(origin='ORD', destination='MIA', note='Flight from Chicago to Miami'),
]

for flight in flights:
    try:
        flight.create()
        print(f"Record created: {repr(flight)}")
    except IntegrityError:
        db.session.remove()
        print(f"Record exists or error: {flight.origin} to {flight.destination}")
        
        
        
# RESTORE
for flight_data in data:
    _ = flight_data.pop('id', None)  # Remove 'id' from post_data
    title = flight_data.get("origin", None)
    flight = Flight.query.filter_by(origin=title).first()
    if flight:
        flight.update(flight_data)
    else:
        flight = Flight(**flight_data)
        flight.update(flight_data)
        flight.create()
        
        
# BACKUP
def main():
    # Step 1: Backup the old database
    with app.app_context():
        backup_data()

Big Idea 2 Data

We used SQLite databases in order to manage all this data:

SQLite Screenshot

Database privacy is kept with the way it is handled through either lsits or dictaries, where the difference is how they are keyed through. Database retrivel is done using the query method to return list of flights or rows in the table, and then can be used with backend to frotnend integraiton to display on the main page. The Datbase abckup and reecovery are used with the init, resotre, and backup python scripts, which just adds to functionality.

Use of Lists, Dictionaries, and Database

Data Handling in the Program

  • Lists: Used to represent rows of data retrieved from the database. Example:
      datas = [
          {"id": 1, "origin": "LAX", "destination": "DEN", "note": "Testing"}
      ]
    
  • Dictionaries: Represent individual database entries as key-value pairs (columns).
      data = {
          "id": 1, 
          "origin": "LAX", 
          "destination": "DEN", 
          "note": "Testing"
      }
    

Database Queries

We use SQLAlchemy to interact with the database:

  • Extracting Rows:
      flight = Flight.query.get(flight_id)  # Returns a list of Flight objects
    
  • Formatting Response Data:
      return jsonify([flight.read() for flight in all_flights])
    

Querying from Database

def get(self):
    flight_id = request.args.get('id')

    if flight_id:
        flight = Flight.query.get(flight_id)
        if not flight:
            return {'message': 'Flight not found'}, 404
        return jsonify(flight.read())

    all_flights = Flight.query.all()
    return jsonify([flight.read() for flight in all_flights])

Method to be compatible with database

def post(self):
    data = request.get_json()

    if not data or 'origin' not in data or 'destination' not in data or 'note' not in data:
        return {'message': 'Origin, destination, and note are required'}, 400

    flight = Flight(
        origin=data.get('origin'),
        destination=data.get('destination'),
        note=data.get('note')
    )

    try:
        flight.create()
        return jsonify(flight.read())
    except Exception as e:
        return {'message': f'Error saving flight: {e}'}, 500

Database Tools: Data Creation and Recovery

  • db_init: Initializes the database schema for the program.
  • db_restore: Recovers tester data for consistent testing environments.
  • db_backup: Saves the current state of the database for restoration.

Algorithmic Code Request

CRUD Operations:

class _CRUD(Resource):
    def post(self):
        data = request.get_json()

        if not data or 'origin' not in data or 'destination' not in data or 'note' not in data:
            return {'message': 'Origin, destination, and note are required'}, 400

        flight = Flight(
            origin=data.get('origin'),
            destination=data.get('destination'),
            note=data.get('note')
        )

        try:
            flight.create()
            return jsonify(flight.read())
        except Exception as e:
            return {'message': f'Error saving flight: {e}'}, 500

    def get(self):
        flight_id = request.args.get('id')

        if flight_id:
            flight = Flight.query.get(flight_id)
            if not flight:
                return {'message': 'Flight not found'}, 404
            return jsonify(flight.read())

        all_flights = Flight.query.all()
        return jsonify([flight.read() for flight in all_flights])

    def put(self):
        data = request.get_json()

        if not data or 'id' not in data:
            return {'message': 'ID is required for updating a flight'}, 400

        flight = Flight.query.get(data['id'])
        if not flight:
            return {'message': 'Flight not found'}, 404

        try:
            flight.update(data)
            return jsonify(flight.read())
        except Exception as e:
            return {'message': f'Error updating flight: {e}'}, 500

    def delete(self):
        data = request.get_json()

        if not data or 'id' not in data:
            return {'message': 'ID is required for deleting a flight'}, 400

        flight = Flight.query.get(data['id'])
        if not flight:
            return {'message': 'Flight not found'}, 404

        try:
            flight.delete()
            return {'message': 'Flight deleted successfully'}, 200
        except Exception as e:
            return {'message': f'Error deleting flight: {e}'}, 500


# Register the CRUD resource
api.add_resource(_CRUD, '/flight')

Big Idea 4 Internet

Being the deployment assistant admin, I ahve to keep records of the deplyoment blog: https://kiruthic-selvakumar.github.io/travel_frontend/2025/02/02/deployment_blog.html

We used Amazon Web services to deploy the application. The domain name system for Intertravel was:

Server: https://intertravel.stu.nighthawkcodingsociety.com/ Domain: nighthawkcodingsociety.com Subdomain: intertravel.stu

Furthermore, we used JWT tokens to autheticate the server. To also contribute to deployment, the ngnix file, docker compose, and other files were created, and kept as records in the blog.

As show ABOVE, the CRUD operations are used to interact with the backend, where the PUT and DELETE functions are sequnecing through the database for specified infromation.