/Kelp

Primary LanguageJavaScript

Kelp README

Kelp is a full-stack, single-page web application clone of Yelp. It is a platform for users to share their experiences of coral reefs via reviews, ratings, and pictures. Along with these user-generated reviews, reefs are displayed on a show page with their relevant information to help provide a list of the best options available to users.

Visit Kelp here: https://kelp1.herokuapp.com/#/reefs

Technologies

Kelp implements a Ruby/Rails backend with a Javascript/React-Redux frontend. Styling is done using CSS and HTML.

Features

  • Reviews and Ratings
  • Google Maps API to display reef locations through markers
  • Auth components(Log in, Sign up, Guest Log in)
  • Search for Reefs

Map Feature

  • Interactive Map that displays reef locations with markers
  • Clicking on markers redirects to the reef's show page

Review Form

  • The review form accepts parameters for submitting a rating, review body, date, and photo. Because photos are their own table in the database schema, submitting a review with a photo required the Review model to accept nested parameters:
class Review < ApplicationRecord
  validates :body, :date, presence: true

  validates :rating, inclusion: { in: (1..5) }


  belongs_to :author,
    foreign_key: :author_id,
    class_name: "User"

  belongs_to :reef,
    foreign_key: :reef_id,
    class_name: "Reef"

  has_many :photos,
    foreign_key: :review_id,
    class_name: "Photo",
    inverse_of: :review

    accepts_nested_attributes_for :photos
end
  • Additionally, the Review Form must accept the nested photo attributes in addition to its own attributes on handling submit of the form:
class ReviewForm extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      body: "",
      date: "",
      rating: "",
      imageUrl: "",
      imageFile: "",
      buttonColor: "#d90007"
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.updateField = this.updateField.bind(this);
    this.updateFile = this.updateFile.bind(this);
    this.ratingStars = this.ratingStars.bind(this);
  }
handleSubmit(e) {
  e.preventDefault();
  const file = this.state.imageFile;
  const review = new FormData();
  const reefId = this.props.reef.id;
  review.append("review[photos_attributes][][image]", file);
  review.append("review[body]", this.state.body);
  review.append("review[rating]", this.state.rating);
  review.append("review[date]", this.state.date);
  review.append("review[reef_id]", reefId);
  review.append("review[author]", this.props.currentUser);
  this.props.createReview(review).then( () => this.props.history.push(`/reefs/${reefId}`));
}

Future

  • Filtered search
  • Modals for logging in/signing up
  • Map markers that render reef details on hover