Skip to the content.

Full Stack of Fair Fares | Rohan Bojja

Fair Fares Frontend to Backend

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>

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.

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.
# 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()

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])
    

Formatting the response data

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

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')

Sequencing and iteration method

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

Parameters and Return Type:

Params:

  • body: Json object to be used in the methods [POST, GET, PUT, DELETE]

Body example [DELETE]: { “id”: 4 }

Response:

  • Type of action done:

Example [DELETE]: { “message”: “Flight deleted successfully” }

Call To Algorithim Request

Frontend Fetch to endpoint

PUT

Reponse: talkes in the id, note, origin, destination, and fetches the PUT method from backend api. The note is updated through the users input, and is “put” into the same id row as before, and is then updated on the webpage.

async function updateFlightData(id, note, origin, destination) {
    const updateData = { note: note };
    const response = await fetch(`${pythonURI}/api/flight`, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            id: id,  // Use the correct ID for the rating to update
            origin: origin,  // Pass the new rating value
            destination: destination,
            note: note

        })
    });

    if (!response.ok) {
        console.error('Failed to update note');
    } else {
        console.log('Note updated');
    }
}

DELETE

Reponse: talkes in the id and fetches the DELETE method, with the /flight endpoint. Deleted in the database and updated on the webpage.

async function deleteFlightData(id) {
    await fetch(`${pythonURI}/api/flight`, {
        ...fetchOptions,
        method: 'DELETE',
        headers: { 
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({ id: id }),  // Use id from the backend response
        
    });

Handling Data and Error Conditions

Normal Conditions: Succesfully deleted or updated. POSTMAN example [PUT]: { “id”: 3, “origin”: “ORD”, “destination”: “MIA”, “note”: “NOTE IS UPDATED” }

Response: 200 OK { “destination”: “MIA”, “id”: 3, “notes”: “NOTE IS UPDATED”, “origin”: “ORD” }

Error Conditions: If not found, displays 404 not found and returns following: { “message”: “Flight not found” }