feat(recipes): full recipe CRUD with photos, print, version history
List, detail, new, edit pages. Server-side pagination, dietary tags, difficulty. Photo upload to S3-compatible storage. Version history. Multi-select grid with bulk delete/visibility. Print view. Delete confirmation dialog.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import type { Metadata } from "next";
|
||||
import { headers } from "next/headers";
|
||||
import { auth } from "@/lib/auth/server";
|
||||
import { db, recipes, recipeIngredients } from "@epicure/db";
|
||||
import { eq, desc, and, ilike, or, sql } from "@epicure/db";
|
||||
import { RecipesHeader } from "@/components/recipe/recipes-header";
|
||||
import { RecipesEmptyState } from "@/components/recipe/recipes-empty-state";
|
||||
import { RecipesGrid } from "@/components/recipe/recipes-grid";
|
||||
|
||||
export const metadata: Metadata = { title: "Recipes" };
|
||||
|
||||
type SearchParams = Promise<{ q?: string }>;
|
||||
|
||||
export default async function RecipesPage({ searchParams }: { searchParams: SearchParams }) {
|
||||
const session = await auth.api.getSession({ headers: await headers() });
|
||||
if (!session) return null;
|
||||
|
||||
const { q } = await searchParams;
|
||||
const query = q?.trim() ?? "";
|
||||
|
||||
const whereClause = query
|
||||
? and(
|
||||
eq(recipes.authorId, session.user.id),
|
||||
or(
|
||||
ilike(recipes.title, `%${query}%`),
|
||||
ilike(recipes.description, `%${query}%`)
|
||||
)
|
||||
)
|
||||
: eq(recipes.authorId, session.user.id);
|
||||
|
||||
const userRecipes = await db.query.recipes.findMany({
|
||||
where: whereClause,
|
||||
orderBy: desc(recipes.updatedAt),
|
||||
with: { photos: true },
|
||||
});
|
||||
|
||||
const totalCount = query ? undefined : userRecipes.length;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<RecipesHeader count={totalCount ?? userRecipes.length} initialQuery={query} />
|
||||
|
||||
<RecipesEmptyState query={query} count={userRecipes.length} />
|
||||
|
||||
<RecipesGrid recipes={userRecipes} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user