diff --git a/dist/index.html b/dist/index.html index b873b1e..504581d 100644 --- a/dist/index.html +++ b/dist/index.html @@ -2,19 +2,131 @@ - My JavaScript App + Back Trekking + -
+
+
+

Back Trekking

+
+ + +
+
+
+ + + + + +
+ +
+ +
+ +
+
+ + + + + + + + + + +
NameContinentCategoryTrip LengthCost (in USD)
+
+
+ + + + + + + + + + + + + + + + + + + + - diff --git a/src/app.js b/src/app.js index e7af594..067d7b7 100644 --- a/src/app.js +++ b/src/app.js @@ -1,13 +1,188 @@ // Vendor Modules import $ from 'jquery'; import _ from 'underscore'; - // CSS import './css/foundation.css'; import './css/style.css'; +// OUR COMPONENTS +import TripList from './collections/trip_list'; +import Trip from './models/trip'; +import Reservation from './models/reservation' + +// TRIP FIELDS +const TRIP_FIELDS = ['id', 'name', 'about', 'continent', 'category', 'weeks', 'cost']; +const RESERVATION_FIELDS = ['name', 'age', 'email']; + +// Trip COLLECTION +const tripList = new TripList(); + +// TEMPLATES +///// still confused why ///// +let tripsTemplate; +let aboutTemplate; +let createNewTripTemplate; +let newReservationTemplate; + +// RENDER LIST OF TRIPS +const loadTrips = function loadTrips(tripList) { + const tripsTableElement = $('#trip-list'); + tripsTableElement.html(''); + + tripList.forEach((trip) => { + const generatedHTML = $(tripsTemplate(trip.attributes)); + tripsTableElement.append(generatedHTML); + }); + + // ADD COLOR TO HEADERS + $('th.sort').removeClass('current-sort-field'); + $(`th.sort.${ tripList.comparator }`).addClass('current-sort-field'); +}; + +const createNewTripHandler = function(event) { + event.preventDefault(); + + const tripData = {}; + TRIP_FIELDS.forEach((field) => { + const inputElement = $(`#trip-create-new input[name="${ field }"]`); + const value = inputElement.val(); + tripData[field] = value; + // clears form after submitted + inputElement.val(''); + }); + + const trip = tripList.add(tripData); + trip.save({}, { + success: (model, response) => { + console.log('Create new trip: success'); + console.log('Server response:'); + console.log(response); + }, + error: (model, response) => { + console.log('Create new trip: failure'); + console.log('Server response:'); + console.log(response); + }, + }); +}; + +///// RESERVATION FORM ///// +const newReservationHandler = function(event) { + event.preventDefault(); + + const reservationData = {}; + RESERVATION_FIELDS.forEach((field) => { + const inputElement = $(`#reservation-form input[name="${ field }"]`); + const value = inputElement.val(); + reservationData[field] = value; + // clears form after submitted + inputElement.val(''); + }); + + // take reservation trip_id from #trip-about data id + reservationData.trip_id = $('#trip-about').data('id') + const reservation = new Reservation(reservationData); + reservation.save({}, { + success: (model, response) => { + console.log(reservation.url()); + console.log('Create new reservation: success'); + }, + error: (model, response) => { + console.log('Create new reservation: failure'); + console.log('Server response:'); + console.log(response); + }, + }); +}; + +////////////////////////// +///// DOCUMENT READY ///// +$(document).ready(() => { + // TEMPLATES + tripsTemplate = _.template($('#trips-template').html()); + aboutTemplate = _.template($('#trip-template').html()); + createNewTripTemplate = _.template($('#create-new-trip-template').html()); + newReservationTemplate = _.template($('#new-reservation-template').html()); + + $('#show-trips').on('click', function() { + console.log('show trips: clicked'); + /// need clarification on this ///// + tripList.on('update', loadTrips); + tripList.on('sort', loadTrips); + tripList.fetch({ + success: () => { + $('#trip-list-table').show(); + console.log('show list table: success'); + $('.hero').animate({height:'40vh'}); + }, + }); + }); + + // RENDER SINGLE TRIP DETAILS TO DOM + $('#trip-list').on('click', 'tr', function() { + $('.hidden').show(); + const aboutElement = $('#trip-about'); + aboutElement.html(''); + console.log('about: clicked'); + // uses 'data' from html data-id + let tripID = $(this).data('id'); + // set the id onto #trip-about to be used on reservation form + $('#trip-about').data('id', tripID); + console.log(tripID); + // uses tripID to find api address for single trip + let singleTrip = new Trip({id: tripID}); + console.log(singleTrip.url()); + + // model refers to singleTrip + // model.fetch(): takes urlRoot and adds id? + //https://stackoverflow.com/questions/16544984/how-backbone-js-model-fetch-method-works + singleTrip.fetch({ + success: (model) => { + const generatedHTML = $(aboutTemplate(model.attributes)); + aboutElement.html(generatedHTML); + + // RENDER 'RESERVATION' FORM TO DOM + $('#new-reservation-btn').on('click', function() { + + $('#trip-about').animate({ + scrollTop: $('#trip-about')[0].scrollHeight}, 2000); + + const newReservationElement = $('#new-reservation'); + newReservationElement.html(''); + const generatedHTML = $(newReservationTemplate()); + newReservationElement.html(generatedHTML); + + console.log('load new reservation form: clicked'); + }); + }, + error: (model) => { + console.log('singleTrip fetch: failure'); + console.log(response); + }, + }); + }) + + // RENDER 'ADD NEW' FORM TO DOM + $('#trip-create-new-btn').on('click', function() { + const newTripElement = $('#trip-create-new'); + newTripElement.html(''); + const generatedHTML = $(createNewTripTemplate()); + newTripElement.html(generatedHTML); + + console.log('load add new form: clicked'); + }); +}) -console.log('it loaded!'); +// submit new reservation +$('#trip-about').on('submit', '#reservation-form', newReservationHandler); +// submit new trip +$('#trip-create-new').on('submit', createNewTripHandler); -$(document).ready( () => { - $('main').html('

Hello World!

'); +// SORT BY CLICKED FIELD +TRIP_FIELDS.forEach((field) => { + const headerElement = $(`th.sort.${ field }`); + headerElement.on('click', (event) => { + console.log(`Sorting table by ${ field }`); + tripList.comparator = field; + tripList.sort(); + }); }); diff --git a/src/collections/trip_list.js b/src/collections/trip_list.js new file mode 100644 index 0000000..b89162a --- /dev/null +++ b/src/collections/trip_list.js @@ -0,0 +1,14 @@ +import Backbone from 'backbone'; +import Trip from '../models/trip'; + +const TripList = Backbone.Collection.extend({ + model: Trip, + url: 'https://ada-backtrek-api.herokuapp.com/trips', + + parse: function(response) { + return response; + }, + comparator: 'name', +}); + +export default TripList; diff --git a/src/css/style.css b/src/css/style.css index b7b2d44..1e320ab 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -1,2 +1,78 @@ +/* +header: +font-family: 'Abril Fatface', cursive; +body: +font-family: 'Roboto', sans-serif; +*/ -/* Your styles go here! */ +body{ + font-family: 'Roboto', sans-serif; +} + +/* header */ +.hero { + background: url('https://i.imgur.com/cq3UAle.jpg') 30% no-repeat; + /* img of canyons with several hot air balloons */ + /* Photo by Egzon Bytyqi on Unsplash */ + background-size: cover; + height: 100vh; + text-align: center; + display: flex; + align-items: center; + justify-content: center; +} + +.hero-section-text h1 { + font-size: 5rem; + color: #20333e; + text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white; + font-family: 'Abril Fatface', cursive; +} + +#show-trips, #trip-create-new-btn { + color: white; + border-color: white; +} + +#show-trips:hover, #trip-create-new-btn:hover { + color: #20333e; +} + +#list { + height: 60vh; + overflow: scroll; +} + +.hidden { + display: none; +} + +#trip-about { + overflow: scroll; + position: relative; + height: 60vh; +} + +/* table */ +#trip-list-table { + display: none; + /*float:left;*/ +} + +th.sort { + cursor: pointer; + background-color: #A7CCA7; +} + +th.current-sort-field { + background-color: #647A6C; + color: white; +} + +#trip-list-table tr:nth-child(even) { + background-color: #EDE3E4; +} + +#trip-list-table tr:nth-child(odd) { + background-color: #F1EAEB; +} diff --git a/src/models/reservation.js b/src/models/reservation.js new file mode 100644 index 0000000..99de15b --- /dev/null +++ b/src/models/reservation.js @@ -0,0 +1,9 @@ +import Backbone from 'backbone'; + +const Reservation = Backbone.Model.extend({ + urlRoot() { + return 'https://ada-backtrek-api.herokuapp.com/trips/' + this.get('trip_id') + '/reservations'; + }, +}); + +export default Reservation; diff --git a/src/models/trip.js b/src/models/trip.js new file mode 100644 index 0000000..22a8034 --- /dev/null +++ b/src/models/trip.js @@ -0,0 +1,7 @@ +import Backbone from 'backbone'; + +const Trip = Backbone.Model.extend({ + urlRoot : 'https://ada-backtrek-api.herokuapp.com/trips/' +}); + +export default Trip;