diff --git a/index.css b/index.css new file mode 100644 index 00000000..7bc3da52 --- /dev/null +++ b/index.css @@ -0,0 +1,141 @@ +body, .button { + font-family: 'Karla', sans-serif; +} + +main { + display: grid; + grid-template-columns: 50% 1fr; + grid-template-rows: 5vh 50vh 1fr; + grid-column-gap: 1em; +} + +h1 { + font-size: 2.25rem; + margin-top: 4px; + margin-bottom: 4px; +} + +header > h1, h3 { + font-family: 'Permanent Marker', cursive; +} + +.button { + width: 8rem; + height: 2rem; + font-size: 1rem; + background-color: white; + border-color: rgb(64, 96, 119); +} + +.button:focus { + outline: none; +} + +.button:hover { + background-color: rgb(240, 216, 232); +} + +.header-background { + min-height: 0.9vh; + background-image: url('space-background.jpeg'); +} + +.trip-table, #trip-info { + overflow-x: scroll; +} + +.trip-table { + max-height: 75vh; + margin-top: 2vh; +} + +#status-message { + grid-column: 1 / span 2; +} + +.success { + color: rgb(38, 175, 11); +} + +.failure { + color: rgba(218, 52, 52, 0.65); +} + +#current-trips { + grid-row: 2 / span 2; +} + +#trip-info { + grid-column-start: 2; +} + +#trip-list { + width: 100%; +} + +#trip-list td { + cursor: pointer; +} + +#trip-list tr:nth-child(odd) { + background-color: rgba(147, 147, 147, 0.16); +} + +#trip-form { + grid-column-start: 2; + grid-row-start: 3; +} + +#trip-form .button { + margin-top: 2vh; +} + +#search-filters { + display: inline; +} + +i { + border: solid black; + border-width: 0 1px 1px 0; + display: inline-block; + padding: 3px; + margin-bottom: 3px; + margin-left: 5px; + transform: rotate(45deg); + -webkit-transform: rotate(45deg); +} + +/* DROPDOWN */ +/* The container
- needed to position the dropdown content */ +.dropdown { + position: relative; + display: inline-block; +} + +/* Dropdown Content (Hidden by Default) */ +.dropdown-content { + display: none; + position: absolute; + background-color: #f1f1f1; + min-width: 160px; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + z-index: 1; +} + +/* Links inside the dropdown */ +.dropdown-content p { + color: black; + padding: 10px 16px; + text-decoration: none; + display: block; + margin-bottom: 0; + margin-top: 0 +} + +/* Change color of dropdown links on hover */ +.dropdown-content p:hover {background-color: rgb(240, 216, 232)} + +/* Show the dropdown menu on hover */ +.dropdown:hover .dropdown-content { + display: block; +} diff --git a/index.html b/index.html new file mode 100644 index 00000000..80802f97 --- /dev/null +++ b/index.html @@ -0,0 +1,56 @@ + + + + + Octo Trips + + + + + + + +
+

TREK

+
+
+ +
+
+ +
+ +
+ + +
+
+ + + +
+
+
+
+ +
+ +
+ +
+ + + + + + + + + diff --git a/index.js b/index.js new file mode 100644 index 00000000..e0e40b18 --- /dev/null +++ b/index.js @@ -0,0 +1,295 @@ +const reportStatus = (message, type) => { + if (type) { + $('#status-message').html(message).attr('class', type); + } else { + $('#status-message').html(message).attr('class', ''); + } +}; + +const reportError = (message, errors) => { + let content = `${message}`; + content += '
'; + + for (const field in errors ){ + for (const problem of errors[field]) { + content += `${field}: ${problem} `; + } + } + content += '
'; + reportStatus(content, 'failure'); +}; + +const baseURL = 'https://ada-backtrek-api.herokuapp.com/trips'; + +const buildTripTable = function buildTripTable(input) { + + $('#trip-list').append(''); + + input.data.forEach( (trip) => { + let content = ''; + content += `${trip.name}`; + content += ``; + $('#trip-list').append(content); + }); + + $('#trip-list').append(''); + reportStatus(`${input.data.length} trips loaded`, 'success'); +} + +const getTrips = () => { + const tripList = $('#trip-list'); + tripList.empty(); + + reportStatus('Loading trips...') + + axios.get(baseURL) + .then((response) => { + $('#trip-list').empty(); + $('#trip-list').append('

All Trips

'); + buildTripTable(response); + }) + .catch((error) => { + // this might not be right + if (error.response.data && error.response.data.errors) { + reportError( + `Encountered an error: ${error.message}`, + error.response.data.errors + ); + } else { + reportStatus(`Error: ${error.message}`, 'failure'); + } + }); +}; + +const buildForm = function buildForm(id, name) { + let formContent = ''; + formContent += `

Reserve Trip: ${name}

`; + formContent += `
`; + formContent += '
'; + formContent += '
'; + formContent += ``; + formContent += ''; + + $('#trip-form').html(formContent); +}; + +const getTripInfo = function getTripInfo(event) { + let tripInfo = $('#trip-info'); + tripInfo.empty(); + + let target = event.target; + let tripLink = baseURL + '/' + target.id.toString(); + + axios.get(tripLink) + .then( (response) => { + let trip = response.data; + let content = ''; + content += ``; + content += ``; + content += ``; + content += `` + content += ``; + content += ``; + content += '
ID ${trip.id}
NAME ${trip.name}
COST $${trip.cost}
WEEKS ${trip.weeks}
CATEGORY ${trip.category}
ABOUT ${trip.about}
'; + $('#trip-info').append('

Trip Info

'); + $('#trip-info').append(content); + buildForm(trip.id, trip.name); + }) + .catch( (error) => { + if (error.response.data && error.response.data.errors) { + reportError( + `Encountered an error: ${error.message}`, + error.response.data.errors + ); + } else { + reportStatus(`Error: ${error.message}`, 'failure'); + } + }); + +}; + +const reserveTrip = function reserveTrip (event) { + + event.preventDefault(); + + const reservationURL = baseURL + '/' + $('input[name="id"]').val() + '/reservations' + + const tripData = { + name: $('input[name="name"]').val(), + email: $('input[name="email"]').val(), + } + + reportStatus('Attempting to book trip...'); + + axios.post(reservationURL, tripData) + .then(() => { + $('input[name="name"]').val(''); // clearing text field + $('input[name="email"]').val(''); + + reportStatus('Successfully booked trip!', 'success'); + }) + .catch((error) => { + if (error.response.data && error.response.data.errors) { + reportError( + `Encountered an error:`, + error.response.data.errors + ); + } else { + reportStatus(`Error: ${error.message}`, 'failure'); + } + }); + +}; + + +// QUERY SEARCHES +const searchBySection = function searchBy (event) { + let target = event.target; + let searchCat = target.id; + + switch(searchCat) { + case 'continent': + $('#search-filters').html( + `` + ); + break; + case 'budget': + $('#search-filters').html( + `
` + ); + break; + case 'weeks': + $('#search-filters').html( + `` + ); + break; + } + +} + +const getSearch = function getSearch(event) { + event.preventDefault(); + let selector = event.currentTarget; + let target = event.target; + + console.log(event); + + if (selector.id === 'continent-search') { + + searchContinent(target); + + } else if (target.defaultValue === 'Submit') { + let input = ''; + let type = ''; + if (selector.id === 'budget-form') { + input = $('input[name="budget"]').val(); + type = 'budget'; + } else if (selector.id === 'weeks-form') { + input = $('input[name="weeks"]').val(); + type = 'weeks'; + } + + searchWeeksOrBudget(input, type); + } +}; + +// INDIVIDUAL API QUERY SEARCH TYPES +const searchContinent = function searchContinent(input) { + let cont = input.innerHTML; + + // I tried separating this into params and couldn't get anywhere + let contURL = baseURL + '/continent' + `?query=${cont}`; + + axios.get(contURL) + .then((response) => { + $('#trip-list').empty(); + $('#trip-list').append(`

${cont} Trips

`); + if (response.data === undefined || response.data.length < 1) { + $('#trip-list').append('No trips at this time'); + } else { + buildTripTable(response); + } + }) + .catch((error) =>{ + if (error.response.data && error.response.data.errors) { + reportError( + `Encountered an error:`, + error.response.data.errors + ); + } else { + reportStatus(`Error: ${error.message}`, 'failure'); + } + }); +}; + +const searchWeeksOrBudget = function searchWeeksOrBudget(input, type) { + let contURL = baseURL + `/${type}` + `?query=${input.toString()}`; + let header = ''; + if (type === 'budget') { + header = `

Trips under $ ${input.toString()}

`; + } else { + header = `

Trips under ${input.toString()} Weeks

`; + } + axios.get(contURL) + .then((response) => { + $('#trip-list').empty(); + $('#trip-list').append(header); + if (response.data === undefined || response.data.length < 1) { + $('#trip-list').append('No trips at this time'); + } else { + buildTripTable(response); + } + }) + .catch((error) =>{ + if (error.response.status === 500) { + reportError( + 'Encountered an error: please enter a value' + ); + } else { + reportStatus(`Error: ${error.message}`, 'failure'); + } + }); +} + + +$(document).ready( () => { + $('#load').click(getTrips); + $('#trip-list').on('click', 'td', getTripInfo); + $('#trip-form').submit(reserveTrip); + $('#search-by').on('click', 'p', searchBySection); + $('#search-filters').on('click', '.filter-content', getSearch); + +}); diff --git a/space-background.jpeg b/space-background.jpeg new file mode 100644 index 00000000..1c3a8a96 Binary files /dev/null and b/space-background.jpeg differ