Skip to content

Commit

Permalink
Add edit functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Andreasgdp committed Oct 20, 2023
1 parent 0c85050 commit 17c47f6
Show file tree
Hide file tree
Showing 16 changed files with 650 additions and 84 deletions.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"contentlayer": "^0.3.4",
"date-fns": "^2.30.0",
"langchain": "^0.0.153",
"lodash": "^4.17.21",
"lucide-react": "^0.279.0",
"next": "13.5.2",
"next-contentlayer": "^0.3.4",
Expand All @@ -102,6 +103,7 @@
"simplebar-react": "^3.2.4",
"sonner": "^1.0.3",
"stripe": "^13.7.0",
"superjson": "^2.0.0",
"tailwind-merge": "^1.14.0",
"tailwindcss": "3.3.3",
"tailwindcss-animate": "^1.0.7",
Expand All @@ -117,6 +119,7 @@
"@faker-js/faker": "^8.1.0",
"@ianvs/prettier-plugin-sort-imports": "^4.1.0",
"@types/eslint": "^8.44.3",
"@types/lodash": "^4.14.200",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"@typescript-eslint/parser": "^6.7.4",
"eslint": "8.51.0",
Expand Down
46 changes: 32 additions & 14 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 5 additions & 7 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ datasource db {
model Recipe {
id String @id @default(cuid())
title String
description String? @db.LongText
description String @db.LongText
isPublic Boolean @default(false)
userId String
timeInKitchen Int?
waitingTime Int?
numberOfPeople Int?
timeInKitchen Int
waitingTime Int
numberOfPeople Int
ratings RecipeRating[]
ingredients IngredientsOnRecipes[]
steps Step[]
Expand All @@ -40,7 +40,7 @@ model RecipeRating {
model Ingredient {
id String @id @default(cuid())
name String
unit String?
unit String
userId String
recipes IngredientsOnRecipes[]
}
Expand All @@ -52,12 +52,10 @@ model IngredientsOnRecipes {
recipeId String
quantity Float
assignedAt DateTime @default(now())
assignedBy String?
@@id([ingredientId, recipeId])
@@index([ingredientId])
@@index([recipeId])
@@index([assignedBy])
}

model Step {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { RecipeSkeleton } from '@/components/skeleton/RecipeSkeleton';

export default function RecipeLoading() {
return <RecipeSkeleton />;
}
15 changes: 15 additions & 0 deletions src/app/(dashboard)/dashboard/recipe/[recipeId]/edit/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ErrorCard } from '@/components/cards/error-card';
import { Shell } from '@/components/shells/shell';

export default function RecipeNotFound() {
return (
<Shell variant="centered" className="max-w-md">
<ErrorCard
title="Recipe not found"
description="The recipe you are looking for does not exist."
retryLink="/recipes"
retryLinkText="Go to Recipes"
/>
</Shell>
);
}
68 changes: 68 additions & 0 deletions src/app/(dashboard)/dashboard/recipe/[recipeId]/edit/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { serverClient } from '@/app/_trpc/serverClient';

Check warning on line 1 in src/app/(dashboard)/dashboard/recipe/[recipeId]/edit/page.tsx

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (master)

❌ New issue: Complex Conditional

ProductPage has 1 complex conditionals with 2 branches, threshold = 2. A complex conditional is an expression inside a branch (e.g. if, for, while) which consists of multiple, logical operators such as AND/OR. The more logical operators in an expression, the more severe the code smell.
import { EditRecipeForm } from '@/components/forms/recipe/UpdateRecipeForm';
import { Breadcrumbs } from '@/components/pagers/breadcrumbs';
import { Shell } from '@/components/shells/shell';
import { toTitleCase } from '@/lib/utils';
import { currentUser } from '@clerk/nextjs/server';
import { notFound } from 'next/navigation';

interface ProductPageProps {
params: {
recipeId: string;
};
}

export async function generateMetadata({ params }: ProductPageProps) {
if (!params.recipeId) {
return {};
}

const recipe = await serverClient.recipe
.getRecipe({ id: params.recipeId })
.catch(() => null);

if (!recipe) {
return {};
}

return {
title: toTitleCase(recipe.title),
description: recipe.description ?? undefined,
};
}

export default async function ProductPage({
params,
}: Readonly<ProductPageProps>) {
if (!params.recipeId) {
notFound();
}

const user = await currentUser();

const recipe = await serverClient.recipe
.getRecipe({ id: params.recipeId })
.catch(() => null);

if (!recipe || !user || recipe.userId !== user.id) {
notFound();
}

return (
<Shell>
<Breadcrumbs
segments={[
{
title: 'My Recipes',
href: '/dashboard/recipes',
},
{
title: recipe.title,
href: `/dashboard/recipe/${recipe.id}`,
},
]}
/>
<EditRecipeForm recipeId={recipe.id} initialRecipe={recipe} />
</Shell>
);
}
2 changes: 1 addition & 1 deletion src/app/(dashboard)/dashboard/recipes/new/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AddRecipeForm } from '@/components/forms/add-recipe-form';
import { AddRecipeForm } from '@/components/forms/recipe/AddRecipeForm';
import {
PageHeader,
PageHeaderDescription,
Expand Down
12 changes: 10 additions & 2 deletions src/app/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,19 @@ export async function createRecipeRevalidate() {
revalidatePath('/dashboard/recipes');
}

export async function updateRecipeRevalidate(id: string) {
revalidatePath('/recipes');
revalidatePath(`/recipe/${id}`);
revalidatePath(`/dashboard/recipes`);
revalidatePath(`/dashboard/recipe/${id}`);
revalidatePath(`/dashboard/recipe/${id}/edit`);
}

export async function deleteRecipeRevalidate(id: string) {
revalidatePath('/recipes');
revalidatePath(`/recipes/${id}`);
revalidatePath(`/recipe/${id}`);
revalidatePath(`/dashboard/recipes`);
revalidatePath(`/dashboard/recipes/${id}`);
revalidatePath(`/dashboard/recipe/${id}`);
}

// For development
Expand Down
30 changes: 15 additions & 15 deletions src/components/forms/add-recipe-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { toast } from 'sonner';
import type { z } from 'zod';
import { Separator } from '../ui/separator';

type Inputs = z.infer<typeof createRecipeInput>;
export type RecipeFormInput = z.infer<typeof createRecipeInput>;

export function AddRecipeForm() {
const router = useRouter();
Expand All @@ -34,21 +34,21 @@ export function AddRecipeForm() {
const createRecipe = trpc.recipe.createRecipe.useMutation();

// react-hook-form
const form = useForm<Inputs>({
const form = useForm<RecipeFormInput>({
resolver: zodResolver(createRecipeInput),
defaultValues: {
title: '',
description: '',
ingredients: [{ name: '', quantity: '1', unit: 'g' }],
steps: [{ step: '' }],
timeInKitchen: '15',
waitingTime: '30',
numberOfPeople: '2',
ingredients: [{ ingredient: { name: '', unit: 'g' }, quantity: 1 }],
steps: [{ content: '' }],
timeInKitchen: 15,
waitingTime: 30,
numberOfPeople: 2,
},
mode: 'onTouched',
});

function onSubmit(data: Inputs) {
function onSubmit(data: RecipeFormInput) {
startTransition(async () => {
try {
await createRecipe.mutateAsync(data);
Expand Down Expand Up @@ -156,7 +156,7 @@ export function AddRecipeForm() {
>
<FormField
control={form.control}
name={`ingredients.${index}.name`}
name={`ingredients.${index}.ingredient.name`}
render={({ field }) => (
<FormItem>
<FormLabel>Ingredient Name</FormLabel>
Expand Down Expand Up @@ -189,7 +189,7 @@ export function AddRecipeForm() {
/>
<FormField
control={form.control}
name={`ingredients.${index}.unit`}
name={`ingredients.${index}.ingredient.unit`}
render={({ field }) => (
<FormItem>
<FormLabel>Unit</FormLabel>
Expand All @@ -205,7 +205,7 @@ export function AddRecipeForm() {
onClick={(event) => {
event.preventDefault();
remove(index);
form.setFocus(`ingredients.${index - 1}.name`);
form.setFocus(`ingredients.${index - 1}.ingredient.name`);
}}
disabled={fields.length === 1}
>
Expand All @@ -217,7 +217,7 @@ export function AddRecipeForm() {
className="mx-auto w-fit bg-cyan-600/90 hover:bg-cyan-600"
onClick={(event) => {
event.preventDefault();
append({ name: '', quantity: '1', unit: 'g' });
append({ ingredient: { name: '', unit: 'g' }, quantity: 1 });
}}
>
<Icons.Add className="h-4 w-4" aria-hidden="true" />
Expand All @@ -236,7 +236,7 @@ export function AddRecipeForm() {
<div key={step.id} className="flex w-full justify-center gap-4">
<FormField
control={form.control}
name={`steps.${index}.step`}
name={`steps.${index}.content`}
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>Step</FormLabel>
Expand All @@ -252,7 +252,7 @@ export function AddRecipeForm() {
onClick={(event) => {
event.preventDefault();
remove(index);
form.setFocus(`steps.${index - 1}.step`);
form.setFocus(`steps.${index - 1}.content`);
}}
disabled={fields.length === 1}
>
Expand All @@ -264,7 +264,7 @@ export function AddRecipeForm() {
className="mx-auto w-fit bg-cyan-600/90 hover:bg-cyan-600"
onClick={(event) => {
event.preventDefault();
append([{ step: '' }]);
append([{ content: '' }]);
}}
>
<Icons.Add className="h-4 w-4" aria-hidden="true" />
Expand Down
Loading

0 comments on commit 17c47f6

Please sign in to comment.