checkpoint

This commit is contained in:
fred 2025-07-09 14:43:45 -07:00
parent 925135d08c
commit 22e2dab830
7 changed files with 155 additions and 2 deletions

View file

@ -7,7 +7,9 @@ const app = express();
app.use(cors()); // to remove cors origin error in dev TODO: remove when dockerized app.use(cors()); // to remove cors origin error in dev TODO: remove when dockerized
app.use(express.json()); app.use(express.json());
// routes // ####### ROUTES #######
// ### GET ALL RECIPES ###
app.get("/recipes", async (req, res) => { app.get("/recipes", async (req, res) => {
try { try {
const recipes = await db('recipes').select('id', 'name'); const recipes = await db('recipes').select('id', 'name');
@ -18,6 +20,7 @@ app.get("/recipes", async (req, res) => {
} }
}); });
// ### GET RECIPE ###
app.get("/recipe/:id", async (req, res) => { app.get("/recipe/:id", async (req, res) => {
const id = req.params.id const id = req.params.id
try { try {
@ -52,6 +55,7 @@ app.get("/recipe/:id", async (req, res) => {
} }
}); });
// ### ADD RECIPE ###
app.post("/add-recipe", async (req, res) => { app.post("/add-recipe", async (req, res) => {
const { name, cuisine, ingredients, steps } = req.body; const { name, cuisine, ingredients, steps } = req.body;
try { try {
@ -99,6 +103,7 @@ app.post("/add-recipe", async (req, res) => {
} }
}); });
// ### DELETE RECIPE ###
app.delete("/delete-recipe", async (req, res) => { app.delete("/delete-recipe", async (req, res) => {
const { id } = req.body; const { id } = req.body;
try { try {

View file

@ -0,0 +1,55 @@
import React, { useState } from 'react';
import { type Ingredient } from "../types/Recipe"
const BulkIngredientsForm: React.FC = () => {
const [ingredients, setIngredients] = useState<Ingredient[]>([]);
const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
// Split the input by newline to get individual ingredients
const lines = e.target.value.split('\n').filter(line => line.trim() !== '');
const pattern = /^([0-9/.]+)?\s*(\S+)\s*((\w+\s*)*)$/;
const parsedIngredients: Ingredient[] = lines.map(line => {
const parts = line.match(pattern); // Updated regex pattern for fractions
let quantity;
if (parts?.[1]) {
// Try to parse the quantity as a fraction first
const [num, denom] = parts[1].split('/');
if (denom) {
quantity = parseFloat(num) / parseFloat(denom);
} else {
quantity = parseFloat(parts[1]);
}
} else {
quantity = 0; // Default to zero if no quantity is found
}
return {
quantity: +quantity.toFixed(2),
name: parts?.[3]?.trim() || '',
unit: parts?.[2]?.trim() || ''
};
});
setIngredients(parsedIngredients);
};
return (
<div>
<p>Please enter ingredients in the following order: Quantity, Unit, Name</p> {/* Prompt for correct input format */}
<textarea
rows={4} // Adjust the number of rows based on your input size expectations
cols={50} // Adjust the number of columns based on your input width expectations
onChange={handleInputChange}
placeholder="Enter ingredients separated by newline..."
/>
<div>
<ul>
{ingredients.map((ing, index) => (
<li key={index}>{`${ing.quantity} ${ing.unit} ${ing.name}`}</li> // Changed order to quantity, unit, name
))}
</ul>
</div>
</div>
);
};
export default BulkIngredientsForm;

View file

View file

@ -0,0 +1,87 @@
import React, { useState } from 'react';
import { type Ingredient } from "../types/Recipe"
const AddIngredientsForm: React.FC = () => {
const [ingredients, setIngredients] = useState<Ingredient[]>([]);
const [newIngredient, setNewIngredient] = useState<Partial<Ingredient>>({});
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setNewIngredient(prev => ({ ...prev, [name]: value }));
};
const handleAddIngredient = () => {
if (newIngredient.name && newIngredient.quantity !== undefined && newIngredient.unit) {
setIngredients(prev => [...prev, newIngredient as Ingredient]);
setNewIngredient({});
}
};
const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleAddIngredient();
}
};
const handleIngredientsSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Here you can parse the input and convert it into ingredients
const lines = newIngredient.name?.split('\n').filter(line => line.trim() !== '');
if (lines) {
const parsedIngredients: Ingredient[] = lines.map(line => {
const parts = line.match(/^([^0-9]*)([0-9.]+)?([a-zA-Z]*)$/);
return {
name: parts?.[1]?.trim() || '',
quantity: parseFloat(parts?.[2]?.trim() || '0'),
unit: parts?.[3]?.trim() || ''
};
});
setIngredients(parsedIngredients);
}
};
return (
<div>
<form onSubmit={handleIngredientsSubmit}>
<input
type="number"
name="quantity"
placeholder="Quantity"
value={(newIngredient.quantity !== undefined ? newIngredient.quantity : '')}
onChange={handleChange}
onKeyDown={handleInputKeyDown}
/>
<select
name="unit"
value={newIngredient.unit || ''}
onChange={handleChange}
>
<option value="">Select Unit</option>
<option value="grams">Grams</option>
<option value="kilograms">Kilograms</option>
<option value="cups">Cups</option>
{/* Add more units as needed */}
</select>
<input
type="text"
name="name"
placeholder="Ingredient Name"
value={newIngredient.name || ''}
onChange={handleChange}
onKeyDown={handleInputKeyDown}
/>
<button type="button" onClick={handleAddIngredient}>Add Ingredient</button>
</form>
<div>
<ul>
{ingredients.map((ing, index) => (
<li key={index}>{`${ing.quantity} ${ing.unit} ${ing.name} `}</li>
))}
</ul>
</div>
</div>
);
};
export default AddIngredientsForm;

View file

@ -1,6 +1,8 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { addRecipe } from "../services/frontendApi.js"; import { addRecipe } from "../services/frontendApi.js";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import AddIngredientsForm from "../components/AddIngredientsForm.tsx"
import AddBulkIngredients from "../components/AddBulkIngredients.tsx"
function AddRecipe() { function AddRecipe() {
const [newRecipeId, setNewRecipeId] = useState<number | null>(null); const [newRecipeId, setNewRecipeId] = useState<number | null>(null);
@ -47,6 +49,10 @@ function AddRecipe() {
submit submit
</button> </button>
</form> </form>
<div>
<AddIngredientsForm />
<AddBulkIngredients />
</div>
</div> </div>
) )
} }

View file

@ -46,7 +46,7 @@ function Cookbook() {
) : ( ) : (
<div className="recipes-grid"> <div className="recipes-grid">
{recipes.map((recipe: Recipe) => ( {recipes.map((recipe: Recipe) => (
<CookbookRecipeTile recipe={recipe} key={recipe.id} handleDelete={handleDelete} /> <CookbookRecipeTile recipe={recipe} key={recipe.details.id} handleDelete={handleDelete} />
))} ))}
</div> </div>
)} )}