Fix dashboard for hour.datetime

This commit is contained in:
Ryan Pandya 2025-02-01 14:47:45 -08:00
parent fbfbdbefee
commit 4222c910eb
6 changed files with 26 additions and 21 deletions

View File

@ -57,7 +57,7 @@ export default function CategoriesView() {
<TableCell className="py-1">{c.name}</TableCell> <TableCell className="py-1">{c.name}</TableCell>
<TableCell className="py-1">{c.description}</TableCell> <TableCell className="py-1">{c.description}</TableCell>
<TableCell className="py-1"> <TableCell className="py-1">
categoryStats[c.id].numEntries {c.id}
</TableCell> </TableCell>
<TableCell className="flex gap-1 py-1"> <TableCell className="flex gap-1 py-1">
<ActionButtonWithTooltip <ActionButtonWithTooltip

View File

@ -49,7 +49,7 @@ export function EditableHourCode({
} }
onSubmit({ onSubmit({
date: hour.date, date: hour.date,
hourTime: hour.time, datetime: hour.datetime,
dayId: hour.dayId, dayId: hour.dayId,
code: newCode ?? "", code: newCode ?? "",
comment: hour.comment, comment: hour.comment,

View File

@ -46,7 +46,7 @@ export function EditableHourComment({
setText(ref.current?.value ?? originalText); setText(ref.current?.value ?? originalText);
onSubmit({ onSubmit({
date: hour.date, date: hour.date,
hourTime: hour.time, datetime: hour.datetime,
dayId: hour.dayId, dayId: hour.dayId,
comment: ref.current?.value ?? "", comment: ref.current?.value ?? "",
code: hour.categoryCode.toString(), code: hour.categoryCode.toString(),

View File

@ -16,6 +16,7 @@ import { Trash, X } from "lucide-react";
import { useDecrementCount, useIncrementCount, useSetValue, } from "@lifetracker/shared-react/hooks/measurements"; import { useDecrementCount, useIncrementCount, useSetValue, } from "@lifetracker/shared-react/hooks/measurements";
import { Separator } from "@radix-ui/react-dropdown-menu"; import { Separator } from "@radix-ui/react-dropdown-menu";
import { EditableText } from "../EditableText"; import { EditableText } from "../EditableText";
import spacetime from "spacetime";
interface CreateMeasurementSchema { interface CreateMeasurementSchema {
type: string; type: string;
@ -168,31 +169,33 @@ export default function HourMeasurementsDialog({
<DialogTrigger asChild>{children}</DialogTrigger> <DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle>Metrics for {hour.date} at {hour.datetime}</DialogTitle> <DialogTitle>Metrics for <span className={"secondary"}>{hour.date}</span> at {spacetime(hour.datetime).format("{hour} {ampm}")}</DialogTitle>
</DialogHeader> </DialogHeader>
<Separator /> <Separator />
{(hour.measurements && hour.measurements.length > 0) || pendingMeasurement ? {(hour.measurements && hour.measurements.length > 0) || pendingMeasurement ?
(<> (<>
{/* <div className="font-bold">Measurements</div> */} {/* <div className="font-bold">Measurements</div> */}
<div className="mx-4 mb-4"> <div className="mx-4 mb-4">
{hour.measurements.map(measurement => { {hour.measurements!.map(measurement => {
const metric = metrics.find(m => m.id === measurement.metricId); const metric = metrics.find(m => m.id === measurement.metricId);
if (metric!.type === "timeseries") { if (metric!.type === "timeseries") {
return ( return (
<div key={measurement.id} className="flex items-center justify-between"> <div key={measurement.id} className="flex items-center justify-between">
<div className="gap-4 flex"><Icon name={titleCase(metric.icon)} size={24} /> <div className="gap-4 flex"><Icon name={titleCase(metric!.icon)} size={24} />
<div>{metric.name}</div></div> <div>{metric!.name}</div></div>
<div className="flex gap-4 items-center"> <div className="flex gap-4 items-center">
<EditableText originalText={measurement.value + " " + metric?.unit} onSave={(value) => { <EditableText
isSaving={false}
originalText={measurement.value + " " + metric?.unit} onSave={(value) => {
setValue({ setValue({
metricId: metric.id, metricId: metric!.id,
hourId: hour.id, hourId: hour.id!,
dayId: hour.dayId, dayId: hour.dayId,
value: parseFloat(value), value: parseFloat(value!),
}); });
}} /> }} />
<Trash size={16} color="red" onClick={() => { <Trash size={16} color="red" onClick={() => {
decrement({ metricId: metric.id, hourId: hour.id, dayId: hour.dayId }); decrement({ metricId: metric!.id!, hourId: hour.id! });
}} /> }} />
</div> </div>

View File

@ -154,7 +154,7 @@ export const hoursAppRouter = router({
.input( .input(
z.object({ z.object({
date: z.string(), date: z.string(),
hourTime: z.number(), datetime: z.date(),
dayId: z.string(), dayId: z.string(),
code: z.string().nullish(), code: z.string().nullish(),
comment: z.string().nullable().optional(), comment: z.string().nullable().optional(),
@ -205,7 +205,7 @@ export const hoursAppRouter = router({
.set(newProps) .set(newProps)
.where( .where(
and( and(
eq(hours.time, input.hourTime), eq(hours.datetime, input.datetime),
eq(hours.dayId, input.dayId), eq(hours.dayId, input.dayId),
eq(hours.userId, ctx.user!.id) eq(hours.userId, ctx.user!.id)
) )
@ -216,7 +216,7 @@ export const hoursAppRouter = router({
// ...hourRes[0] // ...hourRes[0]
// }; // };
return hourJoinsQuery(ctx, input.hourTime, input.dayId,); return hourJoinsQuery(ctx, input.datetime, input.dayId,);
}), }),

View File

@ -1,5 +1,5 @@
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { and, desc, eq, inArray, notExists } from "drizzle-orm"; import { and, asc, desc, eq, inArray, notExists } from "drizzle-orm";
import { z } from "zod"; import { z } from "zod";
import { DatabaseError, ErrorCodes } from "@lifetracker/db"; import { DatabaseError, ErrorCodes } from "@lifetracker/db";
@ -17,7 +17,9 @@ export const metricsAppRouter = router({
const dbMeasurements = await ctx.db const dbMeasurements = await ctx.db
.select() .select()
.from(metrics) .from(metrics)
.where(eq(metrics.userId, ctx.user.id)); .where(eq(metrics.userId, ctx.user.id))
.orderBy(asc(metrics.name))
;
return dbMeasurements; return dbMeasurements;
}), }),