Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@


body {
display: grid;
margin-left: 25px;
margin-right: 25px;
grid-template: 100px fit-content(10%) 1fr 2fr / 1fr 2fr;
}

h1, h2, h3 {
font-family: 'Baloo Da', cursive;
}

h1 {
font-size: 4em;
color: white;
}

ul {
margin: 0;
padding: 0;
}

li {
list-style-type: none;
line-height: 1.5em;
}

#logo {
text-align: center;
background-color: lightblue;
grid-column: span 2;
}

#load {
margin-bottom: 25px;
}

#trips {
grid-row: span 2;
padding-right: 25px;
}

#status-message {
min-height: 10px;
grid-column: span 2;
}

#trip-details {
grid-row: 3 / span 1;
min-height: 100px;
grid-column: 2;
}

#form-section {
grid-column: 2;
grid-row: 4;
}

#submit-div {
padding-top: 15px;
}

.hidden {
display: none;
}
66 changes: 66 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript" src="index.js"></script>
<link href="https://fonts.googleapis.com/css?family=Baloo+Da&display=swap" rel="stylesheet">
<link rel="stylesheet" href="index.css">
<title>TREK</title>
</head>

<body>

<header id="logo">
<h1>TREK</h1>
</header>

<section id="status-message"></section>

<section id="trips">

<button id="load" class="btn btn-primary form-control">Show All Trips</button>
<ul id="trips-list"></ul>
</section>

<section id="trip-details" class="hidden">
<h2>Trip Details</h2>
<h3 id="name"></h3>
<p id="continent"></p>
<p id="category"></p>
<p id="weeks"></p>
<p id="cost"></p>
<p id="about"></p>
</section>

<section id="form-section" class="hidden">
<h2></h2>
<form id="trip-form">
<div id="name-div">
<label for="name">Name (required): </label>
<input type="text" id="customer-name" class="form-control"></input>
</div>
<div id="age-div">
<label for="age">Age: </label>
<input type="text" id="age" class="form-control"></input>
</div>
<div id="email-div">
<label for="name">Email (required): </label>
<input type="text" id="email" class="form-control"></input>
</div>
<div id="hidden-input-div">
<input type="hidden" id="tripID"></input>
</div>
<div id="submit-div">
<input type="submit" value="Submit" class="btn btn-primary form-control">
</div>
</form>
</section>
</body>

</html>
115 changes: 115 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
const URL = 'https://trektravel.herokuapp.com/trips';


const reportStatus = (message, alertClass) => {
$('#status-message').removeClass();
$('#status-message').addClass(alertClass);
$('#status-message').html(message);
};

const reportError = (message, errors) => {
let content = `<p>${message}</p>`
content += "<ul>";
for (const field in errors) {
for (const problem of errors[field]) {
content += `<li>${field}: ${problem}</li>`;
}
}
content += "</ul>";
reportStatus(content, "alert alert-warning");
};

const clearForm = () => {
$('#trip-form').get(0).reset();
};



const loadTrips = () => {
reportStatus('Loading trips...');

Choose a reason for hiding this comment

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

Looks like your editor is set up to make 4-space tabs in JavaScript. At Ada we recommend 2-spaces, which will be important when you start working on pair projects. Please update this setting.

const tripList = $('#trips-list');
tripList.empty();

axios.get(URL)
.then((response) => {
reportStatus(`Successfully loaded ${response.data.length} trips`, "alert alert-success");
response.data.forEach((trip) => {
tripList.append(`<li id='${trip.id}'><a href=#>${trip.name}</a></li><hr />`);
$(`#${trip.id}`).click(function () {
showTrip(trip.id);
});

Choose a reason for hiding this comment

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

Good use of a callback here to track the trip ID.

});
})
.catch((error) => {
reportStatus(`Encountered an error while loading trips: ${error.message}`);
console.log(error);
});
};

const showTrip = (index) => {
$('#status-message').removeClass();
$('#status-message').html('');

axios.get(URL + `/${index}`)
.then((response) => {
$('#form-section').removeClass('hidden');
$('#trip-form').submit(function (event) {
$('#tripID').val(response.data.id);

Choose a reason for hiding this comment

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

The work being done here is complex enough that it might be worthwhile to break it out into its own function.

event.preventDefault();
makeReservation();

Choose a reason for hiding this comment

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

When reserving a second trip, your site makes two POST requests. To reproduce:

  1. Open page
  2. Open chrome dev tools to the "Network" tab
  3. Click See All Trips
  4. Click on the first trip (Cairo to Zanzibar)
  5. Make a reservation and submit
  6. Click on the second trip (Everest Base Camp Trek)
  7. Make a reservation and submit
  8. Observe that on submit, 2 POST requests were made to trek API's /reservations endpoint

The reason for this is that you reuse the same reservation form for each trip, but re-attach the submit handler every time you show details for a trip.

});

$('#trip-details').removeClass('hidden');
$('#form-section h2').html(`Make a Reservation: ${response.data.name}`);
$('#name').html(`Trip ${response.data.id}: ${response.data.name}`);
$('#continent').html(`<strong>Continent:</strong> ${response.data.continent}`)
$('#category').html(`<strong>Category:</strong> ${response.data.category}`)

let weeksString = 'week';
if (response.data.weeks !== 1) {
weeksString += 's';
}
$('#weeks').html(`<strong>Duration:</strong> ${response.data.weeks} ${weeksString}`)
$('#cost').html(`<strong>Cost:</strong> $${response.data.cost}`)
$('#about').html(`<strong>Description:</strong> ${response.data.about}`)
})
.catch((error) => {
reportStatus(`Encountered an error while loading trip: ${error.message}`);
console.log(error);
});
};

const makeReservation = () => {
$('#status-message').html('');
const tripID = $('#tripID').val();

Choose a reason for hiding this comment

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

Using a hidden HTML field feels like an appropriate way to track the trip ID here.

const tripData = {
name: $('#customer-name').val(),
email: $('#email').val(),
age: $('#age').val(),
}

axios.post(URL+`/${tripID}/reservations`, tripData)
.then((response) => {
clearForm();
console.log(response);
reportStatus('Successfully made reservation!', "alert alert-success");
})
.catch((error) => {
console.log(error.response);
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}`, "alert alert-warning");
}
});

}

$(document).ready(() => {
$('#load').click(loadTrips);
});
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.