mirror of
https://github.com/rjNemo/meal_planner
synced 2026-06-06 02:26:49 +00:00
feat: Add categories page with category card and data fetching
This commit is contained in:
parent
2872907a98
commit
e042e06b19
6 changed files with 83 additions and 32 deletions
30
components/CategoryCard.vue
Normal file
30
components/CategoryCard.vue
Normal 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>
|
||||
4
composables/useCategories.ts
Normal file
4
composables/useCategories.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export function useCategories() {
|
||||
const { $client } = useNuxtApp();
|
||||
return $client.listCategories.useQuery();
|
||||
}
|
||||
19
pages/categories.vue
Normal file
19
pages/categories.vue
Normal 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>
|
||||
27
server/trpc/routers/categories.ts
Normal file
27
server/trpc/routers/categories.ts
Normal 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;
|
||||
}),
|
||||
});
|
||||
|
|
@ -1,24 +1,9 @@
|
|||
import type { inferRouterOutputs } from "@trpc/server";
|
||||
import { z } from "zod";
|
||||
import { privateProcedure, router, mergeRouters } from "../trpc";
|
||||
import { mergeRouters } from "../trpc";
|
||||
import { recipeRouter } from "./recipes";
|
||||
import { categoryRouter } from "./categories";
|
||||
|
||||
export const helloRouter = router({
|
||||
// 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 const appRouter = mergeRouters(categoryRouter, recipeRouter);
|
||||
// export type definition of API
|
||||
export type AppRouter = typeof appRouter;
|
||||
export type RouterOutput = inferRouterOutputs<AppRouter>;
|
||||
|
|
|
|||
|
|
@ -65,18 +65,4 @@ export const recipeRouter = router({
|
|||
const recipes = parseRecipeData(data);
|
||||
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;
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue