From beff9736446c9414c8b428968ef0b162781aceff Mon Sep 17 00:00:00 2001 From: George Gebbett Date: Mon, 1 Apr 2024 17:21:58 +0100 Subject: [PATCH] Reinstate the usage of any use-any-unit (#474) --- .../grocy/procedures/createRecipeInGrocy.ts | 19 +++++++++- .../procedures/createRecipeInGrocySchema.ts | 2 +- .../grocy/procedures/getGrocyProducts.ts | 18 ++------- .../modules/grocy/service/getGrocyProducts.ts | 18 +++++++++ src/trpc/react.tsx | 38 ++++++++++++++++++- 5 files changed, 76 insertions(+), 19 deletions(-) create mode 100644 src/server/api/modules/grocy/service/getGrocyProducts.ts diff --git a/src/server/api/modules/grocy/procedures/createRecipeInGrocy.ts b/src/server/api/modules/grocy/procedures/createRecipeInGrocy.ts index 3ad87c0..547c0e2 100644 --- a/src/server/api/modules/grocy/procedures/createRecipeInGrocy.ts +++ b/src/server/api/modules/grocy/procedures/createRecipeInGrocy.ts @@ -3,6 +3,7 @@ import { UnignoredIngredient, } from "~/server/api/modules/grocy/procedures/createRecipeInGrocySchema" import { grocyFetch } from "~/server/api/modules/grocy/service/client" +import { getGrocyProducts } from "~/server/api/modules/grocy/service/getGrocyProducts" import { deleteRecipe } from "~/server/api/modules/recipes/service/deleteRecipe" import { protectedProcedure } from "~/server/api/trpc" import normalizeUrl from "normalize-url" @@ -17,6 +18,8 @@ export const createRecipeInGrocyProcedure = protectedProcedure .mutation(async ({ input }) => { let imageFilename: string | undefined = undefined + const grocyProducts = await getGrocyProducts() + if (input.imageUrl) { const normalised = normalizeUrl(input.imageUrl, { removeQueryParameters: true, @@ -70,17 +73,27 @@ export const createRecipeInGrocyProcedure = protectedProcedure const recipeId = z.coerce.string().parse(recipeJson.created_object_id) const filteredIngredients = input.ingredients.filter( - (a): a is UnignoredIngredient => a.ignored === false + (a): a is UnignoredIngredient => !a.ignored ) for (const ingredient of filteredIngredients) { logger.info(ingredient, `Creating ingredient [${ingredient.scrapedName}]`) + const grocyProduct = grocyProducts.find( + (a) => a.id === ingredient.productId + ) + + if (!grocyProduct) continue + + const useAnyUnit: "1" | "0" = + ingredient.unitId === grocyProduct.qu_id_stock ? "0" : "1" + const body = { recipe_id: recipeId, product_id: ingredient.productId, amount: ingredient.amount, qu_id: ingredient.unitId, + only_check_single_unit_in_stock: useAnyUnit, } const ingredientResponse = await grocyFetch("/objects/recipes_pos", { @@ -91,6 +104,10 @@ export const createRecipeInGrocyProcedure = protectedProcedure const ingredientJson = await ingredientResponse.json() + if (!ingredientResponse.ok) { + throw new Error(ingredientJson.error_message ?? "An error occurred") + } + logger.info(ingredientJson, "Ingredient created") } diff --git a/src/server/api/modules/grocy/procedures/createRecipeInGrocySchema.ts b/src/server/api/modules/grocy/procedures/createRecipeInGrocySchema.ts index b633816..eae1e05 100644 --- a/src/server/api/modules/grocy/procedures/createRecipeInGrocySchema.ts +++ b/src/server/api/modules/grocy/procedures/createRecipeInGrocySchema.ts @@ -7,7 +7,7 @@ const IgnoredIngredientSchema = z.object({ const UnignoredIngredientSchema = z.object({ productId: z.string(), - amount: z.number(), + amount: z.coerce.number(), unitId: z.string(), scrapedName: z.string(), ignored: z.literal(false), diff --git a/src/server/api/modules/grocy/procedures/getGrocyProducts.ts b/src/server/api/modules/grocy/procedures/getGrocyProducts.ts index 5099b90..62b8bbc 100644 --- a/src/server/api/modules/grocy/procedures/getGrocyProducts.ts +++ b/src/server/api/modules/grocy/procedures/getGrocyProducts.ts @@ -1,17 +1,5 @@ -import { grocyFetch } from "~/server/api/modules/grocy/service/client" +import { getGrocyProducts } from "~/server/api/modules/grocy/service/getGrocyProducts" import { protectedProcedure } from "~/server/api/trpc" -import z from "zod" -const grocyProductSchema = z.object({ - id: z.coerce.string(), - name: z.string(), - qu_id_stock: z.coerce.string(), -}) - -export const getGrocyProductsProcedure = protectedProcedure.query(async () => { - const prods = await grocyFetch("/objects/products", { cache: "no-cache" }) - - const json = await prods.json() - - return grocyProductSchema.array().parse(json) -}) +export const getGrocyProductsProcedure = + protectedProcedure.query(getGrocyProducts) diff --git a/src/server/api/modules/grocy/service/getGrocyProducts.ts b/src/server/api/modules/grocy/service/getGrocyProducts.ts new file mode 100644 index 0000000..739faf5 --- /dev/null +++ b/src/server/api/modules/grocy/service/getGrocyProducts.ts @@ -0,0 +1,18 @@ +import { grocyFetch } from "~/server/api/modules/grocy/service/client" +import z from "zod" + +const grocyProductSchema = z.object({ + id: z.coerce.string(), + name: z.string(), + qu_id_stock: z.coerce.string(), +}) + +type GrocyProduct = z.infer + +export const getGrocyProducts = async (): Promise => { + const prods = await grocyFetch("/objects/products", { cache: "no-cache" }) + + const json = await prods.json() + + return grocyProductSchema.array().parse(json) +} diff --git a/src/trpc/react.tsx b/src/trpc/react.tsx index 7a283a2..c82d8b5 100644 --- a/src/trpc/react.tsx +++ b/src/trpc/react.tsx @@ -1,10 +1,16 @@ "use client" import { useState } from "react" -import { QueryClient, QueryClientProvider } from "@tanstack/react-query" +import { + MutationCache, + QueryCache, + QueryClient, + QueryClientProvider, +} from "@tanstack/react-query" import { loggerLink, unstable_httpBatchStreamLink } from "@trpc/client" import { createTRPCReact } from "@trpc/react-query" import { type AppRouter } from "~/server/api/root" +import { toast } from "sonner" import { getUrl, transformer } from "./shared" @@ -14,7 +20,35 @@ export function TRPCReactProvider(props: { children: React.ReactNode cookies: string }) { - const [queryClient] = useState(() => new QueryClient()) + const [queryClient] = useState( + () => + new QueryClient({ + queryCache: new QueryCache({ + onError: (error, query) => { + if (query.state.data !== undefined) { + const title = + (query.meta?.title as string) ?? "Something went wrong" + const description = + (query.meta?.description as string) ?? + (error instanceof Error && `${error.message}`) + + toast.error(title, { description }) + } + }, + }), + mutationCache: new MutationCache({ + onError: (error, _, __, mutation) => { + const title = + (mutation.meta?.title as string) ?? "Something went wrong" + const description = + (mutation.meta?.description as string) ?? + (error instanceof Error && `${error.message}`) + + toast.error(title, { description }) + }, + }), + }) + ) const [trpcClient] = useState(() => api.createClient({