This commit is contained in:
fred 2025-07-17 09:17:10 -07:00
parent 3510cf28a9
commit 6ad2d6d7d3
9 changed files with 26 additions and 71 deletions

View file

@ -2,7 +2,7 @@ services:
db: db:
container_name: recipes_postgres container_name: recipes_postgres
image: docker.io/library/postgres:17 image: docker.io/library/postgres:17
restart: always # restart: always
env_file: env_file:
- .env - .env
environment: environment:

View file

@ -6,6 +6,6 @@
@apply mx-auto text-center; @apply mx-auto text-center;
} }
page-outer { .page-outer {
@apply bg-amber-100 border border-amber-200 rounded-bl-lg rounded-br-lg p-6 md:p-8 lg:p-10 max-w-6xl mx-auto font-serif; @apply bg-amber-100 border border-amber-200 rounded-bl-lg rounded-br-lg p-6 md:p-8 lg:p-10 max-w-6xl mx-auto font-serif;
} }

View file

@ -1,8 +1,8 @@
import "./App.css"; import "./App.css";
import Cookbook from "./pages/Cookbook.tsx"; import Index from "./pages/Index.tsx";
import RecipePage from "./pages/RecipePage.tsx"; import RecipePage from "./pages/RecipePage.tsx";
import AddRecipe from "./pages/AddRecipe.tsx"; import AddRecipe from "./pages/AddRecipe.tsx";
import Search from "./pages/Search.tsx" import About from "./pages/About.tsx"
import RecipeBookTabs from "./components/RecipeBookTabs.tsx"; import RecipeBookTabs from "./components/RecipeBookTabs.tsx";
import { Routes, Route } from "react-router-dom"; import { Routes, Route } from "react-router-dom";
@ -13,10 +13,10 @@ function App() {
<RecipeBookTabs /> <RecipeBookTabs />
<main className="flex-1 overflow-auto"> <main className="flex-1 overflow-auto">
<Routes> <Routes>
<Route path="/" element={<Cookbook />} /> <Route path="/" element={<Index />} />
<Route path="/recipe/:id" element={<RecipePage />} /> <Route path="/recipe/:id" element={<RecipePage />} />
<Route path="/add-recipe" element={<AddRecipe />} /> <Route path="/add-recipe" element={<AddRecipe />} />
<Route path="/search" element={<Search />} /> <Route path="/about" element={<About />} />
</Routes> </Routes>
</main> </main>
</div> </div>

View file

@ -7,7 +7,6 @@ const RecipeBookTabs = () => {
const tabs = [ const tabs = [
{ id: '/', label: 'All Recipes', icon: '📚' }, { id: '/', label: 'All Recipes', icon: '📚' },
{ id: '/recipe/', label: 'Recipe', icon: '🥗' }, { id: '/recipe/', label: 'Recipe', icon: '🥗' },
{ id: '/search', label: 'Search', icon: '🔎' },
{ id: '/add-recipe', label: 'Add Recipe', icon: '' }, { id: '/add-recipe', label: 'Add Recipe', icon: '' },
{ id: '/about', label: 'About', icon: '🍽️' }, { id: '/about', label: 'About', icon: '🍽️' },
]; ];

View file

@ -0,0 +1,13 @@
function About() {
return (
<div className="about page-outer">
<div>
Hello World
</div>
</div>
)
}
export default About

View file

@ -43,7 +43,7 @@ function AddRecipe() {
}, [newRecipeId, navigate]); }, [newRecipeId, navigate]);
return ( return (
<div className="add-recipe-card bg-amber-100 border border-amber-200 rounded-bl-lg rounded-br-lg p-6 md:p-8 lg:p-10 max-w-6xl mx-auto font-serif"> <div className="add-recipe-card page-outer">
<form onSubmit={addRecipeForm} className="add-recipe-form"> <form onSubmit={addRecipeForm} className="add-recipe-form">
<input <input
type="text" type="text"

View file

@ -1,58 +0,0 @@
import CookbookRecipeTile from "../components/CookbookRecipeTile.tsx"
import { useState, useEffect } from "react";
import { getRecipes, deleteRecipe } from "../services/frontendApi.js";
import { type Recipe } from "../types/Recipe"
function Cookbook() {
const [recipes, setRecipes] = useState([]);
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(true);
const [shouldFetchRecipes, setShouldFetchRecipes] = useState(true);
useEffect(() => {
const loadRecipes = async () => {
try {
const recipes = await getRecipes();
setRecipes(recipes);
} catch (error) {
console.log(error);
setError("Failed to load recipes...");
} finally {
setLoading(false);
}
};
if (shouldFetchRecipes) {
loadRecipes().then(() => setShouldFetchRecipes(false));
}
}, [shouldFetchRecipes]);
const handleDelete = async (id: number | void) => {
try {
await deleteRecipe(id);
setShouldFetchRecipes(true);
} catch (error) {
console.error("Error deleting recipe:", error);
}
};
return (
<div className="home">
{error && <div className="error-message">{error}</div>}
{loading ? (
<div className="loading">Loading...</div>
) : (
<div className="recipe-outer bg-amber-100 p-4 md:p-8 lg:p-12">
<h1 className="text-center text-3xl sm:text-4xl md:text-5xl font-bold mb-6 text-amber-800">Recipe Index</h1>
<div className="recipes-grid grid grid-cols-1 md:grid-cols-2 gap-6 lg:gap-8">
{recipes.map((recipe) => (
<CookbookRecipeTile recipe={recipe} key={recipe.id} handleDelete={handleDelete} />
))}
</div>
</div>
)}
</div>
);
}
export default Cookbook;

View file

@ -5,7 +5,7 @@ import { getRecipes, deleteRecipe } from "../services/frontendApi.js";
function Search() { function AllRecipes() {
const [searchQuery, setSearchQuery] = useState(""); const [searchQuery, setSearchQuery] = useState("");
const [recipes, setRecipes] = useState([]); const [recipes, setRecipes] = useState([]);
const [cuisines, setCuisines] = useState([]); const [cuisines, setCuisines] = useState([]);
@ -47,10 +47,11 @@ function Search() {
return ( return (
<div className="add-recipe-card bg-amber-100 border border-amber-200 rounded-bl-lg rounded-br-lg p-6 md:p-8 lg:p-10 max-w-6xl mx-auto font-serif"> <div className="add-recipe-card bg-amber-100 border border-amber-200 rounded-bl-lg rounded-br-lg p-6 md:p-8 lg:p-10 max-w-6xl mx-auto font-serif">
<h1 className="text-center text-3xl sm:text-4xl md:text-5xl font-bold mb-6 text-amber-800">Recipe Index</h1>
<div className="cuisines-buttons flex flex-wrap justify-center"> <div className="cuisines-buttons flex flex-wrap justify-center">
<input <input
type="text" type="text"
placeholder="name" placeholder="search"
className="recipe-name mb-4 p-2 border border-gray-300 rounded w-full" className="recipe-name mb-4 p-2 border border-gray-300 rounded w-full"
value={searchQuery} value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)} onChange={(e) => setSearchQuery(e.target.value)}
@ -81,4 +82,4 @@ function Search() {
); );
} }
export default Search export default AllRecipes

View file

@ -30,7 +30,7 @@ function RecipePage() {
}, [id]); }, [id]);
console.log(recipe) console.log(recipe)
return ( return (
<div className="recipe"> <div className="recipe page-outer">
{error && <div className="error-message">{error}</div>} {error && <div className="error-message">{error}</div>}
@ -38,7 +38,7 @@ function RecipePage() {
<div className="loading">Loading...</div> <div className="loading">Loading...</div>
) : ( ) : (
<div className="recipe-card bg-amber-100 border border-amber-200 rounded-bl-lg rounded-br-lg p-6 md:p-8 lg:p-10 max-w-6xl mx-auto font-serif"> <div className="recipe-card">
<div className="border-b-2 border-amber-300 pb-4 mb-6"> <div className="border-b-2 border-amber-300 pb-4 mb-6">
<h3 className="text-2xl md:text-3xl font-bold text-amber-900 mb-2">{recipe.details.name}</h3> <h3 className="text-2xl md:text-3xl font-bold text-amber-900 mb-2">{recipe.details.name}</h3>
<p className="text-amber-700 italic text-lg">{recipe.details.cuisine}</p> <p className="text-amber-700 italic text-lg">{recipe.details.cuisine}</p>