diff --git a/README.md b/README.md index c461e15..0b81f21 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,69 @@ # Open-API-Project Open API project for Intro to Programming course with Code the Dream + +# Taily Daily dog coffee shop + +## Description +"Taily Daily is a web application designed for users to explore dogs available for adoption in nearby shelters and schedule visits. It features a user-friendly interface that allows users to filter by coffee and dog options while providing detailed information about each dog." + +## Features +- Book a dog +- Display detailed dog information (description, characteristics, location, etc.) +- Navigate through pages with Back/Next buttons +- View images of all dogs near the user's location +- Responsive design for desktop and mobile devices + +## Prerequisites +- A modern web browser (e.g., Chrome, Firefox, Safari) +- Internet connection (for API calls) +- A text editor (e.g., VSCode, Sublime Text) if you want to make changes + +## Installation and Setup +1. Clone the repository or download the project files to your local machine. + ``` + git clone https://github.com/Elena-Nam/Open-API-Project.git + ``` +2. Create a `config.js` file inside the /js directory of your cloned project with your API key: + ```javascript + const config = { + API_KEY: 'your_api_key_here' + }; + ``` + Replace `'your_api_key_here'` with your actual API key from [ADOPT-A-PET API](https://www.adoptapet.com/dog-adoption). + +## Running the Application +1. Open the `index.html` file in your web browser. + +2. The application should now be running in your browser. You can use the search functionality to look up dogs and navigate through the results. + +3. To view the Welcome page, click on the "Home" link in the navigation menu or open `index.html` directly in your browser. + +## File Structure +- `index.html`: Welcome page of the application +- `drinks.html`: Drinks page with information and booking options +- `dogs.html`: Dogs page with information and booking options +- `gifts.html`: Gifts page with information and booking options +- `reservation.html`: Reservation page with user's booked information + +- `css/` + - `index.css`: Styles for all pages + - `media.css`: Styles for media queries +- `js/` + - `index.js`: JavaScript for the index file functionality + - `drinks.js`: JavaScript for the drinks file functionality + - `dogs.js`: JavaScript for the dogs file functionality + - `gifts.js`: JavaScript for the gifts file functionality + - `reservation.js`: JavaScript for the reservation file functionality + - `config.js`: Configuration file for API key (you need to create this) +- `img/`: Directory for storing images used in the project + +## API Usage +This project uses [ADOPT-A-PET API](https://www.adoptapet.com/dog-adoption) and [SAMPLE APIs](https://sampleapis.com/api-list/coffee). You’ll need to sign up for a free API key for each API to use in the config.js file. + +## Contributing +Feel free to fork the project and submit pull requests with any enhancements, bug fixes, or improvements. + +## Contact +Elena Nam - ek28150@gmail.com + +Project Link: https://github.com/Elena-Nam/Open-API-Project \ No newline at end of file diff --git a/index.css b/css/index.css similarity index 70% rename from index.css rename to css/index.css index f8f4bdf..fcc7204 100644 --- a/index.css +++ b/css/index.css @@ -18,11 +18,9 @@ font-size: 2.2em; /* navigation */ .navbar { - /* background-color: #FBEEC1;*/ overflow: hidden; - width: 40%; + width: 60%; margin: 0 auto; - top: 0; display: flex; justify-content: space-evenly; font-family: "Are You Serious", cursive; @@ -68,35 +66,26 @@ a { } .back .next { - background-color: #FBEEC1; /* colors are not working*/ + background-color: #FBEEC1; color: #3b2512; } -.back .next a:hover { - background-color: red; /* colors are not working*/ - color: red; -} - - - .container-main{ - display: grid; - grid-template-columns: 1fr 1fr; + display: flex; margin: auto; justify-content: center; gap: 2em; - - + align-items: center; } #welcome { display: flex; flex-direction: column; - margin-top: 2em; padding: 2rem; - width: 100%; - + width: 100%; + text-align: center; + margin-top: -2em; } .logo { @@ -104,11 +93,6 @@ font-family: "Are You Serious", cursive; font-size: 2em; } -.heart { -padding-left: 10em; - -} - .container_photo { width: 80%; overflow: hidden; @@ -123,6 +107,9 @@ width: 100%; height: 100%; object-fit: cover; opacity: 1; +border: 5px solid #3b2512; +border-radius: 15px; +box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); } @@ -137,51 +124,6 @@ footer { } - -/* COFFEE SECTION */ -/* -.container_coffee { -display: grid; -grid-template-columns: 1fr 1fr 1fr; -flex-wrap: wrap; -gap: 16px; -} - - -.column { -flex: 1 1 calc(33.333% - 16px); // Three columns layout with space // -box-sizing: border-box; -} -.coffee-image img { -width: 100%; // Responsive image width // -height: auto; -} -.coffee-name { -margin-top: 8px; -} -// Hide elements by default // -.column { -display: none; -} -// Show elements with 'show' class // -.show { -display: block; -} -// Style for the active button // -.btn.active { -background-color: #666; -color: white; -} -// Basic button styling // -.btn { -margin: 5px; -padding: 10px 20px; -cursor: pointer; -border: none; -background-color: #f1f1f1; -} -*/ - /* COFFEE SECTION */ #coffee { width: 80%; @@ -189,7 +131,6 @@ padding: 10px; margin: auto; } - .btn { padding: 10px; margin-right: 5px; @@ -210,11 +151,9 @@ background-color: #04AA6D; color:#3b2512; } - .container_coffee { display: flex; flex-wrap: wrap; - } .row { @@ -223,21 +162,18 @@ flex-wrap: wrap; } .column { -flex: 1 1 200px; /* Adjust to fit your layout */ +flex: 1 1 200px; margin: 10px; box-sizing: border-box; - } .coffee-image img { -width: 80%; /* Adjust to fit your layout */ - +width: 80%; } .coffee-name { text-align: center; margin: 10px 0; - } .content { @@ -281,52 +217,9 @@ border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); text-align: center; width: 12em; - -} -form.search { -position: relative; -width: 600px; } -form.search input[type="text"] { -padding: 10px; -font-size: 17px; -border: 1px solid #3b2512; -background: #FBEEC1; -width: calc(100% - 82px); -box-sizing: border-box; -border-radius: 4px 0 0 4px; -} - -form.search button { - width: 80px; - padding: 10px; - background: #FBEEC1; - color: #3b2512; - font-size:17px; - border: 1px solid #3b2512; - border-left: none; - border-radius: 0 4px 4px 0; - position: absolute; - right: 0; - top: 0; - margin-top: 5px; - -} - -.search button:hover { - background: #04AA6D; -} - -form.search::after { - content: ""; - clear: both; - display: table; -} - - .dog_card button { - /*border: none;*/ outline: 0; padding: 5px; color: #3b2512; @@ -337,7 +230,6 @@ form.search::after { height: 2em; font-size: 18px; border-radius: 5px; - } .dog_card button:hover { @@ -376,6 +268,41 @@ form.search::after { } +/* GIFTS SECTION */ +.container_gifts { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-bottom: 2em; +} + +.gift_row { + display: flex; + flex-wrap: wrap; + gap: 1.5em; +} + +#gifts .content { + height: 18em; +} + +.gift-image img { + width: 80%; + height: auto; +} + +.gift-name { + text-align: center; + margin: 10px 0; +} + +.order { + letter-spacing: 1px; + width: 4em; + height: 2em; + font-size: 18px; +} + /* RESERVATION SECTION */ @@ -422,20 +349,29 @@ border: #ddd; border-radius: 5px; cursor: pointer; width: 30%; -/* opacity: 0.9;*/ font-size: .75em; } -/* The popup chat - hidden by default */ - +.chat-popup { + display: none; +} -/* Add styles to the form container */ .form-container { max-width: 100%; padding: 10px; background-color: #FBEEC1; border-radius: 10px; padding: 2em; +display: flex; +flex-direction: column; +justify-content: center; +align-items: center; +} + +#petPhoto { + border: 3px solid #3b2512; + border-radius: 15px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); } /* close button */ @@ -445,7 +381,26 @@ color: #3b2512; padding: .5em; border: none; width: 30%; -margin-bottom: 10px; +margin-top: 1em; border-radius: 5px; } +/* top button */ +#topBtn { + border: #3b2512 1px solid; + background-color: #FBEEC1; + padding: 8px 14px; + font-size: 1rem; + letter-spacing: 2px; + left: 100%; + transform: translateX(-170%); + text-align: right; + border-radius: 5px; + margin: 30px; + position: fixed; + bottom: .5em; +} + +#topBtn:hover { +background-color: #04AA6D; +} diff --git a/css/media.css b/css/media.css new file mode 100644 index 0000000..b74085e --- /dev/null +++ b/css/media.css @@ -0,0 +1,14 @@ +@media (max-width: 850px) { + body { + font-size: 1.25rem; + } + .navbar{ + width: 90%; + } + .container-reserve { + flex-direction: column; + } + .container_booking { + width: 90%; + } +} \ No newline at end of file diff --git a/dogs.html b/dogs.html index 9466728..8c25f98 100644 --- a/dogs.html +++ b/dogs.html @@ -9,9 +9,9 @@ - + + - Dogs @@ -23,6 +23,7 @@ Home Coffee Dogs + Gifts Reservation @@ -51,12 +52,15 @@
- - -
- + + + + + + + diff --git a/drinks.html b/drinks.html index 96d37d1..f8f4382 100644 --- a/drinks.html +++ b/drinks.html @@ -8,9 +8,9 @@ - + + - Drinks @@ -22,6 +22,7 @@ Home Coffee Dogs + Gifts Reservation @@ -29,10 +30,10 @@

Choose a drink

- + - +
@@ -46,6 +47,8 @@

Choose a drink

+ + diff --git a/gifts.html b/gifts.html new file mode 100644 index 0000000..dc67a8a --- /dev/null +++ b/gifts.html @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + Gifts + + +
+
+
+ +
+

Buy a snack or a toy for the dog

+
+
+ +
+
+ chicken snacks +
+

"Bones" snacks

+

+
+ +
+
+ colorful snacks +
+

"Colorful bones" snacks

+

+
+
+
+ dumbbells snacks +
+

"Dumbbells" snacks

+

+
+
+
+ heart snacks +
+

"Hearts" snacks

+

+
+ + +
+
+ big snacks +
+

"Big bones" snacks

+

+
+ +
+
+ duck toy +
+

Duck

+

+
+ +
+
+ ropes toys +
+

Ropes

+

+
+ +
+
+ balls toys +
+

Balls

+

+
+ +
+
+ pink rubber toys +
+

"Rubber toys"

+

+
+
+
+
+ + + + + +
+

Elena Nam ©

+
+ +
+ + + + \ No newline at end of file diff --git a/adoptapet.png b/images/adoptapet.png similarity index 100% rename from adoptapet.png rename to images/adoptapet.png diff --git a/images/big_snacks.jpg b/images/big_snacks.jpg new file mode 100644 index 0000000..47dea72 Binary files /dev/null and b/images/big_snacks.jpg differ diff --git a/images/chicken_snacks.jpg b/images/chicken_snacks.jpg new file mode 100644 index 0000000..87b81ad Binary files /dev/null and b/images/chicken_snacks.jpg differ diff --git a/images/color_snacks.jpg b/images/color_snacks.jpg new file mode 100644 index 0000000..5a9f4ac Binary files /dev/null and b/images/color_snacks.jpg differ diff --git a/dog.jpg b/images/dog.jpg similarity index 100% rename from dog.jpg rename to images/dog.jpg diff --git a/images/duck.jpg b/images/duck.jpg new file mode 100644 index 0000000..291b83a Binary files /dev/null and b/images/duck.jpg differ diff --git a/images/dumbbells.jpg b/images/dumbbells.jpg new file mode 100644 index 0000000..e0619f3 Binary files /dev/null and b/images/dumbbells.jpg differ diff --git a/heart.png b/images/heart.png similarity index 100% rename from heart.png rename to images/heart.png diff --git a/images/heart_snack.jpg b/images/heart_snack.jpg new file mode 100644 index 0000000..1bb2bee Binary files /dev/null and b/images/heart_snack.jpg differ diff --git a/images/pink_toys.jpg b/images/pink_toys.jpg new file mode 100644 index 0000000..a5cf1ce Binary files /dev/null and b/images/pink_toys.jpg differ diff --git a/images/ropes.jpg b/images/ropes.jpg new file mode 100644 index 0000000..109e283 Binary files /dev/null and b/images/ropes.jpg differ diff --git a/images/three_balls.jpg b/images/three_balls.jpg new file mode 100644 index 0000000..5b15f77 Binary files /dev/null and b/images/three_balls.jpg differ diff --git a/index.html b/index.html index dc9f856..114c647 100644 --- a/index.html +++ b/index.html @@ -8,9 +8,9 @@ - + + - Taily Daily @@ -23,6 +23,7 @@ Home Coffee Dogs + Gifts Reservation @@ -33,11 +34,11 @@

Welcome to

Make your coffee break extra cuddly by spending time with our adorable friends! Meet cute adoptable dogs from the shelter while enjoying your coffee in our comfortable and cozy cafe.

- dogs heart + dogs heart
- +
@@ -51,7 +52,7 @@

Welcome to

- + diff --git a/js/dogs.js b/js/dogs.js index ef43a92..63e2169 100644 --- a/js/dogs.js +++ b/js/dogs.js @@ -1,6 +1,7 @@ const url = 'https://api-staging.adoptapet.com/search/pet_search?key=hg4nsv85lppeoqqixy3tnlt3k8lj6o0c&v=3&output=json&city_or_zip=29445&geo_range=50&species=dog&breed_id=real=801&sex=m&age=young&color_id=54&pet_size_range_id=2&hair=&bonded_pair=&special_needs=&include_mixes=&added_after=&start_number=1&end_number=50&meta_only=0'; + async function fetchDogsData() { try { const response = await fetch(url, { @@ -35,7 +36,7 @@ async function fetchDogsData() {

${dog.primary_breed}

-

+

@@ -53,10 +54,6 @@ async function fetchDogsData() { fetchDogsData(); -function bookDog(petName) { - alert(`You chose ${petName}`); -} - function showPopup(age, sex, size, location) { document.getElementById('popup-age').innerText = age; @@ -69,3 +66,46 @@ function showPopup(age, sex, size, location) { function closePopup() { document.getElementById('popup').style.display = 'none'; // Hide the popup } + + +function bookDog(petName, petPhoto) { + alert(`You booked the time with ${petName}`); + + const existingData = sessionStorage.getItem('userInfo'); + let userData = existingData; + + if (existingData) { + userData = JSON.parse(existingData); + } else { + userData = {}; + } + + // Store the chosen dog in the userData + userData.dog = petName; + userData.dogPhoto = petPhoto; + + sessionStorage.setItem('userInfo', JSON.stringify(userData)); + + // Redirect to the gifts page + window.location.href = "gifts.html"; + +} + + +// top button // +let mybutton = document.getElementById("topBtn"); + +// When the user scrolls down 20px from the top of the document, show the button +window.onscroll = function() {scrollFunction()}; +function scrollFunction() { + if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { + mybutton.style.display = "block"; + } else { + mybutton.style.display = "none"; + } +} +// When the user clicks on the button, scroll to the top of the document +function topFunction() { + document.body.scrollTop = 0; // For Safari + document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera +} diff --git a/js/drinks.js b/js/drinks.js index 619fa72..3a75f2d 100644 --- a/js/drinks.js +++ b/js/drinks.js @@ -37,8 +37,38 @@ async function getIcedCoffeeData() { } catch (error) { console.error(error); } +} + +// get data of hot coffee // +/*async function getHotCoffeeData() { + try { + const response = await fetch('https://api.sampleapis.com/coffee/hot'); + if (!response.ok) { + throw new Error('Request failed'); + } + + const data = await response.json(); + console.log(data); +/* + const coffeeList = document.getElementById('coffee-list'); + coffeeList.innerHTML = ''; + data.forEach (coffee => { + coffeeList.innerHTML += `
+
+
+ ${coffee.title} +
+

${coffee.title}

+

+
+
`; +}); + } catch (error) { + console.error(error); + } } +*/ /* Hot coffee */ // get data of hot coffee // @@ -46,15 +76,24 @@ async function getHotCoffeeData() { try { const response = await fetch('https://api.sampleapis.com/coffee/hot'); if (!response.ok) { - throw new Error('Request failed'); + throw new Error('Request failed'); } const data = await response.json(); + const coffeeTerms = ['coffee', 'espresso', 'caffeine', 'latte', 'cappuccino']; + + // Filter drinks to include only those with coffee-related ingredients + const drinksWithCoffee = data.filter(coffee => + coffee.ingredients.some(ingredient => + coffeeTerms.some(term => ingredient.toLowerCase().includes(term)) + ) + ); + const coffeeList = document.getElementById('coffee-list'); coffeeList.innerHTML = ''; - data.forEach (coffee => { + drinksWithCoffee.forEach(coffee => { coffeeList.innerHTML += `
@@ -64,68 +103,54 @@ async function getHotCoffeeData() {

`; -}); + }); + } catch (error) { console.error(error); } - } -getHotCoffeeData(); -getIcedCoffeeData(); - /* Other drinks */ -// how to separate other drinks from hot coffee list? // -/* -async function getHotCoffeeData1() { +// get data of hot coffee and then separate drinks which don't include coffee // +async function getOtherDrinksData() { try { const response = await fetch('https://api.sampleapis.com/coffee/hot'); if (!response.ok) { - throw new Error('Request failed'); + throw new Error('Request failed'); } const data = await response.json(); + const coffeeTerms = ['coffee', 'espresso', 'caffeine', 'latte', 'cappuccino']; + + const drinksWithoutCoffee = data.filter(coffee => + !coffee.ingredients.some(ingredient => + coffeeTerms.some(term => ingredient.toLowerCase().includes(term)) + ) + + ); + const coffeeList = document.getElementById('coffee-list'); coffeeList.innerHTML = ''; - data.forEach (coffee => { - const isOtherDrink = [ - 'Chai Latte', - 'Matcha Latte', - 'Seasonal Brew', - 'Svart Te', - 'Islatte', - 'Islatte Mocha', - 'Frapino Caramel', - 'Frapino Mocka', - 'Apelsinjuice', - 'Frozen Lemonade', - 'Lemonad' - ].includes(coffee.title); - - - const className = isOtherDrink ? 'other-drinks-card' : 'hot-coffee-card'; - coffeeList.innerHTML += `
+ drinksWithoutCoffee.forEach(coffee => { + coffeeList.innerHTML += `
${coffee.title}

${coffee.title}

-

+

`; -}); + }); } catch (error) { console.error(error); } - } + -getHotCoffeeData1(); -*/ - -// Function to filter the drinks +// Function to filter the drinks // function filterSelection(category) { const columns = document.querySelectorAll('.column'); if (category === 'all') { @@ -137,9 +162,36 @@ function filterSelection(category) { } } + +// Collect user data and store in sessionStorage // function chooseDrink(drinkTitle) { alert(`You chose ${drinkTitle}`); + //Create userData + let userData = { + drink: drinkTitle // Store the chosen drink + }; + //Store userData in sessionStorage + sessionStorage.setItem('userInfo', JSON.stringify(userData)); + // Redirect to dogs page + window.location.href = "dogs.html"; } +// top button // +let mybutton = document.getElementById("topBtn"); +// When the user scrolls down 20px from the top of the document, show the button +window.onscroll = function() {scrollFunction()}; +function scrollFunction() { + if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { + mybutton.style.display = "block"; + } else { + mybutton.style.display = "none"; + } +} +// When the user clicks on the button, scroll to the top of the document +function topFunction() { + document.body.scrollTop = 0; // For Safari + document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera +} + diff --git a/js/gifts.js b/js/gifts.js new file mode 100644 index 0000000..2134618 --- /dev/null +++ b/js/gifts.js @@ -0,0 +1,41 @@ + +document.getElementById('year').textContent = new Date().getFullYear(); + +// Collect user data and store in sessionStorage // +function chooseGift(giftTitle) { + alert(`You chose ${giftTitle}`); + + const existingData = sessionStorage.getItem('userInfo'); + let userData = existingData; + + if (existingData) { + userData = JSON.parse(existingData); + } else { + userData = {}; + } + // Store the chosen gift in the userData + userData.gift = giftTitle; +//Store userData in sessionStorage + sessionStorage.setItem('userInfo', JSON.stringify(userData)); +// Redirect to the reservation page + window.location.href = "reservation.html"; +} + + + + // top button // +let mybutton = document.getElementById("topBtn"); +// When the user scrolls down 20px from the top of the document, show the button +window.onscroll = function() {scrollFunction()}; +function scrollFunction() { + if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { + mybutton.style.display = "block"; + } else { + mybutton.style.display = "none"; + } +} +// When the user clicks on the button, scroll to the top of the document +function topFunction() { + document.body.scrollTop = 0; // For Safari + document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera +} \ No newline at end of file diff --git a/js/reservation.js b/js/reservation.js index 3678f92..5d87432 100644 --- a/js/reservation.js +++ b/js/reservation.js @@ -1,3 +1,5 @@ +document.getElementById('year').textContent = new Date().getFullYear(); + document.addEventListener('DOMContentLoaded', () => { const bookNowBtn = document.getElementById('bookNowBtn'); const myForm = document.getElementById('myForm'); @@ -8,7 +10,7 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('userName').textContent = userName || 'Guest'; myForm.style.display = 'block'; // Show the popup // }); - + closeFormBtn.addEventListener('click', () => { myForm.style.display = 'none'; // Hide the popup // }); @@ -19,5 +21,31 @@ document.addEventListener('DOMContentLoaded', () => { myForm.style.display = 'none'; // Hide the popup // } }); - }); - \ No newline at end of file +}); + + + // Retrieve userInfo from session storage // + + const storedData = sessionStorage.getItem('userInfo'); + + if (storedData) { + // Parse the JSON string back into an object + const userInfo = JSON.parse(storedData); + + // Display the chosen drink, gift and dog + const userDrink = document.querySelector('#booking-drink'); + userDrink.innerHTML = `${userInfo.drink}`; + const userGift = document.querySelector('#booking-gift'); + userGift.innerHTML = `${userInfo.gift}`; + const userDog = document.querySelector('#booking-dog'); + userDog.innerHTML = `${userInfo.dog}`; + const userDogPhoto = document.querySelector('#petPhoto'); + userDogPhoto.src = userInfo.dogPhoto; + + } else { + console.log("Make a choice"); + } + + sessionStorage.clear(); + + \ No newline at end of file diff --git a/reservation.html b/reservation.html index 7787257..e4cfc3a 100644 --- a/reservation.html +++ b/reservation.html @@ -8,9 +8,9 @@ - + + - Reservation @@ -22,6 +22,7 @@ Home Coffee Dogs + Gifts Reservation
@@ -35,44 +36,49 @@

Make a reservation

Please fill in this form to finish your reservation.


-
This is the place for dog's photo

+

+ + +
+
+



- -
This is the place for booked drink
- + +
+
- - - +
-
-

Thank you for reservation

- +
-

Thank you, NAME

-

I am looking forward to meeting with you!

-

Dog's photo

- - +

Thank you, NAME

- dogs heart + dogs heart
+

I am looking forward to meeting with you!

+ Dog's photo +
+
- +
+ +