Skip to content
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

Carets - Maria - BackTrek #37

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
95 changes: 92 additions & 3 deletions dist/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,107 @@
<head>
<meta charset="utf-8">
<title>My JavaScript App</title>
<script src="app.bundle.js" type="text/javascript"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<header>

<button id="trips_button" class="button"> Get trips! </button>
<h1>BackTrek</h1>
</header>
<main>

<section id="status-messages">
<ul>
</ul>
</section>

<section id="load_trips" class="columns large-8 small-12">
<h2></h2>

<table id="trips-all">
<thead>
<th class="sort name">Trip Name</th>
<th class="sort continent">Destination</th>
<th class="sort category">Category</th>
<th class="sort weeks">Trip Duration</th>
<th class="sort cost">Cost</th>
</thead>

<tbody id="trip-list">
</tbody>
</table>
</section>

<aside id="single-trip" class="columns large-4 small-12">
<h3></h3>
</aside>

<aside class="columns large-4 small-12">
<h2> Add a Trip</h2>
<form id="add-trip-form">
<label for="name">Name</label>
<input type="text" name="name"></input>

<label for="continent">Continent</label>
<input type="text" name="continent"></input>

<label for="category">Category</label>
<input type="text" name="category"></input>

<label for="weeks">Number of Weeks</label>
<input type="number" name="weeks"></input>

<label for="cost">Cost</label>
<input type="number" name="cost"></input>

<input type="submit" value="Add trip" class="button"></input>
</form>
</aside>

</main>


<footer>

</footer>
<script src="app.bundle.js" type="text/javascript"></script>
</body>

<script id="trip-template" type="text/template">
<tr class="trip" trip-id=<%- id %> >
<td>
<%- name %>
</td>
<td>
<%- continent %>
</td>
<td>
<%- category %>
</td>
<td>
<%- weeks %> week(s)
</td>
<td>
$<%- cost %>
</td>
</script>

<script id="show-template" type="text/template">
<h2> Details for <%- name %> </h2>
<p>
Category: <%- category %>
</p>
<p>
Continent: <%- continent %>
</p>
<p>
Description: <%- about %>
</p>
<p>
Duration: <%- weeks %> week(s)
</p>
<p>
Cost: $<%- cost %>
</p>
</script>
</body>
</html>
104 changes: 102 additions & 2 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,108 @@ import _ from 'underscore';
import './css/foundation.css';
import './css/style.css';

console.log('it loaded!');
import Trip from './app/models/trip';
import TripList from './app/collections/trip_list';

const tripList = new TripList();

let tripTemplate;
let showTemplate;

const fields = ['name', 'continent', 'category', 'weeks', 'cost'];

const render = function render(tripList) {
const tripListElement = $('#trip-list');
tripListElement.empty();

tripList.forEach((trip) => {
tripListElement.append(tripTemplate(trip.attributes));
});
};

const loadTrips = function loadTrips() {
tripList.fetch();
tripList.on('update', render, tripList);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's theoretically possible that the fetch could complete before the update event listener is added. So I would register the listener in $(document).ready when the application starts.

This will also register render as an event listener every time loadTrips is clicked, so the list could be rendered multiple times.

};

const events = {
loadTrip(id) {
const singleTripElement = $('#single-trip');
singleTripElement.empty();
const trip = new Trip({id: id});

$('h3').text('Trip Info');

trip.fetch().done(() => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no detecting that the fetch failed, so no way to provide a msg about when things fail.

let showHTML = showTemplate(trip.attributes);
singleTripElement.append($(showHTML));
});
},

addTrip(event) {
event.preventDefault();

const tripData = {};
fields.forEach((field) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking this into a helper method which reads the form would be better.

const val = $(`input[name=${field}]`).val();
if (val != '') {
tripData[field] = val;
}
});

const trip = new Trip(tripData);
if (trip.isValid()) {
trip.save({}, {
success: events.successfulSave,
error: events.failedSave,
});
} else {
$('#status-messages ul').append(`<li>Error ${trip.validationError['name'][0]}`);
$('#status-messages').show();
}
console.log(tripList);
},

successfulSave(trip, response) {

console.log('Success!');
console.log(trip);
console.log(response);
$('#status-messages ul').empty();
$('#status-messages ul').append(`<li>${trip.get('name')} added!</li>`);
$('#status-messages').show();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also clear the form on a successful save.

tripList.fetch();
},
failedSave(trip, response) {
console.log('Error!');
console.log(trip);
console.log(response);
$('#status-messages ul').empty();
console.log(response.responseJSON.errors);
for(let key in response.responseJSON.errors) {
response.responseJSON.errors[key].forEach((error) => {
$('#status-messages ul').append(`<li>${key}: ${error}</li>`);
})
}
$('#status-messages').show();
trip.destroy();
},
};

$(document).ready( () => {
$('main').html('<h1>Hello World!</h1>');
tripTemplate = _.template($('#trip-template').html());
showTemplate = _.template($('#show-template').html());

$('#trips_button').click(() => {
$('h2').text('Trip Options');
loadTrips();
});

$('#trip-list').on('click', 'tr', function() {
const tripID = $(this).attr('trip-id');
events.loadTrip(tripID);
});

$('#add-trip-form').submit(events.addTrip);

});
12 changes: 12 additions & 0 deletions src/app/collections/trip_list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Backbone from 'backbone';
import Trip from '../models/trip';

const TripList = Backbone.Collection.extend({
model: Trip, //send it an object as a parameter
url: 'https://ada-backtrek-api.herokuapp.com/trips',
parse(response) {
return response; //array from the JSON
},
});

export default TripList;
39 changes: 39 additions & 0 deletions src/app/models/trip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Backbone from 'backbone';

const Trip = Backbone.Model.extend({
urlRoot: 'https://ada-backtrek-api.herokuapp.com/trips',

validate: function(attributes) {
const errors = {};

if (!attributes.name) {
errors['name'] = ['Name can\'t be blank'];
}

if (!attributes.continent) {
errors['continent'] = ['Continent can\'t be blank'];
}

if (!attributes.category) {
errors['category'] = ['Category can\'t be blank'];
}

if (!attributes.weeks) {
errors['weeks'] = ['Weeks can\'t be blank'];
}

if (!attributes.cost) {
errors['cost'] = ['Cost can\'t be blank'];
}

if ( isNaN(attributes.weeks) ) {
errors['weeks'] = ['Weeks must be a number'];
}

if ( isNaN(attributes.cost) ) {
errors['cost'] = ['Cost must be a number'];
}
}
});

export default Trip
10 changes: 10 additions & 0 deletions src/css/style.css
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@

/* Your styles go here! */
#trips_button {
float: right;
margin-top: 2%;
margin-right: 5%;
}

header {
background-color: magenta;
max-width: 100%;
}