diff --git a/package-lock.json b/package-lock.json
index 1e217b9..f0495af 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,11 +10,13 @@
"license": "ISC",
"dependencies": {
"core-js": "^3.32.0",
+ "fractional": "^1.0.0",
"regenerator-runtime": "^0.14.0"
},
"devDependencies": {
"@parcel/transformer-sass": "^2.9.3",
- "parcel": "^2.9.3"
+ "parcel": "^2.9.3",
+ "process": "^0.11.10"
}
},
"node_modules/@babel/code-frame": {
@@ -2592,6 +2594,11 @@
"node": ">=8"
}
},
+ "node_modules/fractional": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fractional/-/fractional-1.0.0.tgz",
+ "integrity": "sha512-4huGcVdAAr0ffcQ7wQY3dhAdZqKd6QgGOP4Kd7ioNoBAS7GdzolwnqgjH/jTzzCpg71oTLbOVwcOWOH+BmwqvA=="
+ },
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
@@ -3337,6 +3344,15 @@
"node": ">=12"
}
},
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/react-error-overlay": {
"version": "6.0.9",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
diff --git a/package.json b/package.json
index eca44e3..b2d8201 100644
--- a/package.json
+++ b/package.json
@@ -10,10 +10,12 @@
"license": "ISC",
"devDependencies": {
"@parcel/transformer-sass": "^2.9.3",
- "parcel": "^2.9.3"
+ "parcel": "^2.9.3",
+ "process": "^0.11.10"
},
"dependencies": {
"core-js": "^3.32.0",
+ "fractional": "^1.0.0",
"regenerator-runtime": "^0.14.0"
}
}
diff --git a/src/js/controller.js b/src/js/controller.js
index 66a4104..4c61901 100644
--- a/src/js/controller.js
+++ b/src/js/controller.js
@@ -1,6 +1,8 @@
-import icons from '../img/icons.svg';
+import * as model from './model.js';
+import recipeView from './views/recipeView.js';
-const recipeContainer = document.querySelector('.recipe');
+import 'core-js/stable';
+import 'regenerator-runtime/runtime';
const timeout = function (s) {
return new Promise(function (_, reject) {
@@ -14,150 +16,23 @@ const timeout = function (s) {
///////////////////////////////////////
-const renderSpinner = function (parentEl) {
- const markup = `
-
-
-
- `;
- parentEl.innerHTML = '';
- parentEl.insertAdjacentHTML('afterbegin', markup);
-};
-
-const showRecipe = async function () {
+const controlRecipes = async function () {
try {
const id = window.location.hash.slice(1);
if (!id) return;
+ recipeView.renderSpinner();
// 1)Loading recipe
- renderSpinner(recipeContainer);
- const res = await fetch(
- `https://forkify-api.herokuapp.com/api/v2/recipes/${id}`
- );
- const data = await res.json();
-
- if (!res.ok) throw new Error(`${data.message} (${res.status})`);
-
- let { recipe } = data.data;
-
- recipe = {
- id: recipe.id,
- title: recipe.title,
- publisher: recipe.publisher,
- sourceUrl: recipe.source_url,
- image: recipe.image_url,
- servings: recipe.servings,
- cookingTime: recipe.cooking_time,
- ingredients: recipe.ingredients,
- };
-
- console.log(recipe);
+ await model.loadRecipe(id);
// 2) Rendering recipe
- const markup = `
-
-
-
- ${recipe.title}
-
-
-
-
-
-
- ${
- recipe.cookingTime
- }
- minutes
-
-
-
-
${
- recipe.servings
- }
-
servings
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
How to cook it
-
- This recipe was carefully designed and tested by
- ${
- recipe.publisher
- }. Please check out
- directions at their website.
-
-
- Directions
-
-
-
- `;
- recipeContainer.innerHTML = '';
- recipeContainer.insertAdjacentHTML('afterbegin', markup);
+ recipeView.render(model.state.recipe);
} catch (error) {
alert(error);
}
};
-['hashchange', 'load'].forEach(ev => window.addEventListener(ev, showRecipe));
+['hashchange', 'load'].forEach(ev =>
+ window.addEventListener(ev, controlRecipes)
+);
diff --git a/src/js/model.js b/src/js/model.js
new file mode 100644
index 0000000..8485bbc
--- /dev/null
+++ b/src/js/model.js
@@ -0,0 +1,31 @@
+export const state = {
+ recipe: {},
+};
+
+export const loadRecipe = async function (id) {
+ try {
+ const res = await fetch(
+ `https://forkify-api.herokuapp.com/api/v2/recipes/${id}`
+ );
+ const data = await res.json();
+
+ if (!res.ok) throw new Error(`${data.message} (${res.status})`);
+
+ const { recipe } = data.data;
+
+ state.recipe = {
+ id: recipe.id,
+ title: recipe.title,
+ publisher: recipe.publisher,
+ sourceUrl: recipe.source_url,
+ image: recipe.image_url,
+ servings: recipe.servings,
+ cookingTime: recipe.cooking_time,
+ ingredients: recipe.ingredients,
+ };
+
+ console.log(state.recipe);
+ } catch (error) {
+ alert(error);
+ }
+};
diff --git a/src/js/views/recipeView.js b/src/js/views/recipeView.js
new file mode 100644
index 0000000..79a7275
--- /dev/null
+++ b/src/js/views/recipeView.js
@@ -0,0 +1,135 @@
+import icons from '../../img/icons.svg';
+import fractional from 'fractional';
+
+class RecipeView {
+ #parentElement = document.querySelector('.recipe');
+ #data;
+
+ render(data) {
+ this.#data = data;
+ const markup = this.#generateMarkup();
+ this.#clear();
+ this.#parentElement.insertAdjacentHTML('afterbegin', markup);
+ }
+
+ #clear() {
+ this.#parentElement.innerHTML = '';
+ }
+
+ renderSpinner = function () {
+ const markup = `
+
+
+
+ `;
+ this.#parentElement.innerHTML = '';
+ this.#parentElement.insertAdjacentHTML('afterbegin', markup);
+ };
+
+ #generateMarkup() {
+ return `
+
+
+
+ ${this.#data.title}
+
+
+
+
+
+
+ ${
+ this.#data.cookingTime
+ }
+ minutes
+
+
+
+
${
+ this.#data.servings
+ }
+
servings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Recipe ingredients
+
+ ${this.#data.ingredients.map(this.#generateMarkupIngredient).join('')}
+
+
+
+
+
How to cook it
+
+ This recipe was carefully designed and tested by
+ ${
+ this.#data.publisher
+ }. Please check out
+ directions at their website.
+
+
+ Directions
+
+
+
+ `;
+ }
+
+ #generateMarkupIngredient(ing) {
+ return `
+
+
+ ${
+ ing.quantity ? new Fraction(ing.quantity).toString() : ''
+ }
+
+ ${ing.unit}
+ ${ing.description}
+
+
+ `;
+ }
+}
+
+export default new RecipeView();