├── .gitignore ├── jsconfig.json ├── src ├── public │ ├── favicon.ico │ ├── icons │ │ ├── 72x72.png │ │ ├── 96x96.png │ │ ├── 128x128.png │ │ ├── 144x144.png │ │ ├── 152x152.png │ │ ├── 192x192.png │ │ ├── 384x384.png │ │ └── 512x512.png │ ├── images │ │ ├── hero.jpg │ │ └── loading.jpg │ └── manifest.json ├── scripts │ ├── views │ │ ├── templates │ │ │ ├── spinner.js │ │ │ ├── like-button.js │ │ │ ├── resto-card.js │ │ │ └── resto-detail.js │ │ ├── App.js │ │ └── pages │ │ │ ├── favorite.js │ │ │ ├── home.js │ │ │ └── detail.js │ ├── global │ │ ├── api-endpoint.js │ │ └── config.js │ ├── routes │ │ ├── routes.js │ │ └── url-parser.js │ ├── components │ │ ├── custom-footer.js │ │ ├── hero.js │ │ └── navbar.js │ ├── utils │ │ ├── drawer-initiator.js │ │ ├── swal-initiator.js │ │ ├── websocket-initiator.js │ │ ├── sw-register.js │ │ ├── post-review.js │ │ ├── websocket-notif.js │ │ ├── like-button-presenter.js │ │ └── sw.js │ ├── data │ │ ├── resto-source.js │ │ └── resto-idb.js │ └── index.js ├── styles │ ├── resto-fav.css │ ├── footer.css │ ├── header.css │ ├── spinner.css │ ├── nav.css │ ├── root.css │ ├── main.css │ ├── responsive.css │ ├── resto-detail.css │ └── normalize.css └── templates │ └── index.html ├── steps_file.js ├── webpack.dev.js ├── .eslintrc.json ├── specs ├── favRestaurantIdbSpec.js ├── helpers │ └── testFactories.js ├── favRestaurantArraySpec.js ├── contract │ └── favRestoContract.js ├── unlikeRestaurant.spec.js └── likeRestaurant.spec.js ├── codecept.conf.js ├── e2e ├── Review_Resto.spec.js └── Favorite_Resto.spec.js ├── webpack.prod.js ├── README.md ├── webpack.common.js ├── sharp.js ├── karma.conf.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true 4 | } 5 | } -------------------------------------------------------------------------------- /src/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/favicon.ico -------------------------------------------------------------------------------- /src/public/icons/72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/72x72.png -------------------------------------------------------------------------------- /src/public/icons/96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/96x96.png -------------------------------------------------------------------------------- /src/public/images/hero.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/images/hero.jpg -------------------------------------------------------------------------------- /src/public/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/128x128.png -------------------------------------------------------------------------------- /src/public/icons/144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/144x144.png -------------------------------------------------------------------------------- /src/public/icons/152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/152x152.png -------------------------------------------------------------------------------- /src/public/icons/192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/192x192.png -------------------------------------------------------------------------------- /src/public/icons/384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/384x384.png -------------------------------------------------------------------------------- /src/public/icons/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/icons/512x512.png -------------------------------------------------------------------------------- /src/public/images/loading.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rifandani/menjadi-web-developer-expert/HEAD/src/public/images/loading.jpg -------------------------------------------------------------------------------- /src/scripts/views/templates/spinner.js: -------------------------------------------------------------------------------- 1 | const Spinner = () => ` 2 |
3 | `; 4 | 5 | export default Spinner; 6 | -------------------------------------------------------------------------------- /src/styles/resto-fav.css: -------------------------------------------------------------------------------- 1 | /* FAVORITE RESTO */ 2 | 3 | #fav-resto { 4 | display: grid; 5 | grid-row-gap: 1.5em; 6 | padding-top: 1.5em; 7 | } 8 | -------------------------------------------------------------------------------- /src/scripts/global/api-endpoint.js: -------------------------------------------------------------------------------- 1 | import CONFIG from './config'; 2 | 3 | const API_ENDPOINT = { 4 | LIST: `${CONFIG.BASE_URL}list`, 5 | DETAIL: (id) => `${CONFIG.BASE_URL}detail/${id}`, 6 | POST_REVIEW: `${CONFIG.BASE_URL}review`, 7 | }; 8 | 9 | export default API_ENDPOINT; 10 | -------------------------------------------------------------------------------- /src/scripts/routes/routes.js: -------------------------------------------------------------------------------- 1 | import Home from '../views/pages/home'; 2 | import Favorite from '../views/pages/favorite'; 3 | import Detail from '../views/pages/detail'; 4 | 5 | const routes = { 6 | '/': Home, 7 | '/favorite': Favorite, 8 | '/resto/:id': Detail, 9 | }; 10 | 11 | export default routes; 12 | -------------------------------------------------------------------------------- /steps_file.js: -------------------------------------------------------------------------------- 1 | // in this file you can append custom step methods to 'I' object 2 | 3 | module.exports = function() { 4 | return actor({ 5 | 6 | // Define custom steps here, use 'this' to access default methods of I. 7 | // It is recommended to place a general 'login' function here. 8 | 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/no-extraneous-dependencies 2 | const { merge } = require('webpack-merge'); 3 | const path = require('path'); 4 | const common = require('./webpack.common'); 5 | 6 | module.exports = merge(common, { 7 | mode: 'development', 8 | devServer: { 9 | contentBase: path.resolve(__dirname, 'dist'), 10 | compress: true, 11 | port: 9000, 12 | }, 13 | }); 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "commonjs": true, 4 | "es2021": true, 5 | "browser": true, 6 | "jasmine": true 7 | }, 8 | "extends": ["airbnb-base", "plugin:codeceptjs/recommended"], 9 | "parserOptions": { 10 | "ecmaVersion": 12 11 | }, 12 | "rules": { 13 | "no-console": "off", 14 | "linebreak-style": "off", 15 | "no-underscore-dangle": "off", 16 | "operator-linebreak": "off" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/styles/footer.css: -------------------------------------------------------------------------------- 1 | /* 2 | * footer 3 | */ 4 | 5 | footer { 6 | padding: 2em; 7 | width: 100%; 8 | height: 100%; 9 | text-align: center; 10 | border-top: 3px groove var(--font-color); 11 | background-color: var(--secondary-color); 12 | } 13 | 14 | footer ul { 15 | margin: 0 auto; 16 | display: flex; 17 | flex-direction: column; 18 | list-style: none; 19 | } 20 | 21 | footer li { 22 | margin: 0.3em 0; 23 | font-size: 14px; 24 | } 25 | -------------------------------------------------------------------------------- /src/scripts/components/custom-footer.js: -------------------------------------------------------------------------------- 1 | class CustomFooter extends HTMLElement { 2 | connectedCallback() { 3 | this.render(); 4 | } 5 | 6 | render() { 7 | this.innerHTML = ` 8 | 14 | `; 15 | } 16 | } 17 | 18 | customElements.define('custom-footer', CustomFooter); 19 | -------------------------------------------------------------------------------- /specs/favRestaurantIdbSpec.js: -------------------------------------------------------------------------------- 1 | import { itActsAsFavoriteRestoModel } from './contract/favRestoContract'; 2 | import FavRestoIdb from '../src/scripts/data/resto-idb'; 3 | 4 | describe('Favorite Movie Idb Contract Test Implementation', () => { 5 | afterEach(async () => { 6 | (await FavRestoIdb.getAllResto()).forEach(async (resto) => { 7 | await FavRestoIdb.deleteResto(resto.id); 8 | }); 9 | }); 10 | 11 | itActsAsFavoriteRestoModel(FavRestoIdb); 12 | }); 13 | -------------------------------------------------------------------------------- /src/scripts/views/templates/like-button.js: -------------------------------------------------------------------------------- 1 | const createLikeButtonTemplate = () => ` 2 | 5 | `; 6 | 7 | const createLikedButtonTemplate = () => ` 8 | 11 | `; 12 | 13 | export { createLikeButtonTemplate, createLikedButtonTemplate }; 14 | -------------------------------------------------------------------------------- /src/scripts/components/hero.js: -------------------------------------------------------------------------------- 1 | class HeroContent extends HTMLElement { 2 | connectedCallback() { 3 | this.render(); 4 | } 5 | 6 | render() { 7 | this.innerHTML = ` 8 |12 | Our restaurants offer more than just great food 13 |
14 | 15 | Read More 16 |
11 |
15 | ${resto.description}
20 |${name}
21 | 22 |${date}
23 |
3 |
4 |
${resto.description}
${review.name}
81 | 82 |${review.date}
83 |