Skip to content
This repository was archived by the owner on Oct 1, 2025. It is now read-only.

Commit 7f2fb82

Browse files
committed
feat: Completed Work in Forkify App Third Section
1 parent 4232bbe commit 7f2fb82

File tree

9 files changed

+257
-35
lines changed

9 files changed

+257
-35
lines changed

10-forkify/index.html

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -250,31 +250,31 @@ <h2 class="heading--2">How to cook it</h2>
250250
<div class="add-recipe-window hidden">
251251
<button class="btn--close-modal">&times;</button>
252252
<form class="upload">
253+
<!--
253254
<div class="upload__column">
254255
<h3 class="upload__heading">Recipe data</h3>
255256
<label>Title</label>
256-
<input value="TEST" required name="title" type="text" />
257+
<input value="the potato" required name="title" type="text" />
257258
<label>URL</label>
258-
<input value="TEST" required name="sourceUrl" type="text" />
259+
<input value="potato.com" required name="sourceUrl" type="text" />
259260
<label>Image URL</label>
260-
<input value="TEST" required name="image" type="text" />
261+
<input value="potato.png" required name="image" type="text" />
261262
<label>Publisher</label>
262-
<input value="TEST" required name="publisher" type="text" />
263+
<input value="king potato" required name="publisher" type="text" />
263264
<label>Prep time</label>
264-
<input value="23" required name="cookingTime" type="number" />
265+
<input value="5" required name="cookingTime" type="number" />
265266
<label>Servings</label>
266-
<input value="23" required name="servings" type="number" />
267+
<input value="5" required name="servings" type="number" />
267268
</div>
268269
269270
<div class="upload__column">
270271
<h3 class="upload__heading">Ingredients</h3>
271272
<label>Ingredient 1</label>
272-
<input value="0.5,kg,Rice" type="text" required name="ingredient-1"
273-
placeholder="Format: 'Quantity,Unit,Description'" />
273+
<input value="1,kg,Potato" type="text" required name="ingredient-1" placeholder="Format: 'Quantity,Unit,Description'" />
274274
<label>Ingredient 2</label>
275-
<input value="1,,Avocado" type="text" name="ingredient-2" placeholder="Format: 'Quantity,Unit,Description'" />
275+
<input value=",,salt" type="text" name="ingredient-2" placeholder="Format: 'Quantity,Unit,Description'" />
276276
<label>Ingredient 3</label>
277-
<input value=",,salt" type="text" name="ingredient-3" placeholder="Format: 'Quantity,Unit,Description'" />
277+
<input type="text" name="ingredient-3" placeholder="Format: 'Quantity,Unit,Description'" />
278278
<label>Ingredient 4</label>
279279
<input type="text" name="ingredient-4" placeholder="Format: 'Quantity,Unit,Description'" />
280280
<label>Ingredient 5</label>
@@ -289,6 +289,7 @@ <h3 class="upload__heading">Ingredients</h3>
289289
</svg>
290290
<span>Upload</span>
291291
</button>
292+
-->
292293
</form>
293294
</div>
294295
</body>

10-forkify/src/js/config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export const API_URL = 'https://forkify-api.herokuapp.com/api/v2/recipes';
2+
export const KEY = '2d6fc87e-ca17-4c19-bcff-c9d49217130e';
23
export const TIMEOUT_SEC = 10;
3-
export const RESULTS_PER_PAGE = 10;
4+
export const RESULTS_PER_PAGE = 10;
5+
export const MODAL_CLOSE_SEC = 2.5;

10-forkify/src/js/controller.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ import 'core-js/stable';
22
import 'regenerator-runtime/runtime';
33

44
import * as model from './model.js';
5+
import { MODAL_CLOSE_SEC } from './config.js';
56
import { getHash } from './helpers.js';
67
import recipeView from './views/recipeView.js';
78
import searchView from './views/searchView.js';
89
import resultsView from './views/resultsView.js';
910
import paginationView from './views/paginationView.js';
1011
import bookmarksView from './views/bookmarksView.js';
12+
import addRecipeView from './views/addRecipeView.js';
1113

1214
// https://forkify-api.herokuapp.com/v2
1315

@@ -106,11 +108,41 @@ const controlInitBookmarks = function ()
106108
bookmarksView.render(model.state.bookmarks);
107109
};
108110

109-
const clearBookmarks = function ()
111+
const controlAddRecipe = async function (newRecipe)
110112
{
111-
localStorage.clear('bookmarks');
113+
try
114+
{
115+
// Render Spinner while the Data is being Fetched
116+
addRecipeView.renderSpinner();
117+
118+
// Upload New Recipe Data
119+
await model.uploadRecipe(newRecipe);
120+
console.log(model.state.recipe);
121+
122+
// Render Recipe
123+
recipeView.render(model.state.recipe);
124+
// Success Message
125+
addRecipeView.renderMessage();
126+
127+
// Change ID in URL
128+
window.history.pushState(null, '', `#${ model.state.recipe.id }`);
129+
130+
// Render Bookmark View
131+
bookmarksView.render(model.state.bookmarks);
132+
133+
// Close Form
134+
setTimeout(function ()
135+
{
136+
if (addRecipeView.isWindowActive())
137+
addRecipeView.toggleWindow();
138+
}, MODAL_CLOSE_SEC * 1000);
139+
}
140+
catch (err)
141+
{
142+
console.error(err);
143+
addRecipeView.renderError(err);
144+
}
112145
};
113-
// clearBookmarks()
114146

115147
const init = function ()
116148
{
@@ -120,6 +152,7 @@ const init = function ()
120152
recipeView.addHandlerBookmark(controlBookmark);
121153
searchView.addHandlerSearch(controlSearchResults);
122154
paginationView.addHandlerPagination(controlPagination);
155+
addRecipeView.addHandlerUpload(controlAddRecipe);
123156
};
124157
init();
125158

10-forkify/src/js/helpers.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,28 @@ export const timeout = function (s)
1111
});
1212
};
1313

14-
1514
export const getHash = function ()
1615
{
1716
// Get Hash ID
1817
return window.location.hash.slice(1);
1918
};
2019

21-
export const getJSON = async function (url)
20+
export const AJAX = async function (url, uploadData = undefined)
2221
{
2322
try
2423
{
24+
const fetchPromise = uploadData ?
25+
fetch(url, {
26+
method: 'POST',
27+
headers: {
28+
'Content-Type': 'application/json'
29+
},
30+
body: JSON.stringify(uploadData)
31+
})
32+
: fetch(url);
33+
2534
// Fetching Data
26-
const res = await Promise.race([fetch(url), timeout(TIMEOUT_SEC)]);
35+
const res = await Promise.race([fetchPromise, timeout(TIMEOUT_SEC)]);
2736
// Get JavaScript Object from JSON
2837
const data = await res.json();
2938

10-forkify/src/js/model.js

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
import { async } from 'regenerator-runtime';
3-
import { API_URL, RESULTS_PER_PAGE } from './config';
4-
import { getJSON } from './helpers.js';
3+
import { API_URL, RESULTS_PER_PAGE, KEY } from './config';
4+
import { AJAX } from './helpers.js';
55

66
export const state = {
77
bookmarks: [],
@@ -13,6 +13,23 @@ export const state = {
1313
}
1414
};
1515

16+
const createRecipeObject = function (data)
17+
{
18+
const { recipe } = data.data;
19+
20+
return {
21+
id: recipe.id,
22+
title: recipe.title,
23+
publisher: recipe.publisher,
24+
sourceUrl: recipe.source_url,
25+
image: recipe.image_url,
26+
servings: recipe.servings,
27+
cookingTime: recipe.cooking_time,
28+
ingredients: recipe.ingredients,
29+
...(recipe.key && { key: recipe.key })
30+
};
31+
};
32+
1633
export const loadRecipe = async function (id)
1734
{
1835
try
@@ -21,19 +38,8 @@ export const loadRecipe = async function (id)
2138
// id = '5ed6604591c37cdc054bc886';
2239

2340
// Fetching Data
24-
const data = await getJSON(`${ API_URL }/${ id }`);
25-
26-
let { recipe } = data.data;
27-
state.recipe = {
28-
id: recipe.id,
29-
title: recipe.title,
30-
publisher: recipe.publisher,
31-
sourceUrl: recipe.source_url,
32-
image: recipe.image_url,
33-
servings: recipe.servings,
34-
cookingTime: recipe.cooking_time,
35-
ingredients: recipe.ingredients
36-
};
41+
const data = await AJAX(`${ API_URL }/${ id }?key=${ KEY }`);
42+
state.recipe = createRecipeObject(data);
3743

3844
state.recipe.bookmarked = state.bookmarks.some(bookmark => bookmark.id === id);
3945

@@ -50,7 +56,7 @@ export const loadSearchResults = async function (query)
5056
{
5157
try
5258
{
53-
const data = await getJSON(`${ API_URL }?search=${ query }`);
59+
const data = await AJAX(`${ API_URL }?search=${ query }&key=${ KEY }`);
5460
state.search.page = 1;
5561

5662
state.search.query = query;
@@ -61,6 +67,7 @@ export const loadSearchResults = async function (query)
6167
title: recipe.title,
6268
publisher: recipe.publisher,
6369
image: recipe.image_url,
70+
...(recipe.key && { key: recipe.key })
6471
};
6572
});
6673
}
@@ -122,6 +129,45 @@ export const delBookmark = function (id)
122129
storeBookmarks();
123130
};
124131

132+
export const uploadRecipe = async function (newRecipe)
133+
{
134+
try
135+
{
136+
const ingredients = Object.entries(newRecipe)
137+
.filter(entry => entry.at(0).startsWith('ingredient') && entry.at(1) !== '')
138+
.map(ing =>
139+
{
140+
const ingArr = ing.at(1).split(',').map(ing => ing.trim());
141+
if (ingArr.length !== 3) throw new Error('Wrong ingredient format');
142+
143+
const [qt, unit, description] = ingArr;
144+
if (description === '') throw new Error('Missing ingredient description');
145+
146+
return { quantity: qt ? +qt : null, unit, description };
147+
});
148+
console.log(ingredients);
149+
150+
const recipe = {
151+
title: newRecipe.title,
152+
source_url: newRecipe.sourceUrl,
153+
image_url: newRecipe.image,
154+
publisher: newRecipe.publisher,
155+
cooking_time: +newRecipe.cookingTime,
156+
servings: +newRecipe.servings,
157+
ingredients,
158+
};
159+
160+
const data = await AJAX(`${ API_URL }?key=${ KEY }`, recipe);
161+
state.recipe = createRecipeObject(data);
162+
addBookmark(state.recipe);
163+
}
164+
catch (err)
165+
{
166+
// Re-throwing the Error
167+
throw (err);
168+
}
169+
};
170+
125171
const init = function ()
126172
{
127173
const storage = localStorage.getItem('bookmarks');
@@ -130,4 +176,10 @@ const init = function ()
130176

131177
state.bookmarks = JSON.parse(storage);
132178
};
133-
init();
179+
init();
180+
181+
const clearBookmarks = function ()
182+
{
183+
localStorage.clear('bookmarks');
184+
};
185+
// clearBookmarks()

0 commit comments

Comments
 (0)