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
Binary file added images/trek-bg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
173 changes: 173 additions & 0 deletions index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
body {
margin: 0;
}

#bg-img-box {
position: fixed;
left: 0;
right: 0;
z-index: -1;
display: block;
background-image: url("images/trek-bg.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
width: 100%;
height: 100%;
opacity: 0.2;
filter: alpha(opacity=20)
}

main {
position: fixed;
left: 0;
right: 0;
z-index: 0;
margin: 0 20px;
font-family: 'Quicksand', sans-serif;
color: #1d1145;
}

.bg-blur {
filter: blur(5px);
-webkit-filter: blur(5px);
}

header {
display: flex;
font-family: 'Do Hyeon', sans-serif;
color: #1d1145;
}

h1 {
font-size: 30px;
}

#app-title:hover {
opacity: 0.2;
filter: alpha(opacity=20)
}

nav {
margin: 10px 0;
}

#status-msg {
margin-left: auto;
align-self: flex-start;
}

.table-border {
border-collapse: collapse;
text-align: center;
background-color: white;
}

th, td {
border-bottom: 1px solid #1d1145;
}

#all-trips, #trip-details, #reserve-trip {
overflow-y: auto;
}

#all-trips {
height: 510px;
}

#all-trips table {
width: 300px;
}

#trip-details, #reserve-trip {
height: 250px;
}

#trip-details table, #reserve-trip table {
width: 600px;
height: 250px;
}

td {
padding: 15px;
}

li {
list-style-type: none;
}

p {
margin: 0;
display: inline;
}

li p {
font-weight: bolder;
}

ul {
text-align: left
}

.trip-name {
font-weight: 100;
color: #0db4b9;
}

#reserve-trip-card h2 {
display: inline;
}

p::after, #to-which-trip::before {
content: " ";
white-space: pre;
}

#trip-console {
display: grid;
grid-template-columns: 1fr 3fr;
grid-gap: 10px;
}

#all-trips {
grid-column: 1 / 2;
}

#trip-pane {
grid-column: 2 / 3;
display: flex;
flex-direction: column;
justify-content: start;
}

#reserve-trip {
margin-top: 10px;
}

.submit-btn {
margin-top: 10px;
}

button, .submit-btn {
background-color: #f2a1a1;
border: none;
color: white;
padding: 15px 25px;
text-align: center;
font-size: 16px;
cursor: pointer;
}

button:hover, .submit-btn:hover {
background-color: #e76d89;
}

#trip-table tr:not(:first-child):hover {
background-color: #f2a1a1;
color: white;
}

#trip-table tr:not(:first-child):active {
background-color: #e76d89;
color: white;
}
32 changes: 32 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>SJ Trek!</title>
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script type="text/javascript" src="index.js"></script>
<link rel="stylesheet" href="index.css">
<link href="https://fonts.googleapis.com/css?family=Quicksand" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Do+Hyeon" rel="stylesheet">
</head>
<body>
<div id="bg-img-box"></div>
<main>
<header>
<h1 id="app-title">Star Trek!</h1>
<section id="status-msg"></section>
</header>
<nav id="trip-buttons">
<button id="load-trips">See All Trips</button>
</nav>
<section id="trip-console">
<article id="all-trips"></article>
<section id="trip-pane">
<article id="trip-details"></article>
<article id="reserve-trip"></article>
</section>
</section>
</main>
</body>
</html>
156 changes: 156 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
const URL = 'https://trektravel.herokuapp.com/trips';

const reportStatus = (message) => {
$('#status-msg').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);
};

const loadAllTrips = () => {
$('#bg-img-box').addClass('bg-blur')
const allTrips = $('#all-trips');
allTrips.empty();
reportStatus('Loading trips...');
allTrips.append('<table id="trip-table"></table>')
const tripTable = $('#trip-table');
axios.get(URL)
.then((response) => {
reportStatus(`Successfully loaded ${response.data.length} trips!`);
tripTable.append('<tr><th><h2>All Trips</h2></th></tr>');
response.data.forEach((trip) => {
tripTable.append(`<tr id="trip-${trip.id}"><td>${trip.name}</td></tr>`);
// build a click handler for each element id
$("#trip-table").on("click", `#trip-${trip.id}`, function() {
loadTripDetails(trip.id);
});
});
$("table").addClass("table-border");
})
.catch((error) => {
reportStatus(`Encountered an error while loading trips: ${error.message}`);
console.log(error);
});
};

const loadTripDetails = (tripId) => {
const tripDetails = $('#trip-details');
tripDetails.empty();
reportStatus('Loading trip details...');
tripDetails.append('<table id="trip-card"></table>')
const tripCard = $('#trip-card');
axios.get(`${URL}/${tripId}`)
.then((response) => {
reportStatus(`Successfully loaded trip ${tripId}!`);
tripCard.append('<tr><th><h2>Trip Details</h2></th></tr>');
const trip = response.data;
console.log(trip);
tripCard.append(
`<tr>
<td>
<ul>
<li><h3><p>Name:</p> <span class="trip-name">${trip.name}</span></h3></li>
<li><p>Continent:</p> ${trip.continent}</li>
<li><p>Category:</p> ${trip.category}</li>
<li><p>Weeks:</p> ${trip.weeks}</li>
<li><p>Cost:</p> $${trip.cost}</li>
<li><p>About:</p> ${trip.about}</li>
</ul>
</td>
</tr>`);
loadReserveTripForm(trip);
$("table").addClass("table-border");
})
.catch((error) => {
reportStatus(`Encountered an error while loading trips: ${error.message}`);
console.log(error);
});
};

const reserveTripForm =
`<table id="reserve-trip-card">
<tr><th><h2 id="reservation-form-header">Reserve A Trip</h2></th></tr>
<tr><td>
<form id="trip-form">
<div>
<label for="name">Your Name</label>
<input type="text" name="name" />
</div>

<div>
<label for="email">Email</label>
<input type="text" name="email" />
</div>

<div>
<label for="age">Age</label>
<input type="number" name="age" />
</div>

<input class="submit-btn" type="submit" name="submit-reservation" value="Reserve" />
</form>
</td></tr>
</table>`;

const loadReserveTripForm = (trip) => {
const reserveTrip = $('#reserve-trip');
reserveTrip.html(reserveTripForm);
$("table").addClass("table-border");
$('#reservation-form-header').append(` To <span class="trip-name" id="to-which-trip">${trip.name}</span>`);
$('#reserve-trip').on("submit", "#trip-form", function(event) {
event.preventDefault();
$(window).scrollTop(0);
reportStatus('Sending form data...');
createReservation(trip.id);
});
};

const readFormData = () => {
let tripForm = document.getElementById("trip-form");
const tripData = new FormData(tripForm);
return tripData;
};

const clearForm = () => {
$("#trip-form")[0].reset();
};

const createReservation = (tripId) => {
postUrl = `${URL}/${tripId}/reservations`
axios.post(postUrl, readFormData())
.then((response) => {
console.log(response);
reportStatus(`Success! You're on your way!
(RESERVATION ID: ${response.data.id} -
TRIP ID: ${response.data.trip_id})`
);
clearForm();
})
.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}`);
}
});
};

$(document).ready(() => {
$('#load-trips').click(loadAllTrips);
$('#app-title').click(function() {
location.reload(true);
})
});