in progress: handle add ingredients to recipe
This commit is contained in:
@@ -2,8 +2,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||||
import { useAuthContext } from './context/AuthContext';
|
import { useAuthContext } from './context/AuthContext';
|
||||||
import jwtDecode from 'jwt-decode';
|
|
||||||
import API from './util/API';
|
|
||||||
|
|
||||||
// pages, ui, components, styles
|
// pages, ui, components, styles
|
||||||
import Subscriptions from './components/pages/Subscriptions/Subscriptions';
|
import Subscriptions from './components/pages/Subscriptions/Subscriptions';
|
||||||
@@ -19,11 +17,10 @@ import CollectionBrowser from './components/pages/CollectionBrowser';
|
|||||||
import { Navbar } from './components/ui';
|
import { Navbar } from './components/ui';
|
||||||
import GroceryList from './components/pages/GroceryList';
|
import GroceryList from './components/pages/GroceryList';
|
||||||
import GroceryListCollection from './components/pages/GroceryListCollection';
|
import GroceryListCollection from './components/pages/GroceryListCollection';
|
||||||
import { TokenType } from './util/types';
|
|
||||||
import './sass/App.scss';
|
|
||||||
import handleToken from './util/handleToken';
|
import handleToken from './util/handleToken';
|
||||||
import AddFriends from './components/pages/AddFriends';
|
import AddFriends from './components/pages/AddFriends';
|
||||||
import Sandbox from './components/Sandbox';
|
import Sandbox from './components/Sandbox';
|
||||||
|
import './sass/App.scss';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const { setUser, token, setToken } = useAuthContext();
|
const { setUser, token, setToken } = useAuthContext();
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
import { useAuthContext } from "../../context/AuthContext";
|
||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
import { v4 } from "uuid";
|
import { v4 } from "uuid";
|
||||||
import { useAuthContext } from "../../context/AuthContext";
|
|
||||||
import { getAllUsers, getFriendships, getPendingFriendRequests, getUserByID } from "../../util/apiUtils";
|
|
||||||
import API from "../../util/API";
|
import API from "../../util/API";
|
||||||
import UserCard from "../ui/UserCard";
|
import UserCard from "../ui/UserCard";
|
||||||
import { IUser, IFriendship } from "../../schemas";
|
import { IUser, IFriendship } from "../../schemas";
|
||||||
@@ -18,9 +17,9 @@ const Friends: FC<{ targetUser?: IUser }> = ({ targetUser }) => {
|
|||||||
(async function() {
|
(async function() {
|
||||||
try {
|
try {
|
||||||
const Friends = new API.Friendship(token);
|
const Friends = new API.Friendship(token);
|
||||||
const result = await Friends.getAll();
|
const result: IFriendship[] | null = await Friends.getAll();
|
||||||
|
|
||||||
if (result.length) {
|
if (result?.length) {
|
||||||
setFriends(result);
|
setFriends(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import { useAuthContext } from "../../context/AuthContext";
|
// library/framework
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { Button, Card, Divider, Page, Panel } from "../ui"
|
import { Autocomplete, TextField } from "@mui/material";
|
||||||
import { DropdownData, IIngredient, IRecipe } from "../../schemas";
|
import { v4 } from "uuid";
|
||||||
import IngredientSelector from "../derived/IngredientSelector";
|
|
||||||
|
// util/api
|
||||||
|
import { useAuthContext } from "../../context/AuthContext";
|
||||||
|
import { DropdownData, IIngredient, IRecipe, RecipeIngredient } from "../../schemas";
|
||||||
|
import { IngredientFieldData } from "../../util/types";
|
||||||
import Protect from "../../util/Protect";
|
import Protect from "../../util/Protect";
|
||||||
import API from "../../util/API";
|
import API from "../../util/API";
|
||||||
import { v4 } from "uuid";
|
|
||||||
import RichText from "../ui/RichText";
|
// ui/components
|
||||||
import { Autocomplete, TextField } from "@mui/material";
|
import { Button, Card, Divider, Panel, RichText, Toast } from "../ui"
|
||||||
import { IngredientFieldData } from "../../util/types";
|
import IngredientSelector from "../derived/IngredientSelector";
|
||||||
import Toast from "../ui/Toast";
|
|
||||||
|
|
||||||
export default function AddRecipe() {
|
export default function AddRecipe() {
|
||||||
/**********************************
|
/**********************************
|
||||||
@@ -103,7 +106,7 @@ export default function AddRecipe() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (courseList) {
|
if (courseList && !courseData.length) {
|
||||||
setCourseData((prev) => {
|
setCourseData((prev) => {
|
||||||
let newEntries = filterDuplicateEntries(courseList, prev);
|
let newEntries = filterDuplicateEntries(courseList, prev);
|
||||||
return [...prev, ...newEntries];
|
return [...prev, ...newEntries];
|
||||||
@@ -112,22 +115,23 @@ export default function AddRecipe() {
|
|||||||
})();
|
})();
|
||||||
}, [token])
|
}, [token])
|
||||||
|
|
||||||
// mount the ingredient selection section once dependencies have loaded
|
// mount the ingredient selection section once conditions met:
|
||||||
|
// 1. ingredients have been fetched
|
||||||
|
// 2. measurements have been fetched
|
||||||
|
// 3. ingredient fields have not already been initialized
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ingredients.length && measurements.length) {
|
const conditionsMet = (ingredients.length && measurements.length) && (!ingredientFields.length);
|
||||||
|
|
||||||
|
if (conditionsMet) {
|
||||||
setIngredientFields([<IngredientSelector key={v4()} position={optionCount} ingredients={ingredients} units={measurements} getRowState={getRowState} destroy={destroySelector} />]);
|
setIngredientFields([<IngredientSelector key={v4()} position={optionCount} ingredients={ingredients} units={measurements} getRowState={getRowState} destroy={destroySelector} />]);
|
||||||
}
|
}
|
||||||
}, [ingredients, measurements])
|
}, [ingredients, measurements])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(ingredientFieldData);
|
|
||||||
}, [getRowState]);
|
|
||||||
|
|
||||||
/**********************************
|
/**********************************
|
||||||
* PAGE SPECIFIC FUNCTIONS
|
* PAGE SPECIFIC FUNCTIONS
|
||||||
*********************************/
|
*********************************/
|
||||||
// submit handler
|
// submit handler
|
||||||
const handleCreate = async () => {
|
async function handleCreate() {
|
||||||
if (!user || !token) return;
|
if (!user || !token) return;
|
||||||
|
|
||||||
// initialize API handlers
|
// initialize API handlers
|
||||||
@@ -153,31 +157,52 @@ export default function AddRecipe() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ingredientSelections = new Array<any>();
|
let preparedIngredientData = new Array<RecipeIngredient>();
|
||||||
let newIngredientCount = 0;
|
let newIngredientCount = 0;
|
||||||
|
|
||||||
// handle ingredient row data
|
// handle ingredient row data
|
||||||
for (let row of ingredientFieldData) {
|
for (let row of ingredientFieldData) {
|
||||||
|
if (!row) continue;
|
||||||
|
console.log(row);
|
||||||
|
|
||||||
if (row.ingredientSelection === undefined) {
|
if (row.ingredientSelection === undefined) {
|
||||||
messages.push("Please ensure you have included ingredient selections for all rows.");
|
messages.push("Please ensure you have included ingredient selections for all rows.");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ingredientSelections.push(row.ingredientSelection);
|
if (!row.quantity) {
|
||||||
|
messages.push("Please provide a quantity for ingredient " + row.ingredientSelection);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!row.measurement) {
|
||||||
|
messages.push(row.ingredientSelection + " missing required unit of measurement");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newID = row.ingredients.filter(ingr => ingr.name == row.ingredientSelection)[0].id;
|
||||||
|
|
||||||
|
const newIngredientData: RecipeIngredient = {
|
||||||
|
id: newID ?? row.ingredients.length + 1,
|
||||||
|
name: row.ingredientSelection as string,
|
||||||
|
quantity: row.quantity,
|
||||||
|
unit: row.measurement
|
||||||
|
}
|
||||||
|
|
||||||
|
preparedIngredientData.push(newIngredientData);
|
||||||
|
|
||||||
for (let ing of row.ingredients) {
|
for (let ing of row.ingredients) {
|
||||||
// filter out recipes that already exist
|
// filter out recipes that already exist
|
||||||
if (ingredients.filter(x => x.name == ing.name).includes(ing)) {
|
if (!ingredients.filter(x => x.name == ing.name).includes(ing)) {
|
||||||
continue;
|
// post the new ingredient to the database
|
||||||
|
const newEntry = await ingredientAPI.post(ing);
|
||||||
|
messages.push(`Successfully created new ingredient: ${ing.name}!`);
|
||||||
|
console.log(newEntry);
|
||||||
|
newIngredientCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the ingredient list
|
// update the ingredient list
|
||||||
setIngredients((prev) => [...prev, ing]);
|
setIngredients((prev) => [...prev, ing]);
|
||||||
|
|
||||||
// post the new ingredient to the database
|
|
||||||
const newEntry = await ingredientAPI.post(ing);
|
|
||||||
messages.push(`Successfully created new ingredient: ${ing.name}!`);
|
|
||||||
console.log(newEntry);
|
|
||||||
newIngredientCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +215,7 @@ export default function AddRecipe() {
|
|||||||
const recipeName = result.recipe.name;
|
const recipeName = result.recipe.name;
|
||||||
let recipeIngredientCount = 0;
|
let recipeIngredientCount = 0;
|
||||||
|
|
||||||
for (let ing of ingredientSelections) {
|
for (let ing of preparedIngredientData) {
|
||||||
const ok = await recipeAPI.addIngredientToRecipe(ing, recipeID);
|
const ok = await recipeAPI.addIngredientToRecipe(ing, recipeID);
|
||||||
if (ok) recipeIngredientCount++;
|
if (ok) recipeIngredientCount++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { Divider, Page, Panel } from "../ui";
|
import { Divider, Page, Panel } from "../ui";
|
||||||
import { IRecipe, IUser, IIngredient } from "../../schemas";
|
import { IRecipe, IUser, IIngredient, RecipeIngredient } from "../../schemas";
|
||||||
import { getRecipeByID } from "../../util/apiUtils";
|
import { getRecipeByID } from "../../util/apiUtils";
|
||||||
import Protect from "../../util/Protect";
|
import Protect from "../../util/Protect";
|
||||||
import API from "../../util/API";
|
import API from "../../util/API";
|
||||||
import { useAuthContext } from "../../context/AuthContext";
|
import { useAuthContext } from "../../context/AuthContext";
|
||||||
import ResourceNotFound from "./StatusPages/404";
|
import ResourceNotFound from "./StatusPages/404";
|
||||||
|
import { v4 } from "uuid";
|
||||||
|
|
||||||
export default function Recipe() {
|
export default function Recipe() {
|
||||||
const { user, token } = useAuthContext();
|
const { user, token } = useAuthContext();
|
||||||
@@ -14,7 +15,7 @@ export default function Recipe() {
|
|||||||
|
|
||||||
const [recipe, setRecipe] = useState<IRecipe | "no recipe">();
|
const [recipe, setRecipe] = useState<IRecipe | "no recipe">();
|
||||||
const [userData, setUserData] = useState<IUser>();
|
const [userData, setUserData] = useState<IUser>();
|
||||||
const [ingredientData, setIngredientData] = useState<IIngredient[]>([]);
|
const [ingredientData, setIngredientData] = useState<RecipeIngredient[]>([]);
|
||||||
const [view, setView] = useState<JSX.Element>(<h1>Loading...</h1>);
|
const [view, setView] = useState<JSX.Element>(<h1>Loading...</h1>);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -32,17 +33,19 @@ export default function Recipe() {
|
|||||||
}, [token])
|
}, [token])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (recipe) {
|
if (recipe && id) {
|
||||||
if (recipe === "no recipe") {
|
if (recipe === "no recipe") {
|
||||||
setView(<ResourceNotFound><h2>We couldn't find a recipe with the ID {id}.</h2></ResourceNotFound>);
|
setView(<ResourceNotFound><h2>We couldn't find a recipe with the ID {id}.</h2></ResourceNotFound>);
|
||||||
} else {
|
} else {
|
||||||
if (!user || !token) return;
|
if (!user || !token) return;
|
||||||
|
|
||||||
(async() => {
|
// while ingredient data has not yet been mapped,
|
||||||
|
// get ingredients and map them
|
||||||
|
(!ingredientData.length) && (async() => {
|
||||||
const ingredientAPI = new API.Ingredient(token);
|
const ingredientAPI = new API.Ingredient(token);
|
||||||
const result = await ingredientAPI.getAllForRecipe(id!);
|
const result = await ingredientAPI.getAllForRecipe(id);
|
||||||
if (result.length) setIngredientData(result);
|
if (result.length) setIngredientData(result);
|
||||||
})
|
})();
|
||||||
|
|
||||||
const selfAuthored = (recipe.authoruserid == user.id!);
|
const selfAuthored = (recipe.authoruserid == user.id!);
|
||||||
if (selfAuthored) {
|
if (selfAuthored) {
|
||||||
@@ -61,7 +64,7 @@ export default function Recipe() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!userData) return;
|
if (!userData) return;
|
||||||
|
|
||||||
if (recipe && recipe !== "no recipe") {
|
if (recipe && ingredientData && recipe !== "no recipe") {
|
||||||
setView(
|
setView(
|
||||||
<Protect redirect={`/recipe/${id}`}>
|
<Protect redirect={`/recipe/${id}`}>
|
||||||
<h1>{recipe.name}</h1>
|
<h1>{recipe.name}</h1>
|
||||||
@@ -75,8 +78,11 @@ export default function Recipe() {
|
|||||||
|
|
||||||
<h2>Ingredients:</h2>
|
<h2>Ingredients:</h2>
|
||||||
{ ingredientData.length
|
{ ingredientData.length
|
||||||
? ingredientData.map((each: IIngredient) => <p>{each.name}</p>)
|
? ingredientData.map((each: RecipeIngredient) => (
|
||||||
: "No ingredients for this recipe"
|
<div key={v4()}>
|
||||||
|
<p>{each.quantity} {each.quantity == 1 ? each.unit : (each.unit + "s")} {each.name}</p>
|
||||||
|
</div>
|
||||||
|
)) : <p>No ingredients for this recipe</p>
|
||||||
}
|
}
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
@@ -86,7 +92,7 @@ export default function Recipe() {
|
|||||||
</Protect>
|
</Protect>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [userData, ingredientData]);
|
}, [userData, recipe, ingredientData]);
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
|
import { useAuthContext } from "../../context/AuthContext";
|
||||||
import Protect from "../../util/Protect";
|
import Protect from "../../util/Protect";
|
||||||
import Form from "./Form/Form";
|
import Form from "./Form/Form";
|
||||||
|
|
||||||
@@ -9,6 +10,8 @@ interface BrowserProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Browser: FC<BrowserProps> = ({ children, header, searchFunction }) => {
|
const Browser: FC<BrowserProps> = ({ children, header, searchFunction }) => {
|
||||||
|
const { user, token } = useAuthContext();
|
||||||
|
|
||||||
const [form, setForm] = useState<any>();
|
const [form, setForm] = useState<any>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import Form from "./Form/Form";
|
|||||||
import Navbar from "./Navbar";
|
import Navbar from "./Navbar";
|
||||||
import Page from "./Page";
|
import Page from "./Page";
|
||||||
import Panel from "./Panel";
|
import Panel from "./Panel";
|
||||||
|
import RichText from "./RichText";
|
||||||
import TextField from "./TextField";
|
import TextField from "./TextField";
|
||||||
|
import Toast from "./Toast";
|
||||||
import Tooltip from "./Tooltip";
|
import Tooltip from "./Tooltip";
|
||||||
import UserCard from "./UserCard";
|
import UserCard from "./UserCard";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Button, Card, Dropdown, Divider, Form, Navbar, Page, Panel, TextField, Tooltip, UserCard
|
Button, Card, Dropdown, Divider, Form, Navbar, Page, Panel, RichText, TextField, Toast, Tooltip, UserCard
|
||||||
}
|
}
|
||||||
@@ -56,29 +56,66 @@ module API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getAll() {
|
async getAll() {
|
||||||
const response = await this.instance.get(this.endpoint, this.headers);
|
const response = await this.instance.get(this.endpoint, this.headers)
|
||||||
return Promise.resolve(response.data);
|
.catch((err: AxiosError) => {
|
||||||
|
console.log(err.message);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return Promise.resolve(response?.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getByID(id: string) {
|
async getByID(id: string) {
|
||||||
const response = await this.instance.get(this.endpoint + "/" + id, this.headers);
|
const response = await this.instance.get(this.endpoint + "/" + id, this.headers)
|
||||||
return Promise.resolve(response.data);
|
.catch((err: AxiosError) => {
|
||||||
|
console.log(err.message);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return Promise.resolve(response?.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
async post(data: T) {
|
async post(data: T) {
|
||||||
console.log(data);
|
try {
|
||||||
const response = await this.instance.post(this.endpoint, data, this.headers);
|
const response = await this.instance.post(this.endpoint, JSON.stringify(data), this.headers);
|
||||||
return Promise.resolve(response.data);
|
return Promise.resolve(response.data);
|
||||||
|
} catch(e: any) {
|
||||||
|
if (e instanceof AxiosError) {
|
||||||
|
const error = e as AxiosError;
|
||||||
|
if (error.message) {
|
||||||
|
console.log(error.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async put(id: string, data: T | Partial<T>) {
|
async put(id: string, data: T | Partial<T>) {
|
||||||
const response = await this.instance.put(this.endpoint + "/" + id, JSON.stringify(data), this.headers);
|
try {
|
||||||
return Promise.resolve(response.data);
|
const response = await this.instance.put(this.endpoint + "/" + id, JSON.stringify(data), this.headers);
|
||||||
|
return Promise.resolve(response.data);
|
||||||
|
} catch(e: any) {
|
||||||
|
if (e instanceof AxiosError) {
|
||||||
|
const error = e as AxiosError;
|
||||||
|
if (error.message) {
|
||||||
|
console.log(error.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string) {
|
async delete(id: string) {
|
||||||
const response = await this.instance.delete(this.endpoint + '/' + id, this.headers);
|
try {
|
||||||
return Promise.resolve(response.data);
|
const response = await this.instance.delete(this.endpoint + '/' + id, this.headers);
|
||||||
|
return Promise.resolve(response.data);
|
||||||
|
} catch(e: any) {
|
||||||
|
if (e instanceof AxiosError) {
|
||||||
|
const error = e as AxiosError;
|
||||||
|
if (error.message) {
|
||||||
|
console.log(error.message);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,19 +178,6 @@ module API {
|
|||||||
super(Settings.getAPISTRING() + "/app/friend", token);
|
super(Settings.getAPISTRING() + "/app/friend", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
override async getAll() {
|
|
||||||
try {
|
|
||||||
const response = await this.instance.get(this.endpoint, this.headers);
|
|
||||||
return Promise.resolve(response.data);
|
|
||||||
} catch(e) {
|
|
||||||
const error = e as AxiosError;
|
|
||||||
if (error.response?.status == 404) {
|
|
||||||
console.log('no friends found');
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getTargetUserFriendships(id: string | number) {
|
async getTargetUserFriendships(id: string | number) {
|
||||||
try {
|
try {
|
||||||
const response = await this.instance.get(this.endpoint + `?targetUser=${id}`, this.headers);
|
const response = await this.instance.get(this.endpoint + `?targetUser=${id}`, this.headers);
|
||||||
@@ -189,8 +213,12 @@ module API {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async addIngredientToRecipe(ingredient: RecipeIngredient, recipeid: string | number) {
|
async addIngredientToRecipe(ingredient: RecipeIngredient, recipeid: string | number) {
|
||||||
const response = await this.instance.post(this.endpoint + `?addIngredients=true&recipeID=${recipeid}`, JSON.stringify(ingredient), this.headers);
|
const response = await this.instance.post(this.endpoint + `?addIngredients=true&recipeID=${recipeid}`, JSON.stringify(ingredient), this.headers)
|
||||||
return Promise.resolve(response.data);
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return Promise.resolve(response?.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ instance.interceptors.response.use((res: AxiosResponse<any,any>) => {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
return Promise.reject(err);
|
console.log(err);
|
||||||
|
// return err;
|
||||||
|
// return Promise.reject(err);
|
||||||
})
|
})
|
||||||
|
|
||||||
export default instance;
|
export default instance;
|
||||||
2
dev.sh
Normal file
2
dev.sh
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
concurrently "cd server && npm run dev" "cd client && npm run dev"
|
||||||
24
package.json
Normal file
24
package.json
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "recipe-manager",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A concept developed by Mikayla Dobson",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"dev": "bash dev.sh"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/innocuous-symmetry/recipe-manager.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/innocuous-symmetry/recipe-manager/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/innocuous-symmetry/recipe-manager#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"concurrently": "^7.6.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,17 @@ export default class IngredientCtl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAllForRecipe(recipeid: string) {
|
||||||
|
try {
|
||||||
|
const result = await IngredientInstance.getAllForRecipe(recipeid);
|
||||||
|
const ok = result !== null;
|
||||||
|
const code = ok ? StatusCode.OK : StatusCode.NotFound;
|
||||||
|
return new ControllerResponse(code, (result || "No ingredient found with this recipe ID"));
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async getOne(id: string) {
|
async getOne(id: string) {
|
||||||
try {
|
try {
|
||||||
const result = await IngredientInstance.getOne(id);
|
const result = await IngredientInstance.getOne(id);
|
||||||
|
|||||||
@@ -25,6 +25,17 @@ export class Ingredient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getAllForRecipe(recipeid: string) {
|
||||||
|
try {
|
||||||
|
const statement = `SELECT * FROM recipin.cmp_recipeingredient WHERE recipeid = $1`;
|
||||||
|
const result = await pool.query(statement, [recipeid]);
|
||||||
|
if (result.rows.length) return result.rows[0];
|
||||||
|
return null;
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async post(data: IIngredient) {
|
async post(data: IIngredient) {
|
||||||
try {
|
try {
|
||||||
const statement = `
|
const statement = `
|
||||||
|
|||||||
@@ -10,9 +10,16 @@ export const ingredientRoute = (app: Express) => {
|
|||||||
app.use('/app/ingredient', router);
|
app.use('/app/ingredient', router);
|
||||||
|
|
||||||
router.get('/', async (req, res, next) => {
|
router.get('/', async (req, res, next) => {
|
||||||
|
const { recipeID } = req.query;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result: CtlResponse<IIngredient[] | string> = await IngredientInstance.getAll();
|
if (recipeID) {
|
||||||
res.status(result.code).send(result.data);
|
const result = await IngredientInstance.getAllForRecipe(recipeID as string);
|
||||||
|
res.status(result.code).send(result.data);
|
||||||
|
} else {
|
||||||
|
const result: CtlResponse<IIngredient[] | string> = await IngredientInstance.getAll();
|
||||||
|
res.status(result.code).send(result.data);
|
||||||
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
next(e);
|
next(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ export const recipeRoute = (app: Express) => {
|
|||||||
const data = req.body;
|
const data = req.body;
|
||||||
const { addIngredients, recipeID } = req.query;
|
const { addIngredients, recipeID } = req.query;
|
||||||
|
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (addIngredients) {
|
if (addIngredients) {
|
||||||
const result = await recipectl.addIngredientToRecipe(data, recipeID as string);
|
const result = await recipectl.addIngredientToRecipe(data, recipeID as string);
|
||||||
|
|||||||
Reference in New Issue
Block a user