diff --git a/index.html b/index.html new file mode 100644 index 00000000..90a22ce1 --- /dev/null +++ b/index.html @@ -0,0 +1,89 @@ + + + + + Get Outta Here + + + + + +
+
+

Trek

+
+ + + +

+ +
+ + + +
+
+ + + + + + diff --git a/index.js b/index.js new file mode 100644 index 00000000..f76700a9 --- /dev/null +++ b/index.js @@ -0,0 +1,205 @@ +// Constant API url +const URL = 'https://ada-backtrek-api.herokuapp.com/trips' + +// Status Message Handling +const reportStatus = (message) => { + $('.status-message').html(message) +} + +const reportError = (message, errors) => { + let content = `

${message}

`; + for (const field in errors) { + for (const problem of errors[field]) { + content += `

${field}: ${problem}

`; + } + } + reportStatus(content); +}; + +// Load All Trips +const loadTrips = (event) => { + $('.all-trips').removeClass('display-none'); + + const tripList = $('#trip-list'); + tripList.empty(); // empty out the list each time so there aren't duplilcates + + reportStatus('Loading trips! Please wait...') + + axios.get(URL) // returns a promise + .then((response) => { + response.data.forEach((trip) => { + tripList.append(`

${trip.name}

`); + }); + reportStatus('Trips loaded!') + }) + .catch((error) => { + reportStatus(`${error.message}`) + }); +} + +// Load Trip Details +const loadDetails = function(event) { + const tripDetails = $('#details'); + const tripResNum = $('#trip-reservation-num') + tripDetails.empty(); + tripResNum.empty(); + + let trip = event.target.id + + $('.trip-creation').removeClass('display-none'); + $('.details').removeClass('display-none'); + $('.reserve-form').removeClass('display-none'); + + $('input').removeClass('highlight') // removes and previous error outlining from form + + $('#reservation-status').html(''); + $('#reservation-status').removeClass('status-message'); // removes previous reservation status if new trip selected + + reportStatus('Loading trip details! Please wait...') + + axios.get(`${URL}\\${trip}`) // returns a promise + .then((response) => { + let tripData = response.data + tripDetails.append( + `

Trip Details

+

Name: ${tripData.name}

+

Continent: ${tripData.continent}

+

Category: ${tripData.category}

+

Weeks: ${tripData.weeks}

+

Cost: ${tripData.cost}

+

About:
${tripData.about}

`); + + tripResNum.append( + `

${tripData.name}

` + ); + + reportStatus('Trip details loaded!') + }) + + .catch((error) => { + console.log(error); + reportStatus(`${error.message}`) + }); + +} + +// Reserve Trip +const FORM_FIELDS = ['name', 'email']; +const inputField = name => $(`#reserve-form input[name="${name}"]`); + +const readFormData = () => { + const getInput = name => { + const input = inputField(name).val(); + return input ? input : undefined; + }; + + const formData = {}; + FORM_FIELDS.forEach((field) => { + formData[field] = getInput(field); + }); + + return formData; +} + +const clearForm = () => { + FORM_FIELDS.forEach((field) => { + inputField(field).val(''); + }); +} + +const reserveTrip = (event) => { + event.preventDefault(); + + $('p:first-of-type').removeClass('status-message'); + $('#reservation-status').addClass('status-message'); + + const tripID = $('#trip-reservation-num p').attr('id'); + const tripData = readFormData(); + + reportStatus('Making reservation...'); + + axios.post(`${URL}\\${tripID}\\reservations`, tripData) + .then((response) => { + $('input').removeClass('highlight') + reportStatus(`Successfully made a reservation!`); + clearForm(); + }) + .catch((error) => { + console.log(error.response); + + $('#reserve-form input').addClass('highlight') + + if (error.response.data && error.response.data.errors) { + reportError( + `Encountered an error: ${error.message}`, + error.response.data.errors + ); + } else { + reportStatus(`Encountered an error: ${error.message}`); + } + }); +}; + +// Create Trip +const CREATE_FORM_FIELDS = ['name', 'continent', 'category', 'weeks', 'cost' ]; +const createInputField = name => $(`#new-trip-form input[name="${name}"]`); + +const readCreateFormData = () => { + const getCreateInput = name => { + const inputCreateForm = createInputField(name).val(); + return inputCreateForm ? inputCreateForm : undefined; + }; + + const createFormData = {}; + CREATE_FORM_FIELDS.forEach((field) => { + createFormData[field] = getCreateInput(field); + }); + + return createFormData; +} + +const createClearForm = () => { + $(`#new-trip-form textarea"]`).val(''); // clears textarea value + CREATE_FORM_FIELDS.forEach((field) => { + inputField(field).val(''); + }); +} + +const createTrip = (event) => { + event.preventDefault(); + + $('p:first-of-type').removeClass('status-message'); + $('#reservation-status').removeClass('status-message'); + $('#creation-status').addClass('status-message'); + + const createTripData = readCreateFormData(); + reportStatus('Creating a trip...'); + + axios.post(URL, createTripData) + .then((response) => { + $('input').removeClass('highlight') + reportStatus(`Successfully made a new trip!`); + clearForm(); + }) + .catch((error) => { + console.log(error.response); + + $('#new-trip-form input').addClass('highlight') + + if (error.response.data && error.response.data.errors) { + reportError( + `Encountered an error: ${error.message}`, + error.response.data.errors + ); + } else { + reportStatus(`Encountered an error: ${error.message}`); + } + }); +}; + +$(document).ready(() => { + $('#trips-button').click(loadTrips); + $('#trip-list').on('click', 'p', loadDetails); + $('#reserve-form').submit(reserveTrip); + $('#new-trip-form').submit(createTrip); +}); diff --git a/style.css b/style.css new file mode 100644 index 00000000..90aa7119 --- /dev/null +++ b/style.css @@ -0,0 +1,54 @@ +header { + border-bottom: 1px solid; +} + +h1, h2 { + padding-left: 5%; +} + +h2, .all-trips p, .details p { + border-bottom: 1px solid; +} + +h3, p, .reserve, .create { + text-align: center; +} + +p:last-of-type { + border-bottom: none; +} + +.display-none, span { + display: none; +} + +.grid-container { + display: grid; + grid-gap: 20px; + grid-template-columns: auto auto; +} + +.details, .reserve-form, .all-trips { + border: 1px solid; + margin-bottom: 3rem; +} + +.details p { + text-align: left; + font-weight: bold; + padding: 0 10px; +} + +.highlight { + border: 2px solid red; +} + +.button { + margin: 2.5%; + border-radius: 5px; +} + +#trip-reservation-num p { + font-size: 2rem; + margin-bottom: 0; +}