lifetracker/packages/trpc/routers/measurements.ts

104 lines
4.6 KiB
TypeScript

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,
};
} 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,
};
} 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",
});
}
}),
});