diff --git a/1-color-flipper/final/app.js b/01-color-flipper/final/app.js similarity index 100% rename from 1-color-flipper/final/app.js rename to 01-color-flipper/final/app.js diff --git a/1-color-flipper/final/hex.html b/01-color-flipper/final/hex.html similarity index 100% rename from 1-color-flipper/final/hex.html rename to 01-color-flipper/final/hex.html diff --git a/1-color-flipper/final/hex.js b/01-color-flipper/final/hex.js similarity index 100% rename from 1-color-flipper/final/hex.js rename to 01-color-flipper/final/hex.js diff --git a/1-color-flipper/final/index.html b/01-color-flipper/final/index.html similarity index 100% rename from 1-color-flipper/final/index.html rename to 01-color-flipper/final/index.html diff --git a/1-color-flipper/final/styles.css b/01-color-flipper/final/styles.css similarity index 100% rename from 1-color-flipper/final/styles.css rename to 01-color-flipper/final/styles.css diff --git a/1-color-flipper/setup/app.js b/01-color-flipper/setup/app.js similarity index 100% rename from 1-color-flipper/setup/app.js rename to 01-color-flipper/setup/app.js diff --git a/1-color-flipper/setup/hex.html b/01-color-flipper/setup/hex.html similarity index 100% rename from 1-color-flipper/setup/hex.html rename to 01-color-flipper/setup/hex.html diff --git a/1-color-flipper/setup/hex.js b/01-color-flipper/setup/hex.js similarity index 100% rename from 1-color-flipper/setup/hex.js rename to 01-color-flipper/setup/hex.js diff --git a/1-color-flipper/setup/index.html b/01-color-flipper/setup/index.html similarity index 100% rename from 1-color-flipper/setup/index.html rename to 01-color-flipper/setup/index.html diff --git a/1-color-flipper/setup/styles.css b/01-color-flipper/setup/styles.css similarity index 100% rename from 1-color-flipper/setup/styles.css rename to 01-color-flipper/setup/styles.css diff --git a/2-counter/final/app.js b/02-counter/final/app.js similarity index 100% rename from 2-counter/final/app.js rename to 02-counter/final/app.js diff --git a/2-counter/final/index.html b/02-counter/final/index.html similarity index 100% rename from 2-counter/final/index.html rename to 02-counter/final/index.html diff --git a/2-counter/final/styles.css b/02-counter/final/styles.css similarity index 100% rename from 2-counter/final/styles.css rename to 02-counter/final/styles.css diff --git a/16-ES6-slider/setup/app.js b/02-counter/setup/app.js similarity index 100% rename from 16-ES6-slider/setup/app.js rename to 02-counter/setup/app.js diff --git a/2-counter/setup/index.html b/02-counter/setup/index.html similarity index 100% rename from 2-counter/setup/index.html rename to 02-counter/setup/index.html diff --git a/2-counter/setup/styles.css b/02-counter/setup/styles.css similarity index 100% rename from 2-counter/setup/styles.css rename to 02-counter/setup/styles.css diff --git a/03-reviews/final/app.js b/03-reviews/final/app.js new file mode 100644 index 000000000..b7aacba1f --- /dev/null +++ b/03-reviews/final/app.js @@ -0,0 +1,84 @@ +// local reviews data +const reviews = [ + { + id: 1, + name: 'susan smith', + job: 'web developer', + img: 'https://www.course-api.com/images/people/person-1.jpeg', + text: "I'm baby meggings twee health goth +1. Bicycle rights tumeric chartreuse before they sold out chambray pop-up. Shaman humblebrag pickled coloring book salvia hoodie, cold-pressed four dollar toast everyday carry", + }, + { + id: 2, + name: 'anna johnson', + job: 'web designer', + img: 'https://www.course-api.com/images/people/person-2.jpeg', + text: 'Helvetica artisan kinfolk thundercats lumbersexual blue bottle. Disrupt glossier gastropub deep v vice franzen hell of brooklyn twee enamel pin fashion axe.photo booth jean shorts artisan narwhal.', + }, + { + id: 3, + name: 'peter jones', + job: 'intern', + img: 'https://www.course-api.com/images/people/person-4.jpeg', + text: 'Sriracha literally flexitarian irony, vape marfa unicorn. Glossier tattooed 8-bit, fixie waistcoat offal activated charcoal slow-carb marfa hell of pabst raclette post-ironic jianbing swag.', + }, + { + id: 4, + name: 'bill anderson', + job: 'the boss', + img: 'https://www.course-api.com/images/people/person-3.jpeg', + text: 'Edison bulb put a bird on it humblebrag, marfa pok pok heirloom fashion axe cray stumptown venmo actually seitan. VHS farm-to-table schlitz, edison bulb pop-up 3 wolf moon tote bag street art shabby chic. ', + }, +]; +// select items +const img = document.getElementById('person-img'); +const author = document.getElementById('author'); +const job = document.getElementById('job'); +const info = document.getElementById('info'); + +const prevBtn = document.querySelector('.prev-btn'); +const nextBtn = document.querySelector('.next-btn'); +const randomBtn = document.querySelector('.random-btn'); + +// set starting item +let currentItem = 0; + +// load initial item +window.addEventListener('DOMContentLoaded', function () { + const item = reviews[currentItem]; + img.src = item.img; + author.textContent = item.name; + job.textContent = item.job; + info.textContent = item.text; +}); + +// show person based on item +function showPerson(person) { + const item = reviews[person]; + img.src = item.img; + author.textContent = item.name; + job.textContent = item.job; + info.textContent = item.text; +} +// show next person +nextBtn.addEventListener('click', function () { + currentItem++; + if (currentItem > reviews.length - 1) { + currentItem = 0; + } + showPerson(currentItem); +}); +// show prev person +prevBtn.addEventListener('click', function () { + currentItem--; + if (currentItem < 0) { + currentItem = reviews.length - 1; + } + showPerson(currentItem); +}); +// show random person +randomBtn.addEventListener('click', function () { + console.log('hello'); + + currentItem = Math.floor(Math.random() * reviews.length); + showPerson(currentItem); +}); diff --git a/3-reviews/final/index.html b/03-reviews/final/index.html similarity index 100% rename from 3-reviews/final/index.html rename to 03-reviews/final/index.html diff --git a/3-reviews/final/person-1.jpeg b/03-reviews/final/person-1.jpeg similarity index 100% rename from 3-reviews/final/person-1.jpeg rename to 03-reviews/final/person-1.jpeg diff --git a/3-reviews/final/styles.css b/03-reviews/final/styles.css similarity index 100% rename from 3-reviews/final/styles.css rename to 03-reviews/final/styles.css diff --git a/03-reviews/setup/app.js b/03-reviews/setup/app.js new file mode 100644 index 000000000..b7aacba1f --- /dev/null +++ b/03-reviews/setup/app.js @@ -0,0 +1,84 @@ +// local reviews data +const reviews = [ + { + id: 1, + name: 'susan smith', + job: 'web developer', + img: 'https://www.course-api.com/images/people/person-1.jpeg', + text: "I'm baby meggings twee health goth +1. Bicycle rights tumeric chartreuse before they sold out chambray pop-up. Shaman humblebrag pickled coloring book salvia hoodie, cold-pressed four dollar toast everyday carry", + }, + { + id: 2, + name: 'anna johnson', + job: 'web designer', + img: 'https://www.course-api.com/images/people/person-2.jpeg', + text: 'Helvetica artisan kinfolk thundercats lumbersexual blue bottle. Disrupt glossier gastropub deep v vice franzen hell of brooklyn twee enamel pin fashion axe.photo booth jean shorts artisan narwhal.', + }, + { + id: 3, + name: 'peter jones', + job: 'intern', + img: 'https://www.course-api.com/images/people/person-4.jpeg', + text: 'Sriracha literally flexitarian irony, vape marfa unicorn. Glossier tattooed 8-bit, fixie waistcoat offal activated charcoal slow-carb marfa hell of pabst raclette post-ironic jianbing swag.', + }, + { + id: 4, + name: 'bill anderson', + job: 'the boss', + img: 'https://www.course-api.com/images/people/person-3.jpeg', + text: 'Edison bulb put a bird on it humblebrag, marfa pok pok heirloom fashion axe cray stumptown venmo actually seitan. VHS farm-to-table schlitz, edison bulb pop-up 3 wolf moon tote bag street art shabby chic. ', + }, +]; +// select items +const img = document.getElementById('person-img'); +const author = document.getElementById('author'); +const job = document.getElementById('job'); +const info = document.getElementById('info'); + +const prevBtn = document.querySelector('.prev-btn'); +const nextBtn = document.querySelector('.next-btn'); +const randomBtn = document.querySelector('.random-btn'); + +// set starting item +let currentItem = 0; + +// load initial item +window.addEventListener('DOMContentLoaded', function () { + const item = reviews[currentItem]; + img.src = item.img; + author.textContent = item.name; + job.textContent = item.job; + info.textContent = item.text; +}); + +// show person based on item +function showPerson(person) { + const item = reviews[person]; + img.src = item.img; + author.textContent = item.name; + job.textContent = item.job; + info.textContent = item.text; +} +// show next person +nextBtn.addEventListener('click', function () { + currentItem++; + if (currentItem > reviews.length - 1) { + currentItem = 0; + } + showPerson(currentItem); +}); +// show prev person +prevBtn.addEventListener('click', function () { + currentItem--; + if (currentItem < 0) { + currentItem = reviews.length - 1; + } + showPerson(currentItem); +}); +// show random person +randomBtn.addEventListener('click', function () { + console.log('hello'); + + currentItem = Math.floor(Math.random() * reviews.length); + showPerson(currentItem); +}); diff --git a/3-reviews/setup/index.html b/03-reviews/setup/index.html similarity index 100% rename from 3-reviews/setup/index.html rename to 03-reviews/setup/index.html diff --git a/3-reviews/setup/person-1.jpeg b/03-reviews/setup/person-1.jpeg similarity index 100% rename from 3-reviews/setup/person-1.jpeg rename to 03-reviews/setup/person-1.jpeg diff --git a/3-reviews/setup/styles.css b/03-reviews/setup/styles.css similarity index 100% rename from 3-reviews/setup/styles.css rename to 03-reviews/setup/styles.css diff --git a/4-navbar/final/app.js b/04-navbar/final/app.js similarity index 100% rename from 4-navbar/final/app.js rename to 04-navbar/final/app.js diff --git a/4-navbar/final/index.html b/04-navbar/final/index.html similarity index 100% rename from 4-navbar/final/index.html rename to 04-navbar/final/index.html diff --git a/4-navbar/final/logo.svg b/04-navbar/final/logo.svg similarity index 100% rename from 4-navbar/final/logo.svg rename to 04-navbar/final/logo.svg diff --git a/4-navbar/final/styles.css b/04-navbar/final/styles.css similarity index 100% rename from 4-navbar/final/styles.css rename to 04-navbar/final/styles.css diff --git a/4-navbar/final/utils.txt b/04-navbar/final/utils.txt similarity index 100% rename from 4-navbar/final/utils.txt rename to 04-navbar/final/utils.txt diff --git a/4-navbar/setup/app.js b/04-navbar/setup/app.js similarity index 100% rename from 4-navbar/setup/app.js rename to 04-navbar/setup/app.js diff --git a/4-navbar/setup/index.html b/04-navbar/setup/index.html similarity index 100% rename from 4-navbar/setup/index.html rename to 04-navbar/setup/index.html diff --git a/4-navbar/setup/logo.svg b/04-navbar/setup/logo.svg similarity index 100% rename from 4-navbar/setup/logo.svg rename to 04-navbar/setup/logo.svg diff --git a/4-navbar/setup/styles.css b/04-navbar/setup/styles.css similarity index 100% rename from 4-navbar/setup/styles.css rename to 04-navbar/setup/styles.css diff --git a/4-navbar/setup/utils.txt b/04-navbar/setup/utils.txt similarity index 100% rename from 4-navbar/setup/utils.txt rename to 04-navbar/setup/utils.txt diff --git a/5-sidebar/final/app.js b/05-sidebar/final/app.js similarity index 100% rename from 5-sidebar/final/app.js rename to 05-sidebar/final/app.js diff --git a/5-sidebar/final/index.html b/05-sidebar/final/index.html similarity index 100% rename from 5-sidebar/final/index.html rename to 05-sidebar/final/index.html diff --git a/5-sidebar/final/logo.svg b/05-sidebar/final/logo.svg similarity index 100% rename from 5-sidebar/final/logo.svg rename to 05-sidebar/final/logo.svg diff --git a/5-sidebar/final/styles.css b/05-sidebar/final/styles.css similarity index 100% rename from 5-sidebar/final/styles.css rename to 05-sidebar/final/styles.css diff --git a/5-sidebar/final/utils.txt b/05-sidebar/final/utils.txt similarity index 100% rename from 5-sidebar/final/utils.txt rename to 05-sidebar/final/utils.txt diff --git a/17-stripe-submenus/setup/app.js b/05-sidebar/setup/app.js similarity index 100% rename from 17-stripe-submenus/setup/app.js rename to 05-sidebar/setup/app.js diff --git a/5-sidebar/setup/index.html b/05-sidebar/setup/index.html similarity index 100% rename from 5-sidebar/setup/index.html rename to 05-sidebar/setup/index.html diff --git a/5-sidebar/setup/logo.svg b/05-sidebar/setup/logo.svg similarity index 100% rename from 5-sidebar/setup/logo.svg rename to 05-sidebar/setup/logo.svg diff --git a/5-sidebar/setup/styles.css b/05-sidebar/setup/styles.css similarity index 95% rename from 5-sidebar/setup/styles.css rename to 05-sidebar/setup/styles.css index 2971968ed..cc36f5499 100644 --- a/5-sidebar/setup/styles.css +++ b/05-sidebar/setup/styles.css @@ -3,7 +3,7 @@ Fonts =============== */ -@import url("https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap"); +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); /* =============== @@ -43,8 +43,8 @@ Variables --clr-green-dark: hsl(125, 67%, 44%); --clr-green-light: hsl(125, 71%, 66%); --clr-black: #222; - --ff-primary: "Roboto", sans-serif; - --ff-secondary: "Open Sans", sans-serif; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; --transition: all 0.3s linear; --spacing: 0.1rem; --radius: 0.25rem; @@ -247,7 +247,7 @@ Sidebar row-gap: 1rem; box-shadow: var(--clr-red-dark); transition: var(--transition); - transform: translate(-100%); + /* transform: translate(-100%); */ } .show-sidebar { transform: translate(0); diff --git a/5-sidebar/setup/utils.txt b/05-sidebar/setup/utils.txt similarity index 100% rename from 5-sidebar/setup/utils.txt rename to 05-sidebar/setup/utils.txt diff --git a/6-modal/final/app.js b/06-modal/final/app.js similarity index 100% rename from 6-modal/final/app.js rename to 06-modal/final/app.js diff --git a/6-modal/final/hero.jpeg b/06-modal/final/hero.jpeg similarity index 100% rename from 6-modal/final/hero.jpeg rename to 06-modal/final/hero.jpeg diff --git a/6-modal/final/index.html b/06-modal/final/index.html similarity index 100% rename from 6-modal/final/index.html rename to 06-modal/final/index.html diff --git a/6-modal/final/logo.svg b/06-modal/final/logo.svg similarity index 100% rename from 6-modal/final/logo.svg rename to 06-modal/final/logo.svg diff --git a/6-modal/final/styles.css b/06-modal/final/styles.css similarity index 100% rename from 6-modal/final/styles.css rename to 06-modal/final/styles.css diff --git a/6-modal/setup/app.js b/06-modal/setup/app.js similarity index 100% rename from 6-modal/setup/app.js rename to 06-modal/setup/app.js diff --git a/6-modal/setup/hero.jpeg b/06-modal/setup/hero.jpeg similarity index 100% rename from 6-modal/setup/hero.jpeg rename to 06-modal/setup/hero.jpeg diff --git a/6-modal/setup/index.html b/06-modal/setup/index.html similarity index 100% rename from 6-modal/setup/index.html rename to 06-modal/setup/index.html diff --git a/6-modal/setup/logo.svg b/06-modal/setup/logo.svg similarity index 100% rename from 6-modal/setup/logo.svg rename to 06-modal/setup/logo.svg diff --git a/6-modal/setup/styles.css b/06-modal/setup/styles.css similarity index 100% rename from 6-modal/setup/styles.css rename to 06-modal/setup/styles.css diff --git a/7-questions/final/app.js b/07-questions/final/app.js similarity index 100% rename from 7-questions/final/app.js rename to 07-questions/final/app.js diff --git a/7-questions/final/index.html b/07-questions/final/index.html similarity index 100% rename from 7-questions/final/index.html rename to 07-questions/final/index.html diff --git a/7-questions/final/logo.svg b/07-questions/final/logo.svg similarity index 100% rename from 7-questions/final/logo.svg rename to 07-questions/final/logo.svg diff --git a/7-questions/final/styles.css b/07-questions/final/styles.css similarity index 100% rename from 7-questions/final/styles.css rename to 07-questions/final/styles.css diff --git a/7-questions/setup/app.js b/07-questions/setup/app.js similarity index 100% rename from 7-questions/setup/app.js rename to 07-questions/setup/app.js diff --git a/7-questions/setup/index.html b/07-questions/setup/index.html similarity index 100% rename from 7-questions/setup/index.html rename to 07-questions/setup/index.html diff --git a/7-questions/setup/logo.svg b/07-questions/setup/logo.svg similarity index 100% rename from 7-questions/setup/logo.svg rename to 07-questions/setup/logo.svg diff --git a/7-questions/setup/styles.css b/07-questions/setup/styles.css similarity index 100% rename from 7-questions/setup/styles.css rename to 07-questions/setup/styles.css diff --git a/8-menu/final/1-basic.js b/08-menu/final/1-basic.js similarity index 100% rename from 8-menu/final/1-basic.js rename to 08-menu/final/1-basic.js diff --git a/8-menu/final/2-naive.txt b/08-menu/final/2-naive.txt similarity index 100% rename from 8-menu/final/2-naive.txt rename to 08-menu/final/2-naive.txt diff --git a/8-menu/final/app.js b/08-menu/final/app.js similarity index 100% rename from 8-menu/final/app.js rename to 08-menu/final/app.js diff --git a/8-menu/final/images/item-1.jpeg b/08-menu/final/images/item-1.jpeg similarity index 100% rename from 8-menu/final/images/item-1.jpeg rename to 08-menu/final/images/item-1.jpeg diff --git a/8-menu/final/images/item-10.jpeg b/08-menu/final/images/item-10.jpeg similarity index 100% rename from 8-menu/final/images/item-10.jpeg rename to 08-menu/final/images/item-10.jpeg diff --git a/8-menu/final/images/item-2.jpeg b/08-menu/final/images/item-2.jpeg similarity index 100% rename from 8-menu/final/images/item-2.jpeg rename to 08-menu/final/images/item-2.jpeg diff --git a/8-menu/final/images/item-3.jpeg b/08-menu/final/images/item-3.jpeg similarity index 100% rename from 8-menu/final/images/item-3.jpeg rename to 08-menu/final/images/item-3.jpeg diff --git a/8-menu/final/images/item-4.jpeg b/08-menu/final/images/item-4.jpeg similarity index 100% rename from 8-menu/final/images/item-4.jpeg rename to 08-menu/final/images/item-4.jpeg diff --git a/8-menu/final/images/item-5.jpeg b/08-menu/final/images/item-5.jpeg similarity index 100% rename from 8-menu/final/images/item-5.jpeg rename to 08-menu/final/images/item-5.jpeg diff --git a/8-menu/final/images/item-6.jpeg b/08-menu/final/images/item-6.jpeg similarity index 100% rename from 8-menu/final/images/item-6.jpeg rename to 08-menu/final/images/item-6.jpeg diff --git a/8-menu/final/images/item-7.jpeg b/08-menu/final/images/item-7.jpeg similarity index 100% rename from 8-menu/final/images/item-7.jpeg rename to 08-menu/final/images/item-7.jpeg diff --git a/8-menu/final/images/item-8.jpeg b/08-menu/final/images/item-8.jpeg similarity index 100% rename from 8-menu/final/images/item-8.jpeg rename to 08-menu/final/images/item-8.jpeg diff --git a/8-menu/final/images/item-9.jpeg b/08-menu/final/images/item-9.jpeg similarity index 100% rename from 8-menu/final/images/item-9.jpeg rename to 08-menu/final/images/item-9.jpeg diff --git a/8-menu/final/index.html b/08-menu/final/index.html similarity index 100% rename from 8-menu/final/index.html rename to 08-menu/final/index.html diff --git a/8-menu/final/logo.svg b/08-menu/final/logo.svg similarity index 100% rename from 8-menu/final/logo.svg rename to 08-menu/final/logo.svg diff --git a/8-menu/final/menu-item.jpeg b/08-menu/final/menu-item.jpeg similarity index 100% rename from 8-menu/final/menu-item.jpeg rename to 08-menu/final/menu-item.jpeg diff --git a/8-menu/final/styles.css b/08-menu/final/styles.css similarity index 100% rename from 8-menu/final/styles.css rename to 08-menu/final/styles.css diff --git a/8-menu/setup/1-basic.js b/08-menu/setup/1-basic.js similarity index 100% rename from 8-menu/setup/1-basic.js rename to 08-menu/setup/1-basic.js diff --git a/8-menu/setup/2-naive.txt b/08-menu/setup/2-naive.txt similarity index 100% rename from 8-menu/setup/2-naive.txt rename to 08-menu/setup/2-naive.txt diff --git a/8-menu/setup/app.js b/08-menu/setup/app.js similarity index 100% rename from 8-menu/setup/app.js rename to 08-menu/setup/app.js diff --git a/8-menu/setup/images/item-1.jpeg b/08-menu/setup/images/item-1.jpeg similarity index 100% rename from 8-menu/setup/images/item-1.jpeg rename to 08-menu/setup/images/item-1.jpeg diff --git a/8-menu/setup/images/item-10.jpeg b/08-menu/setup/images/item-10.jpeg similarity index 100% rename from 8-menu/setup/images/item-10.jpeg rename to 08-menu/setup/images/item-10.jpeg diff --git a/8-menu/setup/images/item-2.jpeg b/08-menu/setup/images/item-2.jpeg similarity index 100% rename from 8-menu/setup/images/item-2.jpeg rename to 08-menu/setup/images/item-2.jpeg diff --git a/8-menu/setup/images/item-3.jpeg b/08-menu/setup/images/item-3.jpeg similarity index 100% rename from 8-menu/setup/images/item-3.jpeg rename to 08-menu/setup/images/item-3.jpeg diff --git a/8-menu/setup/images/item-4.jpeg b/08-menu/setup/images/item-4.jpeg similarity index 100% rename from 8-menu/setup/images/item-4.jpeg rename to 08-menu/setup/images/item-4.jpeg diff --git a/8-menu/setup/images/item-5.jpeg b/08-menu/setup/images/item-5.jpeg similarity index 100% rename from 8-menu/setup/images/item-5.jpeg rename to 08-menu/setup/images/item-5.jpeg diff --git a/8-menu/setup/images/item-6.jpeg b/08-menu/setup/images/item-6.jpeg similarity index 100% rename from 8-menu/setup/images/item-6.jpeg rename to 08-menu/setup/images/item-6.jpeg diff --git a/8-menu/setup/images/item-7.jpeg b/08-menu/setup/images/item-7.jpeg similarity index 100% rename from 8-menu/setup/images/item-7.jpeg rename to 08-menu/setup/images/item-7.jpeg diff --git a/8-menu/setup/images/item-8.jpeg b/08-menu/setup/images/item-8.jpeg similarity index 100% rename from 8-menu/setup/images/item-8.jpeg rename to 08-menu/setup/images/item-8.jpeg diff --git a/8-menu/setup/images/item-9.jpeg b/08-menu/setup/images/item-9.jpeg similarity index 100% rename from 8-menu/setup/images/item-9.jpeg rename to 08-menu/setup/images/item-9.jpeg diff --git a/8-menu/setup/index.html b/08-menu/setup/index.html similarity index 100% rename from 8-menu/setup/index.html rename to 08-menu/setup/index.html diff --git a/8-menu/setup/logo.svg b/08-menu/setup/logo.svg similarity index 100% rename from 8-menu/setup/logo.svg rename to 08-menu/setup/logo.svg diff --git a/8-menu/setup/menu-item.jpeg b/08-menu/setup/menu-item.jpeg similarity index 100% rename from 8-menu/setup/menu-item.jpeg rename to 08-menu/setup/menu-item.jpeg diff --git a/8-menu/setup/styles.css b/08-menu/setup/styles.css similarity index 100% rename from 8-menu/setup/styles.css rename to 08-menu/setup/styles.css diff --git a/9-video/final/app.js b/09-video/final/app.js similarity index 100% rename from 9-video/final/app.js rename to 09-video/final/app.js diff --git a/9-video/final/index.html b/09-video/final/index.html similarity index 100% rename from 9-video/final/index.html rename to 09-video/final/index.html diff --git a/9-video/final/logo.svg b/09-video/final/logo.svg similarity index 100% rename from 9-video/final/logo.svg rename to 09-video/final/logo.svg diff --git a/9-video/final/preloader.gif b/09-video/final/preloader.gif similarity index 100% rename from 9-video/final/preloader.gif rename to 09-video/final/preloader.gif diff --git a/9-video/final/styles.css b/09-video/final/styles.css similarity index 100% rename from 9-video/final/styles.css rename to 09-video/final/styles.css diff --git a/9-video/final/video.mp4 b/09-video/final/video.mp4 similarity index 100% rename from 9-video/final/video.mp4 rename to 09-video/final/video.mp4 diff --git a/9-video/setup/app.js b/09-video/setup/app.js similarity index 100% rename from 9-video/setup/app.js rename to 09-video/setup/app.js diff --git a/9-video/setup/index.html b/09-video/setup/index.html similarity index 100% rename from 9-video/setup/index.html rename to 09-video/setup/index.html diff --git a/9-video/setup/logo.svg b/09-video/setup/logo.svg similarity index 100% rename from 9-video/setup/logo.svg rename to 09-video/setup/logo.svg diff --git a/9-video/setup/preloader.gif b/09-video/setup/preloader.gif similarity index 100% rename from 9-video/setup/preloader.gif rename to 09-video/setup/preloader.gif diff --git a/9-video/setup/styles.css b/09-video/setup/styles.css similarity index 100% rename from 9-video/setup/styles.css rename to 09-video/setup/styles.css diff --git a/9-video/setup/video.mp4 b/09-video/setup/video.mp4 similarity index 100% rename from 9-video/setup/video.mp4 rename to 09-video/setup/video.mp4 diff --git a/16-ES6-slider/VIDEO-URL.md b/16-ES6-slider/VIDEO-URL.md deleted file mode 100644 index 2e3b24f45..000000000 --- a/16-ES6-slider/VIDEO-URL.md +++ /dev/null @@ -1,4 +0,0 @@ -(JS Video)[https://youtu.be/V26mqoNncO4] -
- -(HTML&CSS Video) [https://youtu.be/1I19G1jSkvw] diff --git a/16-ES6-slider/final/app.js b/16-ES6-slider/final/app.js deleted file mode 100644 index b889bee9b..000000000 --- a/16-ES6-slider/final/app.js +++ /dev/null @@ -1,74 +0,0 @@ -import data from "./data.js"; -const container = document.querySelector(".slide-container"); -const nextBtn = document.querySelector(".next-btn"); -const prevBtn = document.querySelector(".prev-btn"); -// if length is 1 hide buttons -if (data.length === 1) { - nextBtn.style.display = "none"; - prevBtn.style.display = "none"; -} -// if length is 2, add copies of slides -let people = [...data]; -if (data.length === 2) { - people = [...data, ...data]; -} -container.innerHTML = people - .map((person, slideIndex) => { - const { img, name, job, text } = person; - let position = "next"; - if (slideIndex === 0) { - position = "active"; - } - if (slideIndex === people.length - 1) { - position = "last"; - } - if (data.length <= 1) { - position = "active"; - } - return `
- ${name} -

${name}

-

${job}

-

- ${text} -

-
- -
-
`; - }) - .join(""); - -const startSlider = (type) => { - // get all three slides active,last next - const active = document.querySelector(".active"); - const last = document.querySelector(".last"); - let next = active.nextElementSibling; - if (!next) { - next = container.firstElementChild; - } - active.classList.remove(["active"]); - last.classList.remove(["last"]); - next.classList.remove(["next"]); - - if (type === "prev") { - active.classList.add("next"); - last.classList.add("active"); - next = last.previousElementSibling; - if (!next) { - next = container.lastElementChild; - } - next.classList.remove(["next"]); - next.classList.add("last"); - return; - } - active.classList.add("last"); - last.classList.add("next"); - next.classList.add("active"); -}; -nextBtn.addEventListener("click", () => { - startSlider(); -}); -prevBtn.addEventListener("click", () => { - startSlider("prev"); -}); diff --git a/16-counter/final/app-class.js b/16-counter/final/app-class.js new file mode 100644 index 000000000..4149d7a45 --- /dev/null +++ b/16-counter/final/app-class.js @@ -0,0 +1,44 @@ +function getElement(selection) { + const element = document.querySelector(selection); + if (element) { + return element; + } + throw new Error( + `Please check "${selection}" selector, no such element exists` + ); +} + +class Counter { + constructor(element, value) { + this.counter = element; + this.value = value; + this.resetBtn = element.querySelector('.reset'); + this.increaseBtn = element.querySelector('.increase'); + this.decreaseBtn = element.querySelector('.decrease'); + this.valueDOM = element.querySelector('.value'); + this.valueDOM.textContent = this.value; + // bind this to all function + this.increase = this.increase.bind(this); + this.decrease = this.decrease.bind(this); + this.reset = this.reset.bind(this); + + this.increaseBtn.addEventListener('click', this.increase); + this.decreaseBtn.addEventListener('click', this.decrease); + this.resetBtn.addEventListener('click', this.reset); + } + increase() { + this.value++; + this.valueDOM.textContent = this.value; + } + decrease() { + this.value--; + this.valueDOM.textContent = this.value; + } + reset() { + this.value = 0; + this.valueDOM.textContent = this.value; + } +} + +const firstCounter = new Counter(getElement('.first-counter'), 100); +const secondCounter = new Counter(getElement('.second-counter'), 200); diff --git a/16-counter/final/app-proto.js b/16-counter/final/app-proto.js new file mode 100644 index 000000000..bf0e256bf --- /dev/null +++ b/16-counter/final/app-proto.js @@ -0,0 +1,43 @@ +function getElement(selection) { + const element = document.querySelector(selection); + if (element) { + return element; + } + throw new Error( + `Please check "${selection}" selector, no such element exists` + ); +} + +function Counter(element, value) { + this.counter = element; + this.value = value; + this.resetBtn = element.querySelector('.reset'); + this.increaseBtn = element.querySelector('.increase'); + this.decreaseBtn = element.querySelector('.decrease'); + this.valueDOM = element.querySelector('.value'); + this.valueDOM.textContent = this.value; + // bind this to all function + this.increase = this.increase.bind(this); + this.decrease = this.decrease.bind(this); + this.reset = this.reset.bind(this); + + this.increaseBtn.addEventListener('click', this.increase); + this.decreaseBtn.addEventListener('click', this.decrease); + this.resetBtn.addEventListener('click', this.reset); +} + +Counter.prototype.increase = function () { + this.value++; + this.valueDOM.textContent = this.value; +}; +Counter.prototype.decrease = function () { + this.value--; + this.valueDOM.textContent = this.value; +}; +Counter.prototype.reset = function () { + this.value = 0; + this.valueDOM.textContent = this.value; +}; + +const firstCounter = new Counter(getElement('.first-counter'), 100); +const secondCounter = new Counter(getElement('.second-counter'), 200); diff --git a/16-counter/final/index.html b/16-counter/final/index.html new file mode 100644 index 000000000..9876ea47f --- /dev/null +++ b/16-counter/final/index.html @@ -0,0 +1,32 @@ + + + + + + Counter + + + + +
+

first counter

+ 0 +
+ + + +
+
+ +
+

second counter

+ 0 +
+ + + +
+
+ + + diff --git a/16-counter/final/styles.css b/16-counter/final/styles.css new file mode 100644 index 000000000..072652eb1 --- /dev/null +++ b/16-counter/final/styles.css @@ -0,0 +1,193 @@ +/* +=============== +Fonts +=============== +*/ +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: hsl(205, 78%, 60%); + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; + --transition: all 0.3s linear; + --spacing: 0.1rem; + --radius: 0.25rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-grey-10); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +/* section */ +.section { + padding: 5rem 0; +} + +.section-center { + width: 90vw; + margin: 0 auto; + max-width: 1170px; +} +@media screen and (min-width: 992px) { + .section-center { + width: 95vw; + } +} +main { + min-height: 100vh; + display: grid; + place-items: center; +} + +/* +=============== +Counter +=============== +*/ + +.container { + text-align: center; + margin: 3rem auto; + background: var(--clr-white); + border-radius: var(--radius); + width: 90vw; + max-width: var(--fixed-width); + padding: 2rem; +} +.value { + font-size: 4rem; + font-weight: bold; + margin-bottom: 1.5rem; + display: inline-block; +} +.btn { + text-transform: uppercase; + background: transparent; + color: var(--clr-black); + padding: 0.375rem 0.75rem; + letter-spacing: var(--spacing); + display: inline-block; + transition: var(--transition); + font-size: 0.875rem; + border: 2px solid var(--clr-black); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + border-radius: var(--radius); + margin: 0.5rem; +} +.btn:hover { + color: var(--clr-white); + background: var(--clr-black); +} diff --git a/2-counter/setup/app.js b/16-counter/starter/app.js similarity index 100% rename from 2-counter/setup/app.js rename to 16-counter/starter/app.js diff --git a/16-counter/starter/index.html b/16-counter/starter/index.html new file mode 100644 index 000000000..ba7a237db --- /dev/null +++ b/16-counter/starter/index.html @@ -0,0 +1,13 @@ + + + + + + Counter Starter + + + +

OOP counter project starter

+ + + diff --git a/16-counter/starter/styles.css b/16-counter/starter/styles.css new file mode 100644 index 000000000..072652eb1 --- /dev/null +++ b/16-counter/starter/styles.css @@ -0,0 +1,193 @@ +/* +=============== +Fonts +=============== +*/ +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: hsl(205, 78%, 60%); + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; + --transition: all 0.3s linear; + --spacing: 0.1rem; + --radius: 0.25rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-grey-10); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +/* section */ +.section { + padding: 5rem 0; +} + +.section-center { + width: 90vw; + margin: 0 auto; + max-width: 1170px; +} +@media screen and (min-width: 992px) { + .section-center { + width: 95vw; + } +} +main { + min-height: 100vh; + display: grid; + place-items: center; +} + +/* +=============== +Counter +=============== +*/ + +.container { + text-align: center; + margin: 3rem auto; + background: var(--clr-white); + border-radius: var(--radius); + width: 90vw; + max-width: var(--fixed-width); + padding: 2rem; +} +.value { + font-size: 4rem; + font-weight: bold; + margin-bottom: 1.5rem; + display: inline-block; +} +.btn { + text-transform: uppercase; + background: transparent; + color: var(--clr-black); + padding: 0.375rem 0.75rem; + letter-spacing: var(--spacing); + display: inline-block; + transition: var(--transition); + font-size: 0.875rem; + border: 2px solid var(--clr-black); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + border-radius: var(--radius); + margin: 0.5rem; +} +.btn:hover { + color: var(--clr-white); + background: var(--clr-black); +} diff --git a/17-gallery/final/app-class.js b/17-gallery/final/app-class.js new file mode 100644 index 000000000..543252d71 --- /dev/null +++ b/17-gallery/final/app-class.js @@ -0,0 +1,98 @@ +function getElement(selection) { + const element = document.querySelector(selection); + if (element) { + return element; + } + throw new Error( + `Please check "${selection}" selector, no such element exists` + ); +} + +class Gallery { + constructor(element) { + this.container = element; + this.list = [...element.querySelectorAll('.img')]; + // target + this.modal = getElement('.modal'); + this.modalImg = getElement('.main-img'); + this.imageName = getElement('.image-name'); + this.modalImages = getElement('.modal-images'); + this.closeBtn = getElement('.close-btn'); + this.nextBtn = getElement('.next-btn'); + this.prevBtn = getElement('.prev-btn'); + // self ref + // let self = this; + // bind functions + // this.openModal = this.openModal.bind(this); + this.closeModal = this.closeModal.bind(this); + this.nextImage = this.nextImage.bind(this); + this.prevImage = this.prevImage.bind(this); + this.chooseImage = this.chooseImage.bind(this); + // container event + this.container.addEventListener( + 'click', + function (e) { + // self.openModal(); + if (e.target.classList.contains('img')) { + this.openModal(e.target, this.list); + } + }.bind(this) + ); + } + openModal(selectedImage, list) { + this.setMainImage(selectedImage); + this.modalImages.innerHTML = list + .map(function (image) { + return ``; + }) + .join(''); + this.modal.classList.add('open'); + this.closeBtn.addEventListener('click', this.closeModal); + this.nextBtn.addEventListener('click', this.nextImage); + this.prevBtn.addEventListener('click', this.prevImage); + this.modalImages.addEventListener('click', this.chooseImage); + } + + setMainImage(selectedImage) { + this.modalImg.src = selectedImage.src; + this.imageName.textContent = selectedImage.title; + } + + closeModal() { + this.modal.classList.remove('open'); + this.closeBtn.removeEventListener('click', this.closeModal); + this.nextBtn.removeEventListener('click', this.nextImage); + this.prevBtn.removeEventListener('click', this.prevImage); + this.modalImages.removeEventListener('click', this.chooseImage); + } + nextImage() { + const selected = this.modalImages.querySelector('.selected'); + const next = + selected.nextElementSibling || this.modalImages.firstElementChild; + selected.classList.remove('selected'); + next.classList.add('selected'); + this.setMainImage(next); + } + prevImage() { + const selected = this.modalImages.querySelector('.selected'); + const prev = + selected.previousElementSibling || this.modalImages.lastElementChild; + selected.classList.remove('selected'); + prev.classList.add('selected'); + this.setMainImage(prev); + } + chooseImage(e) { + if (e.target.classList.contains('modal-img')) { + const selected = this.modalImages.querySelector('.selected'); + selected.classList.remove('selected'); + + this.setMainImage(e.target); + e.target.classList.add('selected'); + } + } +} + +const nature = new Gallery(getElement('.nature')); +const city = new Gallery(getElement('.city')); diff --git a/17-gallery/final/app.js b/17-gallery/final/app.js new file mode 100644 index 000000000..9260baba2 --- /dev/null +++ b/17-gallery/final/app.js @@ -0,0 +1,96 @@ +function getElement(selection) { + const element = document.querySelector(selection); + if (element) { + return element; + } + throw new Error( + `Please check "${selection}" selector, no such element exists` + ); +} + +function Gallery(element) { + this.container = element; + this.list = [...element.querySelectorAll('.img')]; + // target + this.modal = getElement('.modal'); + this.modalImg = getElement('.main-img'); + this.imageName = getElement('.image-name'); + this.modalImages = getElement('.modal-images'); + this.closeBtn = getElement('.close-btn'); + this.nextBtn = getElement('.next-btn'); + this.prevBtn = getElement('.prev-btn'); + // self ref + // let self = this; + // bind functions + // this.openModal = this.openModal.bind(this); + this.closeModal = this.closeModal.bind(this); + this.nextImage = this.nextImage.bind(this); + this.prevImage = this.prevImage.bind(this); + this.chooseImage = this.chooseImage.bind(this); + // container event + this.container.addEventListener( + 'click', + function (e) { + // self.openModal(); + if (e.target.classList.contains('img')) { + this.openModal(e.target, this.list); + } + }.bind(this) + ); +} + +Gallery.prototype.openModal = function (selectedImage, list) { + this.setMainImage(selectedImage); + this.modalImages.innerHTML = list + .map(function (image) { + return ``; + }) + .join(''); + this.modal.classList.add('open'); + this.closeBtn.addEventListener('click', this.closeModal); + this.nextBtn.addEventListener('click', this.nextImage); + this.prevBtn.addEventListener('click', this.prevImage); + this.modalImages.addEventListener('click', this.chooseImage); +}; + +Gallery.prototype.setMainImage = function (selectedImage) { + this.modalImg.src = selectedImage.src; + this.imageName.textContent = selectedImage.title; +}; + +Gallery.prototype.closeModal = function () { + this.modal.classList.remove('open'); + this.closeBtn.removeEventListener('click', this.closeModal); + this.nextBtn.removeEventListener('click', this.nextImage); + this.prevBtn.removeEventListener('click', this.prevImage); + this.modalImages.removeEventListener('click', this.chooseImage); +}; +Gallery.prototype.nextImage = function () { + const selected = this.modalImages.querySelector('.selected'); + const next = + selected.nextElementSibling || this.modalImages.firstElementChild; + selected.classList.remove('selected'); + next.classList.add('selected'); + this.setMainImage(next); +}; +Gallery.prototype.prevImage = function () { + const selected = this.modalImages.querySelector('.selected'); + const prev = + selected.previousElementSibling || this.modalImages.lastElementChild; + selected.classList.remove('selected'); + prev.classList.add('selected'); + this.setMainImage(prev); +}; +Gallery.prototype.chooseImage = function (e) { + if (e.target.classList.contains('modal-img')) { + const selected = this.modalImages.querySelector('.selected'); + selected.classList.remove('selected'); + + this.setMainImage(e.target); + e.target.classList.add('selected'); + } +}; +const nature = new Gallery(getElement('.nature')); +const city = new Gallery(getElement('.city')); diff --git a/17-gallery/final/images/city-1.jpeg b/17-gallery/final/images/city-1.jpeg new file mode 100644 index 000000000..b11412922 Binary files /dev/null and b/17-gallery/final/images/city-1.jpeg differ diff --git a/17-gallery/final/images/city-2.jpeg b/17-gallery/final/images/city-2.jpeg new file mode 100644 index 000000000..238853350 Binary files /dev/null and b/17-gallery/final/images/city-2.jpeg differ diff --git a/17-gallery/final/images/city-3.jpeg b/17-gallery/final/images/city-3.jpeg new file mode 100644 index 000000000..cb3f547d7 Binary files /dev/null and b/17-gallery/final/images/city-3.jpeg differ diff --git a/17-gallery/final/images/city-4.jpeg b/17-gallery/final/images/city-4.jpeg new file mode 100644 index 000000000..33252b006 Binary files /dev/null and b/17-gallery/final/images/city-4.jpeg differ diff --git a/17-gallery/final/images/city-5.jpeg b/17-gallery/final/images/city-5.jpeg new file mode 100644 index 000000000..10faa1fec Binary files /dev/null and b/17-gallery/final/images/city-5.jpeg differ diff --git a/17-gallery/final/images/nature-1.jpeg b/17-gallery/final/images/nature-1.jpeg new file mode 100644 index 000000000..ce22c7777 Binary files /dev/null and b/17-gallery/final/images/nature-1.jpeg differ diff --git a/17-gallery/final/images/nature-2.jpeg b/17-gallery/final/images/nature-2.jpeg new file mode 100644 index 000000000..dbaf2c3ae Binary files /dev/null and b/17-gallery/final/images/nature-2.jpeg differ diff --git a/17-gallery/final/images/nature-3.jpeg b/17-gallery/final/images/nature-3.jpeg new file mode 100644 index 000000000..4d0133d0b Binary files /dev/null and b/17-gallery/final/images/nature-3.jpeg differ diff --git a/17-gallery/final/index.html b/17-gallery/final/index.html new file mode 100644 index 000000000..f599d6360 --- /dev/null +++ b/17-gallery/final/index.html @@ -0,0 +1,115 @@ + + + + + + Gallery + + + + + + + +
+ nature-1 + nature-2 + nature-3 +
+ +
+ city-1 + city-2 + city-3 + city-4 + city-5 +
+ + + + + + diff --git a/17-gallery/final/styles.css b/17-gallery/final/styles.css new file mode 100644 index 000000000..7abcc9795 --- /dev/null +++ b/17-gallery/final/styles.css @@ -0,0 +1,268 @@ +/* +=============== +Fonts +=============== +*/ +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: hsl(205, 78%, 60%); + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; + --transition: all 0.3s linear; + --spacing: 0.1rem; + --radius: 0.25rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.4); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-white); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +/* section */ +.section { + padding: 5rem 0; + width: 90vw; + margin: 0 auto; + max-width: 1170px; + display: grid; + gap: 2rem; +} +@media screen and (min-width: 768px) { + .section { + display: grid; + grid-template-columns: 1fr 1fr; + } +} +@media screen and (min-width: 992px) { + .section { + grid-template-columns: 1fr 1fr 1fr; + width: 95vw; + } + .prev-btn { + left: -4.5rem; + } + .next-btn { + right: -4.5rem; + } +} +.img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: var(--radius); + cursor: pointer; + transition: var(--transition); + box-shadow: var(--light-shadow); + height: 15rem; +} +.img:hover { + box-shadow: var(--dark-shadow); +} + +/* +=============== +Modal +=============== +*/ + +.modal { + position: fixed; + z-index: -1; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: rgb(0, 0, 0); + transition: var(--transition); + opacity: 0; + min-height: 100vh; + overflow: scroll; +} +.modal.open { + opacity: 1; + z-index: 999; +} +.close-btn { + position: absolute; + top: 1rem; + right: 1rem; + font-size: 3rem; + color: var(--clr-white); + background: transparent; + border-color: transparent; + cursor: pointer; +} +.next-btn, +.prev-btn { + position: absolute; + top: 10rem; + transform: translateY(-50%); + background: transparent; + font-size: 2rem; + color: var(--clr-white); + border-color: transparent; + cursor: pointer; +} +.prev-btn { + left: -2.5rem; +} +.next-btn { + right: -2.5rem; +} +@media screen and (min-width: 768px) { + .prev-btn { + left: -4rem; + } + .next-btn { + right: -4rem; + } +} + +.modal-content { + width: 80%; + max-width: var(--max-width); + margin: 0 auto; + margin-top: 10rem; + position: relative; +} +.main-img { + width: 100%; + height: 20rem; + object-fit: cover; + border-radius: var(--radius); +} +.image-name { + text-align: center; + margin: 1rem 0 3rem; + color: var(--clr-white); +} +.modal-images { + display: grid; + grid-template-columns: repeat(5, 1fr); +} +.modal-img { + width: 100%; + height: 5rem; + object-fit: cover; + opacity: 0.5; + transition: var(--transition); + cursor: pointer; +} +.modal-img:hover { + opacity: 1; +} +.modal-img.selected { + opacity: 1; +} diff --git a/17-gallery/starter/app.js b/17-gallery/starter/app.js new file mode 100644 index 000000000..dd302352f --- /dev/null +++ b/17-gallery/starter/app.js @@ -0,0 +1,9 @@ +function getElement(selection) { + const element = document.querySelector(selection); + if (element) { + return element; + } + throw new Error( + `Please check "${selection}" selector, no such element exists` + ); +} diff --git a/17-gallery/starter/images/city-1.jpeg b/17-gallery/starter/images/city-1.jpeg new file mode 100644 index 000000000..b11412922 Binary files /dev/null and b/17-gallery/starter/images/city-1.jpeg differ diff --git a/17-gallery/starter/images/city-2.jpeg b/17-gallery/starter/images/city-2.jpeg new file mode 100644 index 000000000..238853350 Binary files /dev/null and b/17-gallery/starter/images/city-2.jpeg differ diff --git a/17-gallery/starter/images/city-3.jpeg b/17-gallery/starter/images/city-3.jpeg new file mode 100644 index 000000000..cb3f547d7 Binary files /dev/null and b/17-gallery/starter/images/city-3.jpeg differ diff --git a/17-gallery/starter/images/city-4.jpeg b/17-gallery/starter/images/city-4.jpeg new file mode 100644 index 000000000..33252b006 Binary files /dev/null and b/17-gallery/starter/images/city-4.jpeg differ diff --git a/17-gallery/starter/images/city-5.jpeg b/17-gallery/starter/images/city-5.jpeg new file mode 100644 index 000000000..10faa1fec Binary files /dev/null and b/17-gallery/starter/images/city-5.jpeg differ diff --git a/17-gallery/starter/images/nature-1.jpeg b/17-gallery/starter/images/nature-1.jpeg new file mode 100644 index 000000000..ce22c7777 Binary files /dev/null and b/17-gallery/starter/images/nature-1.jpeg differ diff --git a/17-gallery/starter/images/nature-2.jpeg b/17-gallery/starter/images/nature-2.jpeg new file mode 100644 index 000000000..dbaf2c3ae Binary files /dev/null and b/17-gallery/starter/images/nature-2.jpeg differ diff --git a/17-gallery/starter/images/nature-3.jpeg b/17-gallery/starter/images/nature-3.jpeg new file mode 100644 index 000000000..4d0133d0b Binary files /dev/null and b/17-gallery/starter/images/nature-3.jpeg differ diff --git a/17-gallery/starter/index.html b/17-gallery/starter/index.html new file mode 100644 index 000000000..b17887809 --- /dev/null +++ b/17-gallery/starter/index.html @@ -0,0 +1,19 @@ + + + + + + Gallery Starter + + + + + + +

gallery project starter

+ + + diff --git a/17-gallery/starter/styles.css b/17-gallery/starter/styles.css new file mode 100644 index 000000000..7abcc9795 --- /dev/null +++ b/17-gallery/starter/styles.css @@ -0,0 +1,268 @@ +/* +=============== +Fonts +=============== +*/ +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: hsl(205, 78%, 60%); + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; + --transition: all 0.3s linear; + --spacing: 0.1rem; + --radius: 0.25rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.4); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-white); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +/* section */ +.section { + padding: 5rem 0; + width: 90vw; + margin: 0 auto; + max-width: 1170px; + display: grid; + gap: 2rem; +} +@media screen and (min-width: 768px) { + .section { + display: grid; + grid-template-columns: 1fr 1fr; + } +} +@media screen and (min-width: 992px) { + .section { + grid-template-columns: 1fr 1fr 1fr; + width: 95vw; + } + .prev-btn { + left: -4.5rem; + } + .next-btn { + right: -4.5rem; + } +} +.img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: var(--radius); + cursor: pointer; + transition: var(--transition); + box-shadow: var(--light-shadow); + height: 15rem; +} +.img:hover { + box-shadow: var(--dark-shadow); +} + +/* +=============== +Modal +=============== +*/ + +.modal { + position: fixed; + z-index: -1; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: rgb(0, 0, 0); + transition: var(--transition); + opacity: 0; + min-height: 100vh; + overflow: scroll; +} +.modal.open { + opacity: 1; + z-index: 999; +} +.close-btn { + position: absolute; + top: 1rem; + right: 1rem; + font-size: 3rem; + color: var(--clr-white); + background: transparent; + border-color: transparent; + cursor: pointer; +} +.next-btn, +.prev-btn { + position: absolute; + top: 10rem; + transform: translateY(-50%); + background: transparent; + font-size: 2rem; + color: var(--clr-white); + border-color: transparent; + cursor: pointer; +} +.prev-btn { + left: -2.5rem; +} +.next-btn { + right: -2.5rem; +} +@media screen and (min-width: 768px) { + .prev-btn { + left: -4rem; + } + .next-btn { + right: -4rem; + } +} + +.modal-content { + width: 80%; + max-width: var(--max-width); + margin: 0 auto; + margin-top: 10rem; + position: relative; +} +.main-img { + width: 100%; + height: 20rem; + object-fit: cover; + border-radius: var(--radius); +} +.image-name { + text-align: center; + margin: 1rem 0 3rem; + color: var(--clr-white); +} +.modal-images { + display: grid; + grid-template-columns: repeat(5, 1fr); +} +.modal-img { + width: 100%; + height: 5rem; + object-fit: cover; + opacity: 0.5; + transition: var(--transition); + cursor: pointer; +} +.modal-img:hover { + opacity: 1; +} +.modal-img.selected { + opacity: 1; +} diff --git a/17-stripe-submenus/VIDEO-URL.md b/17-stripe-submenus/VIDEO-URL.md deleted file mode 100644 index 0847e059e..000000000 --- a/17-stripe-submenus/VIDEO-URL.md +++ /dev/null @@ -1,2 +0,0 @@ -[JS Video](https://youtu.be/ypH_XA7PYBI) -
diff --git a/18-numbers/final/README.md b/18-numbers/final/README.md new file mode 100644 index 000000000..c64762a5f --- /dev/null +++ b/18-numbers/final/README.md @@ -0,0 +1,43 @@ +## Numbers Project + +#### Structure (HTML) + +- section + - article + - span.number data-value="value" (0) + - p (text) + +#### Logic (JS) + +- select all span's with .number +- iterate over and log each span +- create updateCount function +- accept el as argument +- invoke and pass each span el in iteration + +```js +const updateCount = (el) => { + const value = parseInt(el.dataset.value); + const increment = Math.ceil(value / 1000); + let initialValue = 0; +}; +``` + +```js +const updateCount = (el) => { + const value = parseInt(el.dataset.value); + const increment = Math.ceil(value / 1000); + let initialValue = 0; + + const increaseCount = setInterval(() => { + initialValue += increment; + + if (initialValue > value) { + el.textContent = `${value}+`; + clearInterval(increaseCount); + return; + } + el.textContent = `${initialValue}+`; + }, 1); +}; +``` diff --git a/18-numbers/final/app.js b/18-numbers/final/app.js new file mode 100644 index 000000000..b3ef2e2cb --- /dev/null +++ b/18-numbers/final/app.js @@ -0,0 +1,25 @@ +const items = [...document.querySelectorAll('.number')]; + +const updateCount = (el) => { + const value = parseInt(el.dataset.value); + const increment = Math.ceil(value / 1000); + // const increment = 1; + let initialValue = 0; + + const increaseCount = setInterval(() => { + initialValue += increment; + + if (initialValue > value) { + el.textContent = `${value}+`; + clearInterval(increaseCount); + return; + } + + el.textContent = `${initialValue}+`; + }, 1); + // console.log(increaseCount); +}; + +items.forEach((item) => { + updateCount(item); +}); diff --git a/18-numbers/final/index.html b/18-numbers/final/index.html new file mode 100644 index 000000000..251271636 --- /dev/null +++ b/18-numbers/final/index.html @@ -0,0 +1,33 @@ + + + + + + + Numbers Starter + + + +
+ +
+ 0 +

Succeeded Projects

+
+ + +
+ 0 +

Working Hours Spent

+
+ + +
+ 0 +

Happy Clients

+
+ +
+ + + diff --git a/18-numbers/final/styles.css b/18-numbers/final/styles.css new file mode 100644 index 000000000..bd484059a --- /dev/null +++ b/18-numbers/final/styles.css @@ -0,0 +1,178 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +:root { + --primary-100: hsl(21, 94%, 87%); + --primary-200: hsl(21, 80%, 74%); + --primary-300: hsl(21, 65%, 59%); + --primary-400: hsl(21, 57%, 50%); + /* primary/main color */ + --primary-500: hsl(21, 62%, 45%); + --primary-600: hsl(21, 77%, 34%); + --primary-700: hsl(21, 81%, 29%); + --primary-800: hsl(21, 84%, 25%); + --primary-900: hsl(21, 91%, 17%); + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + --smallText: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + --fluid-width: 90vw; + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-family: var(--headingFont); + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--smallText); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* +=============== +Numbers +=============== +*/ + +section { + padding: 5rem 0; + width: 90vw; + max-width: 1170px; + margin: 0 auto; + display: grid; + gap: 2rem; +} + +@media screen and (min-width: 768px) { + section { + grid-template-columns: 1fr 1fr; + } +} +@media screen and (min-width: 992px) { + section { + grid-template-columns: 1fr 1fr 1fr; + } +} + +article { + background: var(--white); + padding: 1rem 2rem; + border-radius: var(--borderRadius); + border-bottom: 4px solid transparent; +} + +article span { + font-size: 4rem; + font-weight: 700; + line-height: 1.25; +} + +article p { + margin: 0; + text-transform: capitalize; + font-size: 1.5rem; +} + +article:nth-of-type(1) { + border-bottom-color: #f59e0b; +} +article:nth-of-type(2) { + border-bottom-color: #14b8a6; +} +article:nth-of-type(3) { + border-bottom-color: #a855f7; +} diff --git a/18-numbers/starter/README.md b/18-numbers/starter/README.md new file mode 100644 index 000000000..c64762a5f --- /dev/null +++ b/18-numbers/starter/README.md @@ -0,0 +1,43 @@ +## Numbers Project + +#### Structure (HTML) + +- section + - article + - span.number data-value="value" (0) + - p (text) + +#### Logic (JS) + +- select all span's with .number +- iterate over and log each span +- create updateCount function +- accept el as argument +- invoke and pass each span el in iteration + +```js +const updateCount = (el) => { + const value = parseInt(el.dataset.value); + const increment = Math.ceil(value / 1000); + let initialValue = 0; +}; +``` + +```js +const updateCount = (el) => { + const value = parseInt(el.dataset.value); + const increment = Math.ceil(value / 1000); + let initialValue = 0; + + const increaseCount = setInterval(() => { + initialValue += increment; + + if (initialValue > value) { + el.textContent = `${value}+`; + clearInterval(increaseCount); + return; + } + el.textContent = `${initialValue}+`; + }, 1); +}; +``` diff --git a/18-numbers/starter/app.js b/18-numbers/starter/app.js new file mode 100644 index 000000000..9e399f610 --- /dev/null +++ b/18-numbers/starter/app.js @@ -0,0 +1 @@ +console.log('numbers project'); diff --git a/18-numbers/starter/index.html b/18-numbers/starter/index.html new file mode 100644 index 000000000..3d1305757 --- /dev/null +++ b/18-numbers/starter/index.html @@ -0,0 +1,14 @@ + + + + + + + Numbers Starter + + + +

numbers project starter

+ + + diff --git a/18-numbers/starter/styles.css b/18-numbers/starter/styles.css new file mode 100644 index 000000000..bd484059a --- /dev/null +++ b/18-numbers/starter/styles.css @@ -0,0 +1,178 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +:root { + --primary-100: hsl(21, 94%, 87%); + --primary-200: hsl(21, 80%, 74%); + --primary-300: hsl(21, 65%, 59%); + --primary-400: hsl(21, 57%, 50%); + /* primary/main color */ + --primary-500: hsl(21, 62%, 45%); + --primary-600: hsl(21, 77%, 34%); + --primary-700: hsl(21, 81%, 29%); + --primary-800: hsl(21, 84%, 25%); + --primary-900: hsl(21, 91%, 17%); + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + --smallText: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + --fluid-width: 90vw; + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-family: var(--headingFont); + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--smallText); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* +=============== +Numbers +=============== +*/ + +section { + padding: 5rem 0; + width: 90vw; + max-width: 1170px; + margin: 0 auto; + display: grid; + gap: 2rem; +} + +@media screen and (min-width: 768px) { + section { + grid-template-columns: 1fr 1fr; + } +} +@media screen and (min-width: 992px) { + section { + grid-template-columns: 1fr 1fr 1fr; + } +} + +article { + background: var(--white); + padding: 1rem 2rem; + border-radius: var(--borderRadius); + border-bottom: 4px solid transparent; +} + +article span { + font-size: 4rem; + font-weight: 700; + line-height: 1.25; +} + +article p { + margin: 0; + text-transform: capitalize; + font-size: 1.5rem; +} + +article:nth-of-type(1) { + border-bottom-color: #f59e0b; +} +article:nth-of-type(2) { + border-bottom-color: #14b8a6; +} +article:nth-of-type(3) { + border-bottom-color: #a855f7; +} diff --git a/19-dark-mode/final/README.MD b/19-dark-mode/final/README.MD new file mode 100644 index 000000000..cbb67a673 --- /dev/null +++ b/19-dark-mode/final/README.MD @@ -0,0 +1,41 @@ +## Dark Mode + +#### HTML Structure + +- main tags + - nav + - div.nav-center + - span 'overreacted' + - button.btn 'toggle' + - section.articles + - article.post + - h2 'post title' + - div.post-info + - span 'date' + - span 'read time' + - p 'content' + +#### Toggle - JS + +- select button +- add click event listener + +#### Toggle - CSS + +- create .dark-theme class + +#### Toggle - JS + +- select root element (html), toggle .dark-theme + +#### Import Data + +#### Display Articles + +- select articles +- iterate over, return article.post for each article + +#### Format Date + +- import moment.js +- format date diff --git a/19-dark-mode/final/app.js b/19-dark-mode/final/app.js new file mode 100644 index 000000000..461f6b185 --- /dev/null +++ b/19-dark-mode/final/app.js @@ -0,0 +1,25 @@ +const toggleBtn = document.querySelector('.btn'); +const articlesContainer = document.querySelector('.articles'); + +toggleBtn.addEventListener('click', () => { + document.documentElement.classList.toggle('dark-theme'); +}); + +const articlesData = articles + .map((article) => { + const { title, date, length, snippet } = article; + const formatDate = moment(date).format('MMMM Do, YYYY'); + return `
+

${title}

+
+ ${formatDate} + ${length} min read +
+

+ ${snippet} +

+
`; + }) + .join(''); + +articlesContainer.innerHTML = articlesData; diff --git a/19-dark-mode/final/data.js b/19-dark-mode/final/data.js new file mode 100644 index 000000000..90f0582fa --- /dev/null +++ b/19-dark-mode/final/data.js @@ -0,0 +1,30 @@ +const articles = [ + { + id: 1, + title: 'the WET Codbase', + date: new Date(2020, 9, 4), + length: 11, + snippet: `I'm baby ramps kombucha gluten-free ennui swag tattooed street art. Marfa biodiesel letterpress blue bottle subway tile, pop-up pok pok of.`, + }, + { + id: 2, + title: 'goodby, clean code', + date: new Date(2019, 10, 22), + length: 5, + snippet: `Biodiesel artisan seitan plaid sriracha copper mug venmo shabby chic. Kickstarter raclette kombucha, yr post-ironic jianbing try-hard flexitarian vaporware normcore.`, + }, + { + id: 3, + title: 'my decade in review', + date: new Date(2018, 7, 11), + length: 5, + snippet: `Direct trade shabby chic four dollar toast, tilde actually try-hard bicycle rights aesthetic forage. Meditation keytar asymmetrical tacos artisan truffaut. Pabst jean shorts roof party scenester.`, + }, + { + id: 4, + title: 'what are the react team principles', + date: new Date(2015, 5, 4), + length: 5, + snippet: `Selvage street art hammock affogato VHS. Mustache shaman literally wayfarers schlitz. Direct trade four loko narwhal VHS pop-up, chartreuse trust fund typewriter street art swag thundercats art party.`, + }, +]; diff --git a/19-dark-mode/final/index.html b/19-dark-mode/final/index.html new file mode 100644 index 000000000..e10831d53 --- /dev/null +++ b/19-dark-mode/final/index.html @@ -0,0 +1,36 @@ + + + + + + + Dark Mode + + + +
+ +
+ + + +
+
+ + + + + + + + diff --git a/19-dark-mode/final/styles.css b/19-dark-mode/final/styles.css new file mode 100644 index 000000000..1ca6cd8da --- /dev/null +++ b/19-dark-mode/final/styles.css @@ -0,0 +1,93 @@ +/* +=============== +Global Styles +=============== +*/ + +:root { + --clr-bcg: #fff; + --clr-font: #282c35; + --clr-primary: #d23669; + --clr-grey: #64748b; +} + +.dark-theme { + --clr-bcg: #282c35; + --clr-font: #fff; + --clr-primary: #ffa7c4; + --clr-grey: #cbd5e1; +} + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background: var(--clr-bcg); + color: var(--clr-font); + line-height: 1.5; + font-size: 0.875rem; + transition: all 0.3s linear; +} + +/* +=============== +Navbar +=============== +*/ +.nav-center { + width: 90vw; + max-width: 600px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: center; + padding: 2rem 0; +} +.nav-center span { + font-size: 2.5rem; + text-transform: capitalize; + letter-spacing: 2px; +} +.btn { + background: var(--clr-primary); + color: var(--clr-bcg); + padding: 0.25rem 0.5rem; + border-radius: 5px; + border-color: transparent; + text-transform: capitalize; + transition: all 0.3s linear; + font-weight: bold; + letter-spacing: 2px; + cursor: pointer; +} + +.articles { + padding: 5rem 0; + width: 90vw; + max-width: 600px; + margin: 0 auto; +} +.post { + margin-bottom: 3rem; +} + +.post h2 { + color: var(--clr-primary); + text-transform: capitalize; + letter-spacing: 2px; + font-size: 1.75rem; +} +.post-info { + margin-bottom: 0.75rem; + font-style: italic; + color: var(--clr-grey); +} +.post-info span { + margin-right: 0.5rem; +} diff --git a/19-dark-mode/starter/README.MD b/19-dark-mode/starter/README.MD new file mode 100644 index 000000000..cbb67a673 --- /dev/null +++ b/19-dark-mode/starter/README.MD @@ -0,0 +1,41 @@ +## Dark Mode + +#### HTML Structure + +- main tags + - nav + - div.nav-center + - span 'overreacted' + - button.btn 'toggle' + - section.articles + - article.post + - h2 'post title' + - div.post-info + - span 'date' + - span 'read time' + - p 'content' + +#### Toggle - JS + +- select button +- add click event listener + +#### Toggle - CSS + +- create .dark-theme class + +#### Toggle - JS + +- select root element (html), toggle .dark-theme + +#### Import Data + +#### Display Articles + +- select articles +- iterate over, return article.post for each article + +#### Format Date + +- import moment.js +- format date diff --git a/19-dark-mode/starter/app.js b/19-dark-mode/starter/app.js new file mode 100644 index 000000000..81cc4c510 --- /dev/null +++ b/19-dark-mode/starter/app.js @@ -0,0 +1 @@ +console.log('dark mode'); diff --git a/19-dark-mode/starter/data.js b/19-dark-mode/starter/data.js new file mode 100644 index 000000000..90f0582fa --- /dev/null +++ b/19-dark-mode/starter/data.js @@ -0,0 +1,30 @@ +const articles = [ + { + id: 1, + title: 'the WET Codbase', + date: new Date(2020, 9, 4), + length: 11, + snippet: `I'm baby ramps kombucha gluten-free ennui swag tattooed street art. Marfa biodiesel letterpress blue bottle subway tile, pop-up pok pok of.`, + }, + { + id: 2, + title: 'goodby, clean code', + date: new Date(2019, 10, 22), + length: 5, + snippet: `Biodiesel artisan seitan plaid sriracha copper mug venmo shabby chic. Kickstarter raclette kombucha, yr post-ironic jianbing try-hard flexitarian vaporware normcore.`, + }, + { + id: 3, + title: 'my decade in review', + date: new Date(2018, 7, 11), + length: 5, + snippet: `Direct trade shabby chic four dollar toast, tilde actually try-hard bicycle rights aesthetic forage. Meditation keytar asymmetrical tacos artisan truffaut. Pabst jean shorts roof party scenester.`, + }, + { + id: 4, + title: 'what are the react team principles', + date: new Date(2015, 5, 4), + length: 5, + snippet: `Selvage street art hammock affogato VHS. Mustache shaman literally wayfarers schlitz. Direct trade four loko narwhal VHS pop-up, chartreuse trust fund typewriter street art swag thundercats art party.`, + }, +]; diff --git a/19-dark-mode/starter/index.html b/19-dark-mode/starter/index.html new file mode 100644 index 000000000..d2b421b24 --- /dev/null +++ b/19-dark-mode/starter/index.html @@ -0,0 +1,14 @@ + + + + + + + Dark Mode + + + +

dark mode starter

+ + + diff --git a/19-dark-mode/starter/styles.css b/19-dark-mode/starter/styles.css new file mode 100644 index 000000000..aed0f806c --- /dev/null +++ b/19-dark-mode/starter/styles.css @@ -0,0 +1,86 @@ +/* +=============== +Global Styles +=============== +*/ + +:root { + --clr-bcg: #fff; + --clr-font: #282c35; + --clr-primary: #d23669; + --clr-grey: #64748b; +} + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background: var(--clr-bcg); + color: var(--clr-font); + line-height: 1.5; + font-size: 0.875rem; + transition: all 0.3s linear; +} + +/* +=============== +Navbar +=============== +*/ +.nav-center { + width: 90vw; + max-width: 600px; + margin: 0 auto; + display: flex; + justify-content: space-between; + align-items: center; + padding: 2rem 0; +} +.nav-center span { + font-size: 2.5rem; + text-transform: capitalize; + letter-spacing: 2px; +} +.btn { + background: var(--clr-primary); + color: var(--clr-bcg); + padding: 0.25rem 0.5rem; + border-radius: 5px; + border-color: transparent; + text-transform: capitalize; + transition: all 0.3s linear; + font-weight: bold; + letter-spacing: 2px; + cursor: pointer; +} + +.articles { + padding: 5rem 0; + width: 90vw; + max-width: 600px; + margin: 0 auto; +} +.post { + margin-bottom: 3rem; +} + +.post h2 { + color: var(--clr-primary); + text-transform: capitalize; + letter-spacing: 2px; + font-size: 1.75rem; +} +.post-info { + margin-bottom: 0.75rem; + font-style: italic; + color: var(--clr-grey); +} +.post-info span { + margin-right: 0.5rem; +} diff --git a/20-filters/final/README.md b/20-filters/final/README.md new file mode 100644 index 000000000..4f6c664d0 --- /dev/null +++ b/20-filters/final/README.md @@ -0,0 +1,80 @@ +## Filters Project + +#### HTML Structure + +- section.products + + - div.filters-container + - div.products-container + +- .filters-container + + - form.input-form + - input.search-input + - h5(company) + - article.companies + - button.company-btn(temp values) + +- .products-container + - article.product + - img.product-img.img (src from products.js) + - footer + - h5.product-name(name) + - span.product-price(price) + +#### Display Products + +- import products +- make a copy and assign to new variable (use let keyword) +- select .products-container +- setup a function displayProducts, iterate over products, display them + +#### Filter Based On Text + +- select form, input +- listen for 'keyup' events on form +- get input value +- filter based on the input value +- call displayProducts + +```js +// Text Filter + +const form = document.querySelector('.input-form'); +const searchInput = document.querySelector('.search-input'); + +form.addEventListener('keyup', () => { + // keyup - fired when key released + const inputValue = searchInput.value; + filteredProducts = products.filter((product) => { + return product.title.toLowerCase().includes(inputValue); + }); + displayProducts(); +}); +``` + +#### Empty Array + +- displayProducts() +- check length of filteredProducts +- if list.length < 1 +- set productsContainer = some text + +#### Display Filter Buttons + +- select .companies +- create function displayButtons +- get only unique companies (set) +- iterate over results +- return button with data-id +- set .companies innerHTML equal to result + +#### Filter Based on Company + +- add event listener on .companies +- look for event.target +- if contains .company-btn proceed + - if 'all' return all products (copy) + - else filter based on company value +- set search value '' +- call displayProducts diff --git a/20-filters/final/app.js b/20-filters/final/app.js new file mode 100644 index 000000000..429935f52 --- /dev/null +++ b/20-filters/final/app.js @@ -0,0 +1,82 @@ +let filteredProducts = [...products]; + +const productsContainer = document.querySelector('.products-container'); + +const displayProducts = () => { + if (filteredProducts.length < 1) { + productsContainer.innerHTML = `
Sorry, no products matched your search
`; + return; + } + + productsContainer.innerHTML = filteredProducts + .map((product) => { + const { id, title, image, price } = product; + return `
+ + +
`; + }) + .join(''); +}; + +displayProducts(); + +// Text Filter + +const form = document.querySelector('.input-form'); +const searchInput = document.querySelector('.search-input'); + +form.addEventListener('keyup', () => { + const inputValue = searchInput.value; + filteredProducts = products.filter((product) => { + return product.title.toLowerCase().includes(inputValue); + }); + displayProducts(); +}); + +// console.log( +// products.filter((product) => { +// return product.title.toLowerCase().includes(''); +// }) +// ); + +// Filter Buttons + +const companiesDOM = document.querySelector('.companies'); + +const displayButtons = () => { + const buttons = [ + 'all', + ...new Set(products.map((product) => product.company)), + ]; + // console.log(buttons); + companiesDOM.innerHTML = buttons + .map((company) => { + return ``; + }) + .join(''); +}; + +displayButtons(); + +companiesDOM.addEventListener('click', (e) => { + const el = e.target; + if (el.classList.contains('company-btn')) { + if (el.dataset.id === 'all') { + filteredProducts = [...products]; + } else { + filteredProducts = products.filter((product) => { + return product.company === el.dataset.id; + }); + } + searchInput.value = ''; + displayProducts(); + } +}); diff --git a/20-filters/final/index.html b/20-filters/final/index.html new file mode 100644 index 000000000..1eb4c6392 --- /dev/null +++ b/20-filters/final/index.html @@ -0,0 +1,46 @@ + + + + + + + Filters + + + + +
+ +
+ +
+ +
+ +
Company
+
+ + + +
+
+ +
+ +
+ + +
+
+
+ + + + diff --git a/20-filters/final/products.js b/20-filters/final/products.js new file mode 100644 index 000000000..dc1f3e4e2 --- /dev/null +++ b/20-filters/final/products.js @@ -0,0 +1,88 @@ +const products = [ + { + id: 'rec43w3ipXvP28vog', + title: 'high-back bench', + company: 'ikea', + image: 'https://www.course-api.com/images/store/product-1.jpeg', + price: 9.99, + }, + { + id: 'rec4f2RIftFCb7aHh', + title: 'albany table', + company: 'marcos', + image: 'https://www.course-api.com/images/store/product-2.jpeg', + price: 79.99, + }, + { + id: 'rec8kkCmSiMkbkiko', + title: 'accent chair', + company: 'caressa', + image: 'https://www.course-api.com/images/store/product-3.jpeg', + price: 25.99, + }, + { + id: 'recBohCqQsot4Q4II', + title: 'wooden table', + company: 'caressa', + image: 'https://www.course-api.com/images/store/product-4.jpeg', + + price: 45.99, + }, + { + id: 'recDG1JRZnbpRHpoy', + title: 'dining table', + company: 'caressa', + image: 'https://www.course-api.com/images/store/product-5.jpeg', + + price: 6.99, + }, + { + id: 'recNWGyP7kjFhSqw3', + title: 'sofa set', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-6.jpeg', + price: 69.99, + }, + { + id: 'recZEougL5bbY4AEx', + title: 'modern bookshelf', + company: 'marcos', + image: 'https://www.course-api.com/images/store/product-7.jpeg', + price: 8.99, + }, + { + id: 'recjMK1jgTb2ld7sv', + title: 'emperor bed', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-8.jpeg', + price: 21.99, + }, + { + id: 'recmg2a1ctaEJNZhu', + title: 'utopia sofa', + company: 'marcos', + image: 'https://www.course-api.com/images/store/product-9.jpeg', + price: 39.95, + }, + { + id: 'recvKMNR3YFw0bEt3', + title: 'entertainment center', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-10.jpeg', + price: 29.98, + }, + { + id: 'recxaXFy5IW539sgM', + title: 'albany sectional', + company: 'ikea', + image: 'https://www.course-api.com/images/store/product-11.jpeg', + price: 10.99, + }, + { + id: 'recyqtRglGNGtO4Q5', + title: 'leather sofa', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-12.jpeg', + price: 9.99, + }, +]; diff --git a/20-filters/final/styles.css b/20-filters/final/styles.css new file mode 100644 index 000000000..488b6a90d --- /dev/null +++ b/20-filters/final/styles.css @@ -0,0 +1,221 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +:root { + --primary-100: hsl(21, 94%, 87%); + --primary-200: hsl(21, 80%, 74%); + --primary-300: hsl(21, 65%, 59%); + --primary-400: hsl(21, 57%, 50%); + /* primary/main color */ + --primary-500: hsl(21, 62%, 45%); + --primary-600: hsl(21, 77%, 34%); + --primary-700: hsl(21, 81%, 29%); + --primary-800: hsl(21, 84%, 25%); + --primary-900: hsl(21, 91%, 17%); + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + --smallText: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + --fluid-width: 90vw; + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-family: var(--headingFont); + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--smallText); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* +=============== +Products +=============== +*/ +.products { + width: var(--fluid-width); + display: grid; + grid-gap: 1rem; + margin: 4rem auto; + max-width: var(--max-width); +} + +.filters-container h5 { + font-weight: 500; + margin: 1.5rem 0 0.5rem; + font-size: 0.85rem; +} + +.search-input { + padding: 0.5rem; + background: var(--grey-200); + border-radius: var(--borderRadius); + border-color: transparent; + letter-spacing: var(--letterSpacing); +} + +.company-btn { + display: block; + margin: 0.25em 0; + padding: 0.25rem; + text-transform: capitalize; + background: transparent; + border-color: transparent; + letter-spacing: var(--letterSpacing); + color: var(--grey-500); + cursor: pointer; + transition: var(--transition); + font-size: 0.85rem; +} +.company-btn:hover { + color: var(--grey-700); +} +.product { + margin-bottom: 1rem; +} +.product-img { + border-radius: var(--borderRadius); + height: 15rem; +} +.product footer { + padding: 0.75rem 0; + text-align: center; +} +.product-name { + margin-bottom: 0.25rem; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); + color: var(--grey-500); +} +.product-price { + margin-bottom: 0; + color: var(--grey-700); + font-weight: 700; + font-size: 1rem; + letter-spacing: var(--letterSpacing); +} + +@media screen and (min-width: 768px) { + .products { + grid-template-columns: 200px 1fr; + } +} +@media screen and (min-width: 992px) { + .products-container { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + .products-container .product-img { + height: 10rem; + } + .products-container .product-name { + font-size: 0.85rem; + } + .products-container .product-price { + font-size: 0.85rem; + } + .product { + margin-bottom: 0; + } +} +@media screen and (min-width: 1170px) { + .products-container { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/20-filters/starter/README.md b/20-filters/starter/README.md new file mode 100644 index 000000000..4f6c664d0 --- /dev/null +++ b/20-filters/starter/README.md @@ -0,0 +1,80 @@ +## Filters Project + +#### HTML Structure + +- section.products + + - div.filters-container + - div.products-container + +- .filters-container + + - form.input-form + - input.search-input + - h5(company) + - article.companies + - button.company-btn(temp values) + +- .products-container + - article.product + - img.product-img.img (src from products.js) + - footer + - h5.product-name(name) + - span.product-price(price) + +#### Display Products + +- import products +- make a copy and assign to new variable (use let keyword) +- select .products-container +- setup a function displayProducts, iterate over products, display them + +#### Filter Based On Text + +- select form, input +- listen for 'keyup' events on form +- get input value +- filter based on the input value +- call displayProducts + +```js +// Text Filter + +const form = document.querySelector('.input-form'); +const searchInput = document.querySelector('.search-input'); + +form.addEventListener('keyup', () => { + // keyup - fired when key released + const inputValue = searchInput.value; + filteredProducts = products.filter((product) => { + return product.title.toLowerCase().includes(inputValue); + }); + displayProducts(); +}); +``` + +#### Empty Array + +- displayProducts() +- check length of filteredProducts +- if list.length < 1 +- set productsContainer = some text + +#### Display Filter Buttons + +- select .companies +- create function displayButtons +- get only unique companies (set) +- iterate over results +- return button with data-id +- set .companies innerHTML equal to result + +#### Filter Based on Company + +- add event listener on .companies +- look for event.target +- if contains .company-btn proceed + - if 'all' return all products (copy) + - else filter based on company value +- set search value '' +- call displayProducts diff --git a/20-filters/starter/app.js b/20-filters/starter/app.js new file mode 100644 index 000000000..fa29b37d3 --- /dev/null +++ b/20-filters/starter/app.js @@ -0,0 +1 @@ +console.log('filters project'); diff --git a/20-filters/starter/index.html b/20-filters/starter/index.html new file mode 100644 index 000000000..b3d64d1b1 --- /dev/null +++ b/20-filters/starter/index.html @@ -0,0 +1,14 @@ + + + + + + + Filters Starter + + + +

filters projects starter

+ + + diff --git a/20-filters/starter/products.js b/20-filters/starter/products.js new file mode 100644 index 000000000..dc1f3e4e2 --- /dev/null +++ b/20-filters/starter/products.js @@ -0,0 +1,88 @@ +const products = [ + { + id: 'rec43w3ipXvP28vog', + title: 'high-back bench', + company: 'ikea', + image: 'https://www.course-api.com/images/store/product-1.jpeg', + price: 9.99, + }, + { + id: 'rec4f2RIftFCb7aHh', + title: 'albany table', + company: 'marcos', + image: 'https://www.course-api.com/images/store/product-2.jpeg', + price: 79.99, + }, + { + id: 'rec8kkCmSiMkbkiko', + title: 'accent chair', + company: 'caressa', + image: 'https://www.course-api.com/images/store/product-3.jpeg', + price: 25.99, + }, + { + id: 'recBohCqQsot4Q4II', + title: 'wooden table', + company: 'caressa', + image: 'https://www.course-api.com/images/store/product-4.jpeg', + + price: 45.99, + }, + { + id: 'recDG1JRZnbpRHpoy', + title: 'dining table', + company: 'caressa', + image: 'https://www.course-api.com/images/store/product-5.jpeg', + + price: 6.99, + }, + { + id: 'recNWGyP7kjFhSqw3', + title: 'sofa set', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-6.jpeg', + price: 69.99, + }, + { + id: 'recZEougL5bbY4AEx', + title: 'modern bookshelf', + company: 'marcos', + image: 'https://www.course-api.com/images/store/product-7.jpeg', + price: 8.99, + }, + { + id: 'recjMK1jgTb2ld7sv', + title: 'emperor bed', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-8.jpeg', + price: 21.99, + }, + { + id: 'recmg2a1ctaEJNZhu', + title: 'utopia sofa', + company: 'marcos', + image: 'https://www.course-api.com/images/store/product-9.jpeg', + price: 39.95, + }, + { + id: 'recvKMNR3YFw0bEt3', + title: 'entertainment center', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-10.jpeg', + price: 29.98, + }, + { + id: 'recxaXFy5IW539sgM', + title: 'albany sectional', + company: 'ikea', + image: 'https://www.course-api.com/images/store/product-11.jpeg', + price: 10.99, + }, + { + id: 'recyqtRglGNGtO4Q5', + title: 'leather sofa', + company: 'liddy', + image: 'https://www.course-api.com/images/store/product-12.jpeg', + price: 9.99, + }, +]; diff --git a/20-filters/starter/styles.css b/20-filters/starter/styles.css new file mode 100644 index 000000000..488b6a90d --- /dev/null +++ b/20-filters/starter/styles.css @@ -0,0 +1,221 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +:root { + --primary-100: hsl(21, 94%, 87%); + --primary-200: hsl(21, 80%, 74%); + --primary-300: hsl(21, 65%, 59%); + --primary-400: hsl(21, 57%, 50%); + /* primary/main color */ + --primary-500: hsl(21, 62%, 45%); + --primary-600: hsl(21, 77%, 34%); + --primary-700: hsl(21, 81%, 29%); + --primary-800: hsl(21, 84%, 25%); + --primary-900: hsl(21, 91%, 17%); + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + --smallText: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + --fluid-width: 90vw; + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-family: var(--headingFont); + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--smallText); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* +=============== +Products +=============== +*/ +.products { + width: var(--fluid-width); + display: grid; + grid-gap: 1rem; + margin: 4rem auto; + max-width: var(--max-width); +} + +.filters-container h5 { + font-weight: 500; + margin: 1.5rem 0 0.5rem; + font-size: 0.85rem; +} + +.search-input { + padding: 0.5rem; + background: var(--grey-200); + border-radius: var(--borderRadius); + border-color: transparent; + letter-spacing: var(--letterSpacing); +} + +.company-btn { + display: block; + margin: 0.25em 0; + padding: 0.25rem; + text-transform: capitalize; + background: transparent; + border-color: transparent; + letter-spacing: var(--letterSpacing); + color: var(--grey-500); + cursor: pointer; + transition: var(--transition); + font-size: 0.85rem; +} +.company-btn:hover { + color: var(--grey-700); +} +.product { + margin-bottom: 1rem; +} +.product-img { + border-radius: var(--borderRadius); + height: 15rem; +} +.product footer { + padding: 0.75rem 0; + text-align: center; +} +.product-name { + margin-bottom: 0.25rem; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); + color: var(--grey-500); +} +.product-price { + margin-bottom: 0; + color: var(--grey-700); + font-weight: 700; + font-size: 1rem; + letter-spacing: var(--letterSpacing); +} + +@media screen and (min-width: 768px) { + .products { + grid-template-columns: 200px 1fr; + } +} +@media screen and (min-width: 992px) { + .products-container { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + .products-container .product-img { + height: 10rem; + } + .products-container .product-name { + font-size: 0.85rem; + } + .products-container .product-price { + font-size: 0.85rem; + } + .product { + margin-bottom: 0; + } +} +@media screen and (min-width: 1170px) { + .products-container { + grid-template-columns: repeat(3, 1fr); + } +} diff --git a/21-dad-jokes/final/README.md b/21-dad-jokes/final/README.md new file mode 100644 index 000000000..fa83a5d06 --- /dev/null +++ b/21-dad-jokes/final/README.md @@ -0,0 +1,79 @@ +## Dad Jokes Project + +#### HTML Structure + +- div.container + - button.btn + - p.result(dummy text) + +#### External Data + +- the main idea the same, just external data + +#### What is an API? + +[What is an API?](https://www.freecodecamp.org/news/what-is-an-api-in-english-please-b880a3214a82/) + +- https://www.course-api.com/javascript-store-products +- get store products + +- https://www.course-api.com/javascript-store-single-product?id=rec43w3ipXvP28vog +- get single store product + +- https://randomuser.me/api/ +- random user + +#### Docs + +- important +- search engine +- test in the browser + +#### Dad Jokes Docs + +- [Dad Jokes](https://icanhazdadjoke.com/api) + +- random joke +- https://icanhazdadjoke.com/ + +#### Select Elements + +- select btn, result +- check if both elements selected +- listen for click events + +#### FetchDadJoke Function + +- create async function +- setup fetch +- set result.textContent = joke + +```js +const fetchDadJoke = async () => { + const response = await fetch(url, { + headers: { + Accept: 'application/json', + 'User-Agent': 'learning app', + }, + }); + + const data = await response.json(); + result.textContent = data.joke; +}; +``` + +#### Loading + +- set result equal to - 'Loading...' + +#### Error Handling + +- try/catch block +- set result equal to - 'There was an error..' + +#### Check Status + +- Fetch - only throws an error if cannot resolve +- Error response still a response +- check response.ok property +- throw new Error('Whoops!') diff --git a/21-dad-jokes/final/app.js b/21-dad-jokes/final/app.js new file mode 100644 index 000000000..e35cf2225 --- /dev/null +++ b/21-dad-jokes/final/app.js @@ -0,0 +1,31 @@ +const url = 'https://icanhazdadjoke.com/'; + +const btn = document.querySelector('.btn'); +const result = document.querySelector('.result'); + +btn.addEventListener('click', () => { + fetchDadJoke(); +}); + +const fetchDadJoke = async () => { + result.textContent = 'Loading...'; + try { + const response = await fetch(url, { + headers: { + Accept: 'application/json', + 'User-Agent': 'learning app', + }, + }); + if (!response.ok) { + throw new Error(' error'); + } + const data = await response.json(); + + result.textContent = data.joke; + } catch (error) { + console.log(error.message); + result.textContent = 'There was an error...'; + } +}; + +fetchDadJoke(); diff --git a/21-dad-jokes/final/index.html b/21-dad-jokes/final/index.html new file mode 100644 index 000000000..6fd3ba014 --- /dev/null +++ b/21-dad-jokes/final/index.html @@ -0,0 +1,21 @@ + + + + + + + Dad Jokes + + + +
+ +

+ Lorem, ipsum dolor sit amet consectetur adipisicing elit. Exercitationem + unde quibusdam quia ex asperiores consectetur quis maxime corporis + suscipit expedita. +

+
+ + + diff --git a/21-dad-jokes/final/styles.css b/21-dad-jokes/final/styles.css new file mode 100644 index 000000000..51f781979 --- /dev/null +++ b/21-dad-jokes/final/styles.css @@ -0,0 +1,157 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +:root { + --primary-100: hsl(21, 94%, 87%); + --primary-200: hsl(21, 80%, 74%); + --primary-300: hsl(21, 65%, 59%); + --primary-400: hsl(21, 57%, 50%); + /* primary/main color */ + --primary-500: hsl(21, 62%, 45%); + --primary-600: hsl(21, 77%, 34%); + --primary-700: hsl(21, 81%, 29%); + --primary-800: hsl(21, 84%, 25%); + --primary-900: hsl(21, 91%, 17%); + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + --smallText: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + --fluid-width: 90vw; + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-family: var(--headingFont); + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--smallText); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +.btn { + cursor: pointer; + color: var(--white); + background: var(--primary-500); + border: transparent; + border-radius: var(--borderRadius); + letter-spacing: var(--letterSpacing); + padding: 0.375rem 0.75rem; + box-shadow: var(--shadow-1); + transition: var(--transition); + text-transform: capitalize; + display: inline-block; +} +.btn:hover { + background: var(--primary-700); + box-shadow: var(--shadow-3); +} +/* +=============== +Jokes +=============== +*/ + +.container { + width: 90vw; + max-width: 700px; + margin: 0 auto; + padding-top: 5rem; +} + +.result { + font-size: 1.5rem; +} diff --git a/21-dad-jokes/starter/README.md b/21-dad-jokes/starter/README.md new file mode 100644 index 000000000..fa83a5d06 --- /dev/null +++ b/21-dad-jokes/starter/README.md @@ -0,0 +1,79 @@ +## Dad Jokes Project + +#### HTML Structure + +- div.container + - button.btn + - p.result(dummy text) + +#### External Data + +- the main idea the same, just external data + +#### What is an API? + +[What is an API?](https://www.freecodecamp.org/news/what-is-an-api-in-english-please-b880a3214a82/) + +- https://www.course-api.com/javascript-store-products +- get store products + +- https://www.course-api.com/javascript-store-single-product?id=rec43w3ipXvP28vog +- get single store product + +- https://randomuser.me/api/ +- random user + +#### Docs + +- important +- search engine +- test in the browser + +#### Dad Jokes Docs + +- [Dad Jokes](https://icanhazdadjoke.com/api) + +- random joke +- https://icanhazdadjoke.com/ + +#### Select Elements + +- select btn, result +- check if both elements selected +- listen for click events + +#### FetchDadJoke Function + +- create async function +- setup fetch +- set result.textContent = joke + +```js +const fetchDadJoke = async () => { + const response = await fetch(url, { + headers: { + Accept: 'application/json', + 'User-Agent': 'learning app', + }, + }); + + const data = await response.json(); + result.textContent = data.joke; +}; +``` + +#### Loading + +- set result equal to - 'Loading...' + +#### Error Handling + +- try/catch block +- set result equal to - 'There was an error..' + +#### Check Status + +- Fetch - only throws an error if cannot resolve +- Error response still a response +- check response.ok property +- throw new Error('Whoops!') diff --git a/21-dad-jokes/starter/app.js b/21-dad-jokes/starter/app.js new file mode 100644 index 000000000..14681936e --- /dev/null +++ b/21-dad-jokes/starter/app.js @@ -0,0 +1 @@ +console.log('Dad Jokes Starter'); diff --git a/21-dad-jokes/starter/index.html b/21-dad-jokes/starter/index.html new file mode 100644 index 000000000..f220903da --- /dev/null +++ b/21-dad-jokes/starter/index.html @@ -0,0 +1,14 @@ + + + + + + + Dad Jokes Starter + + + +

dad jokes starter

+ + + diff --git a/21-dad-jokes/starter/styles.css b/21-dad-jokes/starter/styles.css new file mode 100644 index 000000000..51f781979 --- /dev/null +++ b/21-dad-jokes/starter/styles.css @@ -0,0 +1,157 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +:root { + --primary-100: hsl(21, 94%, 87%); + --primary-200: hsl(21, 80%, 74%); + --primary-300: hsl(21, 65%, 59%); + --primary-400: hsl(21, 57%, 50%); + /* primary/main color */ + --primary-500: hsl(21, 62%, 45%); + --primary-600: hsl(21, 77%, 34%); + --primary-700: hsl(21, 81%, 29%); + --primary-800: hsl(21, 84%, 25%); + --primary-900: hsl(21, 91%, 17%); + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + --smallText: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + --fluid-width: 90vw; + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-family: var(--headingFont); + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--smallText); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +.btn { + cursor: pointer; + color: var(--white); + background: var(--primary-500); + border: transparent; + border-radius: var(--borderRadius); + letter-spacing: var(--letterSpacing); + padding: 0.375rem 0.75rem; + box-shadow: var(--shadow-1); + transition: var(--transition); + text-transform: capitalize; + display: inline-block; +} +.btn:hover { + background: var(--primary-700); + box-shadow: var(--shadow-3); +} +/* +=============== +Jokes +=============== +*/ + +.container { + width: 90vw; + max-width: 700px; + margin: 0 auto; + padding-top: 5rem; +} + +.result { + font-size: 1.5rem; +} diff --git a/22-products/final/README.md b/22-products/final/README.md new file mode 100644 index 000000000..6fc0056d3 --- /dev/null +++ b/22-products/final/README.md @@ -0,0 +1,100 @@ +## Products Project + +#### Structure (HTML) + +- section.products + + - div.title + - h2(products) + - div.title-underline + - div.products-center + - div.products-container + - a.single-product href="product.html" + - img.single-product-img.img + - footer + - h5.name (product title) + - span.price($9.99) + +- create product.html +- basic structure + +#### Loading and Error + +- (CSS Loading Spinner)[https://youtu.be/DqqZEpctZ8w] +- in .products-center +- div.loading +- p.error + +#### API Docs + +- (Course API)[https://www.course-api.com/] + +- (Products)[https://www.course-api.com/javascript-store-products] + +- (Single Product)[https://www.course-api.com/javascript-store-single-product?id=rec43w3ipXvP28vog] + +#### Fetch Products + +- select .products-center +- fetch products +- log result +- try/catch + +#### Loading and Error + +- add loading while fetching +- add error in catch + +#### Display Products - Setup + +- return data from fetchProducts +- create displayProducts(list) +- create start() +- invoke fetchProducts and displayProducts in start +- invoke start + +#### Display Products - Complete + +- iterate over list +- pull out all the values +- set productsDOM equal to result + +#### Single Product + +- link styles.css +- a.btn.home-link(back home) +- section.product +- div.product-wrapper + - img.img + - div.product-info + - h3 (title) + - h5 (company) + - span (price) + - div.colors + - span.product-color + - p (lorem text) + - button.btn(add to cart) + +#### product.js setup + +- create product.js +- link product.html +- select .product +- get single product url +- setup fetchProduct(),displayProduct(),start() + +#### Loading, Error, Fetch Single Product + +- fetch single product +- setup loading and error +- make id dynamic +- new URLSearchParams +- window.location.search +- get(keyName) + +#### Display Single Product + +#### Display Colors + +- iterate over colors array +- return span with dynamic color value diff --git a/22-products/final/app.js b/22-products/final/app.js new file mode 100644 index 000000000..48c271a71 --- /dev/null +++ b/22-products/final/app.js @@ -0,0 +1,44 @@ +const url = 'https://www.course-api.com/javascript-store-products'; + +const productsDOM = document.querySelector('.products-center'); + +const fetchProducts = async () => { + productsDOM.innerHTML = '
'; + try { + const resp = await fetch(url); + const data = await resp.json(); + return data; + } catch (error) { + productsDOM.innerHTML = '

there was an error

'; + } +}; + +const displayProducts = (list) => { + const productList = list + .map((product) => { + const { id } = product; + const { name: title, price } = product.fields; + const { url: img } = product.fields.image[0]; + const formatPrice = price / 100; + // id,name,price,img + return ` + ${title} + + `; + }) + .join(''); + productsDOM.innerHTML = `
+ ${productList} + +
`; +}; + +const start = async () => { + const data = await fetchProducts(); + displayProducts(data); +}; + +start(); diff --git a/22-products/final/couch.jpg b/22-products/final/couch.jpg new file mode 100644 index 000000000..ce4d87cf5 Binary files /dev/null and b/22-products/final/couch.jpg differ diff --git a/22-products/final/index.html b/22-products/final/index.html new file mode 100644 index 000000000..af8d9d34d --- /dev/null +++ b/22-products/final/index.html @@ -0,0 +1,22 @@ + + + + + + + Products Complete + + + +
+ +
+

our products

+
+
+ +
+
+ + + diff --git a/22-products/final/product.html b/22-products/final/product.html new file mode 100644 index 000000000..0b5d186b2 --- /dev/null +++ b/22-products/final/product.html @@ -0,0 +1,15 @@ + + + + + + + Single Product + + + + back home +
+ + + diff --git a/22-products/final/product.js b/22-products/final/product.js new file mode 100644 index 000000000..0708ebd2e --- /dev/null +++ b/22-products/final/product.js @@ -0,0 +1,63 @@ +const productDOM = document.querySelector('.product'); +const url = 'https://www.course-api.com/javascript-store-single-product'; + +const fetchProduct = async () => { + try { + productDOM.innerHTML = '

Loading...

'; + // console.log(window.location.search); + const params = new URLSearchParams(window.location.search); + const id = params.get('id'); + + const response = await fetch(`${url}?id=${id}`); + const data = await response.json(); + return data; + } catch (error) { + productDOM.innerHTML = + '

There was a problem loading the product. Please try again later

'; + } +}; + +const displayProduct = (product) => { + // company, colors, description, name:title, price, image(url:img) + const { + company, + colors, + description, + name: title, + price, + image, + } = product.fields; + const { url: img } = image[0]; + document.title = title.toUpperCase(); + + // colors + const colorsList = colors + .map((color) => { + return ``; + }) + .join(''); + + productDOM.innerHTML = `
+ ${title} +
+

${title}

+
${company}
+ ${price / 100} +
+ ${colorsList} + +
+

+ ${description} +

+ +
+
`; +}; + +const start = async () => { + const data = await fetchProduct(); + displayProduct(data); +}; + +start(); diff --git a/22-products/final/styles.css b/22-products/final/styles.css new file mode 100644 index 000000000..cfe361180 --- /dev/null +++ b/22-products/final/styles.css @@ -0,0 +1,315 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +html { + font-size: 100%; +} /*16px*/ + +:root { + /* colors */ + --primary-100: #e2e0ff; + --primary-200: #c1beff; + --primary-300: #a29dff; + --primary-400: #837dff; + --primary-500: #645cff; + --primary-600: #504acc; + --primary-700: #3c3799; + --primary-800: #282566; + --primary-900: #141233; + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + /* fonts */ + --small-text: 0.875rem; + --extra-small-text: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--small-text); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* buttons */ + +.btn { + cursor: pointer; + color: var(--white); + background: var(--primary-500); + border: transparent; + border-radius: var(--borderRadius); + letter-spacing: var(--letterSpacing); + padding: 0.375rem 0.75rem; + box-shadow: var(--shadow-1); + transition: var(--transition); + text-transform: capitalize; + display: inline-block; +} +.btn:hover { + background: var(--primary-700); + box-shadow: var(--shadow-3); +} + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} + +.loading { + width: 6rem; + height: 6rem; + border: 5px solid var(--grey-400); + border-radius: 50%; + border-top-color: var(--primary-500); + animation: spinner 0.6s linear infinite; +} +.loading { + margin: 0 auto; + margin-top: 4rem; +} +/* title */ + +.title { + text-align: center; + margin-bottom: 3rem; +} + +.title-underline { + background: var(--primary-500); + width: 7rem; + height: 0.25rem; + margin: 0 auto; + margin-top: -1rem; +} +/* +=============== +Products +=============== +*/ +.products { + padding: 5rem 0; +} +.products-center { + width: 90vw; + max-width: 1170px; + margin: 0 auto; +} +.products-container { + display: grid; + gap: 2rem; +} +.single-product-img { + border-radius: var(--borderRadius); + height: 15rem; +} +.single-product footer { + padding: 0.75rem 0; + text-align: center; +} +.single-product .name { + margin-bottom: 0.25rem; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); + color: var(--grey-500); +} +.single-product .price { + margin-bottom: 0; + color: var(--grey-700); + font-weight: 700; + font-size: 1rem; + letter-spacing: var(--letterSpacing); +} + +@media screen and (min-width: 768px) { + .products-container { + grid-template-columns: repeat(2, 1fr); + } + .single-product-img { + height: 10rem; + } + .single-product .name { + font-size: 0.85rem; + } + .single-product .price { + font-size: 0.85rem; + } + .single-product { + margin-bottom: 0; + } +} +@media screen and (min-width: 1000px) { + .products-container { + grid-template-columns: repeat(3, 1fr); + } +} + +.error { + text-align: center; + font-size: 2rem; +} + +/* +=============== +Single Product +=============== +*/ +.home-link { + display: block; + width: 150px; + margin: 2rem auto; + text-align: center; +} +.product { + padding: 5rem 0; + width: 90vw; + max-width: 1170px; + margin: 0 auto; +} +.product-loading { + text-align: center; +} + +.product-wrapper img { + height: 15rem; + border-radius: var(--borderRadius); +} + +.product-color { + display: inline-block; + width: 1rem; + height: 1rem; + border-radius: 50%; + background: #222; + margin: 0.5rem 0.5rem 0.25rem 0; +} + +.product-info { + padding-top: 1rem; +} +.product-info h3 { + margin: 0; + margin-bottom: 0.25rem; +} +.product-info h5 { + color: var(--grey-500); + margin: 0; + margin-bottom: 0.25rem; +} +.product span { + color: var(--grey-800); +} + +.product p { + margin: 0; + margin-bottom: 1.25rem; +} + +@media screen and (min-width: 768px) { + .product-wrapper { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 2rem; + } + .product-wrapper img { + height: 100%; + max-height: 500px; + } +} diff --git a/22-products/starter/README.md b/22-products/starter/README.md new file mode 100644 index 000000000..6fc0056d3 --- /dev/null +++ b/22-products/starter/README.md @@ -0,0 +1,100 @@ +## Products Project + +#### Structure (HTML) + +- section.products + + - div.title + - h2(products) + - div.title-underline + - div.products-center + - div.products-container + - a.single-product href="product.html" + - img.single-product-img.img + - footer + - h5.name (product title) + - span.price($9.99) + +- create product.html +- basic structure + +#### Loading and Error + +- (CSS Loading Spinner)[https://youtu.be/DqqZEpctZ8w] +- in .products-center +- div.loading +- p.error + +#### API Docs + +- (Course API)[https://www.course-api.com/] + +- (Products)[https://www.course-api.com/javascript-store-products] + +- (Single Product)[https://www.course-api.com/javascript-store-single-product?id=rec43w3ipXvP28vog] + +#### Fetch Products + +- select .products-center +- fetch products +- log result +- try/catch + +#### Loading and Error + +- add loading while fetching +- add error in catch + +#### Display Products - Setup + +- return data from fetchProducts +- create displayProducts(list) +- create start() +- invoke fetchProducts and displayProducts in start +- invoke start + +#### Display Products - Complete + +- iterate over list +- pull out all the values +- set productsDOM equal to result + +#### Single Product + +- link styles.css +- a.btn.home-link(back home) +- section.product +- div.product-wrapper + - img.img + - div.product-info + - h3 (title) + - h5 (company) + - span (price) + - div.colors + - span.product-color + - p (lorem text) + - button.btn(add to cart) + +#### product.js setup + +- create product.js +- link product.html +- select .product +- get single product url +- setup fetchProduct(),displayProduct(),start() + +#### Loading, Error, Fetch Single Product + +- fetch single product +- setup loading and error +- make id dynamic +- new URLSearchParams +- window.location.search +- get(keyName) + +#### Display Single Product + +#### Display Colors + +- iterate over colors array +- return span with dynamic color value diff --git a/22-products/starter/app.js b/22-products/starter/app.js new file mode 100644 index 000000000..db779ad9b --- /dev/null +++ b/22-products/starter/app.js @@ -0,0 +1 @@ +console.log('products starter'); diff --git a/22-products/starter/couch.jpg b/22-products/starter/couch.jpg new file mode 100644 index 000000000..ce4d87cf5 Binary files /dev/null and b/22-products/starter/couch.jpg differ diff --git a/22-products/starter/index.html b/22-products/starter/index.html new file mode 100644 index 000000000..57d1adcd1 --- /dev/null +++ b/22-products/starter/index.html @@ -0,0 +1,22 @@ + + + + + + + Products Starter + + + +
+ +
+

our products

+
+
+ +
+
+ + + diff --git a/22-products/starter/styles.css b/22-products/starter/styles.css new file mode 100644 index 000000000..cfe361180 --- /dev/null +++ b/22-products/starter/styles.css @@ -0,0 +1,315 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +html { + font-size: 100%; +} /*16px*/ + +:root { + /* colors */ + --primary-100: #e2e0ff; + --primary-200: #c1beff; + --primary-300: #a29dff; + --primary-400: #837dff; + --primary-500: #645cff; + --primary-600: #504acc; + --primary-700: #3c3799; + --primary-800: #282566; + --primary-900: #141233; + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + /* fonts */ + --small-text: 0.875rem; + --extra-small-text: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--small-text); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* buttons */ + +.btn { + cursor: pointer; + color: var(--white); + background: var(--primary-500); + border: transparent; + border-radius: var(--borderRadius); + letter-spacing: var(--letterSpacing); + padding: 0.375rem 0.75rem; + box-shadow: var(--shadow-1); + transition: var(--transition); + text-transform: capitalize; + display: inline-block; +} +.btn:hover { + background: var(--primary-700); + box-shadow: var(--shadow-3); +} + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} + +.loading { + width: 6rem; + height: 6rem; + border: 5px solid var(--grey-400); + border-radius: 50%; + border-top-color: var(--primary-500); + animation: spinner 0.6s linear infinite; +} +.loading { + margin: 0 auto; + margin-top: 4rem; +} +/* title */ + +.title { + text-align: center; + margin-bottom: 3rem; +} + +.title-underline { + background: var(--primary-500); + width: 7rem; + height: 0.25rem; + margin: 0 auto; + margin-top: -1rem; +} +/* +=============== +Products +=============== +*/ +.products { + padding: 5rem 0; +} +.products-center { + width: 90vw; + max-width: 1170px; + margin: 0 auto; +} +.products-container { + display: grid; + gap: 2rem; +} +.single-product-img { + border-radius: var(--borderRadius); + height: 15rem; +} +.single-product footer { + padding: 0.75rem 0; + text-align: center; +} +.single-product .name { + margin-bottom: 0.25rem; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); + color: var(--grey-500); +} +.single-product .price { + margin-bottom: 0; + color: var(--grey-700); + font-weight: 700; + font-size: 1rem; + letter-spacing: var(--letterSpacing); +} + +@media screen and (min-width: 768px) { + .products-container { + grid-template-columns: repeat(2, 1fr); + } + .single-product-img { + height: 10rem; + } + .single-product .name { + font-size: 0.85rem; + } + .single-product .price { + font-size: 0.85rem; + } + .single-product { + margin-bottom: 0; + } +} +@media screen and (min-width: 1000px) { + .products-container { + grid-template-columns: repeat(3, 1fr); + } +} + +.error { + text-align: center; + font-size: 2rem; +} + +/* +=============== +Single Product +=============== +*/ +.home-link { + display: block; + width: 150px; + margin: 2rem auto; + text-align: center; +} +.product { + padding: 5rem 0; + width: 90vw; + max-width: 1170px; + margin: 0 auto; +} +.product-loading { + text-align: center; +} + +.product-wrapper img { + height: 15rem; + border-radius: var(--borderRadius); +} + +.product-color { + display: inline-block; + width: 1rem; + height: 1rem; + border-radius: 50%; + background: #222; + margin: 0.5rem 0.5rem 0.25rem 0; +} + +.product-info { + padding-top: 1rem; +} +.product-info h3 { + margin: 0; + margin-bottom: 0.25rem; +} +.product-info h5 { + color: var(--grey-500); + margin: 0; + margin-bottom: 0.25rem; +} +.product span { + color: var(--grey-800); +} + +.product p { + margin: 0; + margin-bottom: 1.25rem; +} + +@media screen and (min-width: 768px) { + .product-wrapper { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 2rem; + } + .product-wrapper img { + height: 100%; + max-height: 500px; + } +} diff --git a/23-random-user/final/app.js b/23-random-user/final/app.js new file mode 100644 index 000000000..1d86ff9a7 --- /dev/null +++ b/23-random-user/final/app.js @@ -0,0 +1,16 @@ +import get from './utils/getElement.js'; +import getUser from './utils/fetchUser.js'; +import displayUser from './utils/displayUser.js'; + +const btn = get('.btn'); + +const showUser = async () => { + // get user from api + const person = await getUser(); + displayUser(person); + + // display user +}; + +window.addEventListener('DOMContentLoaded', showUser); +btn.addEventListener('click', showUser); diff --git a/23-random-user/final/index.html b/23-random-user/final/index.html new file mode 100644 index 000000000..b671c0ab2 --- /dev/null +++ b/23-random-user/final/index.html @@ -0,0 +1,64 @@ + + + + + + Random User + + + + + + + +
+
+
+ random user +

My name is

+

John Smith

+
+ + + + + + + + + + + + + + + + + + +
+ +
+
+ + + diff --git a/23-random-user/final/styles.css b/23-random-user/final/styles.css new file mode 100644 index 000000000..b708c1823 --- /dev/null +++ b/23-random-user/final/styles.css @@ -0,0 +1,253 @@ +/* +=============== +Fonts +=============== +*/ +@import url("https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap"); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: #49a6e9; + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: "Roboto", sans-serif; + --ff-secondary: "Open Sans", sans-serif; + --transition: all 0.3s linear; + --spacing: 0.25rem; + --radius: 0.5rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-grey-10); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} + +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +.btn { + text-transform: uppercase; + background: var(--clr-primary-5); + color: var(--clr-white); + padding: 0.375rem 0.75rem; + letter-spacing: var(--spacing); + display: block; + transition: var(--transition); + font-size: 0.875rem; + border: 2px solid var(--clr-primary-5); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + border-radius: var(--radius); +} +.btn:hover { + color: var(--clr-primary-5); + background: var(--clr-primary-1); + border-color: var(--clr-primary-1); +} +/* section */ +.section { + padding: 5rem 0; +} + +.section-center { + width: 90vw; + margin: 0 auto; + max-width: 1170px; +} +@media screen and (min-width: 992px) { + .section-center { + width: 95vw; + } +} + +/* container */ +.block { + min-height: 50vh; +} +.bcg-black { + background: #2c2e31; +} + +.container { + width: 90vw; + max-width: 730px; + background: var(--clr-white); + margin: 0 auto; + margin-top: -200px; + border-radius: var(--radius); + position: relative; + text-align: center; + padding: 1.5rem; + box-shadow: var(--dark-shadow); +} + +.container::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 130px; + background: var(--clr-grey-10); + border-top-left-radius: var(--radius); + border-top-right-radius: var(--radius); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); +} +.container img { + width: 150px; + height: 150px; + position: relative; + border-radius: 50%; + padding: 5px; + background: var(--clr-white); + border: 1px solid rgba(0, 0, 0, 0.25); + margin-bottom: 2rem; + box-shadow: var(--dark-shadow); +} + +.user-title { + font-size: 18px; + margin-bottom: 0; +} +.user-value { + color: var(--clr-grey-1); + font-size: 28px; +} +.values-list { + display: grid; + grid-template-columns: repeat(6, 1fr); + justify-content: center; +} +.icon { + background: transparent; + border: transparent; + font-size: 1.5rem; + cursor: pointer; + color: var(--clr-grey-5); + transition: var(--transition); +} +.icon:hover { + color: var(--clr-primary-5); +} +.active { + color: var(--clr-primary-5); +} +.btn { + margin: 0 auto; + margin-top: 1.5rem; +} + +@media screen and (min-width: 800px) { + .user-value { + font-size: 38px; + } + .icon { + font-size: 2rem; + } +} diff --git a/23-random-user/final/utils/displayUser.js b/23-random-user/final/utils/displayUser.js new file mode 100644 index 000000000..ed236ce5e --- /dev/null +++ b/23-random-user/final/utils/displayUser.js @@ -0,0 +1,25 @@ +import get from './getElement.js'; +import removeActive from './removeActive.js'; + +const img = get('.user-img'); +const title = get('.user-title'); +const value = get('.user-value'); +const btns = [...document.querySelectorAll('.icon')]; +const displayUser = (person) => { + img.src = person.image; + value.textContent = person.name; + title.textContent = `My name is`; + removeActive(btns); + btns[0].classList.remove('active'); + btns.forEach((btn) => { + const label = btn.dataset.label; + btn.addEventListener('click', () => { + title.textContent = `My ${label} is`; + value.textContent = person[label]; + removeActive(btns); + btn.classList.add('active'); + }); + }); +}; + +export default displayUser; diff --git a/23-random-user/final/utils/fetchUser.js b/23-random-user/final/utils/fetchUser.js new file mode 100644 index 000000000..c3944194e --- /dev/null +++ b/23-random-user/final/utils/fetchUser.js @@ -0,0 +1,29 @@ +const URL = 'https://randomuser.me/api/'; + +const getUser = async () => { + const response = await fetch(URL); + const data = await response.json(); + // destructure + const person = data.results[0]; + const { phone, email } = person; + const { large: image } = person.picture; + const { password } = person.login; + const { first, last } = person.name; + const { + dob: { age }, + } = person; + const { + street: { number, name }, + } = person.location; + return { + image, + phone, + email, + password, + age, + street: `${number} ${name}`, + name: `${first} ${last}`, + }; +}; + +export default getUser; diff --git a/23-random-user/final/utils/getElement.js b/23-random-user/final/utils/getElement.js new file mode 100644 index 000000000..730a547a0 --- /dev/null +++ b/23-random-user/final/utils/getElement.js @@ -0,0 +1,7 @@ +const getElement = (selection) => { + const element = document.querySelector(selection); + if (element) return element; + throw new Error('no element selected'); +}; + +export default getElement; diff --git a/23-random-user/final/utils/removeActive.js b/23-random-user/final/utils/removeActive.js new file mode 100644 index 000000000..e6bccbcb6 --- /dev/null +++ b/23-random-user/final/utils/removeActive.js @@ -0,0 +1,3 @@ +export default function removeActive(items) { + items.forEach((btn) => btn.classList.remove('active')); +} diff --git a/5-sidebar/setup/app.js b/23-random-user/setup/app.js similarity index 100% rename from 5-sidebar/setup/app.js rename to 23-random-user/setup/app.js diff --git a/23-random-user/setup/index.html b/23-random-user/setup/index.html new file mode 100644 index 000000000..9b61f608b --- /dev/null +++ b/23-random-user/setup/index.html @@ -0,0 +1,20 @@ + + + + + + Random Person + + + + + + + +

random person

+ + + diff --git a/23-random-user/setup/styles.css b/23-random-user/setup/styles.css new file mode 100644 index 000000000..b708c1823 --- /dev/null +++ b/23-random-user/setup/styles.css @@ -0,0 +1,253 @@ +/* +=============== +Fonts +=============== +*/ +@import url("https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap"); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: #49a6e9; + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: "Roboto", sans-serif; + --ff-secondary: "Open Sans", sans-serif; + --transition: all 0.3s linear; + --spacing: 0.25rem; + --radius: 0.5rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-grey-10); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} + +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +.btn { + text-transform: uppercase; + background: var(--clr-primary-5); + color: var(--clr-white); + padding: 0.375rem 0.75rem; + letter-spacing: var(--spacing); + display: block; + transition: var(--transition); + font-size: 0.875rem; + border: 2px solid var(--clr-primary-5); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + border-radius: var(--radius); +} +.btn:hover { + color: var(--clr-primary-5); + background: var(--clr-primary-1); + border-color: var(--clr-primary-1); +} +/* section */ +.section { + padding: 5rem 0; +} + +.section-center { + width: 90vw; + margin: 0 auto; + max-width: 1170px; +} +@media screen and (min-width: 992px) { + .section-center { + width: 95vw; + } +} + +/* container */ +.block { + min-height: 50vh; +} +.bcg-black { + background: #2c2e31; +} + +.container { + width: 90vw; + max-width: 730px; + background: var(--clr-white); + margin: 0 auto; + margin-top: -200px; + border-radius: var(--radius); + position: relative; + text-align: center; + padding: 1.5rem; + box-shadow: var(--dark-shadow); +} + +.container::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 130px; + background: var(--clr-grey-10); + border-top-left-radius: var(--radius); + border-top-right-radius: var(--radius); + border-bottom: 1px solid rgba(0, 0, 0, 0.25); +} +.container img { + width: 150px; + height: 150px; + position: relative; + border-radius: 50%; + padding: 5px; + background: var(--clr-white); + border: 1px solid rgba(0, 0, 0, 0.25); + margin-bottom: 2rem; + box-shadow: var(--dark-shadow); +} + +.user-title { + font-size: 18px; + margin-bottom: 0; +} +.user-value { + color: var(--clr-grey-1); + font-size: 28px; +} +.values-list { + display: grid; + grid-template-columns: repeat(6, 1fr); + justify-content: center; +} +.icon { + background: transparent; + border: transparent; + font-size: 1.5rem; + cursor: pointer; + color: var(--clr-grey-5); + transition: var(--transition); +} +.icon:hover { + color: var(--clr-primary-5); +} +.active { + color: var(--clr-primary-5); +} +.btn { + margin: 0 auto; + margin-top: 1.5rem; +} + +@media screen and (min-width: 800px) { + .user-value { + font-size: 38px; + } + .icon { + font-size: 2rem; + } +} diff --git a/24-cocktails/final/app.js b/24-cocktails/final/app.js new file mode 100644 index 000000000..800526b4d --- /dev/null +++ b/24-cocktails/final/app.js @@ -0,0 +1,7 @@ +import presentDrinks from './src/presentDrinks.js'; +import './src/searchForm.js'; +const URL = 'https://www.thecocktaildb.com/api/json/v1/1/search.php?s=a'; + +window.addEventListener('DOMContentLoaded', () => { + presentDrinks(URL); +}); diff --git a/24-cocktails/final/cocktail.jpg b/24-cocktails/final/cocktail.jpg new file mode 100644 index 000000000..4e9061348 Binary files /dev/null and b/24-cocktails/final/cocktail.jpg differ diff --git a/24-cocktails/final/drink.html b/24-cocktails/final/drink.html new file mode 100644 index 000000000..5c16164f4 --- /dev/null +++ b/24-cocktails/final/drink.html @@ -0,0 +1,30 @@ + + + + + + Single Cocktail + + + + + + +
+ loading +
+
+ +
+

+

+ + all cocktails +
+
+ + + diff --git a/24-cocktails/final/index.html b/24-cocktails/final/index.html new file mode 100644 index 000000000..4f941f75b --- /dev/null +++ b/24-cocktails/final/index.html @@ -0,0 +1,34 @@ + + + + + + Cocktails + + + + + + + +
+

cocktails API

+ +
+
+
+ loading +
+

+
+
+ + + diff --git a/24-cocktails/final/loading.gif b/24-cocktails/final/loading.gif new file mode 100644 index 000000000..e1e580cf9 Binary files /dev/null and b/24-cocktails/final/loading.gif differ diff --git a/24-cocktails/final/singleDrink.js b/24-cocktails/final/singleDrink.js new file mode 100644 index 000000000..9d1758269 --- /dev/null +++ b/24-cocktails/final/singleDrink.js @@ -0,0 +1,16 @@ +import fetchDrinks from './src/fetchDrinks.js'; +import displayDrink from './src/displaySingleDrink.js'; + +const presentDrink = async () => { + const id = localStorage.getItem('drink'); + if (!id) { + window.location.replace('index.html'); + } else { + const drink = await fetchDrinks( + `https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${id}` + ); + displayDrink(drink); + } +}; + +window.addEventListener('DOMContentLoaded', presentDrink); diff --git a/24-cocktails/final/src/displayDrinks.js b/24-cocktails/final/src/displayDrinks.js new file mode 100644 index 000000000..b79e838b3 --- /dev/null +++ b/24-cocktails/final/src/displayDrinks.js @@ -0,0 +1,31 @@ +import get from './getElement.js'; +import { hideLoading } from './toggleLoading.js'; +const displayDrinks = ({ drinks }) => { + const section = get('.section-center'); + const title = get('.title'); + if (!drinks) { + // hide loading + hideLoading(); + title.textContent = 'sorry, no drinks matched your search'; + section.innerHTML = null; + return; + } + const newDrinks = drinks + .map((drink) => { + const { idDrink: id, strDrink: name, strDrinkThumb: image } = drink; + + return ` +
+ ${name} +

${name}

+
+
`; + }) + .join(''); + hideLoading(); + title.textContent = ''; + section.innerHTML = newDrinks; + return section; +}; + +export default displayDrinks; diff --git a/24-cocktails/final/src/displaySingleDrink.js b/24-cocktails/final/src/displaySingleDrink.js new file mode 100644 index 000000000..76a4df57b --- /dev/null +++ b/24-cocktails/final/src/displaySingleDrink.js @@ -0,0 +1,31 @@ +import { hideLoading } from './toggleLoading.js'; +import get from './getElement.js'; + +const displayDrink = (data) => { + hideLoading(); + + const drink = data.drinks[0]; + const { strDrinkThumb: image, strDrink: name, strInstructions: desc } = drink; + const list = [ + drink.strIngredient1, + drink.strIngredient2, + drink.strIngredient3, + drink.strIngredient4, + drink.strIngredient5, + ]; + const img = get('.drink-img'); + const drinkName = get('.drink-name'); + const description = get('.drink-desc'); + const ingredients = get('.drink-ingredients'); + img.src = image; + document.title = name; + drinkName.textContent = name; + description.textContent = desc; + ingredients.innerHTML = list + .map((item) => { + if (!item) return; + return `
  • ${item}
  • `; + }) + .join(''); +}; +export default displayDrink; diff --git a/24-cocktails/final/src/fetchDrinks.js b/24-cocktails/final/src/fetchDrinks.js new file mode 100644 index 000000000..76764fcab --- /dev/null +++ b/24-cocktails/final/src/fetchDrinks.js @@ -0,0 +1,13 @@ +import { showLoading } from './toggleLoading.js'; +const fetchDrinks = async (url) => { + showLoading(); + try { + const response = await fetch(url); + const data = await response.json(); + return data; + } catch (error) { + console.log(error); + } +}; + +export default fetchDrinks; diff --git a/24-cocktails/final/src/getElement.js b/24-cocktails/final/src/getElement.js new file mode 100644 index 000000000..1bfca0879 --- /dev/null +++ b/24-cocktails/final/src/getElement.js @@ -0,0 +1,7 @@ +const getElement = (selection) => { + const element = document.querySelector(selection); + if (element) return element; + throw new Error("no element selected"); +}; + +export default getElement; diff --git a/24-cocktails/final/src/presentDrinks.js b/24-cocktails/final/src/presentDrinks.js new file mode 100644 index 000000000..3142fac72 --- /dev/null +++ b/24-cocktails/final/src/presentDrinks.js @@ -0,0 +1,15 @@ +import fetchDrinks from './fetchDrinks.js'; +import displayDrinks from './displayDrinks.js'; +import setDrink from './setDrink.js'; +const showDrinks = async (url) => { + // fetch drinks + const data = await fetchDrinks(url); + + // display drinks + const section = await displayDrinks(data); + if (section) { + setDrink(section); + } +}; + +export default showDrinks; diff --git a/24-cocktails/final/src/searchForm.js b/24-cocktails/final/src/searchForm.js new file mode 100644 index 000000000..26e4522a5 --- /dev/null +++ b/24-cocktails/final/src/searchForm.js @@ -0,0 +1,14 @@ +import get from './getElement.js'; +import presentDrinks from './presentDrinks.js'; + +const baseURL = 'https://www.thecocktaildb.com/api/json/v1/1/search.php?s='; + +const form = get('.search-form'); +const input = get('[name="drink"]'); + +form.addEventListener('keyup', function (e) { + e.preventDefault(); + const value = input.value; + if (!value) return; + presentDrinks(`${baseURL}${value}`); +}); diff --git a/24-cocktails/final/src/setDrink.js b/24-cocktails/final/src/setDrink.js new file mode 100644 index 000000000..bef153ec4 --- /dev/null +++ b/24-cocktails/final/src/setDrink.js @@ -0,0 +1,10 @@ +const setDrink = (section) => { + section.addEventListener('click', function (e) { + // e.preventDefault(); + const id = e.target.parentElement.dataset.id; + // JSON.stringify JSON.parse + localStorage.setItem('drink', id); + }); +}; + +export default setDrink; diff --git a/24-cocktails/final/src/toggleLoading.js b/24-cocktails/final/src/toggleLoading.js new file mode 100644 index 000000000..e1e828639 --- /dev/null +++ b/24-cocktails/final/src/toggleLoading.js @@ -0,0 +1,10 @@ +import get from './getElement.js'; + +const loading = get('.loading'); + +export const showLoading = () => { + loading.classList.remove('hide-loading'); +}; +export const hideLoading = () => { + loading.classList.add('hide-loading'); +}; diff --git a/24-cocktails/final/styles.css b/24-cocktails/final/styles.css new file mode 100644 index 000000000..7634a90a3 --- /dev/null +++ b/24-cocktails/final/styles.css @@ -0,0 +1,299 @@ +/* +=============== +Fonts +=============== +*/ +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: #49a6e9; + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; + --transition: all 0.3s linear; + --spacing: 0.25rem; + --radius: 0.5rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-grey-10); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} + +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +.btn { + text-transform: uppercase; + background: var(--clr-primary-5); + color: var(--clr-white); + padding: 0.375rem 0.75rem; + letter-spacing: var(--spacing); + display: block; + transition: var(--transition); + font-size: 0.875rem; + border: 2px solid var(--clr-primary-5); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + border-radius: var(--radius); +} +.btn:hover { + color: var(--clr-primary-5); + background: var(--clr-primary-1); + border-color: var(--clr-primary-1); +} +/* section */ +.section { + padding: 5rem 0; +} + +.section-center { + width: 85vw; + margin: 0 auto; + max-width: 1170px; +} +@media screen and (min-width: 576px) { + .section-center { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + column-gap: 4rem; + } +} +@media screen and (min-width: 992px) { + .section-center { + width: 95vw; + } +} +/* loading */ +.loading { + min-height: 100vh; + display: grid; + justify-content: center; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--clr-grey-10); + padding-top: 5rem; + z-index: 999; +} + +.hide-loading { + display: none; +} + +/* search form */ +.search-form { + text-align: center; + padding-top: 5rem; + width: 85vw; + max-width: 500px; + margin: 0 auto; +} + +input { + width: 100%; + font-size: 1rem; + border-color: transparent; + margin-top: 1rem; + padding: 0.5rem 1rem; +} +input { + border-radius: var(--radius); +} +input::placeholder { + text-transform: capitalize; + color: var(--clr-grey-3); +} + +/* cocktails */ +.cocktails { + position: relative; +} +.title { + font-size: 2rem; + text-align: center; +} + +.cocktail { + background: var(--clr-white); + border-radius: var(--radius); + box-shadow: var(--light-shadow); + transition: var(--transition); + margin-bottom: 3rem; + position: relative; +} +.cocktail:hover { + box-shadow: var(--dark-shadow); + transform: scale(1.005); +} +.cocktail img { + width: 100%; + display: block; + border-radius: var(--radius); + border: 10px solid var(--clr-white); + transition: var(--transition); + height: 268px; + object-fit: cover; +} +.cocktail:hover img { + filter: blur(2px) grayscale(50%); +} +.cocktail h3 { + position: absolute; + bottom: -1rem; + right: -1rem; + background: var(--clr-black); + color: var(--clr-white); + padding: 1rem 1.5rem; + text-align: center; + margin-bottom: 0; + text-transform: uppercase; + font-family: monospace; + font-size: 2rem; + border-radius: var(--radius); +} + +/* single cocktail */ +.single-drink { + width: 85vw; + max-width: var(--max-width); + margin: 0 auto; + margin-top: 4rem; +} +.drink-img { + width: 100%; + height: 400px; + object-fit: cover; + display: block; + border: 10px solid var(--clr-white); + border-radius: var(--radius); +} +@media screen and (min-width: 992px) { + .single-drink { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 3rem; + } +} +.drink-info { + padding-top: 2rem; +} + +.drink-ingredients .far { + margin-right: 1rem; +} + +.single-drink .btn { + display: inline-block; + margin-top: 2rem; +} diff --git a/24-cocktails/setup/app.js b/24-cocktails/setup/app.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/cocktail.jpg b/24-cocktails/setup/cocktail.jpg new file mode 100644 index 000000000..4e9061348 Binary files /dev/null and b/24-cocktails/setup/cocktail.jpg differ diff --git a/24-cocktails/setup/drink.html b/24-cocktails/setup/drink.html new file mode 100644 index 000000000..0a966e014 --- /dev/null +++ b/24-cocktails/setup/drink.html @@ -0,0 +1,19 @@ + + + + + + Single Cocktail + + + + + + +

    single drink

    + + + diff --git a/24-cocktails/setup/index.html b/24-cocktails/setup/index.html new file mode 100644 index 000000000..c78d52b62 --- /dev/null +++ b/24-cocktails/setup/index.html @@ -0,0 +1,20 @@ + + + + + + Cocktails + + + + + + + +

    drinks page

    + + + diff --git a/24-cocktails/setup/loading.gif b/24-cocktails/setup/loading.gif new file mode 100644 index 000000000..e1e580cf9 Binary files /dev/null and b/24-cocktails/setup/loading.gif differ diff --git a/24-cocktails/setup/singleDrink.js b/24-cocktails/setup/singleDrink.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/displayDrinks.js b/24-cocktails/setup/src/displayDrinks.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/displaySingleDrink.js b/24-cocktails/setup/src/displaySingleDrink.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/fetchDrinks.js b/24-cocktails/setup/src/fetchDrinks.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/getElement.js b/24-cocktails/setup/src/getElement.js new file mode 100644 index 000000000..1bfca0879 --- /dev/null +++ b/24-cocktails/setup/src/getElement.js @@ -0,0 +1,7 @@ +const getElement = (selection) => { + const element = document.querySelector(selection); + if (element) return element; + throw new Error("no element selected"); +}; + +export default getElement; diff --git a/24-cocktails/setup/src/presentDrinks.js b/24-cocktails/setup/src/presentDrinks.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/searchForm.js b/24-cocktails/setup/src/searchForm.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/setDrink.js b/24-cocktails/setup/src/setDrink.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/src/toggleLoading.js b/24-cocktails/setup/src/toggleLoading.js new file mode 100644 index 000000000..e69de29bb diff --git a/24-cocktails/setup/styles.css b/24-cocktails/setup/styles.css new file mode 100644 index 000000000..7634a90a3 --- /dev/null +++ b/24-cocktails/setup/styles.css @@ -0,0 +1,299 @@ +/* +=============== +Fonts +=============== +*/ +@import url('https://fonts.googleapis.com/css?family=Open+Sans|Roboto:400,700&display=swap'); + +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(205, 86%, 17%); + --clr-primary-2: hsl(205, 77%, 27%); + --clr-primary-3: hsl(205, 72%, 37%); + --clr-primary-4: hsl(205, 63%, 48%); + /* primary/main color */ + --clr-primary-5: #49a6e9; + /* lighter shades of primary color */ + --clr-primary-6: hsl(205, 89%, 70%); + --clr-primary-7: hsl(205, 90%, 76%); + --clr-primary-8: hsl(205, 86%, 81%); + --clr-primary-9: hsl(205, 90%, 88%); + --clr-primary-10: hsl(205, 100%, 96%); + /* darkest grey - used for headings */ + --clr-grey-1: hsl(209, 61%, 16%); + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + --ff-primary: 'Roboto', sans-serif; + --ff-secondary: 'Open Sans', sans-serif; + --transition: all 0.3s linear; + --spacing: 0.25rem; + --radius: 0.5rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: var(--ff-secondary); + background: var(--clr-grey-10); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} + +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-family: var(--ff-primary); +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +/* global classes */ + +.btn { + text-transform: uppercase; + background: var(--clr-primary-5); + color: var(--clr-white); + padding: 0.375rem 0.75rem; + letter-spacing: var(--spacing); + display: block; + transition: var(--transition); + font-size: 0.875rem; + border: 2px solid var(--clr-primary-5); + cursor: pointer; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); + border-radius: var(--radius); +} +.btn:hover { + color: var(--clr-primary-5); + background: var(--clr-primary-1); + border-color: var(--clr-primary-1); +} +/* section */ +.section { + padding: 5rem 0; +} + +.section-center { + width: 85vw; + margin: 0 auto; + max-width: 1170px; +} +@media screen and (min-width: 576px) { + .section-center { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + column-gap: 4rem; + } +} +@media screen and (min-width: 992px) { + .section-center { + width: 95vw; + } +} +/* loading */ +.loading { + min-height: 100vh; + display: grid; + justify-content: center; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--clr-grey-10); + padding-top: 5rem; + z-index: 999; +} + +.hide-loading { + display: none; +} + +/* search form */ +.search-form { + text-align: center; + padding-top: 5rem; + width: 85vw; + max-width: 500px; + margin: 0 auto; +} + +input { + width: 100%; + font-size: 1rem; + border-color: transparent; + margin-top: 1rem; + padding: 0.5rem 1rem; +} +input { + border-radius: var(--radius); +} +input::placeholder { + text-transform: capitalize; + color: var(--clr-grey-3); +} + +/* cocktails */ +.cocktails { + position: relative; +} +.title { + font-size: 2rem; + text-align: center; +} + +.cocktail { + background: var(--clr-white); + border-radius: var(--radius); + box-shadow: var(--light-shadow); + transition: var(--transition); + margin-bottom: 3rem; + position: relative; +} +.cocktail:hover { + box-shadow: var(--dark-shadow); + transform: scale(1.005); +} +.cocktail img { + width: 100%; + display: block; + border-radius: var(--radius); + border: 10px solid var(--clr-white); + transition: var(--transition); + height: 268px; + object-fit: cover; +} +.cocktail:hover img { + filter: blur(2px) grayscale(50%); +} +.cocktail h3 { + position: absolute; + bottom: -1rem; + right: -1rem; + background: var(--clr-black); + color: var(--clr-white); + padding: 1rem 1.5rem; + text-align: center; + margin-bottom: 0; + text-transform: uppercase; + font-family: monospace; + font-size: 2rem; + border-radius: var(--radius); +} + +/* single cocktail */ +.single-drink { + width: 85vw; + max-width: var(--max-width); + margin: 0 auto; + margin-top: 4rem; +} +.drink-img { + width: 100%; + height: 400px; + object-fit: cover; + display: block; + border: 10px solid var(--clr-white); + border-radius: var(--radius); +} +@media screen and (min-width: 992px) { + .single-drink { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap: 3rem; + } +} +.drink-info { + padding-top: 2rem; +} + +.drink-ingredients .far { + margin-right: 1rem; +} + +.single-drink .btn { + display: inline-block; + margin-top: 2rem; +} diff --git a/25-slider/final/app.js b/25-slider/final/app.js new file mode 100644 index 000000000..5263ceb67 --- /dev/null +++ b/25-slider/final/app.js @@ -0,0 +1,74 @@ +import data from './data.js' +const container = document.querySelector('.slide-container') +const nextBtn = document.querySelector('.next-btn') +const prevBtn = document.querySelector('.prev-btn') +// if length is 1 hide buttons +if (data.length === 1) { + nextBtn.style.display = 'none' + prevBtn.style.display = 'none' +} +// if length is 2, add copies of slides +let people = [...data] +if (data.length === 2) { + people = [...data, ...data] +} +container.innerHTML = people + .map((person, slideIndex) => { + const { img, name, job, text } = person + let position = 'next' + if (slideIndex === 0) { + position = 'active' + } + if (slideIndex === people.length - 1) { + position = 'last' + } + if (data.length <= 1) { + position = 'active' + } + return `
    + ${name} +

    ${name}

    +

    ${job}

    +

    + ${text} +

    +
    + +
    +
    ` + }) + .join('') + +const startSlider = (type) => { + // get all three slides active,last next + const active = document.querySelector('.active') + const last = document.querySelector('.last') + let next = active.nextElementSibling + if (!next) { + next = container.firstElementChild + } + active.classList.remove('active') + last.classList.remove('last') + next.classList.remove('next') + + if (type === 'prev') { + active.classList.add('next') + last.classList.add('active') + next = last.previousElementSibling + if (!next) { + next = container.lastElementChild + } + next.classList.remove('next') + next.classList.add('last') + return + } + active.classList.add('last') + last.classList.add('next') + next.classList.add('active') +} +nextBtn.addEventListener('click', () => { + startSlider() +}) +prevBtn.addEventListener('click', () => { + startSlider('prev') +}) diff --git a/16-ES6-slider/final/data.js b/25-slider/final/data.js similarity index 52% rename from 16-ES6-slider/final/data.js rename to 25-slider/final/data.js index 679d6b121..78ff8598f 100644 --- a/16-ES6-slider/final/data.js +++ b/25-slider/final/data.js @@ -1,23 +1,20 @@ const people = [ { - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/c_scale,w_200/v1595959121/person-1_aufeoq.jpg", - name: "peter doe", - job: "product manager", + img: 'https://www.course-api.com/images/people/person-3.jpeg', + name: 'peter doe', + job: 'product manager', text: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quoeius recusandae officia voluptas sint deserunt dicta nihil nam omnis? `, }, { - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/c_scale,w_200/v1595959131/person-2_ipcjws.jpg", - name: "susan doe", - job: "developer", + img: 'https://www.course-api.com/images/people/person-1.jpeg', + name: 'susan doe', + job: 'developer', text: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quoeius recusandae officia voluptas sint deserunt dicta nihil nam omnis?`, }, { - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/c_scale,w_200/v1595959131/person-3_rxtqvi.jpg", - name: "emma doe", - job: "designer", + img: 'https://www.course-api.com/images/people/person-2.jpeg', + name: 'emma doe', + job: 'designer', text: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quoeius recusandae officia voluptas sint deserunt dicta nihil nam omnis?`, }, ]; diff --git a/16-ES6-slider/final/index.html b/25-slider/final/index.html similarity index 100% rename from 16-ES6-slider/final/index.html rename to 25-slider/final/index.html diff --git a/16-ES6-slider/final/styles.css b/25-slider/final/styles.css similarity index 100% rename from 16-ES6-slider/final/styles.css rename to 25-slider/final/styles.css diff --git a/25-slider/setup/app.js b/25-slider/setup/app.js new file mode 100644 index 000000000..e69de29bb diff --git a/16-ES6-slider/setup/data.js b/25-slider/setup/data.js similarity index 50% rename from 16-ES6-slider/setup/data.js rename to 25-slider/setup/data.js index 247442d73..78ff8598f 100644 --- a/16-ES6-slider/setup/data.js +++ b/25-slider/setup/data.js @@ -1,23 +1,22 @@ const people = [ { - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/c_scale,w_200/v1595959121/person-1_aufeoq.jpg", - name: "peter doe", - job: "product manager", + img: 'https://www.course-api.com/images/people/person-3.jpeg', + name: 'peter doe', + job: 'product manager', text: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quoeius recusandae officia voluptas sint deserunt dicta nihil nam omnis? `, }, { - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/c_scale,w_200/v1595959131/person-2_ipcjws.jpg", - name: "susan doe", - job: "developer", + img: 'https://www.course-api.com/images/people/person-1.jpeg', + name: 'susan doe', + job: 'developer', text: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quoeius recusandae officia voluptas sint deserunt dicta nihil nam omnis?`, }, { - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/c_scale,w_200/v1595959131/person-3_rxtqvi.jpg", - name: "emma doe", - job: "designer", + img: 'https://www.course-api.com/images/people/person-2.jpeg', + name: 'emma doe', + job: 'designer', text: `Lorem ipsum dolor sit amet consectetur adipisicing elit. Quidem quoeius recusandae officia voluptas sint deserunt dicta nihil nam omnis?`, }, ]; + +export default people; diff --git a/16-ES6-slider/setup/index.html b/25-slider/setup/index.html similarity index 100% rename from 16-ES6-slider/setup/index.html rename to 25-slider/setup/index.html diff --git a/16-ES6-slider/setup/styles.css b/25-slider/setup/styles.css similarity index 100% rename from 16-ES6-slider/setup/styles.css rename to 25-slider/setup/styles.css diff --git a/17-stripe-submenus/final/app.js b/26-stripe-submenus/final/app.js similarity index 100% rename from 17-stripe-submenus/final/app.js rename to 26-stripe-submenus/final/app.js diff --git a/17-stripe-submenus/final/data.js b/26-stripe-submenus/final/data.js similarity index 100% rename from 17-stripe-submenus/final/data.js rename to 26-stripe-submenus/final/data.js diff --git a/17-stripe-submenus/final/images/hero.svg b/26-stripe-submenus/final/images/hero.svg similarity index 100% rename from 17-stripe-submenus/final/images/hero.svg rename to 26-stripe-submenus/final/images/hero.svg diff --git a/17-stripe-submenus/final/images/logo.svg b/26-stripe-submenus/final/images/logo.svg similarity index 100% rename from 17-stripe-submenus/final/images/logo.svg rename to 26-stripe-submenus/final/images/logo.svg diff --git a/17-stripe-submenus/final/images/phone.svg b/26-stripe-submenus/final/images/phone.svg similarity index 100% rename from 17-stripe-submenus/final/images/phone.svg rename to 26-stripe-submenus/final/images/phone.svg diff --git a/17-stripe-submenus/final/index.html b/26-stripe-submenus/final/index.html similarity index 100% rename from 17-stripe-submenus/final/index.html rename to 26-stripe-submenus/final/index.html diff --git a/17-stripe-submenus/final/styles.css b/26-stripe-submenus/final/styles.css similarity index 100% rename from 17-stripe-submenus/final/styles.css rename to 26-stripe-submenus/final/styles.css diff --git a/26-stripe-submenus/setup/app.js b/26-stripe-submenus/setup/app.js new file mode 100644 index 000000000..e69de29bb diff --git a/17-stripe-submenus/setup/data.js b/26-stripe-submenus/setup/data.js similarity index 100% rename from 17-stripe-submenus/setup/data.js rename to 26-stripe-submenus/setup/data.js diff --git a/17-stripe-submenus/setup/images/hero.svg b/26-stripe-submenus/setup/images/hero.svg similarity index 100% rename from 17-stripe-submenus/setup/images/hero.svg rename to 26-stripe-submenus/setup/images/hero.svg diff --git a/17-stripe-submenus/setup/images/logo.svg b/26-stripe-submenus/setup/images/logo.svg similarity index 100% rename from 17-stripe-submenus/setup/images/logo.svg rename to 26-stripe-submenus/setup/images/logo.svg diff --git a/17-stripe-submenus/setup/images/phone.svg b/26-stripe-submenus/setup/images/phone.svg similarity index 100% rename from 17-stripe-submenus/setup/images/phone.svg rename to 26-stripe-submenus/setup/images/phone.svg diff --git a/17-stripe-submenus/setup/index.html b/26-stripe-submenus/setup/index.html similarity index 100% rename from 17-stripe-submenus/setup/index.html rename to 26-stripe-submenus/setup/index.html diff --git a/17-stripe-submenus/setup/styles.css b/26-stripe-submenus/setup/styles.css similarity index 100% rename from 17-stripe-submenus/setup/styles.css rename to 26-stripe-submenus/setup/styles.css diff --git a/18-pagination/final/app.js b/27-pagination/final/app.js similarity index 100% rename from 18-pagination/final/app.js rename to 27-pagination/final/app.js diff --git a/18-pagination/final/displayButtons.js b/27-pagination/final/displayButtons.js similarity index 100% rename from 18-pagination/final/displayButtons.js rename to 27-pagination/final/displayButtons.js diff --git a/18-pagination/final/displayFollowers.js b/27-pagination/final/displayFollowers.js similarity index 100% rename from 18-pagination/final/displayFollowers.js rename to 27-pagination/final/displayFollowers.js diff --git a/18-pagination/final/fetchFollowers.js b/27-pagination/final/fetchFollowers.js similarity index 100% rename from 18-pagination/final/fetchFollowers.js rename to 27-pagination/final/fetchFollowers.js diff --git a/18-pagination/final/index.html b/27-pagination/final/index.html similarity index 100% rename from 18-pagination/final/index.html rename to 27-pagination/final/index.html diff --git a/18-pagination/final/paginate.js b/27-pagination/final/paginate.js similarity index 100% rename from 18-pagination/final/paginate.js rename to 27-pagination/final/paginate.js diff --git a/18-pagination/final/styles.css b/27-pagination/final/styles.css similarity index 100% rename from 18-pagination/final/styles.css rename to 27-pagination/final/styles.css diff --git a/18-pagination/setup/app.js b/27-pagination/setup/app.js similarity index 100% rename from 18-pagination/setup/app.js rename to 27-pagination/setup/app.js diff --git a/18-pagination/setup/displayButtons.js b/27-pagination/setup/displayButtons.js similarity index 100% rename from 18-pagination/setup/displayButtons.js rename to 27-pagination/setup/displayButtons.js diff --git a/18-pagination/setup/displayFollowers.js b/27-pagination/setup/displayFollowers.js similarity index 100% rename from 18-pagination/setup/displayFollowers.js rename to 27-pagination/setup/displayFollowers.js diff --git a/18-pagination/setup/fetchFollowers.js b/27-pagination/setup/fetchFollowers.js similarity index 100% rename from 18-pagination/setup/fetchFollowers.js rename to 27-pagination/setup/fetchFollowers.js diff --git a/18-pagination/setup/index.html b/27-pagination/setup/index.html similarity index 100% rename from 18-pagination/setup/index.html rename to 27-pagination/setup/index.html diff --git a/18-pagination/setup/paginate.js b/27-pagination/setup/paginate.js similarity index 100% rename from 18-pagination/setup/paginate.js rename to 27-pagination/setup/paginate.js diff --git a/18-pagination/setup/styles.css b/27-pagination/setup/styles.css similarity index 100% rename from 18-pagination/setup/styles.css rename to 27-pagination/setup/styles.css diff --git a/28-wikipedia/final/README.md b/28-wikipedia/final/README.md new file mode 100644 index 000000000..03d68ba59 --- /dev/null +++ b/28-wikipedia/final/README.md @@ -0,0 +1,44 @@ +#### HTML Structure + +- section.wiki + - div.container + - img + - h3(text) + - form.form + - input.form-input type='text' + - button.submit-btn (search) type='submit' + - div.results + - div.articles + - a + - h4 + - p (lorem20) + +#### API DOCS + +- [wiki docs](https://www.mediawiki.org/wiki/API:Main_page) + +- ready to go url's + +#### Initial Setup + +- select form, input, results +- listen for submit events +- if empty value, display error +- create fetchPages() +- pass valid input value into the fetchPages() + +#### Fetch Pages + +- display loading while fetching +- construct dynamic url +- display if error +- display error no items +- create renderResults() +- pass valid results into renderResults() + +#### Render Results + +- iterate over the list +- pull out title, snippet, pageid +- setup a card +- set results with div.articles and list inside diff --git a/28-wikipedia/final/app.js b/28-wikipedia/final/app.js new file mode 100644 index 000000000..b2e189ae5 --- /dev/null +++ b/28-wikipedia/final/app.js @@ -0,0 +1,51 @@ +const url = + 'https://en.wikipedia.org/w/api.php?action=query&list=search&srlimit=20&format=json&origin=*&srsearch='; + +const formDOM = document.querySelector('.form'); +const inputDOM = document.querySelector('.form-input'); +const resultsDOM = document.querySelector('.results'); + +formDOM.addEventListener('submit', (e) => { + e.preventDefault(); + const value = inputDOM.value; + if (!value) { + resultsDOM.innerHTML = + '
    please enter valid search term
    '; + return; + } + fetchPages(value); +}); + +const fetchPages = async (searchValue) => { + resultsDOM.innerHTML = '
    '; + try { + const response = await fetch(`${url}${searchValue}`); + const data = await response.json(); + const results = data.query.search; + if (results.length < 1) { + resultsDOM.innerHTML = + '
    no matching results. Please try again
    '; + return; + } + renderResults(results); + } catch (error) { + resultsDOM.innerHTML = '
    there was an error...
    '; + } +}; + +const renderResults = (list) => { + const cardsList = list + .map((item) => { + const { title, snippet, pageid } = item; + return ` +

    ${title}

    +

    + ${snippet} +

    +
    `; + }) + .join(''); + resultsDOM.innerHTML = `
    + ${cardsList} +
    `; +}; diff --git a/28-wikipedia/final/index.html b/28-wikipedia/final/index.html new file mode 100644 index 000000000..bf08fce7a --- /dev/null +++ b/28-wikipedia/final/index.html @@ -0,0 +1,25 @@ + + + + + + + Wikipedia + + + +
    +
    + logo +

    Search Wikipedia

    +
    + + +
    +
    + +
    +
    + + + diff --git a/28-wikipedia/final/styles.css b/28-wikipedia/final/styles.css new file mode 100644 index 000000000..0e57ad877 --- /dev/null +++ b/28-wikipedia/final/styles.css @@ -0,0 +1,284 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +html { + font-size: 100%; +} /*16px*/ + +:root { + /* colors */ + --primary-100: #e2e0ff; + --primary-200: #c1beff; + --primary-300: #a29dff; + --primary-400: #837dff; + --primary-500: #645cff; + --primary-600: #504acc; + --primary-700: #3c3799; + --primary-800: #282566; + --primary-900: #141233; + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + /* fonts */ + --small-text: 0.875rem; + --extra-small-text: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--small-text); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* buttons */ + +.btn { + cursor: pointer; + color: var(--white); + background: var(--primary-500); + border: transparent; + border-radius: var(--borderRadius); + letter-spacing: var(--letterSpacing); + padding: 0.375rem 0.75rem; + box-shadow: var(--shadow-1); + transition: var(--transition); + text-transform: capitalize; + display: inline-block; +} +.btn:hover { + background: var(--primary-700); + box-shadow: var(--shadow-3); +} + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} + +.loading { + width: 6rem; + height: 6rem; + border: 5px solid var(--grey-400); + border-radius: 50%; + border-top-color: var(--primary-500); + animation: spinner 0.6s linear infinite; +} +.loading { + margin: 0 auto; + margin-top: 4rem; +} +/* title */ + +.title { + text-align: center; + margin-bottom: 3rem; +} + +.title-underline { + background: var(--primary-500); + width: 7rem; + height: 0.25rem; + margin: 0 auto; + margin-top: -1rem; +} + +/* +=============== +Wikipedia +=============== +*/ +.wiki { + padding: 5rem 0; + width: 90vw; + max-width: 1170px; + margin: 0 auto; +} +.container { + text-align: center; +} +.container img { + width: 200px; +} +.container h3 { + margin-bottom: 2rem; +} + +.form { + background: #fff; + width: 100%; + margin: 0 auto; + padding: 2.5rem; + border-radius: var(--borderRadius); + display: grid; + grid-template-columns: auto 100px; +} +.form-input, +.submit-btn { + padding: 0.375rem 0.75rem; + background: var(--backgroundColor); + border: 1px solid var(--grey-200); +} +.form-input { + border-right: transparent; + border-top-left-radius: var(--borderRadius); + border-bottom-left-radius: var(--borderRadius); +} +.submit-btn { + border: 1px solid var(--primary-500); + border-left: transparent; + border-top-right-radius: var(--borderRadius); + border-bottom-right-radius: var(--borderRadius); + text-transform: capitalize; + background: var(--primary-500); + color: var(--white); + transition: var(--transition); + cursor: pointer; +} +.submit-btn:hover { + color: var(--primary-900); +} + +.results { + padding: 2rem 0; +} + +.error { + text-align: center; + text-transform: capitalize; + color: var(--red-dark); +} + +.articles { + display: grid; + gap: 1rem; +} + +.articles a { + display: block; + background: var(--white); + color: var(--textColor); + padding: 1.5rem 2rem; + border-radius: var(--borderRadius); + transition: var(--transition); +} +.articles p { + color: var(--grey-500); + transition: var(--transition); +} + +.articles a:hover { + background: var(--black); + color: var(--white); +} + +@media screen and (min-width: 768px) { + .articles { + grid-template-columns: 1fr 1fr; + } + .form { + max-width: 600px; + } +} +@media screen and (min-width: 992px) { + .articles { + grid-template-columns: 1fr 1fr 1fr; + } +} diff --git a/28-wikipedia/final/wiki-logo.png b/28-wikipedia/final/wiki-logo.png new file mode 100644 index 000000000..1bb8adee3 Binary files /dev/null and b/28-wikipedia/final/wiki-logo.png differ diff --git a/28-wikipedia/final/wiki-urls.js b/28-wikipedia/final/wiki-urls.js new file mode 100644 index 000000000..433d81c2e --- /dev/null +++ b/28-wikipedia/final/wiki-urls.js @@ -0,0 +1,10 @@ +const url = + 'https://en.wikipedia.org/w/api.php?action=query&list=search&srlimit=20&format=json&origin=*&srsearch=searchValue'; + +// list=search - perform a full text search +// srsearch="inputValue" - search for page titles or content matching this value. +// srlimit=20 How many total pages to return. +// format=json json response +// "origin=*" fix cors errors + +const page_url = 'href=http://en.wikipedia.org/?curid=${pageid}'; diff --git a/28-wikipedia/starter/README.md b/28-wikipedia/starter/README.md new file mode 100644 index 000000000..03d68ba59 --- /dev/null +++ b/28-wikipedia/starter/README.md @@ -0,0 +1,44 @@ +#### HTML Structure + +- section.wiki + - div.container + - img + - h3(text) + - form.form + - input.form-input type='text' + - button.submit-btn (search) type='submit' + - div.results + - div.articles + - a + - h4 + - p (lorem20) + +#### API DOCS + +- [wiki docs](https://www.mediawiki.org/wiki/API:Main_page) + +- ready to go url's + +#### Initial Setup + +- select form, input, results +- listen for submit events +- if empty value, display error +- create fetchPages() +- pass valid input value into the fetchPages() + +#### Fetch Pages + +- display loading while fetching +- construct dynamic url +- display if error +- display error no items +- create renderResults() +- pass valid results into renderResults() + +#### Render Results + +- iterate over the list +- pull out title, snippet, pageid +- setup a card +- set results with div.articles and list inside diff --git a/28-wikipedia/starter/app.js b/28-wikipedia/starter/app.js new file mode 100644 index 000000000..67301cd32 --- /dev/null +++ b/28-wikipedia/starter/app.js @@ -0,0 +1 @@ +console.log('wiki starter'); diff --git a/28-wikipedia/starter/index.html b/28-wikipedia/starter/index.html new file mode 100644 index 000000000..85ebab7df --- /dev/null +++ b/28-wikipedia/starter/index.html @@ -0,0 +1,14 @@ + + + + + + + Wikipedia Starter + + + +

    wiki starter

    + + + diff --git a/28-wikipedia/starter/styles.css b/28-wikipedia/starter/styles.css new file mode 100644 index 000000000..0e57ad877 --- /dev/null +++ b/28-wikipedia/starter/styles.css @@ -0,0 +1,284 @@ +*, +::after, +::before { + box-sizing: border-box; +} + +html { + font-size: 100%; +} /*16px*/ + +:root { + /* colors */ + --primary-100: #e2e0ff; + --primary-200: #c1beff; + --primary-300: #a29dff; + --primary-400: #837dff; + --primary-500: #645cff; + --primary-600: #504acc; + --primary-700: #3c3799; + --primary-800: #282566; + --primary-900: #141233; + + /* grey */ + --grey-50: #f8fafc; + --grey-100: #f1f5f9; + --grey-200: #e2e8f0; + --grey-300: #cbd5e1; + --grey-400: #94a3b8; + --grey-500: #64748b; + --grey-600: #475569; + --grey-700: #334155; + --grey-800: #1e293b; + --grey-900: #0f172a; + /* rest of the colors */ + --black: #222; + --white: #fff; + --red-light: #f8d7da; + --red-dark: #842029; + --green-light: #d1e7dd; + --green-dark: #0f5132; + + /* fonts */ + --small-text: 0.875rem; + --extra-small-text: 0.7em; + /* rest of the vars */ + --backgroundColor: var(--grey-50); + --textColor: var(--grey-900); + --borderRadius: 0.25rem; + --letterSpacing: 1px; + --transition: 0.3s ease-in-out all; + --max-width: 1120px; + --fixed-width: 600px; + + /* box shadow*/ + --shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06); + --shadow-2: 0 4px 6px -1px rgba(0, 0, 0, 0.1), + 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-3: 0 10px 15px -3px rgba(0, 0, 0, 0.1), + 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-4: 0 20px 25px -5px rgba(0, 0, 0, 0.1), + 0 10px 10px -5px rgba(0, 0, 0, 0.04); +} + +body { + background: var(--backgroundColor); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-weight: 400; + line-height: 1.75; + color: var(--textColor); +} + +p { + margin-bottom: 1.5rem; + max-width: 40em; +} + +h1, +h2, +h3, +h4, +h5 { + margin: 0; + margin-bottom: 1.38rem; + font-weight: 400; + line-height: 1.3; + text-transform: capitalize; + letter-spacing: var(--letterSpacing); +} + +h1 { + margin-top: 0; + font-size: 3.052rem; +} + +h2 { + font-size: 2.441rem; +} + +h3 { + font-size: 1.953rem; +} + +h4 { + font-size: 1.563rem; +} + +h5 { + font-size: 1.25rem; +} + +small, +.text-small { + font-size: var(--small-text); +} + +a { + text-decoration: none; +} +ul { + list-style-type: none; + padding: 0; +} + +.img { + width: 100%; + display: block; + object-fit: cover; +} +/* buttons */ + +.btn { + cursor: pointer; + color: var(--white); + background: var(--primary-500); + border: transparent; + border-radius: var(--borderRadius); + letter-spacing: var(--letterSpacing); + padding: 0.375rem 0.75rem; + box-shadow: var(--shadow-1); + transition: var(--transition); + text-transform: capitalize; + display: inline-block; +} +.btn:hover { + background: var(--primary-700); + box-shadow: var(--shadow-3); +} + +@keyframes spinner { + to { + transform: rotate(360deg); + } +} + +.loading { + width: 6rem; + height: 6rem; + border: 5px solid var(--grey-400); + border-radius: 50%; + border-top-color: var(--primary-500); + animation: spinner 0.6s linear infinite; +} +.loading { + margin: 0 auto; + margin-top: 4rem; +} +/* title */ + +.title { + text-align: center; + margin-bottom: 3rem; +} + +.title-underline { + background: var(--primary-500); + width: 7rem; + height: 0.25rem; + margin: 0 auto; + margin-top: -1rem; +} + +/* +=============== +Wikipedia +=============== +*/ +.wiki { + padding: 5rem 0; + width: 90vw; + max-width: 1170px; + margin: 0 auto; +} +.container { + text-align: center; +} +.container img { + width: 200px; +} +.container h3 { + margin-bottom: 2rem; +} + +.form { + background: #fff; + width: 100%; + margin: 0 auto; + padding: 2.5rem; + border-radius: var(--borderRadius); + display: grid; + grid-template-columns: auto 100px; +} +.form-input, +.submit-btn { + padding: 0.375rem 0.75rem; + background: var(--backgroundColor); + border: 1px solid var(--grey-200); +} +.form-input { + border-right: transparent; + border-top-left-radius: var(--borderRadius); + border-bottom-left-radius: var(--borderRadius); +} +.submit-btn { + border: 1px solid var(--primary-500); + border-left: transparent; + border-top-right-radius: var(--borderRadius); + border-bottom-right-radius: var(--borderRadius); + text-transform: capitalize; + background: var(--primary-500); + color: var(--white); + transition: var(--transition); + cursor: pointer; +} +.submit-btn:hover { + color: var(--primary-900); +} + +.results { + padding: 2rem 0; +} + +.error { + text-align: center; + text-transform: capitalize; + color: var(--red-dark); +} + +.articles { + display: grid; + gap: 1rem; +} + +.articles a { + display: block; + background: var(--white); + color: var(--textColor); + padding: 1.5rem 2rem; + border-radius: var(--borderRadius); + transition: var(--transition); +} +.articles p { + color: var(--grey-500); + transition: var(--transition); +} + +.articles a:hover { + background: var(--black); + color: var(--white); +} + +@media screen and (min-width: 768px) { + .articles { + grid-template-columns: 1fr 1fr; + } + .form { + max-width: 600px; + } +} +@media screen and (min-width: 992px) { + .articles { + grid-template-columns: 1fr 1fr 1fr; + } +} diff --git a/28-wikipedia/starter/wiki-logo.png b/28-wikipedia/starter/wiki-logo.png new file mode 100644 index 000000000..1bb8adee3 Binary files /dev/null and b/28-wikipedia/starter/wiki-logo.png differ diff --git a/28-wikipedia/starter/wiki-urls.js b/28-wikipedia/starter/wiki-urls.js new file mode 100644 index 000000000..433d81c2e --- /dev/null +++ b/28-wikipedia/starter/wiki-urls.js @@ -0,0 +1,10 @@ +const url = + 'https://en.wikipedia.org/w/api.php?action=query&list=search&srlimit=20&format=json&origin=*&srsearch=searchValue'; + +// list=search - perform a full text search +// srsearch="inputValue" - search for page titles or content matching this value. +// srlimit=20 How many total pages to return. +// format=json json response +// "origin=*" fix cors errors + +const page_url = 'href=http://en.wikipedia.org/?curid=${pageid}'; diff --git a/29-comfy-store/.vscode/settings.json b/29-comfy-store/.vscode/settings.json new file mode 100644 index 000000000..6b665aaa0 --- /dev/null +++ b/29-comfy-store/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "liveServer.settings.port": 5501 +} diff --git a/29-comfy-store/final/about.html b/29-comfy-store/final/about.html new file mode 100644 index 000000000..780dcdfe5 --- /dev/null +++ b/29-comfy-store/final/about.html @@ -0,0 +1,130 @@ + + + + + + About | Comfy + + + + + + + + + + + +
    +
    +

    Home / About

    +
    +
    + + + +
    + +
    + +
    +
    +

    / our history

    +
    +

    + Lorem ipsum, dolor sit amet consectetur adipisicing elit. Fugiat + accusantium sapiente tempora sed dolore esse deserunt eaque excepturi, + delectus error accusamus vel eligendi, omnis beatae. Quisquam, dicta. + Eos quod quisquam esse recusandae vitae neque dolore, obcaecati incidunt + sequi blanditiis est exercitationem molestiae delectus saepe odio + eligendi modi porro eaque in libero minus unde sapiente consectetur + architecto. Ullam rerum, nemo iste ex, eaque perspiciatis nisi, eum + totam velit saepe sed quos similique amet. Ex, voluptate accusamus + nesciunt totam vitae esse iste. +

    +
    + + + diff --git a/29-comfy-store/final/images/logo-black.svg b/29-comfy-store/final/images/logo-black.svg new file mode 100644 index 000000000..f12a1801a --- /dev/null +++ b/29-comfy-store/final/images/logo-black.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/29-comfy-store/final/images/logo-white.svg b/29-comfy-store/final/images/logo-white.svg new file mode 100644 index 000000000..fa15b575a --- /dev/null +++ b/29-comfy-store/final/images/logo-white.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/29-comfy-store/final/images/main-bcg.jpeg b/29-comfy-store/final/images/main-bcg.jpeg new file mode 100644 index 000000000..2dd3e455e Binary files /dev/null and b/29-comfy-store/final/images/main-bcg.jpeg differ diff --git a/29-comfy-store/final/index.html b/29-comfy-store/final/index.html new file mode 100644 index 000000000..6ee4ca023 --- /dev/null +++ b/29-comfy-store/final/index.html @@ -0,0 +1,152 @@ + + + + + + + + + + + Home | Comfy + + + + + +
    +
    +

    + rest, relax, unwind +

    +

    Embrace your choices - we do

    + + show now + +
    +
    + + + +
    + +
    + + + + + diff --git a/29-comfy-store/final/index.js b/29-comfy-store/final/index.js new file mode 100644 index 000000000..0d604d567 --- /dev/null +++ b/29-comfy-store/final/index.js @@ -0,0 +1,21 @@ +// global imports +import './src/toggleSidebar.js'; +import './src/cart/toggleCart.js'; +import './src/cart/setupCart.js'; +// specific imports +import fetchProducts from './src/fetchProducts.js'; +import { setupStore, store } from './src/store.js'; +import display from './src/displayProducts.js'; +import { getElement } from './src/utils.js'; + +const init = async () => { + const products = await fetchProducts(); + if (products) { + // add products to the store + setupStore(products); + const featured = store.filter((product) => product.featured === true); + display(featured, getElement('.featured-center')); + } +}; + +window.addEventListener('DOMContentLoaded', init); diff --git a/29-comfy-store/final/product.html b/29-comfy-store/final/product.html new file mode 100644 index 000000000..3da03a7c7 --- /dev/null +++ b/29-comfy-store/final/product.html @@ -0,0 +1,143 @@ + + + + + + Single Product + + + + + + + + + + +
    +
    +

    Home / Single Product

    +
    +
    + + + +
    + +
    + +
    +
    + +
    +
    +

    couch

    +

    + by marcos +

    +

    $30.00

    +
    +

    + Lorem ipsum dolor sit amet, consectetur adipisicing elit. Id, + modi? Minima libero doloremque necessitatibus! Praesentium + recusandae quod nesciunt animi voluptatem! +

    + +
    +
    +
    +
    +
    +

    loading...

    +
    + + + diff --git a/29-comfy-store/final/products.html b/29-comfy-store/final/products.html new file mode 100644 index 000000000..897fbce6b --- /dev/null +++ b/29-comfy-store/final/products.html @@ -0,0 +1,148 @@ + + + + + + Products | Comfy + + + + + + + + + + +
    +
    +

    Home / Products

    +
    +
    + + + +
    + +
    + +
    + +
    +
    + +
    + +
    + +

    Company

    +
    + + +
    + +

    Price

    +
    + +
    +

    +
    +
    + +
    +
    + +
    +

    Loading...

    +
    + + + diff --git a/29-comfy-store/final/src/cart/addToCartDOM.js b/29-comfy-store/final/src/cart/addToCartDOM.js new file mode 100644 index 000000000..c7414043b --- /dev/null +++ b/29-comfy-store/final/src/cart/addToCartDOM.js @@ -0,0 +1,31 @@ +import { formatPrice, getElement } from '../utils.js'; +const cartItemsDOM = getElement('.cart-items'); +const addToCartDOM = ({ id, name, price, image, amount }) => { + const article = document.createElement('article'); + article.classList.add('cart-item'); + article.setAttribute('data-id', id); + article.innerHTML = ` + ${name} +
    +

    ${name}

    +

    ${formatPrice(price)}

    + +
    + +
    + +

    ${amount}

    + +
    + `; + cartItemsDOM.appendChild(article); +}; + +export default addToCartDOM; diff --git a/29-comfy-store/final/src/cart/setupCart.js b/29-comfy-store/final/src/cart/setupCart.js new file mode 100644 index 000000000..79899fdbe --- /dev/null +++ b/29-comfy-store/final/src/cart/setupCart.js @@ -0,0 +1,131 @@ +// import +import { + getStorageItem, + setStorageItem, + formatPrice, + getElement, +} from '../utils.js'; +import { openCart } from './toggleCart.js'; +import { findProduct } from '../store.js'; +import addToCartDOM from './addToCartDOM.js'; +// set items + +const cartItemCountDOM = getElement('.cart-item-count'); +const cartItemsDOM = getElement('.cart-items'); +const cartTotalDOM = getElement('.cart-total'); + +let cart = getStorageItem('cart'); + +export const addToCart = (id) => { + let item = cart.find((cartItem) => cartItem.id === id); + + if (!item) { + let product = findProduct(id); + // add item to the the + product = { ...product, amount: 1 }; + cart = [...cart, product]; + // add item to the DOM; + addToCartDOM(product); + } else { + // update values + const amount = increaseAmount(id); + const items = [...cartItemsDOM.querySelectorAll('.cart-item-amount')]; + const newAmount = items.find((value) => value.dataset.id === id); + newAmount.textContent = amount; + } + // add one to the item count + displayCartItemCount(); + // display cart totals + displayCartTotal(); + // set cart in local storage + + setStorageItem('cart', cart); + //more stuff coming up + openCart(); +}; +function displayCartItemCount() { + const amount = cart.reduce((total, cartItem) => { + return (total += cartItem.amount); + }, 0); + cartItemCountDOM.textContent = amount; +} +function displayCartTotal() { + let total = cart.reduce((total, cartItem) => { + return (total += cartItem.price * cartItem.amount); + }, 0); + cartTotalDOM.textContent = `Total : ${formatPrice(total)} `; +} +function displayCartItemsDOM() { + cart.forEach((cartItem) => { + addToCartDOM(cartItem); + }); +} +function removeItem(id) { + cart = cart.filter((cartItem) => cartItem.id !== id); +} +function increaseAmount(id) { + let newAmount; + cart = cart.map((cartItem) => { + if (cartItem.id === id) { + newAmount = cartItem.amount + 1; + cartItem = { ...cartItem, amount: newAmount }; + } + return cartItem; + }); + return newAmount; +} +function decreaseAmount(id) { + let newAmount; + cart = cart.map((cartItem) => { + if (cartItem.id === id) { + newAmount = cartItem.amount - 1; + cartItem = { ...cartItem, amount: newAmount }; + } + return cartItem; + }); + return newAmount; +} + +function setupCartFunctionality() { + cartItemsDOM.addEventListener('click', function (e) { + const element = e.target; + const parent = e.target.parentElement; + const id = e.target.dataset.id; + const parentID = e.target.parentElement.dataset.id; + // remove + if (element.classList.contains('cart-item-remove-btn')) { + removeItem(id); + // parent.parentElement.remove(); + element.parentElement.parentElement.remove(); + } + // increase + if (parent.classList.contains('cart-item-increase-btn')) { + const newAmount = increaseAmount(parentID); + parent.nextElementSibling.textContent = newAmount; + } + // decrease + if (parent.classList.contains('cart-item-decrease-btn')) { + const newAmount = decreaseAmount(parentID); + if (newAmount === 0) { + removeItem(parentID); + parent.parentElement.parentElement.remove(); + } else { + parent.previousElementSibling.textContent = newAmount; + } + } + displayCartItemCount(); + displayCartTotal(); + setStorageItem('cart', cart); + }); +} +const init = () => { + // display amount of cart items + displayCartItemCount(); + // display total + displayCartTotal(); + // add all cart items to the dom + displayCartItemsDOM(); + // setup cart functionality + setupCartFunctionality(); +}; +init(); diff --git a/29-comfy-store/final/src/cart/toggleCart.js b/29-comfy-store/final/src/cart/toggleCart.js new file mode 100644 index 000000000..bc0814359 --- /dev/null +++ b/29-comfy-store/final/src/cart/toggleCart.js @@ -0,0 +1,16 @@ +import { getElement } from '../utils.js'; + +const cartOverlay = getElement('.cart-overlay'); +const closeCartBtn = getElement('.cart-close'); +const toggleCartBtn = getElement('.toggle-cart'); + +toggleCartBtn.addEventListener('click', () => { + cartOverlay.classList.add('show'); +}); +closeCartBtn.addEventListener('click', () => { + cartOverlay.classList.remove('show'); +}); + +export const openCart = () => { + cartOverlay.classList.add('show'); +}; diff --git a/29-comfy-store/final/src/displayProducts.js b/29-comfy-store/final/src/displayProducts.js new file mode 100644 index 000000000..6bf1c4af8 --- /dev/null +++ b/29-comfy-store/final/src/displayProducts.js @@ -0,0 +1,39 @@ +import { formatPrice } from './utils.js'; +import { addToCart } from './cart/setupCart.js'; +const display = (products, element, filters) => { + // display products + element.innerHTML = products + .map((product) => { + const { id, name, image, price } = product; + return `
    +
    + ${name} + +
    + + + + +
    +
    + +
    `; + }) + .join(''); + + if (filters) return; + + element.addEventListener('click', function (e) { + const parent = e.target.parentElement; + if (parent.classList.contains('product-cart-btn')) { + addToCart(parent.dataset.id); + } + }); +}; + +export default display; diff --git a/29-comfy-store/final/src/fetchProducts.js b/29-comfy-store/final/src/fetchProducts.js new file mode 100644 index 000000000..a8b2ff12f --- /dev/null +++ b/29-comfy-store/final/src/fetchProducts.js @@ -0,0 +1,11 @@ +import { allProductsUrl } from './utils.js'; + +const fetchProducts = async () => { + const response = await fetch(allProductsUrl).catch((err) => console.log(err)); + if (response) { + return response.json(); + } + return response; +}; + +export default fetchProducts; diff --git a/29-comfy-store/final/src/filters/companies.js b/29-comfy-store/final/src/filters/companies.js new file mode 100644 index 000000000..5011ae529 --- /dev/null +++ b/29-comfy-store/final/src/filters/companies.js @@ -0,0 +1,29 @@ +import { getElement } from '../utils.js'; +import display from '../displayProducts.js'; + +const setupCompanies = (store) => { + let companies = ['all', ...new Set(store.map((product) => product.company))]; + const companiesDOM = getElement('.companies'); + companiesDOM.innerHTML = companies + .map((company) => { + return ` `; + }) + .join(''); + companiesDOM.addEventListener('click', function (e) { + const element = e.target; + if (element.classList.contains('company-btn')) { + let newStore = []; + if (element.textContent === 'all') { + newStore = [...store]; + } else { + newStore = store.filter( + (product) => product.company === e.target.textContent + ); + } + + display(newStore, getElement('.products-container'), true); + } + }); +}; + +export default setupCompanies; diff --git a/29-comfy-store/final/src/filters/price.js b/29-comfy-store/final/src/filters/price.js new file mode 100644 index 000000000..0a334ed3e --- /dev/null +++ b/29-comfy-store/final/src/filters/price.js @@ -0,0 +1,29 @@ +import { getElement } from '../utils.js'; +import display from '../displayProducts.js'; + +const setupPrice = (store) => { + const priceInput = getElement('.price-filter'); + const priceValue = getElement('.price-value'); + + // setup filter + let maxPrice = store.map((product) => product.price); + maxPrice = Math.max(...maxPrice); + maxPrice = Math.ceil(maxPrice / 100); + priceInput.value = maxPrice; + priceInput.max = maxPrice; + priceInput.min = 0; + priceValue.textContent = `Value : $${maxPrice}`; + + priceInput.addEventListener('input', function () { + const value = parseInt(priceInput.value); + priceValue.textContent = `Value : $${value}`; + let newStore = store.filter((product) => product.price / 100 <= value); + display(newStore, getElement('.products-container'), true); + if (newStore.length < 1) { + const products = getElement('.products-container'); + products.innerHTML = `

    sorry, no products matched your search

    `; + } + }); +}; + +export default setupPrice; diff --git a/29-comfy-store/final/src/filters/search.js b/29-comfy-store/final/src/filters/search.js new file mode 100644 index 000000000..10d8ac9ec --- /dev/null +++ b/29-comfy-store/final/src/filters/search.js @@ -0,0 +1,29 @@ +import { getElement } from '../utils.js'; +import display from '../displayProducts.js'; +const setupSearch = (store) => { + const form = getElement('.input-form'); + const nameInput = getElement('.search-input'); + form.addEventListener('keyup', function () { + const value = nameInput.value; + if (value) { + const newStore = store.filter((product) => { + let { name } = product; + name = name.toLowerCase(); + if (name.startsWith(value)) { + return product; + } + }); + display(newStore, getElement('.products-container'), true); + if (newStore.length < 1) { + const products = getElement('.products-container'); + products.innerHTML = `

    + sorry, no products matched your search +

    `; + } + } else { + display(store, getElement('.products-container'), true); + } + }); +}; + +export default setupSearch; diff --git a/29-comfy-store/final/src/pages/about.js b/29-comfy-store/final/src/pages/about.js new file mode 100644 index 000000000..e4bf4a496 --- /dev/null +++ b/29-comfy-store/final/src/pages/about.js @@ -0,0 +1,4 @@ +// global imports +import '../toggleSidebar.js'; +import '../cart/toggleCart.js'; +import '../cart/setupCart.js'; diff --git a/29-comfy-store/final/src/pages/product.js b/29-comfy-store/final/src/pages/product.js new file mode 100644 index 000000000..3c4a76e1b --- /dev/null +++ b/29-comfy-store/final/src/pages/product.js @@ -0,0 +1,71 @@ +// global imports +import '../toggleSidebar.js'; +import '../cart/toggleCart.js'; +import '../cart/setupCart.js'; +// specific +import { addToCart } from '../cart/setupCart.js'; +import { singleProductUrl, getElement, formatPrice } from '../utils.js'; + +// selections +const loading = getElement('.page-loading'); +const centerDOM = getElement('.single-product-center'); +const pageTitleDOM = getElement('.page-hero-title'); +const imgDOM = getElement('.single-product-img'); +const titleDOM = getElement('.single-product-title'); +const companyDOM = getElement('.single-product-company'); +const priceDOM = getElement('.single-product-price'); +const colorsDOM = getElement('.single-product-colors'); +const descDOM = getElement('.single-product-desc'); +const cartBtn = getElement('.addToCartBtn'); + +// cart product +let productID; + +// show product when page loads +window.addEventListener('DOMContentLoaded', async function () { + const urlID = window.location.search; + + try { + const response = await fetch(`${singleProductUrl}${urlID}`); + if (response.status >= 200 && response.status <= 299) { + const product = await response.json(); + // grab data + const { id, fields } = product; + productID = id; + + const { name, company, price, colors, description } = fields; + const image = fields.image[0].thumbnails.large.url; + // set values + + document.title = `${name.toUpperCase()} | Comfy`; + pageTitleDOM.textContent = `Home / ${name}`; + imgDOM.src = image; + titleDOM.textContent = name; + companyDOM.textContent = `by ${company}`; + priceDOM.textContent = formatPrice(price); + descDOM.textContent = description; + colors.forEach((color) => { + const span = document.createElement('span'); + span.classList.add('product-color'); + span.style.backgroundColor = `${color}`; + colorsDOM.appendChild(span); + }); + } else { + console.log(response.status, response.statusText); + centerDOM.innerHTML = ` +
    +

    sorry, something went wrong

    + back home +
    + `; + } + } catch (error) { + console.log(error); + } + + loading.style.display = 'none'; +}); + +cartBtn.addEventListener('click', function () { + addToCart(productID); +}); diff --git a/29-comfy-store/final/src/pages/products.js b/29-comfy-store/final/src/pages/products.js new file mode 100644 index 000000000..436bdab2d --- /dev/null +++ b/29-comfy-store/final/src/pages/products.js @@ -0,0 +1,32 @@ +// global imports +import '../toggleSidebar.js'; +import '../cart/toggleCart.js'; +import '../cart/setupCart.js'; + +// filter imports +import setupSearch from '../filters/search.js'; +import setupCompanies from '../filters/companies.js'; +import setupPrice from '../filters/price.js'; + +// specific imports +import { store, setupStore } from '../store.js'; +import display from '../displayProducts.js'; +import { getElement } from '../utils.js'; +// import fetch products +import fetchProducts from '../fetchProducts.js'; + +const init = async () => { + const loading = getElement('.page-loading'); + if (store.length < 1) { + const products = await fetchProducts(); + setupStore(products); + } + display(store, getElement('.products-container')); + + setupSearch(store); + setupCompanies(store); + setupPrice(store); + loading.style.display = 'none'; +}; + +init(); diff --git a/29-comfy-store/final/src/store.js b/29-comfy-store/final/src/store.js new file mode 100644 index 000000000..7a4cf8266 --- /dev/null +++ b/29-comfy-store/final/src/store.js @@ -0,0 +1,20 @@ +import { getStorageItem, setStorageItem } from './utils.js'; +let store = getStorageItem('store'); +const setupStore = (products) => { + store = products.map((product) => { + const { + id, + fields: { featured, name, price, company, colors, image: img }, + } = product; + const image = img[0].thumbnails.large.url; + return { id, featured, name, price, company, colors, image }; + }); + setStorageItem('store', store); +}; + +const findProduct = (id) => { + let product = store.find((product) => product.id === id); + return product; +}; + +export { store, setupStore, findProduct }; diff --git a/29-comfy-store/final/src/toggleSidebar.js b/29-comfy-store/final/src/toggleSidebar.js new file mode 100644 index 000000000..0c502561f --- /dev/null +++ b/29-comfy-store/final/src/toggleSidebar.js @@ -0,0 +1,12 @@ +import { getElement } from './utils.js'; + +const toggleNav = getElement('.toggle-nav'); +const sidebarOverlay = getElement('.sidebar-overlay'); +const closeBtn = getElement('.sidebar-close'); + +toggleNav.addEventListener('click', () => { + sidebarOverlay.classList.add('show'); +}); +closeBtn.addEventListener('click', () => { + sidebarOverlay.classList.remove('show'); +}); diff --git a/29-comfy-store/final/src/utils.js b/29-comfy-store/final/src/utils.js new file mode 100644 index 000000000..eeb4cb9bb --- /dev/null +++ b/29-comfy-store/final/src/utils.js @@ -0,0 +1,49 @@ +// ATTENTION!!!!!!!!!!! +// I SWITCHED TO PERMANENT DOMAIN +// DATA IS THE SAME JUST A DIFFERENT URL, +// DOES NOT AFFECT PROJECT FUNCTIONALITY + +const allProductsUrl = 'https://www.course-api.com/javascript-store-products'; +// temporary single product +// 'https://www.course-api.com/javascript-store-single-product?id=rec43w3ipXvP28vog' +const singleProductUrl = + 'https://www.course-api.com/javascript-store-single-product'; + +const getElement = (selection) => { + const element = document.querySelector(selection); + if (element) return element; + throw new Error( + `Please check "${selection}" selector, no such element exist` + ); +}; + +const formatPrice = (price) => { + let formattedPrice = new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'USD', + }).format((price / 100).toFixed(2)); + return formattedPrice; +}; + +const getStorageItem = (item) => { + let storageItem = localStorage.getItem(item); + if (storageItem) { + storageItem = JSON.parse(localStorage.getItem(item)); + } else { + storageItem = []; + } + return storageItem; +}; + +const setStorageItem = (name, item) => { + localStorage.setItem(name, JSON.stringify(item)); +}; + +export { + allProductsUrl, + singleProductUrl, + getElement, + formatPrice, + getStorageItem, + setStorageItem, +}; diff --git a/29-comfy-store/final/styles.css b/29-comfy-store/final/styles.css new file mode 100644 index 000000000..e671ccd12 --- /dev/null +++ b/29-comfy-store/final/styles.css @@ -0,0 +1,777 @@ +@import url('https://fonts.googleapis.com/css2?family=Kaushan+Script&display=swap'); +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(21, 91%, 17%); + --clr-primary-2: hsl(21, 84%, 25%); + --clr-primary-3: hsl(21, 81%, 29%); + --clr-primary-4: hsl(21, 77%, 34%); + /* primary/main color */ + --clr-primary-5: hsl(21, 62%, 45%); + /* lighter shades of primary color */ + --clr-primary-6: hsl(21, 57%, 50%); + --clr-primary-7: hsl(21, 65%, 59%); + --clr-primary-8: hsl(21, 80%, 74%); + --clr-primary-9: hsl(21, 94%, 87%); + --clr-primary-10: hsl(21, 100%, 94%); + /* darkest grey - used for headings */ + --clr-grey-1: #102a42; + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + + --transition: all 0.3s linear; + --spacing: 0.1rem; + --radius: 0.25rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background: var(--clr-white); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-weight: 400; +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +.img { + width: 100%; + display: block; +} +.text-slanted { + font-family: 'Kaushan Script', cursive; +} +.section-center { + width: 90vw; + max-width: var(--max-width); + margin: 0 auto; +} +.section { + padding: 5rem 0; +} +.btn { + background: var(--clr-primary-5); + color: var(--clr-white); + border-radius: var(--radius); + padding: 0.375rem 0.75rem; + text-transform: uppercase; + letter-spacing: var(--spacing); + display: inline-block; + transition: var(--transition); + border-color: transparent; + cursor: pointer; +} +.btn:hover { + background: var(--clr-primary-7); + color: var(--clr-black); +} +.section-loading { + text-align: center; + position: absolute; + top: 2rem; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; +} +.page-loading { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--clr-grey-10); + display: flex; + align-items: center; + justify-content: center; +} +/* +=============== +Navbar +=============== +*/ + +.navbar { + height: 6rem; + background: transparent; + display: flex; + align-items: center; + justify-content: center; +} + +.nav-center { + width: 90vw; + max-width: var(--max-width); + display: flex; + justify-content: space-between; + align-items: center; +} +.nav-links { + display: none; +} +.toggle-nav { + background: var(--clr-primary-5); + border-color: transparent; + color: var(--clr-white); + width: 3.75rem; + height: 2.25rem; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + border-radius: 2rem; + cursor: pointer; + transition: var(--transition); +} +.toggle-nav:hover { + background: var(--clr-primary-3); +} +.toggle-container { + position: relative; + margin-top: 0.75rem; +} +.toggle-cart { + background: transparent; + border-color: transparent; + font-size: 1.6rem; + color: var(--clr-white); + cursor: pointer; +} +.cart-item-count { + position: absolute; + top: -0.85rem; + right: -0.85rem; + background: var(--clr-primary-5); + width: 1.75rem; + height: 1.75rem; + display: grid; + place-items: center; + border-radius: 50%; + color: var(--clr-white); + font-weight: bold; + font-size: 1rem; +} +@media screen and (min-width: 800px) { + .nav-center { + position: relative; + } + .nav-logo { + position: absolute; + top: 50%; + left: 65%; + transform: translate(-50%, -50%); + } + .toggle-nav { + display: none; + } + .nav-links { + display: flex; + font-size: 1.5rem; + text-transform: capitalize; + } + .nav-link { + color: var(--clr-white); + margin-right: 3rem; + letter-spacing: var(--spacing); + transition: var(--transition); + font-size: 1.25rem; + } + .nav-link:hover { + color: var(--clr-primary-5); + } +} +@media screen and (min-width: 992px) { + .nav-logo { + left: 50%; + } +} +/* page navbar */ +.page .nav-link { + color: var(--clr-grey-1); +} +.page .nav-link:hover { + color: var(--clr-primary-5); +} +.page .toggle-cart { + color: var(--clr-grey-1); +} +/* +=============== +Hero +=============== +*/ +.hero { + min-height: 100vh; + margin-top: -6rem; + background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), + url(./images/main-bcg.jpeg) center/cover; + display: grid; + place-items: center; + color: var(--clr-white); +} +.hero-container { + width: 90vw; + max-width: var(--max-width); +} +.hero h1 { + font-weight: 700; +} +.hero h3 { + text-transform: none; + font-size: 1.5rem; +} +.hero-btn { + color: var(--clr-white); + background: transparent; + border: 1px solid var(--clr-white); + padding: 0.5rem 0.75rem; + display: inline-block; + margin-top: 0.75rem; + text-transform: uppercase; + letter-spacing: var(--spacing); + border-radius: var(--radius); + transition: var(--transition); +} +.hero-btn:hover { + background: var(--clr-white); + color: var(--clr-primary-5); +} + +@media screen and (min-width: 800px) { + .hero h3 { + font-size: 1.5rem; + margin: 1rem 0; + } +} + +@media screen and (min-width: 992px) { + .hero h1 { + font-size: 5.25rem; + letter-spacing: 5px; + } + .hero h3 { + font-size: 2.75rem; + margin: 1.5rem 0; + } +} + +/* +=============== +Sidebar +=============== +*/ +.sidebar-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: grid; + place-items: center; + z-index: -1; + transition: var(--transition); + opacity: 0; + background: rgba(0, 0, 0, 0.5); +} +.sidebar-overlay.show { + opacity: 1; + z-index: 100; +} +.sidebar { + width: 90vw; + height: 95vh; + max-width: var(--fixed-width); + background: var(--clr-white); + border-radius: var(--radius); + box-shadow: var(--dark-shadow); + position: relative; + padding: 4rem; + transform: scale(0); +} +.show .sidebar { + transform: scale(1); +} +.sidebar-close { + font-size: 2rem; + background: transparent; + border-color: transparent; + color: var(--clr-grey-5); + position: absolute; + top: 1rem; + right: 1rem; + cursor: pointer; +} +.sidebar-link { + font-size: 1.5rem; + text-transform: capitalize; + color: var(--clr-grey-1); +} +.sidebar-link i { + color: var(--clr-grey-5); + margin-right: 1rem; + margin-bottom: 1rem; +} +@media screen and (min-width: 800px) { + .sidebar-overlay { + display: none; + } +} +/* +=============== +Cart +=============== +*/ +.cart-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + transition: var(--transition); + opacity: 0; + z-index: -1; +} +.cart-overlay.show { + opacity: 1; + z-index: 100; +} +.cart { + position: fixed; + top: 0; + right: 0; + width: 100%; + height: 100%; + max-width: 400px; + background: var(--clr-grey-10); + padding: 3rem 1rem 0 1rem; + display: grid; + grid-template-rows: auto 1fr auto; + transition: var(--transition); + transform: translateX(100%); + overflow: scroll; +} +.show .cart { + transform: translateX(0); +} +.cart-close { + font-size: 2rem; + background: transparent; + border-color: transparent; + color: var(--clr-grey-5); + position: absolute; + top: 0.5rem; + left: 1rem; + cursor: pointer; +} +.cart header { + text-align: center; +} +.cart header h3 { + font-weight: 500; +} +.cart-total { + text-align: center; + margin-bottom: 2rem; + font-weight: 500; +} +.cart-checkout { + display: block; + width: 75%; + margin: 0 auto; + margin-bottom: 3rem; +} +/* cart item */ +.cart-item { + margin: 1rem 0; + display: grid; + grid-template-columns: auto 1fr auto; + + column-gap: 1.5rem; + align-items: center; +} +.cart-item-img { + width: 75px; + height: 50px; + object-fit: cover; + border-radius: var(--radius); +} +.cart-item-name { + margin-bottom: 0.15rem; +} +.cart-item-price { + margin-bottom: 0; + font-size: 0.75rem; + color: var(--clr-grey-3); +} +.cart-item-remove-btn { + background: transparent; + border-color: transparent; + color: var(--clr-grey-5); + letter-spacing: var(--spacing); + cursor: pointer; +} +.cart-item-amount { + margin-bottom: 0; + text-align: center; + color: var(--clr-grey-3); + line-height: 1; +} +.cart-item-increase-btn, +.cart-item-decrease-btn { + background: transparent; + border-color: transparent; + color: var(--clr-primary-5); + cursor: pointer; + font-size: 0.85rem; + padding: 0.25rem; +} +/* +=============== +Title +=============== +*/ + +.title h2 { + display: flex; + justify-content: center; + align-items: center; + font-weight: 500; +} +.title span { + color: var(--clr-primary-5); + font-size: 0.85em; + margin-right: 1rem; +} +/* +=============== +product +=============== +*/ +.product-img { + height: 15rem; + object-fit: cover; + border-radius: var(--radius); +} +.product-container { + position: relative; +} +.product-icons { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + opacity: 0; + display: flex; + transition: var(--transition); +} +.product-icon { + width: 2.25rem; + height: 2.25rem; + background: var(--clr-primary-5); + color: var(--clr-white); + display: grid; + place-items: center; + border-radius: 50%; + transition: var(--transition); + cursor: pointer; + font-size: 1rem; + border-color: transparent; + margin: 0 0.5rem; +} +.product-icon:hover { + background: var(--clr-primary-7); +} +.product-container:hover .product-icons { + opacity: 1; +} +.product footer { + padding: 0.75rem 0; + text-align: center; +} +.product-name { + margin-bottom: 0.25rem; + text-transform: capitalize; + letter-spacing: var(--spacing); +} +.product-price { + margin-bottom: 0; + color: var(--clr-grey-3); + font-weight: 700; +} + +.featured-center { + margin: 3rem auto 2rem auto; + display: grid; + gap: 1rem; + min-height: 6rem; + position: relative; +} +.featured .btn { + display: block; + width: 11rem; + margin: 0 auto; + text-align: center; +} +@media screen and (min-width: 992px) { + .featured-center { + display: grid; + grid-template-columns: 1fr 1fr; + } +} +@media screen and (min-width: 1200px) { + .featured-center { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + } + .product .img { + height: 13rem; + } +} +/* +=============== +About Page +=============== +*/ +.about-text { + line-height: 2; + max-width: 45em; + margin: 0 auto; + margin-top: 2rem; +} + +/* +=============== +Products Page +=============== +*/ +.products { + width: 90vw; + display: grid; + grid-gap: 1rem; + margin: 4rem auto; + max-width: var(--max-width); + position: relative; +} +.filters-container { + position: sticky; + top: 1rem; +} +.filters h4 { + font-weight: 500; + margin: 1.5rem 0 0.5rem; +} + +.search-input { + padding: 0.5rem; + background: var(--clr-grey-10); + border-radius: var(--radius); + border-color: transparent; + letter-spacing: var(--spacing); +} +.search-input::placeholder { + text-transform: capitalize; +} +.company-btn { + display: block; + margin: 0.25em 0; + padding: 0.25rem; + text-transform: capitalize; + background: transparent; + border-color: transparent; + letter-spacing: var(--spacing); + color: var(--clr-grey-5); + cursor: pointer; + transition: var(--transition); +} +.company-btn:hover { + color: var(--clr-grey-3); +} +.price-filter { + background: var(--clr-grey-5) !important; + color: var(--clr-grey-5); +} +@media screen and (min-width: 768px) { + .products { + grid-template-columns: 200px 1fr; + } + .categories { + position: sticky; + top: 1rem; + } +} +@media screen and (min-width: 992px) { + .products-container { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + .products-container .product-img { + height: 10rem; + } + .products-container .product-name { + font-size: 0.85rem; + } + .products-container .product-price { + font-size: 0.85rem; + } +} +@media screen and (min-width: 1170px) { + .products-container { + grid-template-columns: repeat(3, 1fr); + } +} +.filter-error { + position: absolute; + top: 5rem; + left: 0; + width: 100%; + text-align: center; + margin-top: 4rem; +} +/* +=============== +Single Product Page +=============== +*/ +.page-hero { + min-height: 20vh; + display: grid; + place-items: center; + background: var(--clr-grey-10); + color: var(--clr-grey-5); +} +.page-hero-title { + font-weight: 500; +} +.single-product { + padding: 2rem 0; +} +.single-product-center { + margin: 2rem auto; + display: grid; + gap: 1rem 2rem; +} +.single-product-img { + height: 25rem; + border-radius: var(--radius); + object-fit: cover; +} +.single-product-company { + font-size: 1.2rem; + color: var(--clr-grey-8); + text-transform: uppercase; + letter-spacing: var(--spacing); + margin-bottom: 1.25rem; +} +.single-product-price { + color: var(--clr-grey-3); + font-size: 1.25rem; + font-weight: 500; +} + +.product-color { + display: inline-block; + width: 1rem; + height: 1rem; + border-radius: 50%; + background: #222; + margin: 0.5rem 0.5rem 1.5rem 0; +} + +.single-product-desc { + max-width: 25em; + line-height: 1.8; +} +@media screen and (min-width: 992px) { + .single-product-center { + grid-template-columns: 1fr 1fr; + } +} diff --git a/29-comfy-store/starter/about.html b/29-comfy-store/starter/about.html new file mode 100644 index 000000000..6c79eed51 --- /dev/null +++ b/29-comfy-store/starter/about.html @@ -0,0 +1,21 @@ + + + + + + About | Comfy + + + + + + + + +

    about page

    + + + diff --git a/29-comfy-store/starter/images/logo-black.svg b/29-comfy-store/starter/images/logo-black.svg new file mode 100644 index 000000000..f12a1801a --- /dev/null +++ b/29-comfy-store/starter/images/logo-black.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/29-comfy-store/starter/images/logo-white.svg b/29-comfy-store/starter/images/logo-white.svg new file mode 100644 index 000000000..fa15b575a --- /dev/null +++ b/29-comfy-store/starter/images/logo-white.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/29-comfy-store/starter/images/main-bcg.jpeg b/29-comfy-store/starter/images/main-bcg.jpeg new file mode 100644 index 000000000..2dd3e455e Binary files /dev/null and b/29-comfy-store/starter/images/main-bcg.jpeg differ diff --git a/29-comfy-store/starter/index.html b/29-comfy-store/starter/index.html new file mode 100644 index 000000000..266e65945 --- /dev/null +++ b/29-comfy-store/starter/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + + Home | Comfy + + +

    home page

    + + + diff --git a/29-comfy-store/starter/index.js b/29-comfy-store/starter/index.js new file mode 100644 index 000000000..6204a24d6 --- /dev/null +++ b/29-comfy-store/starter/index.js @@ -0,0 +1,9 @@ +// global imports +import './src/toggleSidebar.js'; +import './src/cart/toggleCart.js'; +import './src/cart/setupCart.js'; +// specific imports +import fetchProducts from './src/fetchProducts.js'; +import { setupStore, store } from './src/store.js'; +import display from './src/displayProducts.js'; +import { getElement } from './src/utils.js'; diff --git a/29-comfy-store/starter/product.html b/29-comfy-store/starter/product.html new file mode 100644 index 000000000..66cb456a2 --- /dev/null +++ b/29-comfy-store/starter/product.html @@ -0,0 +1,20 @@ + + + + + + Single Product + + + + + + + +

    single product

    + + + diff --git a/29-comfy-store/starter/products.html b/29-comfy-store/starter/products.html new file mode 100644 index 000000000..1d3bf7720 --- /dev/null +++ b/29-comfy-store/starter/products.html @@ -0,0 +1,20 @@ + + + + + + Products | Comfy + + + + + + + +

    products page

    + + + diff --git a/29-comfy-store/starter/src/cart/addToCartDOM.js b/29-comfy-store/starter/src/cart/addToCartDOM.js new file mode 100644 index 000000000..e375ab6a6 --- /dev/null +++ b/29-comfy-store/starter/src/cart/addToCartDOM.js @@ -0,0 +1,5 @@ +import { formatPrice, getElement } from '../utils.js'; + +const addToCartDOM = () => {}; + +export default addToCartDOM; diff --git a/29-comfy-store/starter/src/cart/setupCart.js b/29-comfy-store/starter/src/cart/setupCart.js new file mode 100644 index 000000000..897c23393 --- /dev/null +++ b/29-comfy-store/starter/src/cart/setupCart.js @@ -0,0 +1,13 @@ +// import +import { + getStorageItem, + setStorageItem, + formatPrice, + getElement, +} from '../utils.js'; +import { openCart } from './toggleCart.js'; +import { findProduct } from '../store.js'; +import addToCartDOM from './addToCartDOM.js'; +// set items + +export const addToCart = () => {}; diff --git a/29-comfy-store/starter/src/cart/toggleCart.js b/29-comfy-store/starter/src/cart/toggleCart.js new file mode 100644 index 000000000..185dda856 --- /dev/null +++ b/29-comfy-store/starter/src/cart/toggleCart.js @@ -0,0 +1,3 @@ +import { getElement } from '../utils.js'; + +export const openCart = () => {}; diff --git a/29-comfy-store/starter/src/displayProducts.js b/29-comfy-store/starter/src/displayProducts.js new file mode 100644 index 000000000..b2bbbe7f2 --- /dev/null +++ b/29-comfy-store/starter/src/displayProducts.js @@ -0,0 +1,5 @@ +import { formatPrice } from './utils.js'; +import { addToCart } from './cart/setupCart.js'; +const display = () => {}; + +export default display; diff --git a/29-comfy-store/starter/src/fetchProducts.js b/29-comfy-store/starter/src/fetchProducts.js new file mode 100644 index 000000000..694b81253 --- /dev/null +++ b/29-comfy-store/starter/src/fetchProducts.js @@ -0,0 +1,5 @@ +import { allProductsUrl } from './utils.js'; + +const fetchProducts = async () => {}; + +export default fetchProducts; diff --git a/29-comfy-store/starter/src/filters/companies.js b/29-comfy-store/starter/src/filters/companies.js new file mode 100644 index 000000000..f7a053b8f --- /dev/null +++ b/29-comfy-store/starter/src/filters/companies.js @@ -0,0 +1,6 @@ +import { getElement } from '../utils.js'; +import display from '../displayProducts.js'; + +const setupCompanies = () => {}; + +export default setupCompanies; diff --git a/29-comfy-store/starter/src/filters/price.js b/29-comfy-store/starter/src/filters/price.js new file mode 100644 index 000000000..f47d67f49 --- /dev/null +++ b/29-comfy-store/starter/src/filters/price.js @@ -0,0 +1,6 @@ +import { getElement } from '../utils.js'; +import display from '../displayProducts.js'; + +const setupPrice = () => {}; + +export default setupPrice; diff --git a/29-comfy-store/starter/src/filters/search.js b/29-comfy-store/starter/src/filters/search.js new file mode 100644 index 000000000..6bd3dd7e0 --- /dev/null +++ b/29-comfy-store/starter/src/filters/search.js @@ -0,0 +1,5 @@ +import { getElement } from '../utils.js'; +import display from '../displayProducts.js'; +const setupSearch = () => {}; + +export default setupSearch; diff --git a/29-comfy-store/starter/src/pages/about.js b/29-comfy-store/starter/src/pages/about.js new file mode 100644 index 000000000..e4bf4a496 --- /dev/null +++ b/29-comfy-store/starter/src/pages/about.js @@ -0,0 +1,4 @@ +// global imports +import '../toggleSidebar.js'; +import '../cart/toggleCart.js'; +import '../cart/setupCart.js'; diff --git a/29-comfy-store/starter/src/pages/product.js b/29-comfy-store/starter/src/pages/product.js new file mode 100644 index 000000000..ce6f8b9d8 --- /dev/null +++ b/29-comfy-store/starter/src/pages/product.js @@ -0,0 +1,24 @@ +// global imports +import '../toggleSidebar.js'; +import '../cart/toggleCart.js'; +import '../cart/setupCart.js'; +// specific +import { addToCart } from '../cart/setupCart.js'; +import { singleProductUrl, getElement, formatPrice } from '../utils.js'; + +// selections +// const loading = getElement('.page-loading'); +// const centerDOM = getElement('.single-product-center'); +// const pageTitleDOM = getElement('.page-hero-title'); +// const imgDOM = getElement('.single-product-img'); +// const titleDOM = getElement('.single-product-title'); +// const companyDOM = getElement('.single-product-company'); +// const priceDOM = getElement('.single-product-price'); +// const colorsDOM = getElement('.single-product-colors'); +// const descDOM = getElement('.single-product-desc'); +// const cartBtn = getElement('.addToCartBtn'); + +// cart product +// let productID; + +// show product when page loads diff --git a/29-comfy-store/starter/src/pages/products.js b/29-comfy-store/starter/src/pages/products.js new file mode 100644 index 000000000..5e67c061c --- /dev/null +++ b/29-comfy-store/starter/src/pages/products.js @@ -0,0 +1,14 @@ +// global imports +import '../toggleSidebar.js'; +import '../cart/toggleCart.js'; +import '../cart/setupCart.js'; + +// filter imports +import setupSearch from '../filters/search.js'; +import setupCompanies from '../filters/companies.js'; +import setupPrice from '../filters/price.js'; + +// specific imports +import { store } from '../store.js'; +import display from '../displayProducts.js'; +import { getElement } from '../utils.js'; diff --git a/29-comfy-store/starter/src/store.js b/29-comfy-store/starter/src/store.js new file mode 100644 index 000000000..e0ea2af52 --- /dev/null +++ b/29-comfy-store/starter/src/store.js @@ -0,0 +1,5 @@ +import { getStorageItem, setStorageItem } from './utils.js'; +let store = []; +const setupStore = () => {}; +const findProduct = () => {}; +export { store, setupStore, findProduct }; diff --git a/29-comfy-store/starter/src/toggleSidebar.js b/29-comfy-store/starter/src/toggleSidebar.js new file mode 100644 index 000000000..46470512b --- /dev/null +++ b/29-comfy-store/starter/src/toggleSidebar.js @@ -0,0 +1 @@ +import { getElement } from './utils.js'; diff --git a/29-comfy-store/starter/src/utils.js b/29-comfy-store/starter/src/utils.js new file mode 100644 index 000000000..2f36ef175 --- /dev/null +++ b/29-comfy-store/starter/src/utils.js @@ -0,0 +1,32 @@ +// ATTENTION!!!!!!!!!!! +// I SWITCHED TO PERMANENT DOMAIN +// DATA IS THE SAME JUST A DIFFERENT URL, +// DOES NOT AFFECT PROJECT FUNCTIONALITY + +const allProductsUrl = 'https://www.course-api.com/javascript-store-products'; +// temporary single product +// 'https://www.course-api.com/javascript-store-single-product?id=rec43w3ipXvP28vog' +const singleProductUrl = + 'https://www.course-api.com/javascript-store-single-product'; + +const getElement = (selection) => { + const element = document.querySelector(selection); + if (element) return element; + throw new Error( + `Please check "${selection}" selector, no such element exist` + ); +}; + +const formatPrice = () => {}; + +const getStorageItem = () => {}; +const setStorageItem = () => {}; + +export { + allProductsUrl, + singleProductUrl, + getElement, + formatPrice, + getStorageItem, + setStorageItem, +}; diff --git a/29-comfy-store/starter/styles.css b/29-comfy-store/starter/styles.css new file mode 100644 index 000000000..e671ccd12 --- /dev/null +++ b/29-comfy-store/starter/styles.css @@ -0,0 +1,777 @@ +@import url('https://fonts.googleapis.com/css2?family=Kaushan+Script&display=swap'); +/* +=============== +Variables +=============== +*/ + +:root { + /* dark shades of primary color*/ + --clr-primary-1: hsl(21, 91%, 17%); + --clr-primary-2: hsl(21, 84%, 25%); + --clr-primary-3: hsl(21, 81%, 29%); + --clr-primary-4: hsl(21, 77%, 34%); + /* primary/main color */ + --clr-primary-5: hsl(21, 62%, 45%); + /* lighter shades of primary color */ + --clr-primary-6: hsl(21, 57%, 50%); + --clr-primary-7: hsl(21, 65%, 59%); + --clr-primary-8: hsl(21, 80%, 74%); + --clr-primary-9: hsl(21, 94%, 87%); + --clr-primary-10: hsl(21, 100%, 94%); + /* darkest grey - used for headings */ + --clr-grey-1: #102a42; + --clr-grey-2: hsl(211, 39%, 23%); + --clr-grey-3: hsl(209, 34%, 30%); + --clr-grey-4: hsl(209, 28%, 39%); + /* grey used for paragraphs */ + --clr-grey-5: hsl(210, 22%, 49%); + --clr-grey-6: hsl(209, 23%, 60%); + --clr-grey-7: hsl(211, 27%, 70%); + --clr-grey-8: hsl(210, 31%, 80%); + --clr-grey-9: hsl(212, 33%, 89%); + --clr-grey-10: hsl(210, 36%, 96%); + --clr-white: #fff; + --clr-red-dark: hsl(360, 67%, 44%); + --clr-red-light: hsl(360, 71%, 66%); + --clr-green-dark: hsl(125, 67%, 44%); + --clr-green-light: hsl(125, 71%, 66%); + --clr-black: #222; + + --transition: all 0.3s linear; + --spacing: 0.1rem; + --radius: 0.25rem; + --light-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + --dark-shadow: 0 5px 15px rgba(0, 0, 0, 0.2); + --max-width: 1170px; + --fixed-width: 620px; +} +/* +=============== +Global Styles +=============== +*/ + +*, +::after, +::before { + margin: 0; + padding: 0; + box-sizing: border-box; +} +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background: var(--clr-white); + color: var(--clr-grey-1); + line-height: 1.5; + font-size: 0.875rem; +} +ul { + list-style-type: none; +} +a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: var(--spacing); + text-transform: capitalize; + line-height: 1.25; + margin-bottom: 0.75rem; + font-weight: 400; +} +h1 { + font-size: 3rem; +} +h2 { + font-size: 2rem; +} +h3 { + font-size: 1.25rem; +} +h4 { + font-size: 0.875rem; +} +p { + margin-bottom: 1.25rem; + color: var(--clr-grey-5); +} +@media screen and (min-width: 800px) { + h1 { + font-size: 4rem; + } + h2 { + font-size: 2.5rem; + } + h3 { + font-size: 1.75rem; + } + h4 { + font-size: 1rem; + } + body { + font-size: 1rem; + } + h1, + h2, + h3, + h4 { + line-height: 1; + } +} +.img { + width: 100%; + display: block; +} +.text-slanted { + font-family: 'Kaushan Script', cursive; +} +.section-center { + width: 90vw; + max-width: var(--max-width); + margin: 0 auto; +} +.section { + padding: 5rem 0; +} +.btn { + background: var(--clr-primary-5); + color: var(--clr-white); + border-radius: var(--radius); + padding: 0.375rem 0.75rem; + text-transform: uppercase; + letter-spacing: var(--spacing); + display: inline-block; + transition: var(--transition); + border-color: transparent; + cursor: pointer; +} +.btn:hover { + background: var(--clr-primary-7); + color: var(--clr-black); +} +.section-loading { + text-align: center; + position: absolute; + top: 2rem; + left: 50%; + transform: translate(-50%, -50%); + text-align: center; +} +.page-loading { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--clr-grey-10); + display: flex; + align-items: center; + justify-content: center; +} +/* +=============== +Navbar +=============== +*/ + +.navbar { + height: 6rem; + background: transparent; + display: flex; + align-items: center; + justify-content: center; +} + +.nav-center { + width: 90vw; + max-width: var(--max-width); + display: flex; + justify-content: space-between; + align-items: center; +} +.nav-links { + display: none; +} +.toggle-nav { + background: var(--clr-primary-5); + border-color: transparent; + color: var(--clr-white); + width: 3.75rem; + height: 2.25rem; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + border-radius: 2rem; + cursor: pointer; + transition: var(--transition); +} +.toggle-nav:hover { + background: var(--clr-primary-3); +} +.toggle-container { + position: relative; + margin-top: 0.75rem; +} +.toggle-cart { + background: transparent; + border-color: transparent; + font-size: 1.6rem; + color: var(--clr-white); + cursor: pointer; +} +.cart-item-count { + position: absolute; + top: -0.85rem; + right: -0.85rem; + background: var(--clr-primary-5); + width: 1.75rem; + height: 1.75rem; + display: grid; + place-items: center; + border-radius: 50%; + color: var(--clr-white); + font-weight: bold; + font-size: 1rem; +} +@media screen and (min-width: 800px) { + .nav-center { + position: relative; + } + .nav-logo { + position: absolute; + top: 50%; + left: 65%; + transform: translate(-50%, -50%); + } + .toggle-nav { + display: none; + } + .nav-links { + display: flex; + font-size: 1.5rem; + text-transform: capitalize; + } + .nav-link { + color: var(--clr-white); + margin-right: 3rem; + letter-spacing: var(--spacing); + transition: var(--transition); + font-size: 1.25rem; + } + .nav-link:hover { + color: var(--clr-primary-5); + } +} +@media screen and (min-width: 992px) { + .nav-logo { + left: 50%; + } +} +/* page navbar */ +.page .nav-link { + color: var(--clr-grey-1); +} +.page .nav-link:hover { + color: var(--clr-primary-5); +} +.page .toggle-cart { + color: var(--clr-grey-1); +} +/* +=============== +Hero +=============== +*/ +.hero { + min-height: 100vh; + margin-top: -6rem; + background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), + url(./images/main-bcg.jpeg) center/cover; + display: grid; + place-items: center; + color: var(--clr-white); +} +.hero-container { + width: 90vw; + max-width: var(--max-width); +} +.hero h1 { + font-weight: 700; +} +.hero h3 { + text-transform: none; + font-size: 1.5rem; +} +.hero-btn { + color: var(--clr-white); + background: transparent; + border: 1px solid var(--clr-white); + padding: 0.5rem 0.75rem; + display: inline-block; + margin-top: 0.75rem; + text-transform: uppercase; + letter-spacing: var(--spacing); + border-radius: var(--radius); + transition: var(--transition); +} +.hero-btn:hover { + background: var(--clr-white); + color: var(--clr-primary-5); +} + +@media screen and (min-width: 800px) { + .hero h3 { + font-size: 1.5rem; + margin: 1rem 0; + } +} + +@media screen and (min-width: 992px) { + .hero h1 { + font-size: 5.25rem; + letter-spacing: 5px; + } + .hero h3 { + font-size: 2.75rem; + margin: 1.5rem 0; + } +} + +/* +=============== +Sidebar +=============== +*/ +.sidebar-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: grid; + place-items: center; + z-index: -1; + transition: var(--transition); + opacity: 0; + background: rgba(0, 0, 0, 0.5); +} +.sidebar-overlay.show { + opacity: 1; + z-index: 100; +} +.sidebar { + width: 90vw; + height: 95vh; + max-width: var(--fixed-width); + background: var(--clr-white); + border-radius: var(--radius); + box-shadow: var(--dark-shadow); + position: relative; + padding: 4rem; + transform: scale(0); +} +.show .sidebar { + transform: scale(1); +} +.sidebar-close { + font-size: 2rem; + background: transparent; + border-color: transparent; + color: var(--clr-grey-5); + position: absolute; + top: 1rem; + right: 1rem; + cursor: pointer; +} +.sidebar-link { + font-size: 1.5rem; + text-transform: capitalize; + color: var(--clr-grey-1); +} +.sidebar-link i { + color: var(--clr-grey-5); + margin-right: 1rem; + margin-bottom: 1rem; +} +@media screen and (min-width: 800px) { + .sidebar-overlay { + display: none; + } +} +/* +=============== +Cart +=============== +*/ +.cart-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + transition: var(--transition); + opacity: 0; + z-index: -1; +} +.cart-overlay.show { + opacity: 1; + z-index: 100; +} +.cart { + position: fixed; + top: 0; + right: 0; + width: 100%; + height: 100%; + max-width: 400px; + background: var(--clr-grey-10); + padding: 3rem 1rem 0 1rem; + display: grid; + grid-template-rows: auto 1fr auto; + transition: var(--transition); + transform: translateX(100%); + overflow: scroll; +} +.show .cart { + transform: translateX(0); +} +.cart-close { + font-size: 2rem; + background: transparent; + border-color: transparent; + color: var(--clr-grey-5); + position: absolute; + top: 0.5rem; + left: 1rem; + cursor: pointer; +} +.cart header { + text-align: center; +} +.cart header h3 { + font-weight: 500; +} +.cart-total { + text-align: center; + margin-bottom: 2rem; + font-weight: 500; +} +.cart-checkout { + display: block; + width: 75%; + margin: 0 auto; + margin-bottom: 3rem; +} +/* cart item */ +.cart-item { + margin: 1rem 0; + display: grid; + grid-template-columns: auto 1fr auto; + + column-gap: 1.5rem; + align-items: center; +} +.cart-item-img { + width: 75px; + height: 50px; + object-fit: cover; + border-radius: var(--radius); +} +.cart-item-name { + margin-bottom: 0.15rem; +} +.cart-item-price { + margin-bottom: 0; + font-size: 0.75rem; + color: var(--clr-grey-3); +} +.cart-item-remove-btn { + background: transparent; + border-color: transparent; + color: var(--clr-grey-5); + letter-spacing: var(--spacing); + cursor: pointer; +} +.cart-item-amount { + margin-bottom: 0; + text-align: center; + color: var(--clr-grey-3); + line-height: 1; +} +.cart-item-increase-btn, +.cart-item-decrease-btn { + background: transparent; + border-color: transparent; + color: var(--clr-primary-5); + cursor: pointer; + font-size: 0.85rem; + padding: 0.25rem; +} +/* +=============== +Title +=============== +*/ + +.title h2 { + display: flex; + justify-content: center; + align-items: center; + font-weight: 500; +} +.title span { + color: var(--clr-primary-5); + font-size: 0.85em; + margin-right: 1rem; +} +/* +=============== +product +=============== +*/ +.product-img { + height: 15rem; + object-fit: cover; + border-radius: var(--radius); +} +.product-container { + position: relative; +} +.product-icons { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + opacity: 0; + display: flex; + transition: var(--transition); +} +.product-icon { + width: 2.25rem; + height: 2.25rem; + background: var(--clr-primary-5); + color: var(--clr-white); + display: grid; + place-items: center; + border-radius: 50%; + transition: var(--transition); + cursor: pointer; + font-size: 1rem; + border-color: transparent; + margin: 0 0.5rem; +} +.product-icon:hover { + background: var(--clr-primary-7); +} +.product-container:hover .product-icons { + opacity: 1; +} +.product footer { + padding: 0.75rem 0; + text-align: center; +} +.product-name { + margin-bottom: 0.25rem; + text-transform: capitalize; + letter-spacing: var(--spacing); +} +.product-price { + margin-bottom: 0; + color: var(--clr-grey-3); + font-weight: 700; +} + +.featured-center { + margin: 3rem auto 2rem auto; + display: grid; + gap: 1rem; + min-height: 6rem; + position: relative; +} +.featured .btn { + display: block; + width: 11rem; + margin: 0 auto; + text-align: center; +} +@media screen and (min-width: 992px) { + .featured-center { + display: grid; + grid-template-columns: 1fr 1fr; + } +} +@media screen and (min-width: 1200px) { + .featured-center { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + } + .product .img { + height: 13rem; + } +} +/* +=============== +About Page +=============== +*/ +.about-text { + line-height: 2; + max-width: 45em; + margin: 0 auto; + margin-top: 2rem; +} + +/* +=============== +Products Page +=============== +*/ +.products { + width: 90vw; + display: grid; + grid-gap: 1rem; + margin: 4rem auto; + max-width: var(--max-width); + position: relative; +} +.filters-container { + position: sticky; + top: 1rem; +} +.filters h4 { + font-weight: 500; + margin: 1.5rem 0 0.5rem; +} + +.search-input { + padding: 0.5rem; + background: var(--clr-grey-10); + border-radius: var(--radius); + border-color: transparent; + letter-spacing: var(--spacing); +} +.search-input::placeholder { + text-transform: capitalize; +} +.company-btn { + display: block; + margin: 0.25em 0; + padding: 0.25rem; + text-transform: capitalize; + background: transparent; + border-color: transparent; + letter-spacing: var(--spacing); + color: var(--clr-grey-5); + cursor: pointer; + transition: var(--transition); +} +.company-btn:hover { + color: var(--clr-grey-3); +} +.price-filter { + background: var(--clr-grey-5) !important; + color: var(--clr-grey-5); +} +@media screen and (min-width: 768px) { + .products { + grid-template-columns: 200px 1fr; + } + .categories { + position: sticky; + top: 1rem; + } +} +@media screen and (min-width: 992px) { + .products-container { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + .products-container .product-img { + height: 10rem; + } + .products-container .product-name { + font-size: 0.85rem; + } + .products-container .product-price { + font-size: 0.85rem; + } +} +@media screen and (min-width: 1170px) { + .products-container { + grid-template-columns: repeat(3, 1fr); + } +} +.filter-error { + position: absolute; + top: 5rem; + left: 0; + width: 100%; + text-align: center; + margin-top: 4rem; +} +/* +=============== +Single Product Page +=============== +*/ +.page-hero { + min-height: 20vh; + display: grid; + place-items: center; + background: var(--clr-grey-10); + color: var(--clr-grey-5); +} +.page-hero-title { + font-weight: 500; +} +.single-product { + padding: 2rem 0; +} +.single-product-center { + margin: 2rem auto; + display: grid; + gap: 1rem 2rem; +} +.single-product-img { + height: 25rem; + border-radius: var(--radius); + object-fit: cover; +} +.single-product-company { + font-size: 1.2rem; + color: var(--clr-grey-8); + text-transform: uppercase; + letter-spacing: var(--spacing); + margin-bottom: 1.25rem; +} +.single-product-price { + color: var(--clr-grey-3); + font-size: 1.25rem; + font-weight: 500; +} + +.product-color { + display: inline-block; + width: 1rem; + height: 1rem; + border-radius: 50%; + background: #222; + margin: 0.5rem 0.5rem 1.5rem 0; +} + +.single-product-desc { + max-width: 25em; + line-height: 1.8; +} +@media screen and (min-width: 992px) { + .single-product-center { + grid-template-columns: 1fr 1fr; + } +} diff --git a/3-reviews/final/app.js b/3-reviews/final/app.js deleted file mode 100644 index f47c854b0..000000000 --- a/3-reviews/final/app.js +++ /dev/null @@ -1,92 +0,0 @@ -// local reviews data -const reviews = [ - { - id: 1, - name: "susan smith", - job: "web developer", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883334/person-1_rfzshl.jpg", - text: - "I'm baby meggings twee health goth +1. Bicycle rights tumeric chartreuse before they sold out chambray pop-up. Shaman humblebrag pickled coloring book salvia hoodie, cold-pressed four dollar toast everyday carry", - }, - { - id: 2, - name: "anna johnson", - job: "web designer", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883409/person-2_np9x5l.jpg", - text: - "Helvetica artisan kinfolk thundercats lumbersexual blue bottle. Disrupt glossier gastropub deep v vice franzen hell of brooklyn twee enamel pin fashion axe.photo booth jean shorts artisan narwhal.", - }, - { - id: 3, - name: "peter jones", - job: "intern", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883417/person-3_ipa0mj.jpg", - text: - "Sriracha literally flexitarian irony, vape marfa unicorn. Glossier tattooed 8-bit, fixie waistcoat offal activated charcoal slow-carb marfa hell of pabst raclette post-ironic jianbing swag.", - }, - { - id: 4, - name: "bill anderson", - job: "the boss", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883423/person-4_t9nxjt.jpg", - text: - "Edison bulb put a bird on it humblebrag, marfa pok pok heirloom fashion axe cray stumptown venmo actually seitan. VHS farm-to-table schlitz, edison bulb pop-up 3 wolf moon tote bag street art shabby chic. ", - }, -]; -// select items -const img = document.getElementById("person-img"); -const author = document.getElementById("author"); -const job = document.getElementById("job"); -const info = document.getElementById("info"); - -const prevBtn = document.querySelector(".prev-btn"); -const nextBtn = document.querySelector(".next-btn"); -const randomBtn = document.querySelector(".random-btn"); - -// set starting item -let currentItem = 0; - -// load initial item -window.addEventListener("DOMContentLoaded", function () { - const item = reviews[currentItem]; - img.src = item.img; - author.textContent = item.name; - job.textContent = item.job; - info.textContent = item.text; -}); - -// show person based on item -function showPerson(person) { - const item = reviews[person]; - img.src = item.img; - author.textContent = item.name; - job.textContent = item.job; - info.textContent = item.text; -} -// show next person -nextBtn.addEventListener("click", function () { - currentItem++; - if (currentItem > reviews.length - 1) { - currentItem = 0; - } - showPerson(currentItem); -}); -// show prev person -prevBtn.addEventListener("click", function () { - currentItem--; - if (currentItem < 0) { - currentItem = reviews.length - 1; - } - showPerson(currentItem); -}); -// show random person -randomBtn.addEventListener("click", function () { - console.log("hello"); - - currentItem = Math.floor(Math.random() * reviews.length); - showPerson(currentItem); -}); diff --git a/3-reviews/setup/app.js b/3-reviews/setup/app.js deleted file mode 100644 index 94d488f60..000000000 --- a/3-reviews/setup/app.js +++ /dev/null @@ -1,39 +0,0 @@ -// local reviews data -const reviews = [ - { - id: 1, - name: "susan smith", - job: "web developer", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883334/person-1_rfzshl.jpg", - text: - "I'm baby meggings twee health goth +1. Bicycle rights tumeric chartreuse before they sold out chambray pop-up. Shaman humblebrag pickled coloring book salvia hoodie, cold-pressed four dollar toast everyday carry", - }, - { - id: 2, - name: "anna johnson", - job: "web designer", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883409/person-2_np9x5l.jpg", - text: - "Helvetica artisan kinfolk thundercats lumbersexual blue bottle. Disrupt glossier gastropub deep v vice franzen hell of brooklyn twee enamel pin fashion axe.photo booth jean shorts artisan narwhal.", - }, - { - id: 3, - name: "peter jones", - job: "intern", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883417/person-3_ipa0mj.jpg", - text: - "Sriracha literally flexitarian irony, vape marfa unicorn. Glossier tattooed 8-bit, fixie waistcoat offal activated charcoal slow-carb marfa hell of pabst raclette post-ironic jianbing swag.", - }, - { - id: 4, - name: "bill anderson", - job: "the boss", - img: - "https://res.cloudinary.com/diqqf3eq2/image/upload/v1586883423/person-4_t9nxjt.jpg", - text: - "Edison bulb put a bird on it humblebrag, marfa pok pok heirloom fashion axe cray stumptown venmo actually seitan. VHS farm-to-table schlitz, edison bulb pop-up 3 wolf moon tote bag street art shabby chic. ", - }, -]; diff --git a/README.md b/README.md index 040d4ca81..61f6c7d29 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,46 @@ +# Vanilla JS Projects + +#### Enroll In The Course + +[My Javascript Course](https://www.udemy.com/course/javascript-tutorial-for-beginners-w/?referralCode=DD9FA6C0D976918D3E1C) + +#### Support + +Find the Content Useful? [You can always buy me a coffee](https://www.buymeacoffee.com/johnsmilga) + ## You can see all projects in action here [Projects](https://www.vanillajavascriptprojects.com/) + +1. Color Flipper +2. Counter +3. Reviews +4. Navbar +5. Sidebar +6. Modal +7. Questions +8. Menu +9. Video +10. Scroll +11. Tabs +12. Countdown Timer +13. Lorem Ipsum +14. Grocery Bud +15. Slider + +#### Course Exclusive + +16. Counters (OOP) +17. Gallery (OOP) +18. Numbers +19. Dark Mode +20. Filters +21. Dad Jokes +22. Products +23. Random User +24. Cocktails +25. Slider +26. Stripe Submenus +27. Pagination +28. Wikipedia +29. Comfy Sloth