import { TRPCError } from "@trpc/server"; import { and, desc, eq, inArray, notExists } from "drizzle-orm"; import { z, ZodNull } from "zod"; import { SqliteError } from "@lifetracker/db"; import { colors, metrics, measurements, hours } 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"; export const measurementsAppRouter = router({ list: authedProcedure .input(z.object({ hourId: z.string() })) .output(z.array(zMeasurementSchema)) .query(async ({ input, ctx }) => { const dbMeasurements = await ctx.db .select() .from(measurements) .leftJoin(hours, eq(measurements.hourId, hours.id)) .where(and(eq(measurements.userId, ctx.user.id), eq(hours.id, input.hourId)) ); console.log(dbMeasurements.length); return dbMeasurements; }), incrementCount: authedProcedure .input(z.object({ metricId: z.string(), hourId: z.string(), dayId: z.string() })) .output(zMeasurementSchema) .mutation(async ({ input, ctx }) => { const metric = await ctx.db.select().from(metrics).where(eq(metrics.id, input.metricId)); if (!metric[0]) { throw new TRPCError({ code: "NOT_FOUND", message: "Metric not found", }); } // Check if there is a measurement for this metric in this hour, if so, increment it, if not, create it with value 1 const existingMeasurement = await ctx.db.select().from(measurements).where(and( eq(measurements.metricId, input.metricId), eq(measurements.hourId, input.hourId), )); if (existingMeasurement[0]) { const updatedMeasurement = await ctx.db.update(measurements).set({ value: (parseInt(existingMeasurement[0].value) + 1).toString(), }).where(eq(measurements.id, existingMeasurement[0].id)).returning(); return { ...updatedMeasurement[0], icon: metric[0].icon, metricName: metric[0].name, }; } else { const newMeasurement = await ctx.db.insert(measurements).values({ metricId: input.metricId, hourId: input.hourId, dayId: input.dayId, value: 1, userId: ctx.user.id, }).returning(); return { ...newMeasurement[0], icon: metric[0].icon, metricName: metric[0].name, }; } }), decrementCount: authedProcedure .input(z.object({ metricId: z.string(), hourId: z.string() })) .output(zMeasurementSchema.optional()) .mutation(async ({ input, ctx }) => { const metric = await ctx.db.select().from(metrics).where(eq(metrics.id, input.metricId)); if (!metric[0]) { throw new TRPCError({ code: "NOT_FOUND", message: "Metric not found", }); } // Check if there is a measurement for this metric in this hour, if so, decrement it, if not, throw an error const existingMeasurement = await ctx.db.select().from(measurements).where(and( eq(measurements.metricId, input.metricId), eq(measurements.hourId, input.hourId), )); if (existingMeasurement[0]) { if (parseInt(existingMeasurement[0].value) > 1) { const updatedMeasurement = await ctx.db.update(measurements).set({ value: (parseInt(existingMeasurement[0].value) - 1).toString(), }).where(eq(measurements.id, existingMeasurement[0].id)).returning(); return { ...updatedMeasurement[0], icon: metric[0].icon, metricName: metric[0].name, }; } else { // Delete the measurement if it's zerooo await ctx.db.delete(measurements).where(eq(measurements.id, existingMeasurement[0].id)); } } else { throw new TRPCError({ code: "NOT_FOUND", message: "Measurement not found", }); } }), });