import { TRPCError } from "@trpc/server"; import { and, desc, eq, inArray, notExists } from "drizzle-orm"; import { z } from "zod"; import { DatabaseError, ErrorCodes } from "@lifetracker/db"; import { colors, metrics } from "@lifetracker/db/schema"; import { zMetricSchema, zMeasurementSchema } from "@lifetracker/shared/types/metrics"; import type { Context } from "../index"; import { authedProcedure, router } from "../index"; import { zColorSchema } from "@lifetracker/shared/types/colors"; import { titleCase } from "title-case"; export const metricsAppRouter = router({ list: authedProcedure .output(z.array(zMetricSchema)) .query(async ({ ctx }) => { const dbMeasurements = await ctx.db .select() .from(metrics) .where(eq(metrics.userId, ctx.user.id)); return dbMeasurements; }), create: authedProcedure .input(zMetricSchema) .output(zMetricSchema) .mutation(async ({ input, ctx }) => { return ctx.db.transaction(async (trx) => { try { const result = await trx .insert(metrics) .values({ name: titleCase(input.name), userId: ctx.user!.id, unit: input.unit ?? null, type: input.type, description: input.description ?? null, icon: input.icon, }) .returning(); return result[0]; } catch (e) { if (e instanceof DatabaseError) { if (e.code == ErrorCodes.UNIQUE_VIOLATION) { throw new TRPCError({ code: "BAD_REQUEST", message: "This metric already exists", }); } } throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Something went wrong", }); } }); }), update: authedProcedure .input(zMetricSchema) .output(zMetricSchema) .mutation(async ({ input, ctx }) => { return ctx.db.transaction(async (trx) => { try { const result = await trx .update(metrics) .set({ name: input.name, unit: input.unit ?? null, type: input.type, description: input.description ?? null, icon: input.icon, }) .where(eq(metrics.id, input.id)) .returning(); return result[0]; } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Something went wrong", }); } }); }), delete: authedProcedure .input(z.object({ id: z.string() })) .mutation(async ({ input, ctx }) => { return ctx.db.transaction(async (trx) => { try { const result = await trx .delete(metrics) .where(and(eq(metrics.id, input.id), eq(metrics.userId, ctx.user!.id))) } catch (e) { throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "Something went wrong", }); } }); }), });