-
Notifications
You must be signed in to change notification settings - Fork 44
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
Laura Robertson -- Carets #33
base: master
Are you sure you want to change the base?
Changes from all commits
31ced1b
f78db72
b905570
7d0b759
7d22d07
04e7edd
d2246ee
e416d52
4422d18
fe4934a
f3830d6
515b0d6
0ff991f
85e1882
281415e
ded81e1
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 |
---|---|---|
|
@@ -2,19 +2,90 @@ | |
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>My JavaScript App</title> | ||
<title>TrekTrek</title> | ||
<link rel="stylesheet" type="text/css" href="../src/css/foundation.css"> | ||
<link rel="stylesheet" type="text/css" href="../src/css/style.css"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<link rel="shortcut icon" href="favicon.png"> | ||
</head> | ||
<body> | ||
<header> | ||
|
||
<h1>BackTREK<span class='float-right button' id='add-trip-button'>Add a trip</span></h1> | ||
</header> | ||
<main> | ||
|
||
<main class='row'> | ||
|
||
<section id="status-messages"> | ||
<button class="clear float-right"> | ||
<img src="http://www.pvhc.net/img223/xeiwtpbbgpmyhtcnjvwt.png" alt="Clear"> | ||
</button> | ||
<ul></ul> | ||
</section> | ||
|
||
<section class="columns large-6 small-12"> | ||
<button id='all-trips' class='button'>Trips</button> | ||
<table> | ||
<thead> | ||
<th class="sort name">Name</th> | ||
<th class="sort continent">Continent</th> | ||
<th class="sort weeks">Weeks</th> | ||
<th class="sort cost">Cost</th> | ||
<th class="sort category">Category</th> | ||
</thead> | ||
<tbody id="trip-list"> | ||
</tbody> | ||
</table> | ||
</section> | ||
|
||
<section class="columns large-6 small-12" id="trip-details"></section> | ||
|
||
<div id='add-trip'> | ||
<form class='add-trip-form'> | ||
<h4>Add a trip</h4> | ||
<input type='text' name='name' placeholder='Name' /> | ||
<input type='text' name='continent' placeholder='Continent' /> | ||
<input type='text' name='about' placeholder='About' /> | ||
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. A textarea would make a better choice. |
||
<input type='text' name='category' placeholder='Category' /> | ||
<input type='number' name='weeks' placeholder='Weeks' /> | ||
<input type='text' name='cost' placeholder='Cost' /> | ||
<input type="submit" value="Add trip" class="button"></input> | ||
</form> | ||
</div> | ||
|
||
</main> | ||
<footer> | ||
|
||
<footer> | ||
© 2017 | ||
</footer> | ||
|
||
<script type="text/template" id="trip-template"> | ||
<tr class="trip"> | ||
<td><%- name %></td> | ||
<td><%- continent %></td> | ||
<td><%- weeks %> weeks</td> | ||
<td><%- cost %></td> | ||
<td><%- category %></td> | ||
</tr> | ||
</script> | ||
|
||
<script type="text/template" id="trip-details-template"> | ||
<article class="trip"> | ||
<h2><%- name %></h2> | ||
<h5><%- continent %></h5> | ||
<h5><%- weeks %> weeks</h5> | ||
<h5><%- category %></h5> | ||
<p><%- about %></p> | ||
<h3>$ <%- cost %></h3> | ||
|
||
<form class="book-trip" action='https://ada-backtrek-api.herokuapp.com/trips/<%- id %>/reservations' method='post' > | ||
<input type='text' name='name' placeholder='Name' /> | ||
<input type='text' name='age' placeholder='Age' /> | ||
<input type='text' name='email' placeholder='Email' /> | ||
<input type="submit" value="Book it" class="button"></input> | ||
</form> | ||
</article> | ||
</script> | ||
|
||
<script src="app.bundle.js" type="text/javascript"></script> | ||
</body> | ||
</html> |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,12 +2,155 @@ | |
import $ from 'jquery'; | ||
import _ from 'underscore'; | ||
|
||
import Trip from './app/models/trip'; | ||
import TripList from './app/collections/trip_list'; | ||
|
||
// CSS | ||
import './css/foundation.css'; | ||
import './css/style.css'; | ||
|
||
console.log('it loaded!'); | ||
// ----------- All trips / Details ------------ | ||
const tripList = new TripList(); | ||
let tripTemplate; | ||
let tripDetails; | ||
|
||
const render = function render(tripList) { | ||
const $tripList = $('#trip-list'); | ||
$tripList.empty(); | ||
|
||
tripList.forEach((trip) => { | ||
$tripList.append($(tripTemplate(trip.attributes)).attr('id', `${trip.id}`)); | ||
}); | ||
}; | ||
|
||
const fields = ['name', 'continent', 'about', 'category', 'weeks', 'cost']; | ||
// const continents = ['Africa', 'Antarctica', 'Asia', 'Australasia', 'Europe', 'South America', 'North America', 'Null']; | ||
|
||
// ------------- Status Messages -------------- | ||
const updateStatusMessageFrom = (messageHash) => { | ||
$('#status-messages ul').empty(); | ||
for(let messageType in messageHash) { | ||
messageHash[messageType].forEach((message) => { | ||
$('#status-messages ul').append($(`<li>${messageType}: ${message}</li>`)); | ||
}) | ||
} | ||
$('#status-messages').show(); | ||
} | ||
|
||
const updateStatusMessageWith = (message) => { | ||
$('#status-messages ul').empty(); | ||
$('#status-messages ul').append(`${message}</li>`); | ||
$('#status-messages').show(); | ||
} | ||
|
||
const events = { | ||
// ------------- Add a new Trip -------------- | ||
addTrip(event) { | ||
console.log(this); | ||
event.preventDefault(); | ||
const tripData = {}; | ||
fields.forEach((field) => { | ||
tripData[field.toLowerCase()] = $(`.add-trip-form input[name=${field}]`).val(); | ||
console.log(field); | ||
console.log(tripData[field]); | ||
}); | ||
|
||
const trip = new Trip(tripData); | ||
|
||
if (trip.isValid()) { | ||
|
||
trip.save({}, { | ||
success: events.successfullSave, | ||
error: events.failedSave, | ||
}); | ||
} else { | ||
updateStatusMessageFrom(trip.validationError); | ||
} | ||
|
||
}, | ||
successfullSave(trip, response) { | ||
updateStatusMessageWith(`${trip.get('name')} added!`); | ||
tripList.add(trip); | ||
}, | ||
failedSave(trip, response) { | ||
updateStatusMessageFrom(response.responseJSON.errors); | ||
trip.destroy(); | ||
}, | ||
sortTrips(event) { | ||
$('.current-sort-field').removeClass('current-sort-field'); | ||
$(this).addClass('current-sort-field'); | ||
|
||
const classes = $(this).attr('class').split(/\s+/); | ||
|
||
classes.forEach((className) => { | ||
if (fields.includes(className)) { | ||
console.log(className); | ||
if (className === tripList.comparator) { | ||
tripList.models.reverse(); | ||
tripList.trigger('sort', tripList); | ||
} | ||
else { | ||
tripList.comparator = className; | ||
tripList.sort(); | ||
} | ||
} | ||
}); | ||
}, | ||
} | ||
|
||
// ----------- All trips / Details ------------ | ||
$(document).ready( () => { | ||
$('main').html('<h1>Hello World!</h1>'); | ||
tripTemplate = _.template($('#trip-template').html()); | ||
tripDetails = _.template($('#trip-details-template').html()); | ||
$('.add-trip-form').submit(events.addTrip); | ||
$('.sort').click(events.sortTrips); | ||
tripList.on('sort', render, tripList); | ||
|
||
$('#trip-list').hide(); | ||
tripList.on('update', render, tripList); | ||
tripList.fetch(); | ||
|
||
$('#all-trips').on('click', function() { | ||
$('#trip-list').toggle(); | ||
}); | ||
|
||
// ----------- Trip Details ------------- | ||
$('#trip-list').on('click', 'tr', function() { | ||
$('tr').css('background', ''); | ||
const id = $(this).attr('id'); | ||
const url = new Trip(this).url(); | ||
|
||
$(`#${id}`).css('background','pink'); | ||
|
||
$.get(url, function(response) { | ||
$(`#trip-details`).html(tripDetails(response)); | ||
}); | ||
}); | ||
|
||
// ----------- Modal ------------ | ||
$('#add-trip-button').on('click', function() { | ||
$('#add-trip').css('display', 'block'); | ||
}); | ||
|
||
$(document).on('click', function() { | ||
const modal = document.getElementById('add-trip'); | ||
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. Avoid mixing JavaScript and jQuery selections, use one or the other, in this case I'd suggest jQuery. |
||
|
||
if (event.target == modal) { | ||
event.stopPropagation(); | ||
modal.style.display = 'none'; | ||
} | ||
}); | ||
|
||
// ------------- Reserve a Trip -------------- | ||
$('body').on('submit', '.book-trip', function form(e) { | ||
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. validations?? |
||
e.preventDefault(); | ||
const url = $(this).attr('action'); | ||
const formData = $(this).serialize(); | ||
|
||
$.post(url, formData, () => { | ||
$('.book-trip').html('<h3>Booking Complete</h3>'); | ||
}).fail(() => { | ||
$('.book-trip').html('<h3>Booking failed</h3>'); | ||
}); | ||
}); | ||
}); |
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, | ||
url: 'https://ada-backtrek-api.herokuapp.com/trips', | ||
parse(response) { | ||
return response; | ||
}, | ||
}); | ||
|
||
export default TripList; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
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 cannot be blank"]; | ||
} | ||
|
||
if (!attributes.continent) { | ||
errors['continent'] = ["Continent cannot be blank"]; | ||
} | ||
|
||
if (!attributes.category) { | ||
errors['category'] = ["Category cannot be blank"]; | ||
} | ||
|
||
if (!attributes.weeks) { | ||
errors['weeks'] = ["Number of weeks cannot be blank"]; | ||
} | ||
|
||
if ( isNaN( attributes.weeks ) ) { | ||
errors['weeks'] = ["Weeks must be a number"]; | ||
} else if ( parseInt(attributes.weeks) < 1 ) { | ||
errors['weeks'] = ["Number of weeks must be greater than than 0"]; | ||
} | ||
|
||
if (!attributes.cost) { | ||
errors['cost'] = ["Cost cannot be blank"]; | ||
} | ||
|
||
if ( isNaN( attributes.cost ) ) { | ||
errors['cost'] = ["Cost must be a number"]; | ||
} else if ( parseInt(attributes.cost) < 1 ) { | ||
errors['cost'] = ["Cost must be greater than than 0"]; | ||
} | ||
|
||
if ( Object.keys(errors).length > 0 ) { | ||
return errors; | ||
} else { | ||
return false; | ||
} | ||
}, | ||
}); | ||
|
||
export default Trip; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,73 @@ | ||
#add-trip { | ||
display: none; | ||
position: fixed; | ||
z-index: 999; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
background: black; | ||
background: rgba(0,0,0,0.5); | ||
} | ||
|
||
/* Your styles go here! */ | ||
.add-trip-form { | ||
background: white; | ||
position: fixed; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate(-50%, -50%); | ||
padding: 30px; | ||
width: 400px; | ||
border-radius: 20px; | ||
} | ||
|
||
/* Styles for error section at the top */ | ||
#status-messages { | ||
background-color: #dfdfdf; | ||
/* Hide by default */ | ||
display: none; | ||
border-radius: 1rem; | ||
margin: 1rem; | ||
height: 100%; | ||
padding: .8rem; | ||
} | ||
|
||
#status-messages ul { | ||
list-style: none; | ||
margin-left: 0; | ||
} | ||
|
||
#status-messages button.clear { | ||
margin-top: .2rem; | ||
height: 100%; | ||
} | ||
|
||
#status-messages button.clear img { | ||
width: 2rem; | ||
} | ||
|
||
#status-messages .error { | ||
color: red; | ||
} | ||
|
||
#status-messages .success { | ||
color: green; | ||
} | ||
|
||
/* Sorting */ | ||
th.sort { | ||
cursor: pointer; | ||
} | ||
|
||
.current-sort-field { | ||
background-color: darkgrey; | ||
color: white; | ||
} | ||
|
||
table tbody td { | ||
padding: 5px; | ||
} | ||
|
||
table { | ||
table-layout: fixed; | ||
} |
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.
A
select
element would make a better choice, not giving the user an option for an invalid continent.