feat: Add categories page with category card and data fetching

This commit is contained in:
Ruidy (aider) 2024-12-14 15:13:42 +01:00 committed by Ruidy
parent 2872907a98
commit e042e06b19
No known key found for this signature in database
GPG key ID: E00F51288CB857CC
6 changed files with 83 additions and 32 deletions

View file

@ -0,0 +1,30 @@
<template>
<NuxtLink
:to="`/category/${category.strCategory}`"
class="block max-w-sm rounded-lg border border-gray-200 bg-white p-6 shadow hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700"
>
<img
:src="category.strCategoryThumb"
:alt="category.strCategory"
class="mb-4 h-48 w-full object-cover rounded"
/>
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
{{ category.strCategory }}
</h5>
<p class="font-normal text-gray-700 dark:text-gray-400">
{{ category.strCategoryDescription }}
</p>
</NuxtLink>
</template>
<script setup lang="ts">
interface Category {
strCategory: string
strCategoryThumb: string
strCategoryDescription: string
}
defineProps<{
category: Category
}>()
</script>

View file

@ -0,0 +1,4 @@
export function useCategories() {
const { $client } = useNuxtApp();
return $client.listCategories.useQuery();
}

19
pages/categories.vue Normal file
View file

@ -0,0 +1,19 @@
<script setup lang="ts">
const { data: categories, status } = useCategories();
</script>
<template>
<div class="container mx-auto px-4">
<h1 class="text-4xl font-bold mb-8 text-center">Recipe Categories</h1>
<div v-if="status === 'pending'" class="text-center">Loading...</div>
<div v-else class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<category-card
v-for="category in categories"
:key="category.strCategory"
:category="category"
/>
</div>
</div>
</template>

View file

@ -0,0 +1,27 @@
import { publicProcedure, router } from "../trpc";
const { apiUrl } = useRuntimeConfig();
type Category = {
idCategory: string;
strCategory: string;
strCategoryThumb: string;
strCategoryDescription: string;
};
export const categoryRouter = router({
listCategories: publicProcedure.query(async () => {
const data = await $fetch<{ categories: Category[] }>(
new URL("categories.php", apiUrl).toString(),
);
if (!data?.categories) {
throw createError({
statusCode: 500,
statusMessage: "Failed to fetch categories",
});
}
return data.categories;
}),
});

View file

@ -1,24 +1,9 @@
import type { inferRouterOutputs } from "@trpc/server"; import type { inferRouterOutputs } from "@trpc/server";
import { z } from "zod"; import { mergeRouters } from "../trpc";
import { privateProcedure, router, mergeRouters } from "../trpc";
import { recipeRouter } from "./recipes"; import { recipeRouter } from "./recipes";
import { categoryRouter } from "./categories";
export const helloRouter = router({ export const appRouter = mergeRouters(categoryRouter, recipeRouter);
// hello: publicProcedure
hello: privateProcedure
.input(
z.object({
text: z.string().nullish(),
}),
)
.query(({ input }) => {
return {
greeting: `hello ${input?.text ?? "world"}`,
};
}),
});
export const appRouter = mergeRouters(helloRouter, recipeRouter);
// export type definition of API // export type definition of API
export type AppRouter = typeof appRouter; export type AppRouter = typeof appRouter;
export type RouterOutput = inferRouterOutputs<AppRouter>; export type RouterOutput = inferRouterOutputs<AppRouter>;

View file

@ -65,18 +65,4 @@ export const recipeRouter = router({
const recipes = parseRecipeData(data); const recipes = parseRecipeData(data);
return recipes; return recipes;
}), }),
categories: publicProcedure.query(async () => {
const data = await $fetch<{ categories: Category[] }>(
new URL("categories.php", apiUrl).toString(),
);
if (!data?.categories) {
throw createError({
statusCode: 500,
statusMessage: "Failed to fetch categories",
});
}
return data.categories;
}),
}); });