-
Notifications
You must be signed in to change notification settings - Fork 48
Ports - Elle #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Ports - Elle #35
Changes from all commits
3bfd3b9
f9713f3
a1c71dd
9f2c858
5649ee0
da74fe3
8e1f922
561bd67
0070e66
9e5177f
04f6550
7e36b49
146151a
b912740
1b54272
ba0e6e5
50ee636
c8b0ec4
e6fae9b
c4634c7
7b4f87a
a141692
56dc50f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| body { | ||
| background-color: #f0f0f0; | ||
| color: rgb(34, 34, 34); | ||
| margin: 30px 50px; | ||
| padding: 10px 10px; | ||
| } | ||
|
|
||
| h2 { | ||
| font-size: 1.5rem; | ||
| } | ||
|
|
||
| main { | ||
| display: grid; | ||
| grid-template: 1fr 1fr / 1fr 1fr; | ||
| margin-top: 1.5em; | ||
| grid-column-gap: 1.5em; | ||
| } | ||
| #status-message { | ||
| margin-bottom: 2em; | ||
| } | ||
|
|
||
| #trips-list-area { | ||
| grid-area: 1 / 1 / span 1 / span 1; | ||
| } | ||
|
|
||
| #trip-details-area { | ||
| grid-area: 1 / 2 / span 1 / span 1; | ||
| display: flex; | ||
| } | ||
|
|
||
| #sign-up-form { | ||
| margin-top: 3rem; | ||
| } | ||
|
|
||
| .bold { | ||
| font-weight: bold; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en" dir="ltr"></html> | ||
| <html> | ||
| <head> | ||
| <title>Trek</title> | ||
| <meta charset="utf-8"> | ||
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> | ||
| <link href="index.css" media="screen" rel="stylesheet" type="text/css"/> | ||
|
|
||
| </head> | ||
|
|
||
| <body id='body'> | ||
|
|
||
| <section id="status-message"></section> | ||
| <h1>Trek</h1> | ||
| <button id="btn-show-trips"class="btn btn-outline-info">Show All Trips</button> | ||
|
|
||
| <main> | ||
| <section id='trips-list-area'> | ||
| <table class='table table-striped table-hover '> | ||
| <thead></thead> | ||
| <tbody id='list-of-trips'></tbody> | ||
| </table> | ||
| </section> | ||
|
|
||
| <section id='details-and-form' > | ||
| <section id="trip-details" ></section> | ||
|
|
||
| <section id="sign-up-form" hidden> | ||
| <hr> | ||
| <h2>Reserve your spot!</h2> | ||
| <form id='reservation-form' > | ||
|
|
||
| <div><label for="guestname">Name</label> <input type="text" name="guestname" required/></div> | ||
| <div><label for="email">Email Address</label> <input type="text" name="email" required/></div> | ||
| <div><label for="age">Age</label> <input type="number" min="0" name="age"/></div> | ||
| <input type="submit" class="btn btn-outline-info" name="make-reservation" value="Make Reservation"/> | ||
|
|
||
| </form> | ||
| </section> | ||
| </section> | ||
| </main> | ||
|
|
||
|
|
||
|
|
||
|
|
||
| <script src="https://code.jquery.com/jquery-3.4.1.js" | ||
| integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" | ||
| crossorigin="anonymous"></script> | ||
| <script src="https://unpkg.com/axios/dist/axios.min.js"></script> | ||
| <script src="index.js"></script> | ||
|
|
||
|
|
||
| </body> | ||
| </html> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| const BASEURL = "https://trektravel.herokuapp.com/trips"; | ||
|
|
||
| const reportStatus = (message) => { | ||
| $('#status-message').html(message); | ||
| }; | ||
|
|
||
| const handleApiError = (error, customMessage) => { | ||
| // console.log(error); | ||
| // *** need help with figuring out how to test this is working *** | ||
|
|
||
| console.log(error.response); | ||
| if (error.response.data && error.response.data.errors) { | ||
| reportStatus(`${customMessage} Details: ${error.message}, ${error.response.data.errors}`); | ||
| } else { | ||
| reportStatus(`${customMessage} Details: ${error.message}`); | ||
| } | ||
| }; | ||
|
|
||
| // send GET request | ||
| // data comes back, store response object in a variable | ||
| // loop through the object and display each item on the page | ||
|
|
||
| // let allTrips; // not sure this is needed | ||
|
|
||
| const getTripDetails = (tripID) => { | ||
| axios.get(`${BASEURL}/${tripID}`) | ||
| .then((response) => { | ||
| const trip = response.data; | ||
| $("#trip-details").empty(); | ||
|
|
||
| $("#trip-details").append(`<h2>${trip.name}</h2>`); | ||
| $("#trip-details").append(`<p><span class="bold">ID:</span> ${trip.id}</p>`); | ||
| $("#trip-details").append(`<p><span class="bold">Continent:</span> ${trip.continent}</p>`); | ||
| $("#trip-details").append(`<p><span class="bold">Category:</span> ${trip.category}</p>`); | ||
| $("#trip-details").append(`<p><span class="bold">Weeks:</span> ${trip.weeks}</p>`); | ||
| $("#trip-details").append(`<p><span class="bold">Summary:</span><br> ${trip.about}</p>`); | ||
| $("#trip-details").append(`<p><span class="bold">Price:</span> $${trip.cost.toFixed(2)}</p>`); | ||
|
|
||
| $('#reservation-form').unbind('submit'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very good idea to use |
||
| $('#reservation-form').submit(reserveTrip); | ||
| }) | ||
| } | ||
|
|
||
| const loadTrips = () => { | ||
| reportStatus('Loading trips ...'); | ||
| const listOfTrips = $('#list-of-trips'); | ||
| // listOfTrips.empty; // this does not work, must use below syntax | ||
| $("#list-of-trips").empty(); | ||
|
|
||
| // clear details and form sections upon clicking Show Trips button | ||
| $('#trip-details').empty(); | ||
| $("#sign-up-form").hide(); | ||
|
|
||
| axios.get(BASEURL) | ||
| .then((response) => { | ||
| const allTrips = response.data; | ||
| reportStatus(`There are ${allTrips.length} trips available.`); | ||
|
|
||
| $('thead').html('<tr><td><h2>AVAILABLE TRIPS</h2></td></tr>') | ||
|
|
||
| allTrips.forEach((trip) => { | ||
| listOfTrips.append(`<tr id=${trip.id}><td>${trip.name}</td></tr>`); | ||
| // onClick(getTripDetails($(`${trip.id}`)); // <-- START HERE FOR REFACTOR TO .ON() INSTEAD OF .BIND() | ||
|
|
||
| $(`#${trip.id}`).unbind() | ||
| $(`#${trip.id}`).bind('click', {thisTrip:trip}, function(event){ | ||
| // Chris: I realized when I was just about done with this project that .bind() is deprecated. D: This should be changed to a .on() method instead. I will refactor if I get some more time, or perhaps we could talk through it. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, this still works fine, the better way is to use |
||
|
|
||
| // {thisTrip:trip} --> thisTrip variable stores the current trip object, whose details/object/payload/hash becomes available through event.data | ||
| // console.log("******* trip is: ********"); | ||
| // console.log(JSON.stringify(event.data)); | ||
| // {"thisTrip":{"id":74,"name":"Best of New Zealand","continent":"Australasia","category":"everything","weeks":3,"cost":1952.77}} | ||
|
|
||
| const tripID = event.data.thisTrip.id; | ||
|
|
||
| //remove class='selected' from any other table row | ||
| $(".selected").removeClass('selected'); | ||
|
|
||
| //set class='selected' on this table row | ||
| $(`#${tripID}`).addClass('selected'); | ||
| $('#status-message').empty(); | ||
|
|
||
| getTripDetails(`${tripID}`); | ||
|
|
||
| $("#sign-up-form").removeAttr('hidden'); | ||
| $("#sign-up-form").show(); | ||
| }); | ||
|
|
||
| });//END Each loop | ||
|
|
||
| }) | ||
| .catch((error) => { | ||
| // reportStatus(`Error loading trips: ${error.message}`); | ||
| // console.log(error); | ||
| handleApiError(error, "We encountered a problem loading the list of available trips."); | ||
| }); | ||
| }; | ||
|
|
||
| const readFormData = () => { | ||
| const formData = {}; | ||
|
|
||
| // Validations are being done in the HTML. Left these here just in case. | ||
|
|
||
| const nameFromForm = $(`#reservation-form input[name="guestname"]`).val(); | ||
| formData['name'] = nameFromForm ? nameFromForm : undefined; | ||
|
|
||
| const emailFromForm = $(`#reservation-form input[name="email"]`).val(); | ||
| formData['email'] = emailFromForm ? emailFromForm : undefined; | ||
|
|
||
| const ageFromForm = $(`#reservation-form input[name="age"]`).val(); | ||
| formData['age'] = ageFromForm ? ageFromForm : 'not provided'; | ||
|
|
||
| return formData; | ||
| }; | ||
|
|
||
|
|
||
| const clearForm = () => { | ||
| $(`#reservation-form input`).not('.btn').val(''); | ||
| }; | ||
|
|
||
| const reserveTrip = (event) => { | ||
| event.preventDefault(); | ||
|
|
||
| // gets the HTML attribute called id (#id) | ||
| const tripID = $(`.selected`).attr('id'); | ||
|
|
||
| let reservationData = readFormData(); | ||
|
|
||
| console.log(reservationData); | ||
|
|
||
| reportStatus('Submitting reservation...'); | ||
|
|
||
| axios.post(`${BASEURL}/${tripID}/reservations`, reservationData) | ||
| .then((response) => { | ||
| const tripIdNum = $('.selected').attr('id'); | ||
| reportStatus(`Successfully reserved your trip. | ||
| (Trip ID: ${tripIdNum}. Your name: ${response.data.name} Email: ${response.data.email} | ||
| Age: ${reservationData.age})`); | ||
| clearForm(); | ||
| }) | ||
| .catch((error) => { | ||
| handleApiError(error, "We encountered a problem submitting a reservation."); | ||
| clearForm(); | ||
| }); | ||
|
|
||
| // accepted params: | ||
| // name (string) required | ||
| // age (integer) | ||
| // email (string) required | ||
| }; | ||
|
|
||
|
|
||
| $(document).ready(() => { | ||
| $('#btn-show-trips').click(loadTrips); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should respond by also reporting any validation errors. You can loop through the content like we did in Rails.