Fix measurements api post logic for hour.datetime

This commit is contained in:
Ryan Pandya 2025-02-02 15:37:22 -08:00
parent 10b1ed944d
commit 9782d3642c
6 changed files with 89 additions and 7 deletions

View File

@ -21,8 +21,7 @@ export const POST = (req: NextRequest) =>
// })).id;
const hour = await api.hours.get({
dateQuery: datetime.format("iso-short"),
time: datetime.hour(),
dateQuery: spacetime(datetime).startOf("hour").format("iso"),
});
const obj = {

View File

@ -22,7 +22,7 @@ import { ZMetric } from "@lifetracker/shared/types/metrics";
import { Badge } from "@/components/ui/badge";
import { Icon } from "@/components/ui/icon";
import { titleCase } from "title-case";
import { useDecrementCount } from "@lifetracker/shared-react/hooks/measurements";
import { useDecrementCount, useDeleteMeasurement } from "@lifetracker/shared-react/hooks/measurements";
import { useTimezone } from "@/lib/userLocalSettings/client";
@ -98,6 +98,26 @@ export default function EditableHour({
}
});
const { mutate: deleteMeasurement } = useDeleteMeasurement({
onSuccess: (_res, req) => {
const newHour = {
...hour,
measurements: hour.measurements.filter(m => m.metricId !== req.metricId),
};
setHour(newHour);
reload(newHour);
toast({
description: "Measurement deleted!",
});
},
onError: (error) => {
toast({
description: error.message,
});
},
});
const tzOffset = spacetime.now(useTimezone()).offset() / 60;
@ -177,7 +197,10 @@ export default function EditableHour({
(<Icon name={titleCase(m.icon)} size={24}
color={hour.foreground}
tooltip={`${m.metricName}: ${m.value} ${m.unit}`}
key={m.id}
key={m.id} className="hover:cursor-no-drop"
onClick={(e) => {
deleteMeasurement({ metricId: m.metricId, hourId: hour.id });
}}
/>)
: Array.from({ length: m.value }).map((_, index) =>
<div key={`${m.id}-${index}`} className="hover:cursor-no-drop" onClick={(e) => {
@ -208,6 +231,6 @@ export default function EditableHour({
</div>
: ""}
</div>
</div>
</div >
);
}

View File

@ -13,7 +13,7 @@ import { Icon } from "@/components/ui/icon";
import { titleCase } from "title-case";
import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Trash, X } from "lucide-react";
import { useDecrementCount, useIncrementCount, useSetValue, } from "@lifetracker/shared-react/hooks/measurements";
import { useDecrementCount, useDeleteMeasurement, useIncrementCount, useSetValue, } from "@lifetracker/shared-react/hooks/measurements";
import { Separator } from "@radix-ui/react-dropdown-menu";
import { EditableText } from "../EditableText";
import spacetime from "spacetime";
@ -105,6 +105,28 @@ export default function HourMeasurementsDialog({
},
});
const { mutate: deleteMeasurement } = useDeleteMeasurement({
onSuccess: (_res, req) => {
const newHour = {
...hour,
measurements: hour.measurements.filter(m => m.metricId !== req.metricId),
};
setHour(newHour);
reload(newHour);
toast({
description: "Measurement deleted!",
});
},
onError: (error) => {
toast({
description: error.message,
});
},
});
const { mutate: decrement } = useDecrementCount({
onSuccess: (res, req) => {
const oldMeasurementIndex = hour.measurements.findIndex(m => m.metricId === req.metricId);
@ -195,7 +217,7 @@ export default function HourMeasurementsDialog({
});
}} />
<Trash size={16} color="red" onClick={() => {
decrement({ metricId: metric!.id!, hourId: hour.id! });
deleteMeasurement({ metricId: metric!.id!, hourId: hour.id! });
}} />
</div>

View File

@ -35,4 +35,16 @@ export function useDecrementCount(
return opts[0]?.onSuccess?.(res, req, meta);
},
});
}
export function useDeleteMeasurement(
...opts: Parameters<typeof api.measurements.delete.useMutation>
) {
const apiUtils = api.useUtils();
return api.measurements.delete.useMutation({
...opts[0],
onSuccess: (res, req, meta) => {
return opts[0]?.onSuccess?.(res, req, meta);
},
});
}

View File

@ -168,6 +168,30 @@ export const measurementsAppRouter = router({
});
}
}),
delete: authedProcedure
.input(z.object({ metricId: z.string(), hourId: z.string() }))
.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, delete 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]) {
await ctx.db.delete(measurements).where(eq(measurements.id, existingMeasurement[0].id));
} else {
throw new TRPCError({
code: "NOT_FOUND",
message: "Measurement not found",
});
}
}),
timeSinceLastMeasurement: authedProcedure
.input(z.object({ metricId: z.string() }))
.output(z.number())

2
todo Normal file
View File

@ -0,0 +1,2 @@
# Database
[x] Migrate to Postgres