├── .gitignore ├── dist ├── b3909570c94cc41b9906.png ├── index.html ├── runtime.js └── main.js ├── src ├── images │ └── VegetarianRestauratLogo.png ├── Modules │ ├── commentsCounter.js │ ├── errorHandler.js │ ├── getItemsDetails.js │ ├── itemCounter.js │ ├── newApp.js │ ├── getComments.js │ ├── sendComment.js │ ├── likes.js │ ├── getItems.js │ └── commentsPopup.js ├── index.js ├── index.html └── styles.css ├── .babelrc ├── .hintrc ├── .eslintrc.json ├── .stylelintrc.json ├── tests ├── itemCounter.test.js └── commentsCounter.test.js ├── webpack.config.js ├── LICENSE ├── package.json ├── .github └── workflows │ └── linters.yml └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | .DS_Store -------------------------------------------------------------------------------- /dist/b3909570c94cc41b9906.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ClaudiaRojasSoto/Api_dishes/HEAD/dist/b3909570c94cc41b9906.png -------------------------------------------------------------------------------- /src/images/VegetarianRestauratLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ClaudiaRojasSoto/Api_dishes/HEAD/src/images/VegetarianRestauratLogo.png -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "plugins": ["@babel/plugin-transform-modules-commonjs"] 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /src/Modules/commentsCounter.js: -------------------------------------------------------------------------------- 1 | const countComments = () => { 2 | const comments = document.querySelectorAll('.comment-text'); 3 | return comments.length; 4 | }; 5 | 6 | export default countComments; 7 | -------------------------------------------------------------------------------- /src/Modules/errorHandler.js: -------------------------------------------------------------------------------- 1 | const handleFetchError = (error) => { 2 | const errorMessage = document.getElementById('error-message'); 3 | if (errorMessage) { 4 | errorMessage.innerHTML = `${error.message}`; 5 | } 6 | }; 7 | 8 | export default handleFetchError; -------------------------------------------------------------------------------- /src/Modules/getItemsDetails.js: -------------------------------------------------------------------------------- 1 | const getItemDetails = async (id) => { 2 | const request = await fetch(`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${id}`); 3 | const data = await request.json(); 4 | return data.meals[0]; 5 | }; 6 | 7 | export default getItemDetails; -------------------------------------------------------------------------------- /src/Modules/itemCounter.js: -------------------------------------------------------------------------------- 1 | const homeItemCounter = (containerItems) => { 2 | const hometitle = document.querySelector('#mainTitle'); 3 | hometitle.textContent = `${containerItems} Vegetarian Recipes`; 4 | return hometitle.textContent; 5 | }; 6 | 7 | export default homeItemCounter; -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './styles.css'; 2 | import mylogo from './images/VegetarianRestauratLogo.png'; 3 | import getItems from './Modules/getItems.js'; 4 | 5 | document.querySelector('#logo').src = mylogo; 6 | 7 | window.addEventListener('load', () => { 8 | getItems(); 9 | }); 10 | -------------------------------------------------------------------------------- /src/Modules/newApp.js: -------------------------------------------------------------------------------- 1 | // Request for the ID in the Involvement API 2 | 3 | const getID = async () => { 4 | const request = await fetch('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/', { 5 | method: 'POST', 6 | }); 7 | const data = await request.text(); 8 | return data; 9 | }; 10 | 11 | export default getID; 12 | -------------------------------------------------------------------------------- /src/Modules/getComments.js: -------------------------------------------------------------------------------- 1 | const getComments = async (appId, id) => { 2 | try { 3 | const response = await fetch(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/${appId}/comments?item_id=${id}`); 4 | const data = await response.json(); 5 | return data; 6 | } catch (error) { 7 | return error; 8 | } 9 | }; 10 | 11 | export default getComments; -------------------------------------------------------------------------------- /.hintrc: -------------------------------------------------------------------------------- 1 | { 2 | "connector": { 3 | "name": "local", 4 | "options": { 5 | "pattern": ["**", "!.git/**", "!node_modules/**"] 6 | } 7 | }, 8 | "extends": ["development"], 9 | "formatters": ["stylish"], 10 | "hints": [ 11 | "button-type", 12 | "disown-opener", 13 | "html-checker", 14 | "meta-charset-utf-8", 15 | "meta-viewport", 16 | "no-inline-styles:error" 17 | ] 18 | } -------------------------------------------------------------------------------- /src/Modules/sendComment.js: -------------------------------------------------------------------------------- 1 | const sendComment = async (appId, id, username1, comment1) => { 2 | const response = await fetch(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/${appId}/comments`, { 3 | method: 'POST', 4 | headers: { 5 | 'Content-Type': 'application/json', 6 | }, 7 | body: JSON.stringify({ 8 | item_id: id, 9 | username: username1, 10 | comment: comment1, 11 | }), 12 | }); 13 | 14 | if (!response.ok) { 15 | throw new Error('Error sending the comment'); 16 | } 17 | }; 18 | 19 | export default sendComment; -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es6": true, 5 | "jest": true 6 | }, 7 | "parser": "babel-eslint", 8 | "parserOptions": { 9 | "ecmaVersion": 2018, 10 | "sourceType": "module" 11 | }, 12 | "extends": ["airbnb-base"], 13 | "rules": { 14 | "no-shadow": "off", 15 | "no-param-reassign": "off", 16 | "eol-last": "off", 17 | "import/extensions": [ 1, { 18 | "js": "always", "json": "always" 19 | }] 20 | }, 21 | "ignorePatterns": [ 22 | "dist/", 23 | "build/" 24 | ] 25 | } -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard"], 3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"], 4 | "rules": { 5 | "at-rule-no-unknown": [ 6 | true, 7 | { 8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 9 | } 10 | ], 11 | "scss/at-rule-no-unknown": [ 12 | true, 13 | { 14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"] 15 | } 16 | ], 17 | "csstree/validator": true 18 | }, 19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"] 20 | } -------------------------------------------------------------------------------- /tests/itemCounter.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | import homeItemCounter from '../src/Modules/itemCounter.js'; 6 | 7 | describe('Return the number of items displayed in the screen', () => { 8 | it('Case 1', () => { 9 | document.body.innerHTML = ` 10 |

11 | `; 12 | const items = [1, 2, 3, 4]; 13 | const result = homeItemCounter(items.length); 14 | expect(result).toMatch(/4 Vegetarian Recipes/); 15 | }); 16 | 17 | it('Case 2', () => { 18 | document.body.innerHTML = ` 19 |

20 | `; 21 | const items = [1, 2, 3, 4, 5, 6, 7]; 22 | const result = homeItemCounter(items.length); 23 | expect(result).toMatch(/7 Vegetarian Recipes/); 24 | }); 25 | }); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 3 | 4 | module.exports = { 5 | mode: 'development', 6 | entry: './src/index.js', 7 | devServer: { 8 | static: './dist', 9 | }, 10 | plugins: [ 11 | new HtmlWebpackPlugin({ 12 | template: './src/index.html', 13 | }), 14 | ], 15 | output: { 16 | filename: '[name].js', 17 | path: path.resolve(__dirname, 'dist'), 18 | }, 19 | optimization: { 20 | runtimeChunk: 'single', 21 | }, 22 | module: { 23 | rules: [ 24 | { 25 | test: /\.css$/i, 26 | use: ['style-loader', 'css-loader'], 27 | }, 28 | { 29 | test: /\.(png|svg|jpg|jpeg|gif)$/i, 30 | type: 'asset/resource', 31 | }, 32 | ], 33 | }, 34 | }; -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 12 | 17 |
18 |
19 |
20 |

21 |
22 |
23 |
24 | 27 | 28 | -------------------------------------------------------------------------------- /tests/commentsCounter.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment jsdom 3 | */ 4 | 5 | import countComments from '../src/Modules/commentsCounter.js'; 6 | 7 | describe('Comments Counter', () => { 8 | document.body.innerHTML = ` 9 |
10 |

Comment 1

11 |

Comment 2

12 |

Comment 3

13 |
14 | `; 15 | 16 | test('should return the correct number of comments', () => { 17 | expect(countComments()).toBe(3); 18 | }); 19 | 20 | test('should return 0 if no comments are present', () => { 21 | document.querySelector('#commentsContainer').innerHTML = ''; 22 | expect(countComments()).toBe(0); 23 | }); 24 | 25 | test('should not count non-comment elements', () => { 26 | document.querySelector('#commentsContainer').innerHTML += '
Not a comment
'; 27 | expect(countComments()).toBe(0); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 |
11 | 12 | 17 |
18 |
19 |
20 |

21 |
22 |
23 |
24 | 27 | 28 | -------------------------------------------------------------------------------- /src/Modules/likes.js: -------------------------------------------------------------------------------- 1 | const postLikes = async (id) => { 2 | const sendData = await fetch('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/k513WvYOj4wUaRdaeuNF/likes/', { 3 | method: 'POST', 4 | headers: { 5 | 'Content-type': 'application/json; charset=UTF-8', 6 | }, 7 | body: JSON.stringify({ 8 | item_id: id, 9 | }), 10 | }); 11 | const result = await sendData.text(); 12 | return result; 13 | }; 14 | 15 | export const getLikes = async () => { 16 | const requestLikes = await fetch('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/k513WvYOj4wUaRdaeuNF/likes/'); 17 | const dataLikes = await requestLikes.json(); 18 | return dataLikes; 19 | }; 20 | 21 | export const updateText = async (idmeal, span) => { 22 | const numberOfLikes = await getLikes(); 23 | let likes = 0; 24 | numberOfLikes.forEach((elem) => { 25 | if (elem.item_id === idmeal) { 26 | likes = elem.likes; 27 | } 28 | }); 29 | span.textContent = `${likes} likes`; 30 | }; 31 | 32 | export default postLikes; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Andrea Manuel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software and to permit persons to whom the Software is 10 | furnished to do so subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "javascriptcapstone", 3 | "version": "1.0.0", 4 | "description": "The leaderboard website displays scores submitted by different players. It also allows you to submit your score. All data is preserved thanks to the external Leaderboard API service.", 5 | "private": true, 6 | "scripts": { 7 | "test": "jest", 8 | "start": "webpack serve --open", 9 | "build": "webpack", 10 | "predeploy": "npm run build", 11 | "deploy": "gh-pages -d dist" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@babel/plugin-transform-modules-commonjs": "^7.22.5", 18 | "babel-eslint": "^10.1.0", 19 | "css-loader": "^6.8.1", 20 | "eslint": "^7.32.0", 21 | "eslint-config-airbnb-base": "^14.2.1", 22 | "eslint-plugin-import": "^2.27.5", 23 | "gh-pages": "^5.0.0", 24 | "hint": "^7.1.9", 25 | "html-webpack-plugin": "^5.5.3", 26 | "jest": "^29.5.0", 27 | "jest-environment-jsdom": "^29.5.0", 28 | "style-loader": "^3.3.3", 29 | "stylelint": "^13.13.1", 30 | "stylelint-config-standard": "^21.0.0", 31 | "stylelint-csstree-validator": "^1.9.0", 32 | "stylelint-scss": "^3.21.0", 33 | "webpack": "^5.87.0", 34 | "webpack-cli": "^5.1.4", 35 | "webpack-dev-server": "^4.15.1" 36 | }, 37 | "dependencies": { 38 | "lodash": "^4.17.21" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Modules/getItems.js: -------------------------------------------------------------------------------- 1 | import showCommentsPopup from './commentsPopup.js'; 2 | import handleFetchError from './errorHandler.js'; 3 | import postLikes, { getLikes, updateText } from './likes.js'; 4 | import homeItemCounter from './itemCounter.js'; 5 | 6 | const container = document.querySelector('#itemsContainer'); 7 | 8 | const displayItems = (dataMeals) => { 9 | dataMeals.forEach(async (meals) => { 10 | const numberOfLikes = await getLikes(); 11 | let likes = 0; 12 | numberOfLikes.forEach((elem) => { 13 | if (elem.item_id === meals.idMeal) { 14 | likes = elem.likes; 15 | } 16 | }); 17 | const mainDiv = document.createElement('div'); 18 | mainDiv.className = 'dflex container'; 19 | mainDiv.innerHTML = ` 20 |
21 | ${meals.strMealThumb} 22 |
23 |

${meals.strMeal}

24 |
25 | ${likes} likes 26 | 27 |
28 |
29 | 30 |
31 | `; 32 | 33 | mainDiv.querySelectorAll('#comments').forEach((commentsButton) => { 34 | commentsButton.addEventListener('click', async () => { 35 | await showCommentsPopup(meals.idMeal).catch(handleFetchError); 36 | }); 37 | }); 38 | 39 | mainDiv.querySelector('#likes').addEventListener('click', async (event) => { 40 | const id = event.target.className; 41 | await postLikes(id); 42 | const updateLikes = mainDiv.querySelector('#likesNumber'); 43 | await updateText(meals.idMeal, updateLikes); 44 | }); 45 | 46 | container.appendChild(mainDiv); 47 | }); 48 | }; 49 | 50 | const getItems = async () => { 51 | const request = await fetch('https://themealdb.com/api/json/v1/1/filter.php?c=Vegetarian'); 52 | const data = await request.json(); 53 | displayItems(data.meals); 54 | homeItemCounter(data.meals.length); 55 | }; 56 | 57 | export default getItems; -------------------------------------------------------------------------------- /.github/workflows/linters.yml: -------------------------------------------------------------------------------- 1 | name: Linters 2 | 3 | on: pull_request 4 | 5 | env: 6 | FORCE_COLOR: 1 7 | 8 | jobs: 9 | lighthouse: 10 | name: Lighthouse 11 | runs-on: ubuntu-22.04 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: "18.x" 17 | - name: Setup Lighthouse 18 | run: npm install -g @lhci/cli@0.11.x 19 | - name: Lighthouse Report 20 | run: lhci autorun --upload.target=temporary-public-storage --collect.staticDistDir=. 21 | webhint: 22 | name: Webhint 23 | runs-on: ubuntu-22.04 24 | steps: 25 | - uses: actions/checkout@v3 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: "18.x" 29 | - name: Setup Webhint 30 | run: | 31 | npm install --save-dev hint@7.x 32 | [ -f .hintrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.hintrc 33 | - name: Webhint Report 34 | run: npx hint . 35 | stylelint: 36 | name: Stylelint 37 | runs-on: ubuntu-22.04 38 | steps: 39 | - uses: actions/checkout@v3 40 | - uses: actions/setup-node@v3 41 | with: 42 | node-version: "18.x" 43 | - name: Setup Stylelint 44 | run: | 45 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x 46 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.stylelintrc.json 47 | - name: Stylelint Report 48 | run: npx stylelint "**/*.{css,scss}" 49 | eslint: 50 | name: ESLint 51 | runs-on: ubuntu-22.04 52 | steps: 53 | - uses: actions/checkout@v3 54 | - uses: actions/setup-node@v3 55 | with: 56 | node-version: "18.x" 57 | - name: Setup ESLint 58 | run: | 59 | npm install --save-dev eslint@7.x eslint-config-airbnb-base@14.x eslint-plugin-import@2.x babel-eslint@10.x 60 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/html-css-js/.eslintrc.json 61 | - name: ESLint Report 62 | run: npx eslint . 63 | nodechecker: 64 | name: node_modules checker 65 | runs-on: ubuntu-22.04 66 | steps: 67 | - uses: actions/checkout@v3 68 | - name: Check node_modules existence 69 | run: | 70 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi 71 | -------------------------------------------------------------------------------- /src/Modules/commentsPopup.js: -------------------------------------------------------------------------------- 1 | import getItemDetails from './getItemsDetails.js'; 2 | import getComments from './getComments.js'; 3 | import sendComment from './sendComment.js'; 4 | import countComments from './commentsCounter.js'; 5 | 6 | const showCommentsPopup = async (id) => { 7 | const details = await getItemDetails(id); 8 | const appId = 'k513WvYOj4wUaRdaeuNF'; 9 | 10 | const popup = document.createElement('div'); 11 | popup.id = 'commentsPopup'; 12 | popup.innerHTML = ` 13 |

${details.strMeal}

14 | ${details.strMeal} 15 |

${details.strInstructions}

16 |
17 |

Add a comment

18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 | 26 |
27 | 28 | `; 29 | 30 | document.body.appendChild(popup); 31 | 32 | const commentsContainer = popup.querySelector('#commentsContainer'); 33 | 34 | // Create a new element to display the comment count 35 | const commentsCountElement = document.createElement('p'); 36 | commentsCountElement.id = 'commentsCount'; 37 | commentsCountElement.classList.add('comments-count'); 38 | 39 | popup.insertBefore(commentsCountElement, commentsContainer); 40 | 41 | const updateComments = async () => { 42 | const comments = await getComments(appId, id); 43 | if (!Array.isArray(comments)) { 44 | // This block it's designed to handle the empty data in comments 45 | } else { 46 | commentsContainer.innerHTML = ''; 47 | comments.forEach((comment) => { 48 | const commentElement = document.createElement('p'); 49 | commentElement.textContent = `${comment.creation_date} - ${comment.username}: ${comment.comment}`; 50 | commentElement.classList.add('comment-text'); 51 | commentsContainer.appendChild(commentElement); 52 | }); 53 | // Update the comments count after updating the comments 54 | commentsCountElement.textContent = `Comments: ${countComments()}`; 55 | } 56 | }; 57 | 58 | await updateComments(); 59 | 60 | const form = popup.querySelector('#commentForm'); 61 | form.addEventListener('submit', async (event) => { 62 | const usernameInput = popup.querySelector('#nameInput'); 63 | const commentInput = popup.querySelector('#commentInput'); 64 | 65 | event.preventDefault(); 66 | 67 | const username = usernameInput.value; 68 | const comment = commentInput.value; 69 | 70 | await sendComment(appId, id, username, comment); 71 | await updateComments(); // Update the comments (and the count) after submitting a comment 72 | 73 | // Clear the input fields after the comment has been sent and comments have been updated 74 | usernameInput.value = ''; 75 | commentInput.value = ''; 76 | }); 77 | 78 | popup.querySelector('.closeButton').addEventListener('click', () => { 79 | document.body.removeChild(popup); 80 | }); 81 | }; 82 | 83 | export default showCommentsPopup; 84 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | background-color: rgb(161, 230, 230); 5 | } 6 | 7 | .dflex { 8 | display: flex; 9 | justify-content: space-around; 10 | align-items: center; 11 | gap: 15px; 12 | flex-wrap: wrap; 13 | } 14 | 15 | header, 16 | footer { 17 | background-color: rgb(245, 209, 109); 18 | } 19 | 20 | main { 21 | padding: 15px; 22 | } 23 | 24 | #logo { 25 | max-width: 100px; 26 | } 27 | 28 | ul, 29 | li a { 30 | text-decoration: none; 31 | list-style: none; 32 | color: black; 33 | font-size: 15px; 34 | } 35 | 36 | footer { 37 | font-size: 15px; 38 | text-align: center; 39 | justify-content: center; 40 | height: 50px; 41 | } 42 | 43 | .mealimg { 44 | width: 200px; 45 | } 46 | 47 | .mealtitle { 48 | justify-content: center; 49 | flex-direction: column; 50 | text-align: center; 51 | } 52 | 53 | h2 { 54 | color: brown; 55 | } 56 | 57 | .container, 58 | .item { 59 | width: 300px; 60 | height: 460px; 61 | margin-bottom: 40px; 62 | } 63 | 64 | .item { 65 | border: 3px solid brown; 66 | flex-direction: column; 67 | padding: 10px; 68 | background-color: rgba(250, 232, 182, 0.705); 69 | } 70 | 71 | #likes { 72 | background-color: transparent; 73 | border: transparent; 74 | font-size: 30px; 75 | color: brown; 76 | } 77 | 78 | #likes:active { 79 | color: red; 80 | font-weight: 900; 81 | } 82 | 83 | #comments { 84 | background-color: rgb(245, 209, 109); 85 | width: 100px; 86 | height: 34px; 87 | border-radius: 12px; 88 | border: 3px solid brown; 89 | } 90 | 91 | #commentsPopup { 92 | position: fixed; 93 | top: 50%; 94 | left: 50%; 95 | transform: translate(-50%, -50%); 96 | width: 90%; 97 | max-width: 90vw; 98 | height: 90vh; 99 | max-height: 90vh; 100 | overflow-y: auto; 101 | background-color: rgb(250, 232, 182); 102 | padding: 20px; 103 | box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); 104 | text-align: center; 105 | border: 3px solid brown; 106 | } 107 | 108 | #commentsPopup h2 { 109 | margin-bottom: 20px; 110 | } 111 | 112 | #commentsPopup img { 113 | width: 400px; 114 | height: 300px; 115 | object-fit: cover; 116 | } 117 | 118 | #details-instructions { 119 | color: brown; 120 | padding: 30px; 121 | margin-left: 90px; 122 | margin-right: 90px; 123 | } 124 | 125 | #commentsPopup h3 { 126 | color: brown; 127 | margin-bottom: 25px; 128 | } 129 | 130 | #nameInput { 131 | margin-bottom: 10px; 132 | width: 70%; 133 | padding: 5px; 134 | border: 1px solid brown; 135 | } 136 | 137 | #commentInput { 138 | margin-bottom: 20px; 139 | width: 70%; 140 | padding: 5px; 141 | height: 100px; 142 | border: 1px solid brown; 143 | } 144 | 145 | #commentsPopup .closeButton { 146 | position: absolute; 147 | top: 20px; 148 | right: 20px; 149 | background: none; 150 | border: none; 151 | padding: 0; 152 | font-size: 40px; 153 | cursor: pointer; 154 | color: brown; 155 | } 156 | 157 | #submitCommentButton { 158 | background-color: rgb(245, 209, 109); 159 | width: 120px; 160 | height: 40px; 161 | border-radius: 12px; 162 | border: 2px solid brown; 163 | color: brown; 164 | font-size: 16px; 165 | margin-bottom: 20px; 166 | } 167 | 168 | .comment-text { 169 | color: brown; 170 | font-size: 14px; 171 | } 172 | 173 | .comments-count { 174 | color: brown; 175 | font-size: 15px; 176 | font-weight: bold; 177 | } 178 | 179 | #mainTitle { 180 | color: brown; 181 | font-size: 30px; 182 | font-weight: 900; 183 | } 184 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaScriptCapstone 2 | 3 | 4 | 5 | # 📗 Table of Contents 6 | 7 | - [JavaScriptCapstone](#javascriptcapstone) 8 | - [📗 Table of Contents](#-table-of-contents) 9 | - [📖 JavaScriptCapstone ](#-javascriptcapstone-) 10 | - [🛠 Built With ](#-built-with-) 11 | - [Tech Stack ](#tech-stack-) 12 | - [Key Features ](#key-features-) 13 | - [💻 Getting Started ](#-getting-started-) 14 | - [Project Structure](#project-structure) 15 | - [Setup](#setup) 16 | - [Install](#install) 17 | - [Usage](#usage) 18 | - [Run tests](#run-tests) 19 | - [👥 Authors ](#-authors-) 20 | - [🔭 Future Features ](#-future-features-) 21 | - [🤝 Contributing ](#-contributing-) 22 | - [⭐️ Show your support ](#️-show-your-support-) 23 | - [🙏 Acknowledgments ](#-acknowledgments-) 24 | - [📝 License ](#-license-) 25 | 26 | # 📖 JavaScriptCapstone 27 | 28 | > This is the JavaScript Capstone project, where we built a web application based on an external API. The project is a webapp that revolves around a selected API, providing data about a topic of our choice. 29 | > [Here](https://youtu.be/Hi2MclqUOjU) is the link to the video presentation 30 | 31 | ## 🛠 Built With 32 | 33 | ### Tech Stack 34 | 35 |
36 | HTML 37 | 40 |
41 | 42 |
43 | CSS 44 | 47 |
48 | 49 |
50 | Linters 51 | 60 |
61 | 62 |
63 | Webpack 64 | 69 |
70 | 71 |
72 | API's 73 | 77 |
78 |
79 | 80 | ### Key Features 81 | 82 | - **Webpack Configuration** 83 | - **HTML Generation** 84 | - **CSS Styling** 85 | - **Development Server** 86 | - **Code Quality** 87 | - **Modular Structure** 88 | - **ES6 Syntax** 89 | - **JavaScript Functionality** 90 | - **Gitflow** 91 | - **Send and receive data from API** 92 | - **Jest testing** 93 | - **API's** 94 | 95 |

(back to top)

96 | 97 | 98 | ## 💻 Getting Started 99 | 100 | > To get a local copy up and running, follow these steps. 101 | > This project requires Node.js and npm installed on your machine. 102 | 103 | -Node.js 104 | -npm 105 | 106 | > -Clone this repository to your local machine using: 107 | 108 | > git clone https://github.com/andream2429/JavaScriptCapstone.git 109 | 110 | > -Navigate to the project folder: 111 | 112 | > cd Leaderboard 113 | 114 | > -Install the project dependencies: 115 | 116 | > npm install 117 | 118 | > o start the development server, run the following command: 119 | 120 | > npm start 121 | 122 | ### Project Structure 123 | 124 | > The project follows the following folder and file structure: 125 | 126 | > /src: Contains the source files of the application. 127 | > /src/index.js: Main entry point of the JavaScript application. 128 | > /src/style.css: CSS file for the application styles. 129 | > /src/index.html: Base HTML file of the application. 130 | > /dist: Contains the generated production files. 131 | > webpack.config.js: Webpack configuration file. 132 | 133 | ### Setup 134 | 135 | > Clone this repository to your desired folder: https://github.com/andream2429/JavaScriptCapstone.git 136 | 137 | ### Install 138 | 139 | > Install this project with: install WebLint and ESLint 140 | 141 | ### Usage 142 | 143 | > To run the project, execute the following command: just need a web Browser 144 | 145 | ### Run tests 146 | 147 | > To run tests, run the following command: you just need a simple web browser to run this project for a test 148 | 149 | ## 👥 Authors 150 | 151 | 👤 **Andrea Manuel** 152 | 153 | - GitHub: [@AndreaM2429](https://github.com/AndreaM2429) 154 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/andrea-manuel-2b075026a/) 155 | 156 | 👤 **Claudia Rojas** 157 | 158 | - GitHub: [@githubhandle](https://github.com/ClaudiaRojasSoto) 159 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/claudia-soto-260504208/) 160 | 161 | 162 |

(back to top)

163 | 164 | ## 🔭 Future Features 165 | 166 | 167 | - **[User Authentication]** 168 | 169 |

(back to top)

170 | 171 | ## 🤝 Contributing 172 | 173 | > Contributions, issues, and feature requests are welcome! 174 | 175 | > Feel free to check the [issues page](https://github.com/AndreaM2429/JavaScriptCapstone/issues). 176 | 177 |

(back to top)

178 | 179 | ## ⭐️ Show your support 180 | 181 | > If you like this project show support by following this account 182 | 183 |

(back to top)

184 | 185 | 186 | 187 | ## 🙏 Acknowledgments 188 | 189 | > - Microverse for providing the opportunity to learn Git and GitHub in a collaborative environment. 190 | 191 | > - GitHub Docs for providing a wealth of information on Git and GitHub. 192 | 193 |

(back to top)

194 | 195 | 196 | 197 | ## 📝 License 198 | 199 | > This project is [MIT](./LICENSE). 200 | 201 |

(back to top)

202 | -------------------------------------------------------------------------------- /dist/runtime.js: -------------------------------------------------------------------------------- 1 | /* 2 | * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). 3 | * This devtool is neither made for production nor for readable output files. 4 | * It uses "eval()" calls to create a separate source file in the browser devtools. 5 | * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) 6 | * or disable the default devtool with "devtool: false". 7 | * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). 8 | */ 9 | /******/ (() => { // webpackBootstrap 10 | /******/ "use strict"; 11 | /******/ var __webpack_modules__ = ({}); 12 | /************************************************************************/ 13 | /******/ // The module cache 14 | /******/ var __webpack_module_cache__ = {}; 15 | /******/ 16 | /******/ // The require function 17 | /******/ function __webpack_require__(moduleId) { 18 | /******/ // Check if module is in cache 19 | /******/ var cachedModule = __webpack_module_cache__[moduleId]; 20 | /******/ if (cachedModule !== undefined) { 21 | /******/ return cachedModule.exports; 22 | /******/ } 23 | /******/ // Create a new module (and put it into the cache) 24 | /******/ var module = __webpack_module_cache__[moduleId] = { 25 | /******/ id: moduleId, 26 | /******/ // no module.loaded needed 27 | /******/ exports: {} 28 | /******/ }; 29 | /******/ 30 | /******/ // Execute the module function 31 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 32 | /******/ 33 | /******/ // Return the exports of the module 34 | /******/ return module.exports; 35 | /******/ } 36 | /******/ 37 | /******/ // expose the modules object (__webpack_modules__) 38 | /******/ __webpack_require__.m = __webpack_modules__; 39 | /******/ 40 | /************************************************************************/ 41 | /******/ /* webpack/runtime/chunk loaded */ 42 | /******/ (() => { 43 | /******/ var deferred = []; 44 | /******/ __webpack_require__.O = (result, chunkIds, fn, priority) => { 45 | /******/ if(chunkIds) { 46 | /******/ priority = priority || 0; 47 | /******/ for(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1]; 48 | /******/ deferred[i] = [chunkIds, fn, priority]; 49 | /******/ return; 50 | /******/ } 51 | /******/ var notFulfilled = Infinity; 52 | /******/ for (var i = 0; i < deferred.length; i++) { 53 | /******/ var [chunkIds, fn, priority] = deferred[i]; 54 | /******/ var fulfilled = true; 55 | /******/ for (var j = 0; j < chunkIds.length; j++) { 56 | /******/ if ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) { 57 | /******/ chunkIds.splice(j--, 1); 58 | /******/ } else { 59 | /******/ fulfilled = false; 60 | /******/ if(priority < notFulfilled) notFulfilled = priority; 61 | /******/ } 62 | /******/ } 63 | /******/ if(fulfilled) { 64 | /******/ deferred.splice(i--, 1) 65 | /******/ var r = fn(); 66 | /******/ if (r !== undefined) result = r; 67 | /******/ } 68 | /******/ } 69 | /******/ return result; 70 | /******/ }; 71 | /******/ })(); 72 | /******/ 73 | /******/ /* webpack/runtime/compat get default export */ 74 | /******/ (() => { 75 | /******/ // getDefaultExport function for compatibility with non-harmony modules 76 | /******/ __webpack_require__.n = (module) => { 77 | /******/ var getter = module && module.__esModule ? 78 | /******/ () => (module['default']) : 79 | /******/ () => (module); 80 | /******/ __webpack_require__.d(getter, { a: getter }); 81 | /******/ return getter; 82 | /******/ }; 83 | /******/ })(); 84 | /******/ 85 | /******/ /* webpack/runtime/define property getters */ 86 | /******/ (() => { 87 | /******/ // define getter functions for harmony exports 88 | /******/ __webpack_require__.d = (exports, definition) => { 89 | /******/ for(var key in definition) { 90 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 91 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 92 | /******/ } 93 | /******/ } 94 | /******/ }; 95 | /******/ })(); 96 | /******/ 97 | /******/ /* webpack/runtime/global */ 98 | /******/ (() => { 99 | /******/ __webpack_require__.g = (function() { 100 | /******/ if (typeof globalThis === 'object') return globalThis; 101 | /******/ try { 102 | /******/ return this || new Function('return this')(); 103 | /******/ } catch (e) { 104 | /******/ if (typeof window === 'object') return window; 105 | /******/ } 106 | /******/ })(); 107 | /******/ })(); 108 | /******/ 109 | /******/ /* webpack/runtime/hasOwnProperty shorthand */ 110 | /******/ (() => { 111 | /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 112 | /******/ })(); 113 | /******/ 114 | /******/ /* webpack/runtime/make namespace object */ 115 | /******/ (() => { 116 | /******/ // define __esModule on exports 117 | /******/ __webpack_require__.r = (exports) => { 118 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 119 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 120 | /******/ } 121 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 122 | /******/ }; 123 | /******/ })(); 124 | /******/ 125 | /******/ /* webpack/runtime/publicPath */ 126 | /******/ (() => { 127 | /******/ var scriptUrl; 128 | /******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + ""; 129 | /******/ var document = __webpack_require__.g.document; 130 | /******/ if (!scriptUrl && document) { 131 | /******/ if (document.currentScript) 132 | /******/ scriptUrl = document.currentScript.src; 133 | /******/ if (!scriptUrl) { 134 | /******/ var scripts = document.getElementsByTagName("script"); 135 | /******/ if(scripts.length) { 136 | /******/ var i = scripts.length - 1; 137 | /******/ while (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src; 138 | /******/ } 139 | /******/ } 140 | /******/ } 141 | /******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration 142 | /******/ // or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic. 143 | /******/ if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser"); 144 | /******/ scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/"); 145 | /******/ __webpack_require__.p = scriptUrl; 146 | /******/ })(); 147 | /******/ 148 | /******/ /* webpack/runtime/jsonp chunk loading */ 149 | /******/ (() => { 150 | /******/ // no baseURI 151 | /******/ 152 | /******/ // object to store loaded and loading chunks 153 | /******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched 154 | /******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded 155 | /******/ var installedChunks = { 156 | /******/ "runtime": 0 157 | /******/ }; 158 | /******/ 159 | /******/ // no chunk on demand loading 160 | /******/ 161 | /******/ // no prefetching 162 | /******/ 163 | /******/ // no preloaded 164 | /******/ 165 | /******/ // no HMR 166 | /******/ 167 | /******/ // no HMR manifest 168 | /******/ 169 | /******/ __webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0); 170 | /******/ 171 | /******/ // install a JSONP callback for chunk loading 172 | /******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { 173 | /******/ var [chunkIds, moreModules, runtime] = data; 174 | /******/ // add "moreModules" to the modules object, 175 | /******/ // then flag all "chunkIds" as loaded and fire callback 176 | /******/ var moduleId, chunkId, i = 0; 177 | /******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { 178 | /******/ for(moduleId in moreModules) { 179 | /******/ if(__webpack_require__.o(moreModules, moduleId)) { 180 | /******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; 181 | /******/ } 182 | /******/ } 183 | /******/ if(runtime) var result = runtime(__webpack_require__); 184 | /******/ } 185 | /******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); 186 | /******/ for(;i < chunkIds.length; i++) { 187 | /******/ chunkId = chunkIds[i]; 188 | /******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { 189 | /******/ installedChunks[chunkId][0](); 190 | /******/ } 191 | /******/ installedChunks[chunkId] = 0; 192 | /******/ } 193 | /******/ return __webpack_require__.O(result); 194 | /******/ } 195 | /******/ 196 | /******/ var chunkLoadingGlobal = self["webpackChunkjavascriptcapstone"] = self["webpackChunkjavascriptcapstone"] || []; 197 | /******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); 198 | /******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); 199 | /******/ })(); 200 | /******/ 201 | /******/ /* webpack/runtime/nonce */ 202 | /******/ (() => { 203 | /******/ __webpack_require__.nc = undefined; 204 | /******/ })(); 205 | /******/ 206 | /************************************************************************/ 207 | /******/ 208 | /******/ 209 | /******/ })() 210 | ; -------------------------------------------------------------------------------- /dist/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /* 3 | * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). 4 | * This devtool is neither made for production nor for readable output files. 5 | * It uses "eval()" calls to create a separate source file in the browser devtools. 6 | * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) 7 | * or disable the default devtool with "devtool: false". 8 | * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). 9 | */ 10 | (self["webpackChunkjavascriptcapstone"] = self["webpackChunkjavascriptcapstone"] || []).push([["main"],{ 11 | 12 | /***/ "./node_modules/css-loader/dist/cjs.js!./src/styles.css": 13 | /*!**************************************************************!*\ 14 | !*** ./node_modules/css-loader/dist/cjs.js!./src/styles.css ***! 15 | \**************************************************************/ 16 | /***/ ((module, __webpack_exports__, __webpack_require__) => { 17 | 18 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `body {\n padding: 0;\n margin: 0;\n background-color: rgb(161, 230, 230);\n}\n\n.dflex {\n display: flex;\n justify-content: space-around;\n align-items: center;\n gap: 15px;\n flex-wrap: wrap;\n}\n\nheader,\nfooter {\n background-color: rgb(245, 209, 109);\n}\n\nmain {\n padding: 15px;\n}\n\n#logo {\n max-width: 100px;\n}\n\nul,\nli a {\n text-decoration: none;\n list-style: none;\n color: black;\n font-size: 15px;\n}\n\nfooter {\n font-size: 15px;\n text-align: center;\n justify-content: center;\n height: 50px;\n}\n\n.mealimg {\n width: 200px;\n}\n\n.mealtitle {\n justify-content: center;\n flex-direction: column;\n text-align: center;\n}\n\nh2 {\n color: brown;\n}\n\n.container,\n.item {\n width: 300px;\n height: 460px;\n margin-bottom: 40px;\n}\n\n.item {\n border: 3px solid brown;\n flex-direction: column;\n padding: 10px;\n background-color: rgba(250, 232, 182, 0.705);\n}\n\n#likes {\n background-color: transparent;\n border: transparent;\n font-size: 30px;\n color: brown;\n}\n\n#likes:active {\n color: red;\n font-weight: 900;\n}\n\n#comments {\n background-color: rgb(245, 209, 109);\n width: 100px;\n height: 34px;\n border-radius: 12px;\n border: 3px solid brown;\n}\n\n#commentsPopup {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 90%;\n max-width: 90vw;\n height: 90vh;\n max-height: 90vh;\n overflow-y: auto;\n background-color: rgb(250, 232, 182);\n padding: 20px;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);\n text-align: center;\n border: 3px solid brown;\n}\n\n#commentsPopup h2 {\n margin-bottom: 20px;\n}\n\n#commentsPopup img {\n width: 400px;\n height: 300px;\n object-fit: cover;\n}\n\n#details-instructions {\n color: brown;\n padding: 30px;\n margin-left: 90px;\n margin-right: 90px;\n}\n\n#commentsPopup h3 {\n color: brown;\n margin-bottom: 25px;\n}\n\n#nameInput {\n margin-bottom: 10px;\n width: 70%;\n padding: 5px;\n border: 1px solid brown;\n}\n\n#commentInput {\n margin-bottom: 20px;\n width: 70%;\n padding: 5px;\n height: 100px;\n border: 1px solid brown;\n}\n\n#commentsPopup .closeButton {\n position: absolute;\n top: 20px;\n right: 20px;\n background: none;\n border: none;\n padding: 0;\n font-size: 40px;\n cursor: pointer;\n color: brown;\n}\n\n#submitCommentButton {\n background-color: rgb(245, 209, 109);\n width: 120px;\n height: 40px;\n border-radius: 12px;\n border: 2px solid brown;\n color: brown;\n font-size: 16px;\n margin-bottom: 20px;\n}\n\n.comment-text {\n color: brown;\n font-size: 14px;\n}\n\n.comments-count {\n color: brown;\n font-size: 15px;\n font-weight: bold;\n}\n\n#mainTitle {\n color: brown;\n font-size: 30px;\n font-weight: 900;\n}\n`, \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://javascriptcapstone/./src/styles.css?./node_modules/css-loader/dist/cjs.js"); 19 | 20 | /***/ }), 21 | 22 | /***/ "./node_modules/css-loader/dist/runtime/api.js": 23 | /*!*****************************************************!*\ 24 | !*** ./node_modules/css-loader/dist/runtime/api.js ***! 25 | \*****************************************************/ 26 | /***/ ((module) => { 27 | 28 | eval("\n\n/*\n MIT License http://www.opensource.org/licenses/mit-license.php\n Author Tobias Koppers @sokra\n*/\nmodule.exports = function (cssWithMappingToString) {\n var list = [];\n\n // return the list of modules as css string\n list.toString = function toString() {\n return this.map(function (item) {\n var content = \"\";\n var needLayer = typeof item[5] !== \"undefined\";\n if (item[4]) {\n content += \"@supports (\".concat(item[4], \") {\");\n }\n if (item[2]) {\n content += \"@media \".concat(item[2], \" {\");\n }\n if (needLayer) {\n content += \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\");\n }\n content += cssWithMappingToString(item);\n if (needLayer) {\n content += \"}\";\n }\n if (item[2]) {\n content += \"}\";\n }\n if (item[4]) {\n content += \"}\";\n }\n return content;\n }).join(\"\");\n };\n\n // import a list of modules into the list\n list.i = function i(modules, media, dedupe, supports, layer) {\n if (typeof modules === \"string\") {\n modules = [[null, modules, undefined]];\n }\n var alreadyImportedModules = {};\n if (dedupe) {\n for (var k = 0; k < this.length; k++) {\n var id = this[k][0];\n if (id != null) {\n alreadyImportedModules[id] = true;\n }\n }\n }\n for (var _k = 0; _k < modules.length; _k++) {\n var item = [].concat(modules[_k]);\n if (dedupe && alreadyImportedModules[item[0]]) {\n continue;\n }\n if (typeof layer !== \"undefined\") {\n if (typeof item[5] === \"undefined\") {\n item[5] = layer;\n } else {\n item[1] = \"@layer\".concat(item[5].length > 0 ? \" \".concat(item[5]) : \"\", \" {\").concat(item[1], \"}\");\n item[5] = layer;\n }\n }\n if (media) {\n if (!item[2]) {\n item[2] = media;\n } else {\n item[1] = \"@media \".concat(item[2], \" {\").concat(item[1], \"}\");\n item[2] = media;\n }\n }\n if (supports) {\n if (!item[4]) {\n item[4] = \"\".concat(supports);\n } else {\n item[1] = \"@supports (\".concat(item[4], \") {\").concat(item[1], \"}\");\n item[4] = supports;\n }\n }\n list.push(item);\n }\n };\n return list;\n};\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/css-loader/dist/runtime/api.js?"); 29 | 30 | /***/ }), 31 | 32 | /***/ "./node_modules/css-loader/dist/runtime/noSourceMaps.js": 33 | /*!**************************************************************!*\ 34 | !*** ./node_modules/css-loader/dist/runtime/noSourceMaps.js ***! 35 | \**************************************************************/ 36 | /***/ ((module) => { 37 | 38 | eval("\n\nmodule.exports = function (i) {\n return i[1];\n};\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/css-loader/dist/runtime/noSourceMaps.js?"); 39 | 40 | /***/ }), 41 | 42 | /***/ "./src/styles.css": 43 | /*!************************!*\ 44 | !*** ./src/styles.css ***! 45 | \************************/ 46 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 47 | 48 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js */ \"./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/styleDomAPI.js */ \"./node_modules/style-loader/dist/runtime/styleDomAPI.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/insertBySelector.js */ \"./node_modules/style-loader/dist/runtime/insertBySelector.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js */ \"./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/insertStyleElement.js */ \"./node_modules/style-loader/dist/runtime/insertStyleElement.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! !../node_modules/style-loader/dist/runtime/styleTagTransform.js */ \"./node_modules/style-loader/dist/runtime/styleTagTransform.js\");\n/* harmony import */ var _node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5__);\n/* harmony import */ var _node_modules_css_loader_dist_cjs_js_styles_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../node_modules/css-loader/dist/cjs.js!./styles.css */ \"./node_modules/css-loader/dist/cjs.js!./src/styles.css\");\n\n \n \n \n \n \n \n \n \n \n\nvar options = {};\n\noptions.styleTagTransform = (_node_modules_style_loader_dist_runtime_styleTagTransform_js__WEBPACK_IMPORTED_MODULE_5___default());\noptions.setAttributes = (_node_modules_style_loader_dist_runtime_setAttributesWithoutAttributes_js__WEBPACK_IMPORTED_MODULE_3___default());\n\n options.insert = _node_modules_style_loader_dist_runtime_insertBySelector_js__WEBPACK_IMPORTED_MODULE_2___default().bind(null, \"head\");\n \noptions.domAPI = (_node_modules_style_loader_dist_runtime_styleDomAPI_js__WEBPACK_IMPORTED_MODULE_1___default());\noptions.insertStyleElement = (_node_modules_style_loader_dist_runtime_insertStyleElement_js__WEBPACK_IMPORTED_MODULE_4___default());\n\nvar update = _node_modules_style_loader_dist_runtime_injectStylesIntoStyleTag_js__WEBPACK_IMPORTED_MODULE_0___default()(_node_modules_css_loader_dist_cjs_js_styles_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"], options);\n\n\n\n\n /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_node_modules_css_loader_dist_cjs_js_styles_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"] && _node_modules_css_loader_dist_cjs_js_styles_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals ? _node_modules_css_loader_dist_cjs_js_styles_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals : undefined);\n\n\n//# sourceURL=webpack://javascriptcapstone/./src/styles.css?"); 49 | 50 | /***/ }), 51 | 52 | /***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js": 53 | /*!****************************************************************************!*\ 54 | !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***! 55 | \****************************************************************************/ 56 | /***/ ((module) => { 57 | 58 | eval("\n\nvar stylesInDOM = [];\nfunction getIndexByIdentifier(identifier) {\n var result = -1;\n for (var i = 0; i < stylesInDOM.length; i++) {\n if (stylesInDOM[i].identifier === identifier) {\n result = i;\n break;\n }\n }\n return result;\n}\nfunction modulesToDom(list, options) {\n var idCountMap = {};\n var identifiers = [];\n for (var i = 0; i < list.length; i++) {\n var item = list[i];\n var id = options.base ? item[0] + options.base : item[0];\n var count = idCountMap[id] || 0;\n var identifier = \"\".concat(id, \" \").concat(count);\n idCountMap[id] = count + 1;\n var indexByIdentifier = getIndexByIdentifier(identifier);\n var obj = {\n css: item[1],\n media: item[2],\n sourceMap: item[3],\n supports: item[4],\n layer: item[5]\n };\n if (indexByIdentifier !== -1) {\n stylesInDOM[indexByIdentifier].references++;\n stylesInDOM[indexByIdentifier].updater(obj);\n } else {\n var updater = addElementStyle(obj, options);\n options.byIndex = i;\n stylesInDOM.splice(i, 0, {\n identifier: identifier,\n updater: updater,\n references: 1\n });\n }\n identifiers.push(identifier);\n }\n return identifiers;\n}\nfunction addElementStyle(obj, options) {\n var api = options.domAPI(options);\n api.update(obj);\n var updater = function updater(newObj) {\n if (newObj) {\n if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap && newObj.supports === obj.supports && newObj.layer === obj.layer) {\n return;\n }\n api.update(obj = newObj);\n } else {\n api.remove();\n }\n };\n return updater;\n}\nmodule.exports = function (list, options) {\n options = options || {};\n list = list || [];\n var lastIdentifiers = modulesToDom(list, options);\n return function update(newList) {\n newList = newList || [];\n for (var i = 0; i < lastIdentifiers.length; i++) {\n var identifier = lastIdentifiers[i];\n var index = getIndexByIdentifier(identifier);\n stylesInDOM[index].references--;\n }\n var newLastIdentifiers = modulesToDom(newList, options);\n for (var _i = 0; _i < lastIdentifiers.length; _i++) {\n var _identifier = lastIdentifiers[_i];\n var _index = getIndexByIdentifier(_identifier);\n if (stylesInDOM[_index].references === 0) {\n stylesInDOM[_index].updater();\n stylesInDOM.splice(_index, 1);\n }\n }\n lastIdentifiers = newLastIdentifiers;\n };\n};\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js?"); 59 | 60 | /***/ }), 61 | 62 | /***/ "./node_modules/style-loader/dist/runtime/insertBySelector.js": 63 | /*!********************************************************************!*\ 64 | !*** ./node_modules/style-loader/dist/runtime/insertBySelector.js ***! 65 | \********************************************************************/ 66 | /***/ ((module) => { 67 | 68 | eval("\n\nvar memo = {};\n\n/* istanbul ignore next */\nfunction getTarget(target) {\n if (typeof memo[target] === \"undefined\") {\n var styleTarget = document.querySelector(target);\n\n // Special case to return head of iframe instead of iframe itself\n if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n try {\n // This will throw an exception if access to iframe is blocked\n // due to cross-origin restrictions\n styleTarget = styleTarget.contentDocument.head;\n } catch (e) {\n // istanbul ignore next\n styleTarget = null;\n }\n }\n memo[target] = styleTarget;\n }\n return memo[target];\n}\n\n/* istanbul ignore next */\nfunction insertBySelector(insert, style) {\n var target = getTarget(insert);\n if (!target) {\n throw new Error(\"Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.\");\n }\n target.appendChild(style);\n}\nmodule.exports = insertBySelector;\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/style-loader/dist/runtime/insertBySelector.js?"); 69 | 70 | /***/ }), 71 | 72 | /***/ "./node_modules/style-loader/dist/runtime/insertStyleElement.js": 73 | /*!**********************************************************************!*\ 74 | !*** ./node_modules/style-loader/dist/runtime/insertStyleElement.js ***! 75 | \**********************************************************************/ 76 | /***/ ((module) => { 77 | 78 | eval("\n\n/* istanbul ignore next */\nfunction insertStyleElement(options) {\n var element = document.createElement(\"style\");\n options.setAttributes(element, options.attributes);\n options.insert(element, options.options);\n return element;\n}\nmodule.exports = insertStyleElement;\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/style-loader/dist/runtime/insertStyleElement.js?"); 79 | 80 | /***/ }), 81 | 82 | /***/ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js": 83 | /*!**********************************************************************************!*\ 84 | !*** ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js ***! 85 | \**********************************************************************************/ 86 | /***/ ((module, __unused_webpack_exports, __webpack_require__) => { 87 | 88 | eval("\n\n/* istanbul ignore next */\nfunction setAttributesWithoutAttributes(styleElement) {\n var nonce = true ? __webpack_require__.nc : 0;\n if (nonce) {\n styleElement.setAttribute(\"nonce\", nonce);\n }\n}\nmodule.exports = setAttributesWithoutAttributes;\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js?"); 89 | 90 | /***/ }), 91 | 92 | /***/ "./node_modules/style-loader/dist/runtime/styleDomAPI.js": 93 | /*!***************************************************************!*\ 94 | !*** ./node_modules/style-loader/dist/runtime/styleDomAPI.js ***! 95 | \***************************************************************/ 96 | /***/ ((module) => { 97 | 98 | eval("\n\n/* istanbul ignore next */\nfunction apply(styleElement, options, obj) {\n var css = \"\";\n if (obj.supports) {\n css += \"@supports (\".concat(obj.supports, \") {\");\n }\n if (obj.media) {\n css += \"@media \".concat(obj.media, \" {\");\n }\n var needLayer = typeof obj.layer !== \"undefined\";\n if (needLayer) {\n css += \"@layer\".concat(obj.layer.length > 0 ? \" \".concat(obj.layer) : \"\", \" {\");\n }\n css += obj.css;\n if (needLayer) {\n css += \"}\";\n }\n if (obj.media) {\n css += \"}\";\n }\n if (obj.supports) {\n css += \"}\";\n }\n var sourceMap = obj.sourceMap;\n if (sourceMap && typeof btoa !== \"undefined\") {\n css += \"\\n/*# sourceMappingURL=data:application/json;base64,\".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), \" */\");\n }\n\n // For old IE\n /* istanbul ignore if */\n options.styleTagTransform(css, styleElement, options.options);\n}\nfunction removeStyleElement(styleElement) {\n // istanbul ignore if\n if (styleElement.parentNode === null) {\n return false;\n }\n styleElement.parentNode.removeChild(styleElement);\n}\n\n/* istanbul ignore next */\nfunction domAPI(options) {\n if (typeof document === \"undefined\") {\n return {\n update: function update() {},\n remove: function remove() {}\n };\n }\n var styleElement = options.insertStyleElement(options);\n return {\n update: function update(obj) {\n apply(styleElement, options, obj);\n },\n remove: function remove() {\n removeStyleElement(styleElement);\n }\n };\n}\nmodule.exports = domAPI;\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/style-loader/dist/runtime/styleDomAPI.js?"); 99 | 100 | /***/ }), 101 | 102 | /***/ "./node_modules/style-loader/dist/runtime/styleTagTransform.js": 103 | /*!*********************************************************************!*\ 104 | !*** ./node_modules/style-loader/dist/runtime/styleTagTransform.js ***! 105 | \*********************************************************************/ 106 | /***/ ((module) => { 107 | 108 | eval("\n\n/* istanbul ignore next */\nfunction styleTagTransform(css, styleElement) {\n if (styleElement.styleSheet) {\n styleElement.styleSheet.cssText = css;\n } else {\n while (styleElement.firstChild) {\n styleElement.removeChild(styleElement.firstChild);\n }\n styleElement.appendChild(document.createTextNode(css));\n }\n}\nmodule.exports = styleTagTransform;\n\n//# sourceURL=webpack://javascriptcapstone/./node_modules/style-loader/dist/runtime/styleTagTransform.js?"); 109 | 110 | /***/ }), 111 | 112 | /***/ "./src/Modules/commentsCounter.js": 113 | /*!****************************************!*\ 114 | !*** ./src/Modules/commentsCounter.js ***! 115 | \****************************************/ 116 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 117 | 118 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nconst countComments = () => {\n const comments = document.querySelectorAll('.comment-text');\n return comments.length;\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (countComments);\n\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/commentsCounter.js?"); 119 | 120 | /***/ }), 121 | 122 | /***/ "./src/Modules/commentsPopup.js": 123 | /*!**************************************!*\ 124 | !*** ./src/Modules/commentsPopup.js ***! 125 | \**************************************/ 126 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 127 | 128 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _getItemsDetails_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./getItemsDetails.js */ \"./src/Modules/getItemsDetails.js\");\n/* harmony import */ var _getComments_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./getComments.js */ \"./src/Modules/getComments.js\");\n/* harmony import */ var _sendComment_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sendComment.js */ \"./src/Modules/sendComment.js\");\n/* harmony import */ var _commentsCounter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./commentsCounter.js */ \"./src/Modules/commentsCounter.js\");\n\n\n\n\n\nconst showCommentsPopup = async (id) => {\n const details = await (0,_getItemsDetails_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(id);\n const appId = 'k513WvYOj4wUaRdaeuNF';\n\n const popup = document.createElement('div');\n popup.id = 'commentsPopup';\n popup.innerHTML = `\n

${details.strMeal}

\n \"${details.strMeal}\"\n

${details.strInstructions}

\n
\n

Add a comment

\n
\n
\n \n
\n
\n \n
\n \n
\n \n`;\n\n document.body.appendChild(popup);\n\n const commentsContainer = popup.querySelector('#commentsContainer');\n\n // Create a new element to display the comment count\n const commentsCountElement = document.createElement('p');\n commentsCountElement.id = 'commentsCount';\n commentsCountElement.classList.add('comments-count');\n\n popup.insertBefore(commentsCountElement, commentsContainer);\n\n const updateComments = async () => {\n const comments = await (0,_getComments_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(appId, id);\n if (!Array.isArray(comments)) {\n // This block it's designed to handle the empty data in comments\n } else {\n commentsContainer.innerHTML = '';\n comments.forEach((comment) => {\n const commentElement = document.createElement('p');\n commentElement.textContent = `${comment.creation_date} - ${comment.username}: ${comment.comment}`;\n commentElement.classList.add('comment-text');\n commentsContainer.appendChild(commentElement);\n });\n // Update the comments count after updating the comments\n commentsCountElement.textContent = `Comments: ${(0,_commentsCounter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])()}`;\n }\n };\n\n await updateComments();\n\n const form = popup.querySelector('#commentForm');\n form.addEventListener('submit', async (event) => {\n const usernameInput = popup.querySelector('#nameInput');\n const commentInput = popup.querySelector('#commentInput');\n\n event.preventDefault();\n\n const username = usernameInput.value;\n const comment = commentInput.value;\n\n await (0,_sendComment_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(appId, id, username, comment);\n await updateComments(); // Update the comments (and the count) after submitting a comment\n\n // Clear the input fields after the comment has been sent and comments have been updated\n usernameInput.value = '';\n commentInput.value = '';\n });\n\n popup.querySelector('.closeButton').addEventListener('click', () => {\n document.body.removeChild(popup);\n });\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (showCommentsPopup);\n\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/commentsPopup.js?"); 129 | 130 | /***/ }), 131 | 132 | /***/ "./src/Modules/errorHandler.js": 133 | /*!*************************************!*\ 134 | !*** ./src/Modules/errorHandler.js ***! 135 | \*************************************/ 136 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 137 | 138 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nconst handleFetchError = (error) => {\n const errorMessage = document.getElementById('error-message');\n if (errorMessage) {\n errorMessage.innerHTML = `${error.message}`;\n }\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (handleFetchError);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/errorHandler.js?"); 139 | 140 | /***/ }), 141 | 142 | /***/ "./src/Modules/getComments.js": 143 | /*!************************************!*\ 144 | !*** ./src/Modules/getComments.js ***! 145 | \************************************/ 146 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 147 | 148 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nconst getComments = async (appId, id) => {\n try {\n const response = await fetch(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/${appId}/comments?item_id=${id}`);\n const data = await response.json();\n return data;\n } catch (error) {\n return error;\n }\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getComments);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/getComments.js?"); 149 | 150 | /***/ }), 151 | 152 | /***/ "./src/Modules/getItems.js": 153 | /*!*********************************!*\ 154 | !*** ./src/Modules/getItems.js ***! 155 | \*********************************/ 156 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 157 | 158 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _commentsPopup_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./commentsPopup.js */ \"./src/Modules/commentsPopup.js\");\n/* harmony import */ var _errorHandler_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./errorHandler.js */ \"./src/Modules/errorHandler.js\");\n/* harmony import */ var _likes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./likes.js */ \"./src/Modules/likes.js\");\n/* harmony import */ var _itemCounter_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./itemCounter.js */ \"./src/Modules/itemCounter.js\");\n\n\n\n\n\nconst container = document.querySelector('#itemsContainer');\n\nconst displayItems = (dataMeals) => {\n dataMeals.forEach(async (meals) => {\n const numberOfLikes = await (0,_likes_js__WEBPACK_IMPORTED_MODULE_2__.getLikes)();\n let likes = 0;\n numberOfLikes.forEach((elem) => {\n if (elem.item_id === meals.idMeal) {\n likes = elem.likes;\n }\n });\n const mainDiv = document.createElement('div');\n mainDiv.className = 'dflex container';\n mainDiv.innerHTML = `\n
\n \"${meals.strMealThumb}\"\n
\n

${meals.strMeal}

\n
\n ${likes} likes\n \n
\n
\n \n
\n `;\n\n mainDiv.querySelectorAll('#comments').forEach((commentsButton) => {\n commentsButton.addEventListener('click', async () => {\n await (0,_commentsPopup_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])(meals.idMeal).catch(_errorHandler_js__WEBPACK_IMPORTED_MODULE_1__[\"default\"]);\n });\n });\n\n mainDiv.querySelector('#likes').addEventListener('click', async (event) => {\n const id = event.target.className;\n await (0,_likes_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])(id);\n const updateLikes = mainDiv.querySelector('#likesNumber');\n await (0,_likes_js__WEBPACK_IMPORTED_MODULE_2__.updateText)(meals.idMeal, updateLikes);\n });\n\n container.appendChild(mainDiv);\n });\n};\n\nconst getItems = async () => {\n const request = await fetch('https://themealdb.com/api/json/v1/1/filter.php?c=Vegetarian');\n const data = await request.json();\n displayItems(data.meals);\n (0,_itemCounter_js__WEBPACK_IMPORTED_MODULE_3__[\"default\"])(data.meals.length);\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getItems);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/getItems.js?"); 159 | 160 | /***/ }), 161 | 162 | /***/ "./src/Modules/getItemsDetails.js": 163 | /*!****************************************!*\ 164 | !*** ./src/Modules/getItemsDetails.js ***! 165 | \****************************************/ 166 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 167 | 168 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nconst getItemDetails = async (id) => {\n const request = await fetch(`https://www.themealdb.com/api/json/v1/1/lookup.php?i=${id}`);\n const data = await request.json();\n return data.meals[0];\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (getItemDetails);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/getItemsDetails.js?"); 169 | 170 | /***/ }), 171 | 172 | /***/ "./src/Modules/itemCounter.js": 173 | /*!************************************!*\ 174 | !*** ./src/Modules/itemCounter.js ***! 175 | \************************************/ 176 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 177 | 178 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nconst homeItemCounter = (containerItems) => {\n const hometitle = document.querySelector('#mainTitle');\n hometitle.textContent = `${containerItems} Vegetarian Recipes`;\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (homeItemCounter);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/itemCounter.js?"); 179 | 180 | /***/ }), 181 | 182 | /***/ "./src/Modules/likes.js": 183 | /*!******************************!*\ 184 | !*** ./src/Modules/likes.js ***! 185 | \******************************/ 186 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 187 | 188 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__),\n/* harmony export */ getLikes: () => (/* binding */ getLikes),\n/* harmony export */ updateText: () => (/* binding */ updateText)\n/* harmony export */ });\nconst postLikes = async (id) => {\n const sendData = await fetch('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/k513WvYOj4wUaRdaeuNF/likes/', {\n method: 'POST',\n headers: {\n 'Content-type': 'application/json; charset=UTF-8',\n },\n body: JSON.stringify({\n item_id: id,\n }),\n });\n const result = await sendData.text();\n return result;\n};\n\nconst getLikes = async () => {\n const requestLikes = await fetch('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/k513WvYOj4wUaRdaeuNF/likes/');\n const dataLikes = await requestLikes.json();\n return dataLikes;\n};\n\nconst updateText = async (idmeal, span) => {\n const numberOfLikes = await getLikes();\n let likes = 0;\n numberOfLikes.forEach((elem) => {\n if (elem.item_id === idmeal) {\n likes = elem.likes;\n }\n });\n span.textContent = `${likes} likes`;\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (postLikes);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/likes.js?"); 189 | 190 | /***/ }), 191 | 192 | /***/ "./src/Modules/sendComment.js": 193 | /*!************************************!*\ 194 | !*** ./src/Modules/sendComment.js ***! 195 | \************************************/ 196 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 197 | 198 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\nconst sendComment = async (appId, id, username1, comment1) => {\n const response = await fetch(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/${appId}/comments`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n item_id: id,\n username: username1,\n comment: comment1,\n }),\n });\n\n if (!response.ok) {\n throw new Error('Error sending the comment');\n }\n};\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sendComment);\n\n//# sourceURL=webpack://javascriptcapstone/./src/Modules/sendComment.js?"); 199 | 200 | /***/ }), 201 | 202 | /***/ "./src/index.js": 203 | /*!**********************!*\ 204 | !*** ./src/index.js ***! 205 | \**********************/ 206 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { 207 | 208 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _styles_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./styles.css */ \"./src/styles.css\");\n/* harmony import */ var _images_VegetarianRestauratLogo_png__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./images/VegetarianRestauratLogo.png */ \"./src/images/VegetarianRestauratLogo.png\");\n/* harmony import */ var _Modules_getItems_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Modules/getItems.js */ \"./src/Modules/getItems.js\");\n\n\n\n\ndocument.querySelector('#logo').src = _images_VegetarianRestauratLogo_png__WEBPACK_IMPORTED_MODULE_1__;\n\nwindow.addEventListener('load', () => {\n (0,_Modules_getItems_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"])();\n});\n\n\n//# sourceURL=webpack://javascriptcapstone/./src/index.js?"); 209 | 210 | /***/ }), 211 | 212 | /***/ "./src/images/VegetarianRestauratLogo.png": 213 | /*!************************************************!*\ 214 | !*** ./src/images/VegetarianRestauratLogo.png ***! 215 | \************************************************/ 216 | /***/ ((module, __unused_webpack_exports, __webpack_require__) => { 217 | 218 | eval("module.exports = __webpack_require__.p + \"b3909570c94cc41b9906.png\";\n\n//# sourceURL=webpack://javascriptcapstone/./src/images/VegetarianRestauratLogo.png?"); 219 | 220 | /***/ }) 221 | 222 | }, 223 | /******/ __webpack_require__ => { // webpackRuntimeModules 224 | /******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId)) 225 | /******/ var __webpack_exports__ = (__webpack_exec__("./src/index.js")); 226 | /******/ } 227 | ]); --------------------------------------------------------------------------------