├── .gitignore
├── intro.png
├── photo.png
├── src
├── assets
│ ├── logo.png
│ └── restau.png
├── modules
│ ├── counter.test.js
│ └── functions.js
├── index.html
├── index.js
└── style.css
├── babel.config.js
├── dist
├── assets
│ └── logo-a8be307ad975a70883e3.png
├── index.html
└── main.js
├── .hintrc
├── .stylelintrc.json
├── .eslintrc.json
├── webpack.config.js
├── LICENSE
├── package.json
├── .github
└── workflows
│ └── linters.yml
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | usefulCommands.txt
4 |
5 | coverage
6 |
--------------------------------------------------------------------------------
/intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/momo-87/JS-capstone-project/HEAD/intro.png
--------------------------------------------------------------------------------
/photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/momo-87/JS-capstone-project/HEAD/photo.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/momo-87/JS-capstone-project/HEAD/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/restau.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/momo-87/JS-capstone-project/HEAD/src/assets/restau.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [['@babel/preset-env', { targets: { node: 'current' } }]],
3 | };
--------------------------------------------------------------------------------
/dist/assets/logo-a8be307ad975a70883e3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/momo-87/JS-capstone-project/HEAD/dist/assets/logo-a8be307ad975a70883e3.png
--------------------------------------------------------------------------------
/.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 | }
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["stylelint-config-standard"],
3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"],
4 | "rules": {
5 | "at-rule-no-unknown": null,
6 | "scss/at-rule-no-unknown": [
7 | true,
8 | {
9 | "ignoreAtRules": [
10 | "tailwind",
11 | "apply",
12 | "variants",
13 | "responsive",
14 | "screen"
15 | ]
16 | }
17 | ]
18 | },
19 | "csstree/validator": true,
20 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css"]
21 | }
22 |
--------------------------------------------------------------------------------
/.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 | "max-classes-per-file": 0,
15 | "no-shadow": "off",
16 | "no-param-reassign": "off",
17 | "eol-last": "off",
18 | "import/extensions": [ 1, {
19 | "js": "always", "json": "always"
20 | }]
21 | },
22 | "ignorePatterns": [
23 | "dist/",
24 | "build/"
25 | ]
26 | }
--------------------------------------------------------------------------------
/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: 'main.js',
17 | path: path.resolve(__dirname, 'dist'),
18 | clean: true,
19 | },
20 | module: {
21 | rules: [
22 | {
23 | test: /\.css$/i,
24 | use: ['style-loader', 'css-loader'],
25 | },
26 | {
27 | test: /\.html$/i,
28 | use: 'html-loader',
29 | },
30 | {
31 | test: /\.(png|jpg|gif|svg|eot|ttf|woff)$/i,
32 | type: 'asset/resource',
33 | generator: {
34 | filename: 'assets/[name]-[hash][ext]',
35 | },
36 | },
37 | ],
38 | },
39 | };
--------------------------------------------------------------------------------
/src/modules/counter.test.js:
--------------------------------------------------------------------------------
1 | // import the counter function
2 | import { counter } from './functions.js';
3 |
4 | const MOCK_DATA = {
5 | meals:
6 | [
7 | { idMeal: 1, meal: 'Eru', ingredients: 'ingred1, ingred2, ingred3' },
8 | { idMeal: 2, meal: 'Ndolès', ingredients: 'ingred1, ingred2, ingred3' },
9 | { idMeal: 3, meal: 'Achu', ingredients: 'ingred1, ingred2, ingred3' },
10 | { idMeal: 4, meal: 'Koki', ingredients: 'ingred1, ingred2, ingred3' },
11 | { idMeal: 5, meal: 'Okok', ingredients: 'ingred1, ingred2, ingred3' },
12 | ],
13 | };
14 | const MOCK_NB_OF_ITEMS = MOCK_DATA.meals.length;
15 | // Mock the fetch call
16 | global.fetch = jest.fn(() => Promise.resolve({
17 | json: () => Promise.resolve(MOCK_DATA),
18 | }));
19 |
20 | describe('Testing counter function', () => {
21 | test('The correct number of items should be returned', async () => {
22 | const nbOfItems = await counter();
23 | expect(fetch).toHaveBeenCalledTimes(1);
24 | expect(nbOfItems).toBe(MOCK_NB_OF_ITEMS);
25 | });
26 | });
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | API-Perso
9 |
10 |
11 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Christian Romuald MOMO TONFACK
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 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | API-Perso
11 |
12 |
13 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "repository": {
3 | "url": "https://github.com/momo-87/JS-capstone-project.git"
4 | },
5 | "name": "js-capstone-project",
6 | "version": "1.0.0",
7 | "description": "",
8 | "private": true,
9 | "scripts": {
10 | "test": "jest --coverage",
11 | "build": "webpack",
12 | "start": "webpack serve --open",
13 | "predeploy": "npm run build",
14 | "deploy": "gh-pages -d dist"
15 | },
16 | "keywords": [],
17 | "author": "",
18 | "license": "ISC",
19 | "devDependencies": {
20 | "@babel/core": "^7.21.8",
21 | "@babel/preset-env": "^7.21.5",
22 | "@types/jest": "^29.5.1",
23 | "babel-eslint": "^10.1.0",
24 | "babel-jest": "^29.5.0",
25 | "css-loader": "^6.7.4",
26 | "eslint": "^7.32.0",
27 | "eslint-config-airbnb-base": "^14.2.1",
28 | "eslint-plugin-import": "^2.27.5",
29 | "gh-pages": "^5.0.0",
30 | "hint": "^7.1.8",
31 | "html-loader": "^4.2.0",
32 | "html-webpack-plugin": "^5.5.1",
33 | "jest": "^29.5.0",
34 | "style-loader": "^3.3.3",
35 | "stylelint": "^13.13.1",
36 | "stylelint-config-standard": "^21.0.0",
37 | "stylelint-csstree-validator": "^1.9.0",
38 | "stylelint-scss": "^3.21.0",
39 | "ts-jest": "^29.1.0",
40 | "typescript": "^5.0.4",
41 | "webpack": "^5.83.1",
42 | "webpack-cli": "^5.1.1",
43 | "webpack-dev-server": "^4.15.0"
44 | },
45 | "dependencies": {
46 | "axios": "^1.4.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/.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/index.js:
--------------------------------------------------------------------------------
1 | // import style from style.css file (required)
2 | import './style.css';
3 |
4 | // import the required functions from module
5 | import {
6 | getMealData, populatedishes, addLike, getLikesData, diplayLikes, counter, diplayNumberOfItems,
7 | PopupContent, errorMsg, addComment, getCommentData, populateComments, commentcounter,
8 | diplayNumberOfComments,
9 | } from './modules/functions.js';
10 |
11 | // Getting data from the theMealDB API
12 | const mealData = await getMealData();
13 |
14 | // Getting data from the Involvement API function
15 | const likesData = await getLikesData();
16 |
17 | // Populating items in the home page
18 | populatedishes(mealData);
19 |
20 | // Getting and diplaying the number of items
21 | const nbOfItems = await counter();
22 | diplayNumberOfItems(nbOfItems);
23 |
24 | // Diplaying likes data in the home page
25 | mealData.forEach((element) => {
26 | diplayLikes(likesData, `M${element.idMeal}`);
27 | });
28 |
29 | const foodListSection = document.querySelector('.food-list');
30 | // Add event listener to the like icon and open comment button
31 | foodListSection.addEventListener('click', async (e) => {
32 | e.preventDefault();
33 | if (e.target && e.target.matches('i.heart')) {
34 | const targetId = e.target.id;
35 | await addLike(targetId);
36 | const likesData = await getLikesData();
37 | diplayLikes(likesData, targetId);
38 | } else if (e.target && e.target.matches('button.comment')) {
39 | const targetId = e.target.id;
40 | const idMeal = targetId.replace('CBtn', '');
41 | PopupContent(mealData, idMeal);
42 |
43 | // We need to use the prefix M because we initially used it to post likes in the API
44 | const itemId = targetId.replace('CBtn', 'M');
45 |
46 | // Getting and displaying the number of comments
47 | const nbComments = await commentcounter(itemId);
48 | diplayNumberOfComments(nbComments);
49 |
50 | // Get comment the corresponding comment data from the API
51 | const commentData = await getCommentData(itemId);
52 |
53 | // Populate comment data in the popup window after checking that data is not empty
54 | if (commentData.length) {
55 | populateComments(commentData);
56 | }
57 |
58 | // Add event listener to the submit comment button
59 | const submitCommentBtn = document.querySelector('button.submit-comment');
60 | submitCommentBtn.addEventListener('click', async (e) => {
61 | e.preventDefault();
62 | const userName = document.querySelector('input.user-name').value;
63 | const insights = document.querySelector('textarea.insights').value;
64 | if (!userName || !insights) {
65 | errorMsg(userName, insights);
66 | }
67 | await addComment(itemId, userName, insights);
68 | document.querySelector('input.user-name').value = '';
69 | document.querySelector('textarea.insights').value = '';
70 |
71 | // Clean the board
72 | document.querySelector('div.comments-box').innerHTML = '';
73 | // Gettint the updated comment data from the API and populate
74 | const commentData = await getCommentData(itemId);
75 | // Repopulate using the updated comment data
76 | populateComments(commentData);
77 |
78 | // Getting and displaying the number of comments
79 | const nbComments = await commentcounter(itemId);
80 | diplayNumberOfComments(nbComments);
81 | });
82 | }
83 | });
84 |
85 | // Add event listener to close popup icon
86 | const popupWindow = document.querySelector('.popup-window');
87 | popupWindow.addEventListener('click', (e) => {
88 | if (e.target && e.target.matches('i.close-popup')) {
89 | popupWindow.innerHTML = '';
90 | }
91 | });
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
API-based Webapp (Resraurant)
8 |
9 |
10 |
11 |
12 |
13 | # 📗 Table of Contents
14 |
15 | - [📖 About the Project](#about-project)
16 | - [🛠 Built With](#built-with)
17 | - [Tech Stack](#tech-stack)
18 | - [Key Features](#key-features)
19 | - [🚀 Live Demo](#live-demo)
20 | - [💻 Getting Started](#getting-started)
21 | - [Setup](#setup)
22 | - [Prerequisites](#prerequisites)
23 | - [Install](#install)
24 | - [Usage](#usage)
25 | - [Run tests](#run-tests)
26 | - [Deployment](#triangular_flag_on_post-deployment)
27 | - [👥 Authors](#authors)
28 | - [🔭 Future Features](#future-features)
29 | - [🤝 Contributing](#contributing)
30 | - [⭐️ Show your support](#support)
31 | - [🙏 Acknowledgements](#acknowledgements)
32 | - [❓ FAQ (OPTIONAL)](#faq)
33 | - [📝 License](#license)
34 |
35 |
36 |
37 | # 📖 API-based Webapp(Restaurant)
38 | > The Restaurant web application is based on an external API. We used JavaScript to make the websites dynamic and build a basic single-page app. The application has three user interfaces: A home page showing a list of dishes that a user can "like", a popup window with more data about a dish that a user can leave a comment and a popup window with more data about a dish that a user can use to reserve it for some time.
39 |
40 |
41 | ## 🛠 Built With
42 | - JavaScript
43 | - HTML
44 | - CSS
45 | - Webpack
46 | - Jest for testing
47 |
48 | ### Tech Stack
49 |
50 | Client
51 |
58 |
59 |
60 | API
61 |
65 |
66 |
67 |
68 | ### Key Features
69 | - A home page showing a list of items that a user can "like."
70 | - A popup window with more data about an item that user can use to comment on it.
71 | (back to top )
72 |
73 | ## 🚀 Live Demo
74 | >[Live Demo](https://momo-87.github.io/JS-capstone-project/)
75 | (back to top )
76 |
77 |
78 | ## 💻 Getting Started
79 | >To get a local copy up and running, follow these steps.
80 |
81 | ### Prerequisites
82 | 1. Web browser.
83 | 2. Code Editor.
84 | 3. Git-smc.
85 |
86 | ### Setup
87 | > To clone this repository to your desired folder, run this command:
88 | ```sh
89 | cd my-folder
90 | git clone https://github.com/momo-87/JS-capstone-project.git
91 | ```
92 |
93 | ### Install
94 | > Run this command:
95 | ```sh
96 | cd my-project
97 | npm install
98 | ```
99 |
100 | ### Usage
101 | > To run the project, open index.html from dist folder using live server extension.
102 |
103 | ### Run tests
104 | > Coming soon
105 |
106 | ### Deployment
107 | > Published
108 | (back to top )
109 |
110 |
111 | ## 👥 Author
112 | 👤 Christian Romuald MOMO TONFACK
113 | - GitHub: [@githubhandle](https://github.com/Momo-87)
114 | - Twitter: [@twitterhandle](https://twitter.com/Momo_yde)
115 | - LinkedIn: [LinkedIn](https://www.linkedin.com/in/christian-momo/)
116 | (back to top )
117 |
118 |
119 | ## 🔭 Future Features
120 | - [ ] A popup window with more data about an item that user can use to reserve it for a period of time.
121 | - [ ] Reservation popup window
122 | (back to top )
123 |
124 | ## 🤝 Contributing
125 | > Contributions, issues, and feature requests are welcome!
126 | Feel free to check the [issues page](https://github.com/momo-87/JS-capstone-project/issues).
127 | (back to top )
128 |
129 |
130 | ## ⭐️ Show your support
131 | >If you like this project just give it a star ⭐️.
132 | (back to top )
133 |
134 | ## 🙏 Acknowledgments
135 | >I would like to thank Microverse comnunity for their supports.
136 | (back to top )
137 |
138 | ## 📝 License
139 | >This project is [MIT](./LICENSE) licensed.
140 | (back to top )
141 |
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | padding: 0;
4 | margin: 0;
5 | color: #2f2c28;
6 | }
7 |
8 | body {
9 | background-color: #d3d3d3;
10 | font-size: 1rem;
11 | }
12 |
13 | .flex-column {
14 | display: flex;
15 | flex-direction: column;
16 | }
17 |
18 | .flex-row {
19 | display: flex;
20 | flex-direction: row;
21 | }
22 |
23 | ul {
24 | list-style: none;
25 | }
26 |
27 | button:hover,
28 | .heart:hover {
29 | cursor: pointer;
30 | }
31 |
32 | @media only screen and (min-width: 320px) {
33 | /* Styling Home page start */
34 | header {
35 | width: 100%;
36 | justify-content: space-between;
37 | align-items: center;
38 | padding-top: 10px;
39 | position: fixed;
40 | background-color: #8b4513;
41 | }
42 |
43 | .logo-box {
44 | width: 30%;
45 | }
46 |
47 | .logo {
48 | width: 100%;
49 | }
50 |
51 | ul {
52 | width: 65%;
53 | column-gap: 5%;
54 | }
55 |
56 | ul li:nth-child(1) {
57 | text-decoration: underline;
58 | color: #ffffed;
59 | }
60 |
61 | ul li a {
62 | color: #2beb83;
63 | text-decoration: none;
64 | }
65 |
66 | section.food-list {
67 | width: 100%;
68 | padding-top: 60px;
69 | gap: 10px;
70 | }
71 |
72 | .food-card {
73 | width: 90%;
74 | justify-content: center;
75 | margin: 0 5%;
76 | row-gap: 30px;
77 | }
78 |
79 | .image-box {
80 | width: 100%;
81 | }
82 |
83 | .image-box img {
84 | width: 100%;
85 | border-radius: 15px;
86 | }
87 |
88 | .image-box img:hover {
89 | width: 103%;
90 | border-radius: 15px;
91 | }
92 |
93 | .meal-title-and-interactions-box {
94 | margin-top: -30px;
95 | justify-content: space-between;
96 | }
97 |
98 | .meal-title-and-interactions-box h2 {
99 | font-size: 1.2rem;
100 | width: 67%;
101 | }
102 |
103 | .meal-title-and-interactions-box span {
104 | font-size: 1.1rem;
105 | color: #8b4513;
106 | }
107 |
108 | .buttons-box {
109 | justify-content: space-between;
110 | margin-top: -20px;
111 | }
112 |
113 | button {
114 | width: 30%;
115 | }
116 |
117 | /* Styling Home page end */
118 |
119 | /* Styling popup window start */
120 | .popup-window {
121 | width: 100%;
122 | position: fixed;
123 | top: 0;
124 | }
125 |
126 | .popup-wrapper {
127 | width: 95%;
128 | position: fixed;
129 | top: 10px;
130 | height: 98%;
131 | background-color: #d3d3d3;
132 | align-items: center;
133 | margin: 0 2.5% 0 2.5%;
134 | border-radius: 20px;
135 | z-index: 10;
136 | overflow-y: auto;
137 | padding-bottom: 20px;
138 | border: 2px solid #cd853f;
139 | }
140 |
141 | i.close-popup:hover {
142 | cursor: pointer;
143 | }
144 |
145 | .popup-wrapper h2 {
146 | font-size: 1.2rem;
147 | }
148 |
149 | h2.add-comment {
150 | margin-top: 30px;
151 | }
152 |
153 | .popup-window i {
154 | margin: 15px 10% 15px 90%;
155 | }
156 |
157 | .meal-section {
158 | width: 100%;
159 | align-items: center;
160 | }
161 |
162 | .popup-image-box {
163 | width: 90%;
164 | align-items: center;
165 | }
166 |
167 | img.popup-img {
168 | width: 100%;
169 | border-radius: 15px;
170 | }
171 |
172 | h2.meal-name {
173 | margin-top: 10px;
174 | }
175 |
176 | .meal-infos {
177 | display: grid;
178 | grid-template-columns: auto auto;
179 | width: 90%;
180 | margin-top: 10px;
181 | }
182 |
183 | .meal-infos span {
184 | font-weight: bolder;
185 | }
186 |
187 | .instruction-box {
188 | grid-column: 1 / span 2;
189 | margin-top: 10px;
190 | text-align: justify;
191 | }
192 |
193 | .comments-section {
194 | display: flex;
195 | margin-top: 30px;
196 | width: 90%;
197 | justify-content: center;
198 | }
199 |
200 | .comments-box p {
201 | font-size: 0.9rem;
202 | margin-top: 5px;
203 | font-style: italic;
204 | }
205 |
206 | .add-comment-section {
207 | width: 100%;
208 | align-items: center;
209 | }
210 |
211 | form.add-comment {
212 | width: 90%;
213 | row-gap: 5px;
214 | }
215 |
216 | input.user-name {
217 | height: 25px;
218 | }
219 |
220 | textarea.insights {
221 | height: 60px;
222 | }
223 |
224 | input.user-name:focus,
225 | textarea.insights:focus {
226 | outline-color: #8b4513;
227 | padding: 3%;
228 | }
229 |
230 | ::placeholder {
231 | padding-left: 2%;
232 | }
233 |
234 | /* Styling popup window end */
235 | }
236 |
237 | @media only screen and (min-width: 375px) {
238 | header ul {
239 | width: 60%;
240 | column-gap: 5%;
241 | margin-left: 15%;
242 | }
243 |
244 | .meal-title-and-interactions-box h2 {
245 | width: 70%;
246 | }
247 | }
248 |
249 | @media only screen and (min-width: 425px) {
250 | header ul {
251 | width: 60%;
252 | column-gap: 5%;
253 | margin-left: 18%;
254 | }
255 |
256 | section.food-list {
257 | padding-top: 80px;
258 | }
259 |
260 | .meal-title-and-interactions-box h2 {
261 | width: 75%;
262 | }
263 |
264 | button {
265 | width: 20%;
266 | }
267 | }
268 |
269 | @media only screen and (min-width: 768px) {
270 | .logo {
271 | width: 90%;
272 | }
273 |
274 | header ul {
275 | column-gap: 5%;
276 | margin-left: 40%;
277 | }
278 |
279 | section.food-list {
280 | width: 100%;
281 | padding-top: 100px;
282 | display: grid;
283 | grid-template-columns: 49% 49%;
284 | grid-template-columns: auto auto;
285 | }
286 |
287 | button {
288 | width: 25%;
289 | }
290 |
291 | /* Styling popup window start */
292 | button.submit-comment {
293 | width: 12%;
294 | }
295 |
296 | /* Styling popup window end */
297 | }
298 |
299 | @media only screen and (min-width: 1024px) {
300 | section.food-list {
301 | width: 100%;
302 | padding-top: 100px;
303 | display: grid;
304 | grid-template-columns: 35% 35% 35%;
305 | grid-template-columns: auto auto auto;
306 | }
307 |
308 | /* Styling popup window start */
309 | .meal-section {
310 | width: 95%;
311 | flex-direction: row;
312 | column-gap: 2%;
313 | }
314 |
315 | .popup-image-box {
316 | width: 40%;
317 | }
318 |
319 | .add-comment-section {
320 | width: 70%;
321 | }
322 |
323 | /* Styling popup window end */
324 | }
325 |
326 | @media only screen and (min-width: 1440px) {
327 | section.food-list {
328 | width: 80%;
329 | margin: 0 10%;
330 | }
331 |
332 | .logo-box {
333 | width: 20%;
334 | }
335 |
336 | .logo {
337 | width: 100%;
338 | }
339 |
340 | header ul {
341 | column-gap: 5%;
342 | margin-left: 50%;
343 | }
344 | }
345 |
--------------------------------------------------------------------------------
/src/modules/functions.js:
--------------------------------------------------------------------------------
1 | // Getting data from the theMealDB API function
2 | export const getMealData = async () => {
3 | const request = new Request('https://themealdb.com/api/json/v1/1/search.php?f=c');
4 | const response = await fetch(request);
5 | const data = await response.json();
6 | return data.meals;
7 | };
8 |
9 | // Populating items in the DOM function
10 | export const populatedishes = async (mealData) => {
11 | const foodListSection = document.querySelector('.food-list');
12 | mealData.forEach((element) => {
13 | const foodCard = document.createElement('div');
14 | foodCard.classList.add('food-card', 'flex-column');
15 | foodCard.innerHTML = `
16 |
17 |
${element.strMeal}
18 | 0 likes
19 |
20 |
21 |
22 | Reservation
23 |
24 |
25 | `;
26 | foodListSection.appendChild(foodCard);
27 | });
28 | };
29 |
30 | // Create new app function
31 | export const newApp = async () => {
32 | const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/');
33 | await fetch(request, {
34 | method: 'POST',
35 | });
36 | };
37 |
38 | // Add likes to API function
39 | export const addLike = async (targetId) => {
40 | const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/likes/');
41 | await fetch(request, {
42 | headers: {
43 | 'Content-type': 'application/json',
44 | },
45 | method: 'POST',
46 | body: JSON.stringify({
47 | item_id: targetId,
48 | }),
49 | });
50 | };
51 |
52 | // Getting likes data from the Involvement API function
53 | export const getLikesData = async () => {
54 | const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/likes/');
55 | const response = await fetch(request);
56 | const data = await response.json();
57 | return data;
58 | };
59 |
60 | // Diplaying likes data in the home page function
61 | export const diplayLikes = async (likesData, itemId) => {
62 | likesData.forEach((element) => {
63 | if (element.item_id === itemId) {
64 | // Replace M from the i tag id by L for obtaining the span id
65 | const likeId = itemId.replace('M', 'L');
66 | const span = document.querySelector(`#${likeId}`);
67 | span.textContent = `${element.likes} likes`;
68 | }
69 | });
70 | };
71 |
72 | // counter meals items function
73 | export const counter = async () => {
74 | const request = new Request('https://themealdb.com/api/json/v1/1/search.php?f=c');
75 | const response = await fetch(request);
76 | const data = await response.json();
77 | return data.meals.length;
78 | };
79 |
80 | // Display the number of meal on the home page function
81 | export const diplayNumberOfItems = (nbOfItems) => {
82 | const li = document.querySelector('li.number-of-items');
83 | li.textContent = `Meals(${nbOfItems})`;
84 | };
85 |
86 | // Populating popup window content function
87 | export const PopupContent = (data, id) => {
88 | const popupBox = document.querySelector('.popup-window');
89 | data.forEach((element) => {
90 | if (element.idMeal === id) {
91 | popupBox.innerHTML = `
92 |
93 |
94 |
95 |
96 |
${element.strMeal}
97 |
98 |
99 |
Area: ${element.strArea}
100 |
Category: ${element.strCategory}
101 |
Instructions: ${element.strInstructions}
102 |
103 |
104 |
105 |
109 |
110 |
122 |
123 | `;
124 | }
125 | });
126 | };
127 |
128 | // Throw error message function
129 | export const errorMsg = (userName, insights) => {
130 | const p1 = document.querySelector('p.user-name-error');
131 | const p2 = document.querySelector('p.insights-error');
132 | if (!userName) {
133 | p1.innerHTML = 'required field';
134 | p1.style.color = 'red';
135 | p1.style.fontSize = '0.9rem';
136 | } else {
137 | p1.innerHTML = '';
138 | }
139 | if (!insights) {
140 | p2.innerHTML = 'required field';
141 | p2.style.color = 'red';
142 | p2.style.fontSize = '0.9rem';
143 | } else {
144 | p2.innerHTML = '';
145 | }
146 | };
147 |
148 | // Add comment to API function
149 | export const addComment = async (id, userName, insights) => {
150 | const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/comments');
151 | await fetch(request, {
152 | headers: {
153 | 'Content-type': 'application/json',
154 | },
155 | method: 'POST',
156 | body: JSON.stringify({
157 | item_id: id,
158 | username: userName,
159 | comment: insights,
160 | }),
161 | });
162 | };
163 |
164 | // Getting comment data from the Involvement API function
165 | export const getCommentData = async (id) => {
166 | const request = new Request(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/comments?item_id=${id}`);
167 | const response = await fetch(request);
168 | const data = await response.json();
169 | return data;
170 | };
171 |
172 | // populating comment data function
173 | export const populateComments = (data) => {
174 | const commentsBox = document.querySelector('div.comments-box');
175 | data.forEach((element) => {
176 | if (element.creation_date && element.username && element.comment) {
177 | const p = document.createElement('p');
178 | p.textContent = `${element.creation_date} ${element.username}: ${element.comment}`;
179 | commentsBox.appendChild(p);
180 | }
181 | });
182 | };
183 |
184 | // counter comment function
185 | export const commentcounter = async (id) => {
186 | const request = new Request(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/comments?item_id=${id}`);
187 | const response = await fetch(request);
188 | const data = await response.json();
189 | // Since some data objects are empty:
190 | let n = 0;
191 | if (data.length) {
192 | data.forEach((element) => {
193 | if (element.creation_date && element.username && element.comment) {
194 | n += 1;
195 | }
196 | });
197 | }
198 | return n;
199 | };
200 |
201 | // Display the number of comment on the popup window function
202 | export const diplayNumberOfComments = (nbOfItems) => {
203 | const h2 = document.querySelector('h2.comment-title');
204 | h2.textContent = `comments (${nbOfItems})`;
205 | };
--------------------------------------------------------------------------------
/dist/main.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 | /***/ "./node_modules/css-loader/dist/cjs.js!./src/style.css":
14 | /*!*************************************************************!*\
15 | !*** ./node_modules/css-loader/dist/cjs.js!./src/style.css ***!
16 | \*************************************************************/
17 | /***/ ((module, __webpack_exports__, __webpack_require__) => {
18 |
19 | 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, \"* {\\r\\n box-sizing: border-box;\\r\\n padding: 0;\\r\\n margin: 0;\\r\\n color: #2f2c28;\\r\\n}\\r\\n\\r\\nbody {\\r\\n background-color: #d3d3d3;\\r\\n font-size: 1rem;\\r\\n}\\r\\n\\r\\n.flex-column {\\r\\n display: flex;\\r\\n flex-direction: column;\\r\\n}\\r\\n\\r\\n.flex-row {\\r\\n display: flex;\\r\\n flex-direction: row;\\r\\n}\\r\\n\\r\\nul {\\r\\n list-style: none;\\r\\n}\\r\\n\\r\\nbutton:hover,\\r\\n.heart:hover {\\r\\n cursor: pointer;\\r\\n}\\r\\n\\r\\n@media only screen and (min-width: 320px) {\\r\\n /* Styling Home page start */\\r\\n header {\\r\\n width: 100%;\\r\\n justify-content: space-between;\\r\\n align-items: center;\\r\\n padding-top: 10px;\\r\\n position: fixed;\\r\\n background-color: #8b4513;\\r\\n }\\r\\n\\r\\n .logo-box {\\r\\n width: 30%;\\r\\n }\\r\\n\\r\\n .logo {\\r\\n width: 100%;\\r\\n }\\r\\n\\r\\n ul {\\r\\n width: 65%;\\r\\n column-gap: 5%;\\r\\n }\\r\\n\\r\\n ul li:nth-child(1) {\\r\\n text-decoration: underline;\\r\\n color: #ffffed;\\r\\n }\\r\\n\\r\\n ul li a {\\r\\n color: #2beb83;\\r\\n text-decoration: none;\\r\\n }\\r\\n\\r\\n section.food-list {\\r\\n width: 100%;\\r\\n padding-top: 60px;\\r\\n gap: 10px;\\r\\n }\\r\\n\\r\\n .food-card {\\r\\n width: 90%;\\r\\n justify-content: center;\\r\\n margin: 0 5%;\\r\\n row-gap: 30px;\\r\\n }\\r\\n\\r\\n .image-box {\\r\\n width: 100%;\\r\\n }\\r\\n\\r\\n .image-box img {\\r\\n width: 100%;\\r\\n border-radius: 15px;\\r\\n }\\r\\n\\r\\n .image-box img:hover {\\r\\n width: 103%;\\r\\n border-radius: 15px;\\r\\n }\\r\\n\\r\\n .meal-title-and-interactions-box {\\r\\n margin-top: -30px;\\r\\n justify-content: space-between;\\r\\n }\\r\\n\\r\\n .meal-title-and-interactions-box h2 {\\r\\n font-size: 1.2rem;\\r\\n width: 67%;\\r\\n }\\r\\n\\r\\n .meal-title-and-interactions-box span {\\r\\n font-size: 1.1rem;\\r\\n color: #8b4513;\\r\\n }\\r\\n\\r\\n .buttons-box {\\r\\n justify-content: space-between;\\r\\n margin-top: -20px;\\r\\n }\\r\\n\\r\\n button {\\r\\n width: 30%;\\r\\n }\\r\\n\\r\\n /* Styling Home page end */\\r\\n\\r\\n /* Styling popup window start */\\r\\n .popup-window {\\r\\n width: 100%;\\r\\n position: fixed;\\r\\n top: 0;\\r\\n }\\r\\n\\r\\n .popup-wrapper {\\r\\n width: 95%;\\r\\n position: fixed;\\r\\n top: 10px;\\r\\n height: 98%;\\r\\n background-color: #d3d3d3;\\r\\n align-items: center;\\r\\n margin: 0 2.5% 0 2.5%;\\r\\n border-radius: 20px;\\r\\n z-index: 10;\\r\\n overflow-y: auto;\\r\\n padding-bottom: 20px;\\r\\n border: 2px solid #cd853f;\\r\\n }\\r\\n\\r\\n i.close-popup:hover {\\r\\n cursor: pointer;\\r\\n }\\r\\n\\r\\n .popup-wrapper h2 {\\r\\n font-size: 1.2rem;\\r\\n }\\r\\n\\r\\n h2.add-comment {\\r\\n margin-top: 30px;\\r\\n }\\r\\n\\r\\n .popup-window i {\\r\\n margin: 15px 10% 15px 90%;\\r\\n }\\r\\n\\r\\n .meal-section {\\r\\n width: 100%;\\r\\n align-items: center;\\r\\n }\\r\\n\\r\\n .popup-image-box {\\r\\n width: 90%;\\r\\n align-items: center;\\r\\n }\\r\\n\\r\\n img.popup-img {\\r\\n width: 100%;\\r\\n border-radius: 15px;\\r\\n }\\r\\n\\r\\n h2.meal-name {\\r\\n margin-top: 10px;\\r\\n }\\r\\n\\r\\n .meal-infos {\\r\\n display: grid;\\r\\n grid-template-columns: auto auto;\\r\\n width: 90%;\\r\\n margin-top: 10px;\\r\\n }\\r\\n\\r\\n .meal-infos span {\\r\\n font-weight: bolder;\\r\\n }\\r\\n\\r\\n .instruction-box {\\r\\n grid-column: 1 / span 2;\\r\\n margin-top: 10px;\\r\\n text-align: justify;\\r\\n }\\r\\n\\r\\n .comments-section {\\r\\n display: flex;\\r\\n margin-top: 30px;\\r\\n width: 90%;\\r\\n justify-content: center;\\r\\n }\\r\\n\\r\\n .comments-box p {\\r\\n font-size: 0.9rem;\\r\\n margin-top: 5px;\\r\\n font-style: italic;\\r\\n }\\r\\n\\r\\n .add-comment-section {\\r\\n width: 100%;\\r\\n align-items: center;\\r\\n }\\r\\n\\r\\n form.add-comment {\\r\\n width: 90%;\\r\\n row-gap: 5px;\\r\\n }\\r\\n\\r\\n input.user-name {\\r\\n height: 25px;\\r\\n }\\r\\n\\r\\n textarea.insights {\\r\\n height: 60px;\\r\\n }\\r\\n\\r\\n input.user-name:focus,\\r\\n textarea.insights:focus {\\r\\n outline-color: #8b4513;\\r\\n padding: 3%;\\r\\n }\\r\\n\\r\\n ::placeholder {\\r\\n padding-left: 2%;\\r\\n }\\r\\n\\r\\n /* Styling popup window end */\\r\\n}\\r\\n\\r\\n@media only screen and (min-width: 375px) {\\r\\n header ul {\\r\\n width: 60%;\\r\\n column-gap: 5%;\\r\\n margin-left: 15%;\\r\\n }\\r\\n\\r\\n .meal-title-and-interactions-box h2 {\\r\\n width: 70%;\\r\\n }\\r\\n}\\r\\n\\r\\n@media only screen and (min-width: 425px) {\\r\\n header ul {\\r\\n width: 60%;\\r\\n column-gap: 5%;\\r\\n margin-left: 18%;\\r\\n }\\r\\n\\r\\n section.food-list {\\r\\n padding-top: 80px;\\r\\n }\\r\\n\\r\\n .meal-title-and-interactions-box h2 {\\r\\n width: 75%;\\r\\n }\\r\\n\\r\\n button {\\r\\n width: 20%;\\r\\n }\\r\\n}\\r\\n\\r\\n@media only screen and (min-width: 768px) {\\r\\n .logo {\\r\\n width: 90%;\\r\\n }\\r\\n\\r\\n header ul {\\r\\n column-gap: 5%;\\r\\n margin-left: 40%;\\r\\n }\\r\\n\\r\\n section.food-list {\\r\\n width: 100%;\\r\\n padding-top: 100px;\\r\\n display: grid;\\r\\n grid-template-columns: 49% 49%;\\r\\n grid-template-columns: auto auto;\\r\\n }\\r\\n\\r\\n button {\\r\\n width: 25%;\\r\\n }\\r\\n\\r\\n /* Styling popup window start */\\r\\n button.submit-comment {\\r\\n width: 12%;\\r\\n }\\r\\n\\r\\n /* Styling popup window end */\\r\\n}\\r\\n\\r\\n@media only screen and (min-width: 1024px) {\\r\\n section.food-list {\\r\\n width: 100%;\\r\\n padding-top: 100px;\\r\\n display: grid;\\r\\n grid-template-columns: 35% 35% 35%;\\r\\n grid-template-columns: auto auto auto;\\r\\n }\\r\\n\\r\\n /* Styling popup window start */\\r\\n .meal-section {\\r\\n width: 95%;\\r\\n flex-direction: row;\\r\\n column-gap: 2%;\\r\\n }\\r\\n\\r\\n .popup-image-box {\\r\\n width: 40%;\\r\\n }\\r\\n\\r\\n .add-comment-section {\\r\\n width: 70%;\\r\\n }\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n /* Styling popup window end */\\r\\n}\\r\\n\\r\\n@media only screen and (min-width: 1440px) {\\r\\n section.food-list {\\r\\n width: 80%;\\r\\n margin: 0 10%;\\r\\n }\\r\\n\\r\\n .logo-box {\\r\\n width: 20%;\\r\\n }\\r\\n\\r\\n .logo {\\r\\n width: 100%;\\r\\n }\\r\\n\\r\\n header ul {\\r\\n column-gap: 5%;\\r\\n margin-left: 50%;\\r\\n }\\r\\n}\\r\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://js-capstone-project/./src/style.css?./node_modules/css-loader/dist/cjs.js");
20 |
21 | /***/ }),
22 |
23 | /***/ "./node_modules/css-loader/dist/runtime/api.js":
24 | /*!*****************************************************!*\
25 | !*** ./node_modules/css-loader/dist/runtime/api.js ***!
26 | \*****************************************************/
27 | /***/ ((module) => {
28 |
29 | 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://js-capstone-project/./node_modules/css-loader/dist/runtime/api.js?");
30 |
31 | /***/ }),
32 |
33 | /***/ "./node_modules/css-loader/dist/runtime/noSourceMaps.js":
34 | /*!**************************************************************!*\
35 | !*** ./node_modules/css-loader/dist/runtime/noSourceMaps.js ***!
36 | \**************************************************************/
37 | /***/ ((module) => {
38 |
39 | eval("\n\nmodule.exports = function (i) {\n return i[1];\n};\n\n//# sourceURL=webpack://js-capstone-project/./node_modules/css-loader/dist/runtime/noSourceMaps.js?");
40 |
41 | /***/ }),
42 |
43 | /***/ "./src/style.css":
44 | /*!***********************!*\
45 | !*** ./src/style.css ***!
46 | \***********************/
47 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
48 |
49 | 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_style_css__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! !!../node_modules/css-loader/dist/cjs.js!./style.css */ \"./node_modules/css-loader/dist/cjs.js!./src/style.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_style_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_style_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"] && _node_modules_css_loader_dist_cjs_js_style_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals ? _node_modules_css_loader_dist_cjs_js_style_css__WEBPACK_IMPORTED_MODULE_6__[\"default\"].locals : undefined);\n\n\n//# sourceURL=webpack://js-capstone-project/./src/style.css?");
50 |
51 | /***/ }),
52 |
53 | /***/ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js":
54 | /*!****************************************************************************!*\
55 | !*** ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js ***!
56 | \****************************************************************************/
57 | /***/ ((module) => {
58 |
59 | 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://js-capstone-project/./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js?");
60 |
61 | /***/ }),
62 |
63 | /***/ "./node_modules/style-loader/dist/runtime/insertBySelector.js":
64 | /*!********************************************************************!*\
65 | !*** ./node_modules/style-loader/dist/runtime/insertBySelector.js ***!
66 | \********************************************************************/
67 | /***/ ((module) => {
68 |
69 | 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://js-capstone-project/./node_modules/style-loader/dist/runtime/insertBySelector.js?");
70 |
71 | /***/ }),
72 |
73 | /***/ "./node_modules/style-loader/dist/runtime/insertStyleElement.js":
74 | /*!**********************************************************************!*\
75 | !*** ./node_modules/style-loader/dist/runtime/insertStyleElement.js ***!
76 | \**********************************************************************/
77 | /***/ ((module) => {
78 |
79 | 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://js-capstone-project/./node_modules/style-loader/dist/runtime/insertStyleElement.js?");
80 |
81 | /***/ }),
82 |
83 | /***/ "./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js":
84 | /*!**********************************************************************************!*\
85 | !*** ./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js ***!
86 | \**********************************************************************************/
87 | /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
88 |
89 | 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://js-capstone-project/./node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js?");
90 |
91 | /***/ }),
92 |
93 | /***/ "./node_modules/style-loader/dist/runtime/styleDomAPI.js":
94 | /*!***************************************************************!*\
95 | !*** ./node_modules/style-loader/dist/runtime/styleDomAPI.js ***!
96 | \***************************************************************/
97 | /***/ ((module) => {
98 |
99 | 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://js-capstone-project/./node_modules/style-loader/dist/runtime/styleDomAPI.js?");
100 |
101 | /***/ }),
102 |
103 | /***/ "./node_modules/style-loader/dist/runtime/styleTagTransform.js":
104 | /*!*********************************************************************!*\
105 | !*** ./node_modules/style-loader/dist/runtime/styleTagTransform.js ***!
106 | \*********************************************************************/
107 | /***/ ((module) => {
108 |
109 | 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://js-capstone-project/./node_modules/style-loader/dist/runtime/styleTagTransform.js?");
110 |
111 | /***/ }),
112 |
113 | /***/ "./src/index.js":
114 | /*!**********************!*\
115 | !*** ./src/index.js ***!
116 | \**********************/
117 | /***/ ((module, __webpack_exports__, __webpack_require__) => {
118 |
119 | eval("__webpack_require__.a(module, async (__webpack_handle_async_dependencies__, __webpack_async_result__) => { try {\n__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./style.css */ \"./src/style.css\");\n/* harmony import */ var _modules_functions_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/functions.js */ \"./src/modules/functions.js\");\n// import style from style.css file (required)\n\n\n// import the required functions from module\n\n\n// Getting data from the theMealDB API\nconst mealData = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.getMealData)();\n\n// Getting data from the Involvement API function\nconst likesData = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.getLikesData)();\n\n// Populating items in the home page\n(0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.populatedishes)(mealData);\n\n// Getting and diplaying the number of items\nconst nbOfItems = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.counter)();\n(0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.diplayNumberOfItems)(nbOfItems);\n\n// Diplaying likes data in the home page\nmealData.forEach((element) => {\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.diplayLikes)(likesData, `M${element.idMeal}`);\n});\n\nconst foodListSection = document.querySelector('.food-list');\n// Add event listener to the like icon and open comment button\nfoodListSection.addEventListener('click', async (e) => {\n e.preventDefault();\n if (e.target && e.target.matches('i.heart')) {\n const targetId = e.target.id;\n await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.addLike)(targetId);\n const likesData = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.getLikesData)();\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.diplayLikes)(likesData, targetId);\n } else if (e.target && e.target.matches('button.comment')) {\n const targetId = e.target.id;\n const idMeal = targetId.replace('CBtn', '');\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.PopupContent)(mealData, idMeal);\n\n // We need to use the prefix M because we initially used it to post likes in the API\n const itemId = targetId.replace('CBtn', 'M');\n\n // Getting and displaying the number of comments\n const nbComments = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.commentcounter)(itemId);\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.diplayNumberOfComments)(nbComments);\n\n // Get comment the corresponding comment data from the API\n const commentData = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.getCommentData)(itemId);\n\n // Populate comment data in the popup window after checking that data is not empty\n if (commentData.length) {\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.populateComments)(commentData);\n }\n\n // Add event listener to the submit comment button\n const submitCommentBtn = document.querySelector('button.submit-comment');\n submitCommentBtn.addEventListener('click', async (e) => {\n e.preventDefault();\n const userName = document.querySelector('input.user-name').value;\n const insights = document.querySelector('textarea.insights').value;\n if (!userName || !insights) {\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.errorMsg)(userName, insights);\n }\n await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.addComment)(itemId, userName, insights);\n document.querySelector('input.user-name').value = '';\n document.querySelector('textarea.insights').value = '';\n\n // Clean the board\n document.querySelector('div.comments-box').innerHTML = '';\n // Gettint the updated comment data from the API and populate\n const commentData = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.getCommentData)(itemId);\n // Repopulate using the updated comment data\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.populateComments)(commentData);\n\n // Getting and displaying the number of comments\n const nbComments = await (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.commentcounter)(itemId);\n (0,_modules_functions_js__WEBPACK_IMPORTED_MODULE_1__.diplayNumberOfComments)(nbComments);\n });\n }\n});\n\n// Add event listener to close popup icon\nconst popupWindow = document.querySelector('.popup-window');\npopupWindow.addEventListener('click', (e) => {\n if (e.target && e.target.matches('i.close-popup')) {\n popupWindow.innerHTML = '';\n }\n});\n\n__webpack_async_result__();\n} catch(e) { __webpack_async_result__(e); } }, 1);\n\n//# sourceURL=webpack://js-capstone-project/./src/index.js?");
120 |
121 | /***/ }),
122 |
123 | /***/ "./src/modules/functions.js":
124 | /*!**********************************!*\
125 | !*** ./src/modules/functions.js ***!
126 | \**********************************/
127 | /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
128 |
129 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ PopupContent: () => (/* binding */ PopupContent),\n/* harmony export */ addComment: () => (/* binding */ addComment),\n/* harmony export */ addLike: () => (/* binding */ addLike),\n/* harmony export */ commentcounter: () => (/* binding */ commentcounter),\n/* harmony export */ counter: () => (/* binding */ counter),\n/* harmony export */ diplayLikes: () => (/* binding */ diplayLikes),\n/* harmony export */ diplayNumberOfComments: () => (/* binding */ diplayNumberOfComments),\n/* harmony export */ diplayNumberOfItems: () => (/* binding */ diplayNumberOfItems),\n/* harmony export */ errorMsg: () => (/* binding */ errorMsg),\n/* harmony export */ getCommentData: () => (/* binding */ getCommentData),\n/* harmony export */ getLikesData: () => (/* binding */ getLikesData),\n/* harmony export */ getMealData: () => (/* binding */ getMealData),\n/* harmony export */ newApp: () => (/* binding */ newApp),\n/* harmony export */ populateComments: () => (/* binding */ populateComments),\n/* harmony export */ populatedishes: () => (/* binding */ populatedishes)\n/* harmony export */ });\n// Getting data from the theMealDB API function\nconst getMealData = async () => {\n const request = new Request('https://themealdb.com/api/json/v1/1/search.php?f=c');\n const response = await fetch(request);\n const data = await response.json();\n return data.meals;\n};\n\n// Populating items in the DOM function\nconst populatedishes = async (mealData) => {\n const foodListSection = document.querySelector('.food-list');\n mealData.forEach((element) => {\n const foodCard = document.createElement('div');\n foodCard.classList.add('food-card', 'flex-column');\n foodCard.innerHTML = `\n \n
${element.strMeal} \n 0 likes \n \n \n \n Reservation \n
\n \n `;\n foodListSection.appendChild(foodCard);\n });\n};\n\n// Create new app function\nconst newApp = async () => {\n const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/');\n await fetch(request, {\n method: 'POST',\n });\n};\n\n// Add likes to API function\nconst addLike = async (targetId) => {\n const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/likes/');\n await fetch(request, {\n headers: {\n 'Content-type': 'application/json',\n },\n method: 'POST',\n body: JSON.stringify({\n item_id: targetId,\n }),\n });\n};\n\n// Getting likes data from the Involvement API function\nconst getLikesData = async () => {\n const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/likes/');\n const response = await fetch(request);\n const data = await response.json();\n return data;\n};\n\n// Diplaying likes data in the home page function\nconst diplayLikes = async (likesData, itemId) => {\n likesData.forEach((element) => {\n if (element.item_id === itemId) {\n // Replace M from the i tag id by L for obtaining the span id\n const likeId = itemId.replace('M', 'L');\n const span = document.querySelector(`#${likeId}`);\n span.textContent = `${element.likes} likes`;\n }\n });\n};\n\n// counter meals items function\nconst counter = async () => {\n const request = new Request('https://themealdb.com/api/json/v1/1/search.php?f=c');\n const response = await fetch(request);\n const data = await response.json();\n return data.meals.length;\n};\n\n// Display the number of meal on the home page function\nconst diplayNumberOfItems = (nbOfItems) => {\n const li = document.querySelector('li.number-of-items');\n li.textContent = `Meals(${nbOfItems})`;\n};\n\n// Populating popup window content function\nconst PopupContent = (data, id) => {\n const popupBox = document.querySelector('.popup-window');\n data.forEach((element) => {\n if (element.idMeal === id) {\n popupBox.innerHTML = `\n `;\n }\n });\n};\n\n// Throw error message function\nconst errorMsg = (userName, insights) => {\n const p1 = document.querySelector('p.user-name-error');\n const p2 = document.querySelector('p.insights-error');\n if (!userName) {\n p1.innerHTML = 'required field';\n p1.style.color = 'red';\n p1.style.fontSize = '0.9rem';\n } else {\n p1.innerHTML = '';\n }\n if (!insights) {\n p2.innerHTML = 'required field';\n p2.style.color = 'red';\n p2.style.fontSize = '0.9rem';\n } else {\n p2.innerHTML = '';\n }\n};\n\n// Add comment to API function\nconst addComment = async (id, userName, insights) => {\n const request = new Request('https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/comments');\n await fetch(request, {\n headers: {\n 'Content-type': 'application/json',\n },\n method: 'POST',\n body: JSON.stringify({\n item_id: id,\n username: userName,\n comment: insights,\n }),\n });\n};\n\n// Getting comment data from the Involvement API function\nconst getCommentData = async (id) => {\n const request = new Request(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/comments?item_id=${id}`);\n const response = await fetch(request);\n const data = await response.json();\n return data;\n};\n\n// populating comment data function\nconst populateComments = (data) => {\n const commentsBox = document.querySelector('div.comments-box');\n data.forEach((element) => {\n if (element.creation_date && element.username && element.comment) {\n const p = document.createElement('p');\n p.textContent = `${element.creation_date} ${element.username}: ${element.comment}`;\n commentsBox.appendChild(p);\n }\n });\n};\n\n// counter comment function\nconst commentcounter = async (id) => {\n const request = new Request(`https://us-central1-involvement-api.cloudfunctions.net/capstoneApi/apps/R20mJzx45L3RyqatiuEZ/comments?item_id=${id}`);\n const response = await fetch(request);\n const data = await response.json();\n // Since some data objects are empty:\n let n = 0;\n if (data.length) {\n data.forEach((element) => {\n if (element.creation_date && element.username && element.comment) {\n n += 1;\n }\n });\n }\n return n;\n};\n\n// Display the number of comment on the popup window function\nconst diplayNumberOfComments = (nbOfItems) => {\n const h2 = document.querySelector('h2.comment-title');\n h2.textContent = `comments (${nbOfItems})`;\n};\n\n//# sourceURL=webpack://js-capstone-project/./src/modules/functions.js?");
130 |
131 | /***/ })
132 |
133 | /******/ });
134 | /************************************************************************/
135 | /******/ // The module cache
136 | /******/ var __webpack_module_cache__ = {};
137 | /******/
138 | /******/ // The require function
139 | /******/ function __webpack_require__(moduleId) {
140 | /******/ // Check if module is in cache
141 | /******/ var cachedModule = __webpack_module_cache__[moduleId];
142 | /******/ if (cachedModule !== undefined) {
143 | /******/ return cachedModule.exports;
144 | /******/ }
145 | /******/ // Create a new module (and put it into the cache)
146 | /******/ var module = __webpack_module_cache__[moduleId] = {
147 | /******/ id: moduleId,
148 | /******/ // no module.loaded needed
149 | /******/ exports: {}
150 | /******/ };
151 | /******/
152 | /******/ // Execute the module function
153 | /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
154 | /******/
155 | /******/ // Return the exports of the module
156 | /******/ return module.exports;
157 | /******/ }
158 | /******/
159 | /************************************************************************/
160 | /******/ /* webpack/runtime/async module */
161 | /******/ (() => {
162 | /******/ var webpackQueues = typeof Symbol === "function" ? Symbol("webpack queues") : "__webpack_queues__";
163 | /******/ var webpackExports = typeof Symbol === "function" ? Symbol("webpack exports") : "__webpack_exports__";
164 | /******/ var webpackError = typeof Symbol === "function" ? Symbol("webpack error") : "__webpack_error__";
165 | /******/ var resolveQueue = (queue) => {
166 | /******/ if(queue && !queue.d) {
167 | /******/ queue.d = 1;
168 | /******/ queue.forEach((fn) => (fn.r--));
169 | /******/ queue.forEach((fn) => (fn.r-- ? fn.r++ : fn()));
170 | /******/ }
171 | /******/ }
172 | /******/ var wrapDeps = (deps) => (deps.map((dep) => {
173 | /******/ if(dep !== null && typeof dep === "object") {
174 | /******/ if(dep[webpackQueues]) return dep;
175 | /******/ if(dep.then) {
176 | /******/ var queue = [];
177 | /******/ queue.d = 0;
178 | /******/ dep.then((r) => {
179 | /******/ obj[webpackExports] = r;
180 | /******/ resolveQueue(queue);
181 | /******/ }, (e) => {
182 | /******/ obj[webpackError] = e;
183 | /******/ resolveQueue(queue);
184 | /******/ });
185 | /******/ var obj = {};
186 | /******/ obj[webpackQueues] = (fn) => (fn(queue));
187 | /******/ return obj;
188 | /******/ }
189 | /******/ }
190 | /******/ var ret = {};
191 | /******/ ret[webpackQueues] = x => {};
192 | /******/ ret[webpackExports] = dep;
193 | /******/ return ret;
194 | /******/ }));
195 | /******/ __webpack_require__.a = (module, body, hasAwait) => {
196 | /******/ var queue;
197 | /******/ hasAwait && ((queue = []).d = 1);
198 | /******/ var depQueues = new Set();
199 | /******/ var exports = module.exports;
200 | /******/ var currentDeps;
201 | /******/ var outerResolve;
202 | /******/ var reject;
203 | /******/ var promise = new Promise((resolve, rej) => {
204 | /******/ reject = rej;
205 | /******/ outerResolve = resolve;
206 | /******/ });
207 | /******/ promise[webpackExports] = exports;
208 | /******/ promise[webpackQueues] = (fn) => (queue && fn(queue), depQueues.forEach(fn), promise["catch"](x => {}));
209 | /******/ module.exports = promise;
210 | /******/ body((deps) => {
211 | /******/ currentDeps = wrapDeps(deps);
212 | /******/ var fn;
213 | /******/ var getResult = () => (currentDeps.map((d) => {
214 | /******/ if(d[webpackError]) throw d[webpackError];
215 | /******/ return d[webpackExports];
216 | /******/ }))
217 | /******/ var promise = new Promise((resolve) => {
218 | /******/ fn = () => (resolve(getResult));
219 | /******/ fn.r = 0;
220 | /******/ var fnQueue = (q) => (q !== queue && !depQueues.has(q) && (depQueues.add(q), q && !q.d && (fn.r++, q.push(fn))));
221 | /******/ currentDeps.map((dep) => (dep[webpackQueues](fnQueue)));
222 | /******/ });
223 | /******/ return fn.r ? promise : getResult();
224 | /******/ }, (err) => ((err ? reject(promise[webpackError] = err) : outerResolve(exports)), resolveQueue(queue)));
225 | /******/ queue && (queue.d = 0);
226 | /******/ };
227 | /******/ })();
228 | /******/
229 | /******/ /* webpack/runtime/compat get default export */
230 | /******/ (() => {
231 | /******/ // getDefaultExport function for compatibility with non-harmony modules
232 | /******/ __webpack_require__.n = (module) => {
233 | /******/ var getter = module && module.__esModule ?
234 | /******/ () => (module['default']) :
235 | /******/ () => (module);
236 | /******/ __webpack_require__.d(getter, { a: getter });
237 | /******/ return getter;
238 | /******/ };
239 | /******/ })();
240 | /******/
241 | /******/ /* webpack/runtime/define property getters */
242 | /******/ (() => {
243 | /******/ // define getter functions for harmony exports
244 | /******/ __webpack_require__.d = (exports, definition) => {
245 | /******/ for(var key in definition) {
246 | /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
247 | /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
248 | /******/ }
249 | /******/ }
250 | /******/ };
251 | /******/ })();
252 | /******/
253 | /******/ /* webpack/runtime/hasOwnProperty shorthand */
254 | /******/ (() => {
255 | /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
256 | /******/ })();
257 | /******/
258 | /******/ /* webpack/runtime/make namespace object */
259 | /******/ (() => {
260 | /******/ // define __esModule on exports
261 | /******/ __webpack_require__.r = (exports) => {
262 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
263 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
264 | /******/ }
265 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
266 | /******/ };
267 | /******/ })();
268 | /******/
269 | /******/ /* webpack/runtime/nonce */
270 | /******/ (() => {
271 | /******/ __webpack_require__.nc = undefined;
272 | /******/ })();
273 | /******/
274 | /************************************************************************/
275 | /******/
276 | /******/ // startup
277 | /******/ // Load entry module and return exports
278 | /******/ // This entry module can't be inlined because the eval devtool is used.
279 | /******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
280 | /******/
281 | /******/ })()
282 | ;
--------------------------------------------------------------------------------
Comments (0)
107 | 108 |