diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9bea433 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ + +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..1b82aff --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# E-commerce Website in JavaScript +πŸ›’ - Exercise to learn how to make an e-commerce site in JavaScrip + +## Where are the most important files located? + +```bash +$ js/app.js +$ js/search.js +$ data/courses.js +$ index.html +``` + +## Explainations +This repository is the result of a school exercise and of a sprint of 1 week to learn JS and to apply some bases. + +## License +[MIT](https://choosealicense.com/licenses/mit/) + +## Quality certification +[![CodeFactor](https://www.codefactor.io/repository/github/CodingFactory-Repos/JavaScript-Shopping-Cart/badge)](https://www.codefactor.io/repository/github/CodingFactory-Repos/JavaScript-Shopping-Cart) diff --git a/css/skeleton.css b/css/skeleton.css new file mode 100644 index 0000000..f28bf6c --- /dev/null +++ b/css/skeleton.css @@ -0,0 +1,418 @@ +/* +* Skeleton V2.0.4 +* Copyright 2014, Dave Gamache +* www.getskeleton.com +* Free to use under the MIT license. +* http://www.opensource.org/licenses/mit-license.php +* 12/29/2014 +*/ + + +/* Table of contents +–––––––––––––––––––––––––––––––––––––––––––––––––– +- Grid +- Base Styles +- Typography +- Links +- Buttons +- Forms +- Lists +- Code +- Tables +- Spacing +- Utilities +- Clearing +- Media Queries +*/ + + +/* Grid +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.container { + position: relative; + width: 100%; + max-width: 960px; + margin: 0 auto; + padding: 0 20px; + box-sizing: border-box; } +.column, +.columns { + width: 100%; + float: left; + box-sizing: border-box; } + +/* For devices larger than 400px */ +@media (min-width: 400px) { + .container { + width: 85%; + padding: 0; } +} + +/* For devices larger than 550px */ +@media (min-width: 550px) { + .container { + width: 80%; } + .column, + .columns { + margin-left: 4%; } + .column:first-child, + .columns:first-child { + margin-left: 0; } + + .one.column, + .one.columns { width: 4.66666666667%; } + .two.columns { width: 13.3333333333%; } + .three.columns { width: 22%; } + .four.columns { width: 30.6666666667%; } + .five.columns { width: 39.3333333333%; } + .six.columns { width: 48%; } + .seven.columns { width: 56.6666666667%; } + .eight.columns { width: 65.3333333333%; } + .nine.columns { width: 74.0%; } + .ten.columns { width: 82.6666666667%; } + .eleven.columns { width: 91.3333333333%; } + .twelve.columns { width: 100%; margin-left: 0; } + + .one-third.column { width: 30.6666666667%; } + .two-thirds.column { width: 65.3333333333%; } + + .one-half.column { width: 48%; } + + /* Offsets */ + .offset-by-one.column, + .offset-by-one.columns { margin-left: 8.66666666667%; } + .offset-by-two.column, + .offset-by-two.columns { margin-left: 17.3333333333%; } + .offset-by-three.column, + .offset-by-three.columns { margin-left: 26%; } + .offset-by-four.column, + .offset-by-four.columns { margin-left: 34.6666666667%; } + .offset-by-five.column, + .offset-by-five.columns { margin-left: 43.3333333333%; } + .offset-by-six.column, + .offset-by-six.columns { margin-left: 52%; } + .offset-by-seven.column, + .offset-by-seven.columns { margin-left: 60.6666666667%; } + .offset-by-eight.column, + .offset-by-eight.columns { margin-left: 69.3333333333%; } + .offset-by-nine.column, + .offset-by-nine.columns { margin-left: 78.0%; } + .offset-by-ten.column, + .offset-by-ten.columns { margin-left: 86.6666666667%; } + .offset-by-eleven.column, + .offset-by-eleven.columns { margin-left: 95.3333333333%; } + + .offset-by-one-third.column, + .offset-by-one-third.columns { margin-left: 34.6666666667%; } + .offset-by-two-thirds.column, + .offset-by-two-thirds.columns { margin-left: 69.3333333333%; } + + .offset-by-one-half.column, + .offset-by-one-half.columns { margin-left: 52%; } + +} + + +/* Base Styles +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* NOTE +html is set to 62.5% so that all the REM measurements throughout Skeleton +are based on 10px sizing. So basically 1.5rem = 15px :) */ +html { + font-size: 62.5%; } +body { + font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */ + line-height: 1.6; + font-weight: 400; + font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #222; } + + +/* Typography +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 2rem; + font-weight: 300; } +h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;} +h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; } +h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; } +h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; } +h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; } +h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; } + +/* Larger than phablet */ +@media (min-width: 550px) { + h1 { font-size: 5.0rem; } + h2 { font-size: 4.2rem; } + h3 { font-size: 3.6rem; } + h4 { font-size: 3.0rem; } + h5 { font-size: 2.4rem; } + h6 { font-size: 1.5rem; } +} + +p { + margin-top: 0; } + + +/* Links +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +a { + color: #1EAEDB; } +a:hover { + color: #0FA0CE; } + + +/* Buttons +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.button, +button, +input[type="submit"], +input[type="reset"], +input[type="button"] { + display: inline-block; + height: 38px; + padding: 0 30px; + color: #555; + text-align: center; + font-size: 11px; + font-weight: 600; + line-height: 38px; + letter-spacing: .1rem; + text-transform: uppercase; + text-decoration: none; + white-space: nowrap; + background-color: transparent; + border-radius: 4px; + border: 1px solid #bbb; + cursor: pointer; + box-sizing: border-box; } +.button:hover, +button:hover, +input[type="submit"]:hover, +input[type="reset"]:hover, +input[type="button"]:hover, +.button:focus, +button:focus, +input[type="submit"]:focus, +input[type="reset"]:focus, +input[type="button"]:focus { + color: #333; + border-color: #888; + outline: 0; } +.button.button-primary, +button.button-primary, +input[type="submit"].button-primary, +input[type="reset"].button-primary, +input[type="button"].button-primary { + color: #FFF; + background-color: #33C3F0; + border-color: #33C3F0; } +.button.button-primary:hover, +button.button-primary:hover, +input[type="submit"].button-primary:hover, +input[type="reset"].button-primary:hover, +input[type="button"].button-primary:hover, +.button.button-primary:focus, +button.button-primary:focus, +input[type="submit"].button-primary:focus, +input[type="reset"].button-primary:focus, +input[type="button"].button-primary:focus { + color: #FFF; + background-color: #1EAEDB; + border-color: #1EAEDB; } + + +/* Forms +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea, +select { + height: 38px; + padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */ + background-color: #fff; + border: 1px solid #D1D1D1; + border-radius: 4px; + box-shadow: none; + box-sizing: border-box; } +/* Removes awkward default styles on some inputs for iOS */ +input[type="email"], +input[type="number"], +input[type="search"], +input[type="text"], +input[type="tel"], +input[type="url"], +input[type="password"], +textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; } +textarea { + min-height: 65px; + padding-top: 6px; + padding-bottom: 6px; } +input[type="email"]:focus, +input[type="number"]:focus, +input[type="search"]:focus, +input[type="text"]:focus, +input[type="tel"]:focus, +input[type="url"]:focus, +input[type="password"]:focus, +textarea:focus, +select:focus { + border: 1px solid #33C3F0; + outline: 0; } +label, +legend { + display: block; + margin-bottom: .5rem; + font-weight: 600; } +fieldset { + padding: 0; + border-width: 0; } +input[type="checkbox"], +input[type="radio"] { + display: inline; } +label > .label-body { + display: inline-block; + margin-left: .5rem; + font-weight: normal; } + + +/* Lists +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +ul { + list-style: circle inside; } +ol { + list-style: decimal inside; } +ol, ul { + padding-left: 0; + margin-top: 0; } +ul ul, +ul ol, +ol ol, +ol ul { + margin: 1.5rem 0 1.5rem 3rem; + font-size: 90%; } +li { + margin-bottom: 1rem; } + + +/* Code +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +code { + padding: .2rem .5rem; + margin: 0 .2rem; + font-size: 90%; + white-space: nowrap; + background: #F1F1F1; + border: 1px solid #E1E1E1; + border-radius: 4px; } +pre > code { + display: block; + padding: 1rem 1.5rem; + white-space: pre; } + + +/* Tables +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +th, +td { + padding: 12px 15px; + text-align: left; + border-bottom: 1px solid #E1E1E1; } +th:first-child, +td:first-child { + padding-left: 0; } +th:last-child, +td:last-child { + padding-right: 0; } + + +/* Spacing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +button, +.button { + margin-bottom: 1rem; } +input, +textarea, +select, +fieldset { + margin-bottom: 1.5rem; } +pre, +blockquote, +dl, +figure, +table, +p, +ul, +ol, +form { + margin-bottom: 2.5rem; } + + +/* Utilities +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +.u-full-width { + width: 100%; + box-sizing: border-box; } +.u-max-full-width { + max-width: 100%; + box-sizing: border-box; } +.u-pull-right { + float: right; } +.u-pull-left { + float: left; } + + +/* Misc +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +hr { + margin-top: 3rem; + margin-bottom: 3.5rem; + border-width: 0; + border-top: 1px solid #E1E1E1; } + + +/* Clearing +–––––––––––––––––––––––––––––––––––––––––––––––––– */ + +/* Self Clearing Goodness */ +.container:after, +.row:after, +.u-cf { + content: ""; + display: table; + clear: both; } + + +/* Media Queries +–––––––––––––––––––––––––––––––––––––––––––––––––– */ +/* +Note: The best way to structure the use of media queries is to create the queries +near the relevant code. For example, if you wanted to change the styles for buttons +on small devices, paste the mobile query code up in the buttons section and style it +there. +*/ + + +/* Larger than mobile */ +@media (min-width: 400px) {} + +/* Larger than phablet (also point when grid becomes active) */ +@media (min-width: 550px) {} + +/* Larger than tablet */ +@media (min-width: 750px) {} + +/* Larger than desktop */ +@media (min-width: 1000px) {} + +/* Larger than Desktop HD */ +@media (min-width: 1200px) {} diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..1298d39 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,431 @@ +body { + overflow-x: hidden; + background: #fff; + font-family: 'IBM Plex Sans', sans-serif; +} + +* { + margin: 0; + padding: 0; +} + +h1 { + text-align: center; + pointer-events: none; +} + +.hidden { + display: none !important; +} + + +/* +* Header +*/ + +header { + padding: 20px 0 0; + background: white; + text-align: center; + display: flex; + justify-content: space-between; +} + +header .logo img { + width: 100%; +} + +header .submenu { + position: relative; + list-style-type: none; + width: 50%; +} + +header .submenu #img-cart { + width: 25px; + margin-top: 15px; + cursor: pointer; +} + + +/** cart **/ + +#cart { + box-shadow: 0 1px 5px 0 #adadad; +} + +#cart table { + border-collapse: collapse; +} + +#cart table thead tr { + background: #f4f4f4; +} + +#cart table thead th { + font-size: 11px; + font-weight: 600; + border: none; +} + +#cart table tbody td img { + width: auto; + height: 40px; +} + +#cart table tbody .supprimer-item { + display: block; + background-color: #ff5454; + border-radius: 50%; + padding: 8px; + height: 10px; + line-height: 13px; + text-decoration: none; + color: white; + font-size: 11px; + font-weight: bold; + width: 10px; + text-align: center; +} + +header .submenu #cart { + display: none; +} + +header .submenu:hover #cart { + display: block; + position: absolute; + right: 0; + top: 100%; + z-index: 1; + background-color: white; + padding: 8px; + max-height: 400px; + min-width: 400px; + overflow-y: scroll; +} + +header .submenu:hover #cart::-webkit-scrollbar { + width: 4px; +} + +header .submenu:hover #cart::-webkit-scrollbar-track { + background: #f1f1f1; +} + +header .submenu:hover #cart::-webkit-scrollbar-thumb { + background: #888; +} + +header .submenu:hover #cart::-webkit-scrollbar-thumb:hover { + background: #555; +} + + +/* +* Search form +*/ + +.search-form { + display: flex; + max-width: 700px; + width: 70%; + min-width: 450px; + margin: 30px auto; + position: relative; + display: flex; +} + +.search-form input { + width: 100%; + padding: 15px; + border: none; + outline: none; + border-radius: 3px; + font-size: 14px; +} + +#no_course { + text-align: center; + font-size: 30px; + color: #979797; + padding: 25px; +} + + +/* +* Courses list +*/ + +#courses-list h1 { + text-align: left; + width: fit-content; + margin: 0 auto 25px; + font-size: 30px; + font-weight: 100; + padding: 8px 15px; + position: relative; + color: #383838; +} + +#courses-list h1:after { + content: ""; + display: block; + height: 15px; + width: 100%; + background: #00b4bdbf; + position: absolute; + bottom: 6px; + left: 10px; + z-index: -1; +} + +.entete__courses { + margin-bottom: 30px; +} + +.courses__container { + margin-top: 30px; + display: grid; + grid-gap: 25px; + max-width: 1080px; + margin: 0 auto; + padding: 0 10px; +} + +.course__item { + border: 1px solid rgba(0, 0, 0, 0.25); + box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22); + display: flex; + flex-direction: column; + padding: 0 0 10px; +} + +.course__item .course_img { + height: 120px; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; +} + +.course__item .course_img img { + width: 100%; +} + +.course__item .mark { + width: 70px; + height: 15px; + overflow: hidden; +} + +.course__item .mark img { + width: 100%; +} + +.course__item .mark.m_5 img { + margin-top: 0; +} + +.course__item .mark.m_4 img { + margin-top: -15px; +} + +.course__item .mark.m_3 img { + margin-top: -30px; +} + +.course__item .mark.m_2 img { + margin-top: -45px; +} + +.course__item .mark.m_1 img { + margin-top: -60px; +} + +.course__item .info__card { + padding: 10px; + position: relative; +} + +.course__item .info__card h4 { + font-size: 16px; + font-weight: 700; +} + +.course__item .price { + text-decoration: line-through; + color: red; +} + +.course__item .discount { + color: black; + font-weight: bold; + float: right; + font-size: 1.25em; +} + +.course__item .add-to-cart { + background: #00B2BD; + padding: 5px 10px; + border-radius: 6px; + color: white; + text-decoration: none; + font-weight: bold; + font-size: 0.8em; + position: absolute; + bottom: 0; + transition: 0.4s; +} + +.course__item .add-to-cart:hover { + background: #0098a0; + transform: scale(1.05); + box-shadow: 8px 5px 8px rgba(82, 82, 82, 0.399); + transition: 0.4s; + color: white; +} + +.fa { + margin-bottom: 0; + margin-right: 8px; + transition: 1.3s; +} + +.fa-trash:hover { + font-size: 1.2em; + color: red; + transition: 1.3s; +} + +@media (min-width: 750px) { + header { + text-align: left; + } +} + +@media (min-width: 472px) and (max-width: 767px) { + .courses__container { + grid-template-columns: 1fr 1fr; + } +} + +@media all and (min-width: 768px) { + .courses__container { + grid-template-columns: 1fr 1fr 1fr; + } +} + +@media all and (min-width: 949px) { + .courses__container { + grid-template-columns: 1fr 1fr 1fr 1fr; + } +} + +/* +* Notification +*/ +#notification_container { + position: fixed; + top: 40px; + right: 25px; + + width: 200px; + height: auto; +} + +#notification_container .content { + box-shadow: 0 1px 5px 0 #adadad; + padding: 8px; + border-radius: 4px; + overflow: hidden; + + display: flex; + align-items: center; + + margin: 0 0 15px; +} + +#notification_container .content.success { + background: #b2dbff; + color: #000; +} +#notification_container .content.danger { + background: #ff7979; + color: #fff; +} + +#notification_container .content img { + width: 25px; + height: 25px; + padding: 0 10px; +} + +#notification_container .content p { + margin: auto; + font-weight: 600; + font-size: 13px; +} + +/*drop*/ + + +/* Style The Dropdown Button */ + +.dropbtn { + /* padding: 16px; */ + font-size: 16px; +} + + +/* The container
- needed to position the dropdown content */ + +.dropdown { + position: relative; + display: inline-block; +} + + +/* Dropdown Content (Hidden by Default) */ + +.dropdown-content { + display: none; + position: absolute; + background-color: #f9f9f9; + min-width: 160px; + box-shadow: 0px 8px 16px 0px #555; + z-index: 1; +} + + +/* Links inside the dropdown */ + +.dropdown-content a { + color: #555; + padding: 12px 16px; + text-decoration: none; + display: block; +} + + +/* Change color of dropdown links on hover */ + +.dropdown-content a:hover { + background-color: #f1f1f1 +} + + +/* Show the dropdown menu on hover */ + +.dropdown:hover .dropdown-content { + display: block; +} + +/* +* Footer +*/ + +footer { + display: block; + margin-top: 50px; +} \ No newline at end of file diff --git a/data/courses.js b/data/courses.js new file mode 100644 index 0000000..dadc81b --- /dev/null +++ b/data/courses.js @@ -0,0 +1,7 @@ +const COURSES = [ + { id: 1, img: 'ux_ui.jpg', title: 'UX/UI', slug: 'ux_ui', initial_price: 200, price: 12.99, mark: 4, stock: 10 }, + { id: 2, img: 'php_8.png', title: 'PHP 8', slug: 'php_8', initial_price: 200, price: 10.99, mark: 5, stock: 10 }, + { id: 3, img: 'react_js.png', title: 'React JS', slug: 'react_js', initial_price: 200, price: 14.99, mark: 2, stock: 5 }, + { id: 4, img: 'node_js.jpg', title: 'Node JS', slug: 'node_js', initial_price: 200, price: 17.99, mark: 1, stock: 3 }, + { id: 5, img: 'my_sql.png', title: 'MySQL', slug: 'mysql', initial_price: 200, price: 20.99, mark: 3, stock: 2 } +] \ No newline at end of file diff --git a/img/5etoiles.jpeg b/img/5etoiles.jpeg new file mode 100644 index 0000000..23531c6 Binary files /dev/null and b/img/5etoiles.jpeg differ diff --git a/img/5etoiles.png b/img/5etoiles.png new file mode 100644 index 0000000..6de489d Binary files /dev/null and b/img/5etoiles.png differ diff --git a/img/cart.png b/img/cart.png new file mode 100644 index 0000000..51fe00b Binary files /dev/null and b/img/cart.png differ diff --git a/img/coding_factory.jpg b/img/coding_factory.jpg new file mode 100644 index 0000000..9cf54ba Binary files /dev/null and b/img/coding_factory.jpg differ diff --git a/img/courses/my_sql.png b/img/courses/my_sql.png new file mode 100644 index 0000000..47c1bf2 Binary files /dev/null and b/img/courses/my_sql.png differ diff --git a/img/courses/node_js.jpg b/img/courses/node_js.jpg new file mode 100644 index 0000000..a9c63f4 Binary files /dev/null and b/img/courses/node_js.jpg differ diff --git a/img/courses/php_8.png b/img/courses/php_8.png new file mode 100644 index 0000000..eefd73e Binary files /dev/null and b/img/courses/php_8.png differ diff --git a/img/courses/react_js.png b/img/courses/react_js.png new file mode 100644 index 0000000..7c5f989 Binary files /dev/null and b/img/courses/react_js.png differ diff --git a/img/courses/ux_ui.jpg b/img/courses/ux_ui.jpg new file mode 100644 index 0000000..dbb825a Binary files /dev/null and b/img/courses/ux_ui.jpg differ diff --git a/img/hero.jpg b/img/hero.jpg new file mode 100644 index 0000000..570d176 Binary files /dev/null and b/img/hero.jpg differ diff --git a/img/icono1.png b/img/icono1.png new file mode 100644 index 0000000..b562ba1 Binary files /dev/null and b/img/icono1.png differ diff --git a/img/icono2.png b/img/icono2.png new file mode 100644 index 0000000..f30b4de Binary files /dev/null and b/img/icono2.png differ diff --git a/img/icono3.png b/img/icono3.png new file mode 100644 index 0000000..8247522 Binary files /dev/null and b/img/icono3.png differ diff --git a/img/info.png b/img/info.png new file mode 100644 index 0000000..9a208bd Binary files /dev/null and b/img/info.png differ diff --git a/img/interro.jpg b/img/interro.jpg new file mode 100644 index 0000000..1486e6d Binary files /dev/null and b/img/interro.jpg differ diff --git a/img/logo.jpg b/img/logo.jpg new file mode 100644 index 0000000..fdbbe6a Binary files /dev/null and b/img/logo.jpg differ diff --git a/img/lupa.png b/img/lupa.png new file mode 100644 index 0000000..7bf3506 Binary files /dev/null and b/img/lupa.png differ diff --git a/img/rates.png b/img/rates.png new file mode 100644 index 0000000..92397ba Binary files /dev/null and b/img/rates.png differ diff --git a/img/stars.png b/img/stars.png new file mode 100644 index 0000000..16b3989 Binary files /dev/null and b/img/stars.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..5e96581 --- /dev/null +++ b/index.html @@ -0,0 +1,86 @@ + + + + + + + Cours en ligne + + + + + + + +
+ + +
+ + +
+ +
+ +

Cours en ligne

+
+ +
+ +
+ +
+ + + + + + + + + \ No newline at end of file diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..4305749 --- /dev/null +++ b/js/app.js @@ -0,0 +1,182 @@ +// On document load, execute the following code +document.addEventListener('DOMContentLoaded', function () { // On document load, execute the following code + console.image('https://avatars.githubusercontent.com/u/91029631') // Console log the image + + for (var i = 0; i < COURSES.length; i++) { // Loop through all courses + if (localStorage.getItem(`inCart-${COURSES[i].id}`)) { // Check if product is already in cart + COURSES[i].stock = COURSES[i].stock - JSON.parse(localStorage.getItem(`inCart-${COURSES[i].id}`)).productsInCart; // Update the stock quantity + productItemsInCart(COURSES[i], JSON.parse(localStorage.getItem(`inCart-${COURSES[i].id}`))); // Set the product in cart + } + } + + showAllProducts('.courses__container', COURSES); // Show all products +}); + +function addToCart(id) { // Add product to cart function + let product = getProductDetails(Number(id)); // Get the product details + + if (product.stock <= 0) { // If stock is 0 or less + notification(`Il n'y a plus de stock dispo`, `danger`); // Alert the user with notification + return; // Return + } else { // Otherwise + product.stock--; // Decrease 1 to the product in cart + document.querySelector(`.stock-${product.id}`).innerHTML = product.stock; // Display the new stock + } + // Check if product is already in cart + const productCartName = `inCart-${product.id}`; // Set the product cart name + let cart = localStorage.getItem(productCartName); // Get the product cart + if (cart) { // If the product cart exists + + cart = JSON.parse(cart); // Parse the product cart + cart.productsInCart++; // Add 1 to the product in cart + localStorage.setItem(productCartName, JSON.stringify(cart)); // Set the product cart + + // Update the cart + document.querySelector(`.${product.slug}-inCart`).innerHTML = cart.productsInCart; // Update the product in cart + + } else { // If the product cart doesn't exist + // Add product to cart + cart = { "productsInCart": 1 }; // Create the product cart + localStorage.setItem(productCartName, JSON.stringify(cart)); // Set the product cart + + productItemsInCart(product, cart); // Add the product in cart + } + // Show notification + notification(`Vous avez ajoutΓ© ${product.title} au panier`); // Run notification function +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// All Functions UwU +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +function notification(message, type='success') { // Function to show notification + // Show notification + document.querySelector('#notification_container').innerHTML += ` +
+ +

${message}

+
+ `; + + setTimeout(function () { // Hide notification after 3 seconds + document.querySelector('#notification_container .content').remove(); // Remove notification + }, 3000); +} + +function productItems(querySelector, product) { // Function allowing to display in HTML the products in home page + document.querySelector(querySelector).innerHTML += ` +
+
+ +
+
+

${product.title}

+
+ +
+

+ ${product.initial_price} € + ${product.price} € +

+

+ Disponible: ${product.stock} +

+ Ajouter au panier +
+
+ `; +} + +function showAllProducts(querySelector, products) { // Function allowing get All Products and Show them + for (var i = 0; i < products.length; i++) { // Loop through all courses + productItems(querySelector, products[i]); // Show all products + } +} + +function productItemsInCart(product, cart) { // Function allowing to display in HTML the products in the cart + document.querySelector('#cart-table tbody').innerHTML += ` + + ${product.title} image + ${product.title} + ${product.price}€ + ${cart.productsInCart} + + + `; +} + +function getProductDetails(id) { // Function allowing to have the information of a product + for (var i = 0; i < COURSES.length; i++) { // Loop through all courses + if (COURSES[i].id === id) { // Check if the product correspond to the id + return COURSES[i]; // Return the product + } + } + + return null; // Or return null +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// All Buttons +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +document.addEventListener('click', function (e) { // On click, execute the following code + if (e.target.classList.contains('add-to-cart')) { // If the user clicks on the add-to-cart button, execute the following code + //----------------------------------------------------// + // This button allows you to add an item to the cart // + //--------------------------------------------------// + + addToCart(e.target.dataset.id); // Add to cart + + } else if (e.target.classList.contains('empty-cart')) { // If the user clicks on the empty-cart button, execute the following code + //----------------------------------------------------// + // This button allows you to delete all the items in // + // the cart. // + //-------------------------------------------------// + + for (var i = 0; i < COURSES.length; i++) { // Loop through all courses + const getItem = JSON.parse(localStorage.getItem(`inCart-${COURSES[i].id}`)); // Get the product in cart + + if (getItem !== null) { // Check if the product is already in the cart + COURSES[i].stock += getItem.productsInCart; // Increment the quantity of the product in stock + + document.querySelector(`.stock-${COURSES[i].id}`).innerHTML = COURSES[i].stock; // Display the new stock + } + } + + localStorage.clear(); // Clear the localStorage + document.querySelector('#cart-table tbody').innerHTML = ""; // Clear cart + notification(`Le panier Γ  Γ©tΓ© totalement vidΓ©`, `danger`); // Alert the user with notification + + } else if (e.target.classList.contains('fa-trash')) { // If the user clicks on the fr-trash button, execute the following code + //----------------------------------------------------// + // This button allows you to remove an item from // + // your cart // + //-------------------------------------------------// + + let product = getProductDetails(Number(e.target.parentNode.parentNode.dataset.id)); // Get the product details + + product.stock++; // Add 1 to the product stock + document.querySelector(`.stock-${product.id}`).innerHTML = product.stock; // Display the new stock + + let getItem = JSON.parse(localStorage.getItem(`inCart-${product.id}`)); // See how many times the product is in the cart + + if (getItem.productsInCart <= 1) { // If only 1 product is in the cart + localStorage.removeItem(`inCart-${product.id}`); // Remove the product from the localStorage + document.querySelector(`.${e.target.parentNode.parentNode.classList[0]}`).remove(); // Remove the product from the cart + notification(`${product.title} Γ  totalement Γ©tΓ© supprimΓ© du panier`, `danger`); // Alert the user with notification + } else { // Otherwise + getItem.productsInCart--; // Decrease 1 to the product in cart + localStorage.setItem(`inCart-${product.id}`, JSON.stringify(getItem)); // Remove the product from the localStorage + document.querySelector(`.${product.slug}-inCart`).innerHTML = getItem.productsInCart; // Remove the product from the cart + notification(`1 cours "${product.title}" Γ  Γ©tΓ© supprimΓ© du panier`, `danger`); // Alert the user with notification + } + } else if (e.target.classList.contains('noteOrdre')) { // If the user clicks on the noteOrdre button, execuse the following code + filtre("noteCroissant"); // Sort the products by note + } else if (e.target.classList.contains('noteDesordre')) { // If the user clicks on the noteDesordre button, execuse the following code + filtre("noteDecroissant"); // Sort the products by note + } else if (e.target.classList.contains('prixOrdre')) { // If the user clicks on the prixOrdre button, execuse the following code + filtre("prixCroissant"); // Sort the products by price + } else if (e.target.classList.contains('prixDesordre')) { // If the user clicks on the prixDesordre button, execuse the following code + filtre("prixDecroissant"); // Sort the products by price + } +}); \ No newline at end of file diff --git a/js/search.js b/js/search.js new file mode 100644 index 0000000..e673b8c --- /dev/null +++ b/js/search.js @@ -0,0 +1,44 @@ +// search bar + +document.querySelector('form.search-form input').addEventListener('input', function(e) { // If a change in the search bar is detected, run the function + search(e.target.value); +}); + +function search(e) { + var filter = e.toUpperCase(); // Convert the value to uppercase + + document.querySelector("#courses-list .courses__container").innerHTML = ""; // Clear results + + if (e) { // If the input is not empty + for (let i = 0; i < COURSES.length; i++) { // Loop through all courses + if (COURSES[i].title.toUpperCase().includes(filter)) { // If the course title includes the value of the search bar + productItems('#courses-list .courses__container', COURSES[i]); // Show the product + + document.querySelector('#no_course').classList.add('hidden'); // Hide the no results message + } else if (!document.querySelector("#courses-list .courses__container").innerHTML) { // Otherwise, if there are no results + document.querySelector('#no_course').classList.remove('hidden'); // Show the no results message + } + } + } else { // Otherwise, if the input is empty + showAllProducts('.courses__container', COURSES); // Show all products + } +} + +function filtre(type) { // Search filter function + if (type === "noteCroissant") { // If the filter is note croissant + COURSES.sort((a, b) => a.mark - b.mark) // Sort the courses by note + } else if (type === "noteDecroissant") { // If the filter is note decroissant + COURSES.sort((a, b) => b.mark - a.mark) // Sort the courses by note + } else if (type === "prixCroissant") { // If the filter is prix croissant + COURSES.sort((a, b) => a.price - b.price) // Sort the courses by price + } else if (type === "prixDecroissant") { // If the filter is prix decroissant + COURSES.sort((a, b) => b.price - a.price) // Sort the courses by price + } + + if (document.querySelector('form.search-form input').value) { + search(document.querySelector('form.search-form input').value); + } else { + document.querySelector('.courses__container').innerHTML = ""; // Clear products + showAllProducts('.courses__container', COURSES); // Show all products + } +} \ No newline at end of file