Skip to the content.

Sprint 5

This is a Jupyter Notebook where I explain the purpose of my feature on our website.

Blog: My Work on the Recommended Destinations Feature

Purpose of our Project: Our project aims to aid travelers in choosing a destination to travel to, based on features like recommended travel destinations, comments section, and a landscape feature that explains more information about each landscape. All these features help to solidify a user’s decision on where to travel to.

Purpose of my “Recommended Destinations” Feature

The goal of my individual feature is to allow users to post recommended destinations for others to see. This creates a collaborative and interactive experience where users can share their favorite places and explore suggestions from others. It contributes to our group’s overall goal of building a platform that connects people through shared recommendations. Through this project, we are able to learn all backend and database operations while communicating frontend.

Frontend Work image.png

In the frontend, I created a layout where users can type in a destination and post it. This form includes:

A text input field for the destination name.

A “Post” button to submit their recommendation.

The design is clean and user-friendly, ensuring that users can easily add recommendations without confusion. Once submitted, the input data is sent to the backend.

image.png

Backend Work

In the backend, I implemented the following functionalities:

API Endpoints: I created endpoints to handle user submissions. For example:

A POST request to accept new recommendations.

A GET request to retrieve all submitted recommendations for display on the frontend.

Database Integration:

Recommendations are stored in a database table, where each entry includes fields such as the destination name and a unique ID.

I ensured proper database handling to avoid duplicate entries by checking for unique destination names.

Error Handling:

Added checks to validate user input and ensure that empty or invalid submissions are not stored.

Built error responses to inform the frontend if something goes wrong.

Testing and Integration

To ensure the feature works seamlessly:

I tested API requests using Postman to confirm that the backend correctly receives and processes data.

I collaborated with my team to integrate the feature into the group project.

I verified that user-submitted destinations appear on the frontend after being processed by the backend.

Collaboration with My Group

Collaboration was a key part of developing this feature. I worked closely with my team to ensure our features were aligned and compatible. Specifically:

I coordinated with the teammate handling the recommendations list display to ensure my API provided the necessary data in the correct format.

We conducted group testing sessions to identify and resolve integration issues.

During meetings, we discussed design choices and decided on a consistent style and functionality for our project.

I supported teammates by reviewing their code and providing feedback, particularly on areas that overlapped with my feature.

Live Demo Plan

During the review, I plan to demonstrate live interactions using the following steps:

Use the frontend to type a destination in the text input field and submit it.

Show how the recommendation is sent to the backend via a POST request and added to the database.

Refresh the page or retrieve data with a GET request to display the updated recommendations list.

Use Postman to showcase raw API requests and responses, including error handling for invalid or duplicate submissions.

Technical Highlights

Database Queries:

Used SQLAlchemy to query the database for existing destinations, add new entries, and retrieve all recommendations.

Converted database rows into JSON format for the frontend to display.

API Methods:

POST: Accepts data from the form and stores it in the database.

GET: Fetches all stored recommendations and sends them to the frontend in JSON format.

Error Response Examples:

If a user submits a duplicate destination, the API returns an error response indicating the issue.

Code Example (Backend Method):

class DestinationAPI: @staticmethod def post(): data = request.get_json() name = data.get(‘name’) if not name: return jsonify({“error”: “Destination name is required.”}), 400

    existing_destination = Destination.query.filter_by(name=name).first()
    if existing_destination:
        return jsonify({"error": "Destination already exists."}), 409

    new_destination = Destination(name=name)
    db.session.add(new_destination)
    db.session.commit()

    return jsonify({"message": "Destination added successfully!"}), 201

This method demonstrates sequencing (data validation and processing), selection (checking if a destination already exists), and iteration (if applicable when processing data in bulk).

tablename: Specifies the table name in the database as vacations. id: A primary key (unique identifier) for each record. name: A string column (max 255 characters) for the vacation name. This field is required (nullable=False). climate: A string column for the type of climate of the vacation spot (e.g., Arid, Temperate). This field is required. country: A string column for the country where the vacation spot is located. This field is required.

Next Steps

Moving forward, I plan to:

Enhance the frontend to display a confirmation message when a recommendation is successfully posted.

Work with my team to refine the presentation of the recommendations list for better user engagement.

Implement additional features like editing or deleting recommendations if time permits.

Conclusion

This feature has been a rewarding project, as it showcases the power of collaboration and user interaction. By enabling users to share and discover destinations, it fulfills a key purpose of our website while integrating well with other features my team has developed.

def post(self):
        try:
            # Parse JSON data from request
            data = request.get_json()
            if not data:
                return jsonify({"error": "Invalid input: No JSON data provided"}), 400

            # Validate required fields
            required_fields = ['name', 'climate', 'country']
            for field in required_fields:
                if field not in data or not data[field].strip():
                    return jsonify({"error": f"Missing or empty field: {field}"}), 400

            # Create a new Vacation object
            new_vacation = Vacation(
                name=data['name'].strip(),
                climate=data['climate'].strip(),
                country=data['country'].strip()
            )

            # Add to the database
            db.session.add(new_vacation)
            db.session.commit()
            return "Vacation record added successfully", 201
            # Return the serialized data of the new vacation
            return jsonify(new_vacation.serialize()), 201
        except Exception as e:
            db.session.rollback()
            return jsonify({"error": f"An error occurred: {str(e)}"}), 500

    def delete(self):
        try:
            # Parse JSON data from request
            data = request.get_json()
            if not data or 'id' not in data:
                return jsonify({"error": "Invalid input: No ID provided"}), 400

            # Fetch the vacation by ID
            vacation = Vacation.query.get(data['id'])
            if not vacation:
                return jsonify({"error": "Vacation not found"}), 404

            # Delete the vacation from the database
            db.session.delete(vacation)
            db.session.commit()

            return jsonify({"message": "Vacation record deleted successfully"}), 200
        except Exception as e:
            db.session.rollback()
            return jsonify({"error": f"An error occurred: {str(e)}"}), 500

# Add the resource to the API
api.add_resource(VacationAPI, '/vacations')

def initVacation():
    """
    The initVacation function creates the Vacation table (if not already created)
    and populates it with test data.
    """
    try:
        db.create_all()

        # Check if data already exists
        if not Vacation.query.first():
            vacations = [
                Vacation(
                    name="Grand Canyon",
                    climate="Arid",
                    country="USA"
                ),
                Vacation(
                    name="Great Wall of China",
                    climate="Continental",
                    country="China"
                ),
                Vacation(
                    name="Eiffel Tower",
                    climate="Temperate",
                    country="France"
                )
            ]
            for vacation in vacations:
                vacation.create()

        logging.info("Vacation table initialized and seeded successfully.")
    except Exception as e:
        logging.error(f"Error initializing Vacation table: {e}")
        raise e