Compare commits
No commits in common. "a10f3e37c2d5dd33cbb53a7e51c835251d7955bf" and "a50497426b0471f19ff8ba459ce4ba6712f2db60" have entirely different histories.
a10f3e37c2
...
a50497426b
5 changed files with 27 additions and 64 deletions
|
|
@ -2,7 +2,6 @@ import { BrowserRouter as Router, Routes, Route } from "react-router-dom"
|
||||||
import RecipeDetailPage from "./components/recipes/RecipeDetailPage"
|
import RecipeDetailPage from "./components/recipes/RecipeDetailPage"
|
||||||
import RecipeEditPage from "./components/recipes/RecipeEditPage"
|
import RecipeEditPage from "./components/recipes/RecipeEditPage"
|
||||||
import RecipeListPage from "./components/recipes/RecipeListPage"
|
import RecipeListPage from "./components/recipes/RecipeListPage"
|
||||||
import { getRecipeAddUrlDefinition, getRecipeDetailsUrlDefinition, getRecipeEditUrlDefinition, getRootUrlDefinition } from "./routes"
|
|
||||||
|
|
||||||
import "./App.css"
|
import "./App.css"
|
||||||
|
|
||||||
|
|
@ -15,16 +14,13 @@ function App() {
|
||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
{/* Home page: list of recipes */}
|
{/* Home page: list of recipes */}
|
||||||
<Route path= {getRootUrlDefinition()} element={<RecipeListPage />} />
|
<Route path="/" element={<RecipeListPage />} />
|
||||||
|
|
||||||
{/* Detail page: shows one recipe */}
|
{/* Detail page: shows one recipe */}
|
||||||
<Route path={getRecipeDetailsUrlDefinition()} element={<RecipeDetailPage />} />
|
<Route path="/recipe/:id" element={<RecipeDetailPage />} />
|
||||||
|
|
||||||
{/* Edit page: form to edit a recipe */}
|
{/* Edit page: form to edit a recipe */}
|
||||||
<Route path={getRecipeEditUrlDefinition()} element={<RecipeEditPage />} />
|
<Route path="/recipe/:id/edit" element={<RecipeEditPage />} />
|
||||||
|
|
||||||
{/* Add page: form to add a recipe */}
|
|
||||||
<Route path={getRecipeAddUrlDefinition()} element={<RecipeEditPage />} />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { useParams, Link } from "react-router-dom"
|
||||||
import type { Recipe } from "../../types/recipe"
|
import type { Recipe } from "../../types/recipe"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { fetchRecipe } from "../../api/recipePoint"
|
import { fetchRecipe } from "../../api/recipePoint"
|
||||||
import { getRecipeEditUrl, getRecipeListUrl } from "../../routes"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -124,13 +123,13 @@ export default function RecipeDetailPage() {
|
||||||
{/* Action buttons */}
|
{/* Action buttons */}
|
||||||
<div className="button-group">
|
<div className="button-group">
|
||||||
<Link
|
<Link
|
||||||
to={ getRecipeEditUrl(recipe.id) }
|
to={`/recipe/${recipe.id}/edit`}
|
||||||
className="primary-button"
|
className="primary-button"
|
||||||
>
|
>
|
||||||
Bearbeiten
|
Bearbeiten
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to={getRecipeListUrl()}
|
to="/"
|
||||||
className="default-button"
|
className="default-button"
|
||||||
>
|
>
|
||||||
Zurueck
|
Zurueck
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { useEffect, useState } from "react"
|
||||||
import type { Recipe } from "../../types/recipe"
|
import type { Recipe } from "../../types/recipe"
|
||||||
import RecipeEditor from "./RecipeEditor"
|
import RecipeEditor from "./RecipeEditor"
|
||||||
import { fetchRecipe, createRecipe, updateRecipe } from "../../api/recipePoint"
|
import { fetchRecipe, createRecipe, updateRecipe } from "../../api/recipePoint"
|
||||||
import { getRecipeDetailUrl, getRecipeListUrl, getRootUrl } from "../../routes"
|
|
||||||
|
|
||||||
export default function RecipeEditPage() {
|
export default function RecipeEditPage() {
|
||||||
// Extract recipe ID from route params
|
// Extract recipe ID from route params
|
||||||
|
|
@ -63,10 +62,10 @@ export default function RecipeEditPage() {
|
||||||
const navigateBack = () => {
|
const navigateBack = () => {
|
||||||
if(recipe && recipe.id){
|
if(recipe && recipe.id){
|
||||||
console.log("navigating to recipe with id", recipe.id)
|
console.log("navigating to recipe with id", recipe.id)
|
||||||
navigate(getRecipeDetailUrl(recipe.id)) // go back to detail view
|
navigate("/recipe/" + recipe.id) // go back to detail view
|
||||||
} else {
|
} else {
|
||||||
console.log("navigating back to list as no recipe was selected")
|
console.log("navigating back to list as no recipe was selected")
|
||||||
navigate(getRecipeListUrl()) // no recipe -> go back to list
|
navigate("/") // no recipe -> go back to list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// error handling -> if there is no recipe, we cannot open edit view
|
// error handling -> if there is no recipe, we cannot open edit view
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import { useEffect, useState } from "react"
|
||||||
import RecipeListItem from "./RecipeListItem"
|
import RecipeListItem from "./RecipeListItem"
|
||||||
import type { Recipe } from "../../types/recipe"
|
import type { Recipe } from "../../types/recipe"
|
||||||
import { fetchRecipeList } from "../../api/recipePoint"
|
import { fetchRecipeList } from "../../api/recipePoint"
|
||||||
import { useNavigate } from "react-router-dom"
|
|
||||||
import { getRecipeAddUrl, getRecipeAddUrlDefinition, getRecipeDetailUrl } from "../../routes"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a list of recipes in a sidebar layout.
|
* Displays a list of recipes in a sidebar layout.
|
||||||
|
|
@ -11,7 +9,6 @@ import { getRecipeAddUrl, getRecipeAddUrlDefinition, getRecipeDetailUrl } from "
|
||||||
*/
|
*/
|
||||||
export default function RecipeListPage() {
|
export default function RecipeListPage() {
|
||||||
|
|
||||||
const navigate = useNavigate()
|
|
||||||
const [recipeList, setRecipeList] = useState<Recipe[]|null>(null)
|
const [recipeList, setRecipeList] = useState<Recipe[]|null>(null)
|
||||||
// load recipes once on render
|
// load recipes once on render
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -28,37 +25,24 @@ export default function RecipeListPage() {
|
||||||
loadRecipeList()
|
loadRecipeList()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const handleAdd = () => {
|
if(!recipeList) { return <div>Unable to load recipes1</div>}
|
||||||
navigate(getRecipeAddUrl())
|
|
||||||
}
|
|
||||||
if(!recipeList) { return <div>Unable to load recipes!</div>}
|
|
||||||
return (
|
return (
|
||||||
/*Contaier spanning entire screen used to center content horizontally */
|
/*Contaier spanning entire screen used to center content horizontally */
|
||||||
<div className="w-screen min-h-screen flex justify-center">
|
<div className="w-screen min-h-screen flex justify-center">
|
||||||
{/* Container defining the maximum width of the content */}
|
{/* Container defining the maximum width of the content */}
|
||||||
<div className="bg-gray-100 w-full min-h-screen max-w-5xl shadow-xl p-8">
|
<div className="bg-gray-100 w-full min-h-screen max-w-5xl shadow-xl p-8">
|
||||||
{/* Header - remains in position when scrolling */}
|
{/* Header - remains in position when scrolling */}
|
||||||
<div className="sticky bg-gray-100 top-0 left-0 right-0 pb-4 border-b-2 border-gray-300">
|
<div className="sticky bg-gray-100 top-0 left-0 right-0 mb-4">
|
||||||
<h1 className="content-title text-blue-900">Recipes</h1>
|
<h1 className="content-title text-blue-900">Recipes</h1>
|
||||||
<div className="flex columns-4 content-stretch gap-2 items-center">
|
<label>{recipeList.length} Recipes</label>
|
||||||
<label className="text-gray-500 w-2/3">{recipeList.length} Recipes</label>
|
|
||||||
<input className="input-field"
|
|
||||||
placeholder="Search"
|
|
||||||
></input>
|
|
||||||
<button className="primary-button"
|
|
||||||
onClick={handleAdd}
|
|
||||||
>
|
|
||||||
Add recipe
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/*Content - List of recipe cards */}
|
{/*Content - List of recipe cards */}
|
||||||
<div className="grid pt-4 gap-6 grid-cols-[repeat(auto-fit,minmax(220px,1fr))]">
|
<div className="grid gap-6 grid-cols-[repeat(auto-fit,minmax(220px,1fr))]">
|
||||||
{recipeList.map((recipe) => (
|
{recipeList.map((recipe) => (
|
||||||
<RecipeListItem
|
<RecipeListItem
|
||||||
key={recipe.id}
|
key={recipe.id}
|
||||||
title = {recipe.title}
|
title = {recipe.title}
|
||||||
targetPath={getRecipeDetailUrl(recipe.id)}
|
targetPath={'recipe/'+recipe.id}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
/**
|
|
||||||
* Routes for all pages
|
|
||||||
*/
|
|
||||||
// Route definitions using :id as placeholder for the id
|
|
||||||
export function getRootUrlDefinition() : string { return getRootUrl()}
|
|
||||||
export function getRecipeDetailsUrlDefinition() : string {return getRecipeDetailUrl(":id")}
|
|
||||||
export function getRecipeEditUrlDefinition() : string {return getRecipeEditUrl(":id")}
|
|
||||||
export function getRecipeAddUrlDefinition() : string {return getRecipeAddUrl()}
|
|
||||||
|
|
||||||
// URLs including id
|
|
||||||
export function getRootUrl () : string { return "/"}
|
|
||||||
export function getRecipeListUrl() : string {return getRootUrl()}
|
|
||||||
export function getRecipeDetailUrl(id: string) : string {return "/recipe/" + id}
|
|
||||||
export function getRecipeEditUrl(id: string) : string {return "/recipe/" + id + "/edit"}
|
|
||||||
export function getRecipeAddUrl() : string {return "/new-recipe"}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue