import config from '../config'; import * as Errors from './Errors'; class Api { constructor() { } baseUrl() { return config.baseApiUrl; } url(path) { return this.baseUrl() + path; } checkStatus(response) { if (response.status == 204) { return null; } else if (response.ok) { return response.json(); } else if (response.status === 404) { throw new Errors.ApiNotFoundError(response.statusText, response); } else if (response.status === 422) { return response.json().then(json => { throw new Errors.ApiValidationError(null, response, json) }, jsonErr => { throw new Errors.ApiValidationError(null, response, null) }); } else { throw new Errors.ApiServerError(response.statusText || "Unknown Server Error", response); } } parseJSON(response) { return response.json(); } performRequest(url, method, params = {}) { const hasBody = Object.keys(params || {}).length !== 0; const headers = new Headers(); headers.append('Accept', 'application/json'); headers.append('Content-Type', 'application/json'); const opts = { headers, method: method, credentials: "same-origin" }; if (hasBody) { opts.body = JSON.stringify(params); } return fetch(url, opts).then(this.checkStatus); } objectToUrlParams(obj, queryParams = [], prefixes = []) { for (let key in obj) { const val = obj[key]; const paramName = prefixes.join("[") + "[".repeat(Math.min(prefixes.length, 1)) + encodeURIComponent(key) + "]".repeat(prefixes.length); if (Array.isArray(val)) { for (let x of val) { queryParams.push(paramName + "[]=" + (x === null ? '' : encodeURIComponent(x))); } } else if (typeof(val) === "object") { this.objectToUrlParams(val, queryParams, prefixes.concat([key])); } else { queryParams.push(paramName + "=" + (val === null ? '' : encodeURIComponent(val))); } } return queryParams; } get(url, params = {}) { const queryParams = this.objectToUrlParams(params); if (queryParams.length) { url = url + "?" + queryParams.join("&"); } return this.performRequest(url, "GET"); } post(url, params = {}) { return this.performRequest(url, "POST", params); } patch(url, params = {}) { return this.performRequest(url, "PATCH", params); } del(url, params = {}) { return this.performRequest(url, "DELETE", params); } getRecipeList(page, per, sortColumn, sortDirection, name, tags) { const params = { criteria: { page: page || null, per: per || null, sort_column: sortColumn || null, sort_direction: sortDirection || null, name: name || null, tags: tags || null } }; return this.get("/recipes", params); } getRecipe(id) { return this.get("/recipes/" + id); } buildRecipeParams(recipe) { const params = { recipe: { name: recipe.name, description: recipe.description, source: recipe.source, yields: recipe.yields, total_time: recipe.total_time, active_time: recipe.active_time, step_text: recipe.step_text, tag_names: recipe.tag_names, recipe_ingredients_attributes: recipe.ingredients.map(i => { if (i._destroy) { return { id: i.id, _destroy: true }; } else { return { id: i.id, name: i.name, ingredient_id: i.ingredient_id, quantity: i.quantity, units: i.units, preparation: i.preparation, sort_order: i.sort_order }; } }) } }; return params; } patchRecipe(recipe) { return this.patch("/recipes/" + recipe.id, this.buildRecipeParams(recipe)); } postRecipe(recipe) { return this.post("/recipes/", this.buildRecipeParams(recipe)); } postPreviewSteps(step_text) { const params = { step_text: step_text }; return this.post("/recipes/preview_steps", params); } getSearchIngredients(query) { const params = { query: query }; return this.get("/ingredients/search", params); } getCalculate(input, output_unit, density) { const params = { input, output_unit, density }; return this.get("/calculator/calculate", params); } getIngredientList(page, per, name) { const params = { page, per, name }; return this.get("/ingredients/", params); } getIngredient(id) { return this.get("/ingredients/" + id); } buildIngredientParams(ingredient) { return { ingredient: { name: ingredient.name, notes: ingredient.notes, ndbn: ingredient.ndbn, density: ingredient.density, water: ingredient.water, ash: ingredient.ash, protein: ingredient.protein, kcal: ingredient.kcal, fiber: ingredient.fiber, sugar: ingredient.sugar, carbohydrates: ingredient.carbohydrates, calcium: ingredient.calcium, iron: ingredient.iron, magnesium: ingredient.magnesium, phosphorus: ingredient.phosphorus, potassium: ingredient.potassium, sodium: ingredient.sodium, zinc: ingredient.zinc, copper: ingredient.copper, manganese: ingredient.manganese, vit_c: ingredient.vit_c, vit_b6: ingredient.vit_b6, vit_b12: ingredient.vit_b12, vit_a: ingredient.vit_a, vit_e: ingredient.vit_e, vit_d: ingredient.vit_d, vit_k: ingredient.vit_k, cholesterol: ingredient.cholesterol, lipids: ingredient.lipids, ingredient_units_attributes: ingredient.ingredient_units.map(iu => { if (iu._destroy) { return { id: iu.id, _destroy: true }; } else { return { id: iu.id, name: iu.name, gram_weight: iu.gram_weight }; } }) } } } postIngredient(ingredient) { return this.post("/ingredients/", this.buildIngredientParams(ingredient)); } patchIngredient(ingredient) { return this.patch("/ingredients/" + ingredient.id, this.buildIngredientParams(ingredient)); } postIngredientSelectNdbn(ingredient) { const url = ingredient.id ? "/ingredients/" + ingredient.id + "/select_ndbn" : "/ingredients/select_ndbn"; return this.post(url, this.buildIngredientParams(ingredient)); } getUsdaFoodSearch(query) { return this.get("/ingredients/usda_food_search", {query: query}); } getNoteList() { return this.get("/notes/"); } postNote(note) { const params = { content: note.content }; return this.post("/notes/", params); } deleteNote(note) { return this.del("/notes/" + note.id); } postLogin(username, password) { const params = { username: username, password: password }; return this.post("/login", params); } getLogout() { return this.get("/logout"); } getCurrentUser() { return this.get("/user") } } const api = new Api(); export default api;