102 lines
3.7 KiB
TypeScript
102 lines
3.7 KiB
TypeScript
"use client";
|
|
import { useEffect, useState, useRef } from "react";
|
|
import { toast } from "@/components/ui/use-toast";
|
|
import { api } from "@/lib/trpc";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { TRPCClientError } from "@trpc/client";
|
|
import { useForm } from "react-hook-form";
|
|
import { z } from "zod";
|
|
import { zMeasurementSchema, ZMetric } from "@lifetracker/shared/types/metrics";
|
|
import { ZHour } from "@lifetracker/shared/types/days";
|
|
|
|
import { Icon } from "@/components/ui/icon";
|
|
import { titleCase } from "title-case";
|
|
import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
|
import { X } from "lucide-react";
|
|
import { useIncrementCount, } from "@lifetracker/shared-react/hooks/measurements";
|
|
|
|
type CreateMeasurementSchema = z.infer<typeof zMeasurementSchema>;
|
|
|
|
export default function HourMeasurementsDialog({
|
|
hour: initialHour,
|
|
metrics,
|
|
reload,
|
|
children,
|
|
}: {
|
|
hour: ZHour,
|
|
metrics: ZMetric[],
|
|
reload: (newHour: ZHour) => void,
|
|
children?: React.ReactNode;
|
|
}) {
|
|
const [hour, setHour] = useState(initialHour);
|
|
const [isOpen, onOpenChange] = useState(false);
|
|
|
|
const { mutate: increment } = useIncrementCount({
|
|
onSuccess: (res) => {
|
|
onOpenChange(false);
|
|
|
|
const oldMeasurement = hour.measurements.find(m => m.metricId === res.metricId);
|
|
const newHour = {
|
|
...hour,
|
|
measurements: oldMeasurement ? hour.measurements.map(m => m.metricId === res.metricId ? res : m) : [...hour.measurements, res],
|
|
};
|
|
|
|
reload(newHour);
|
|
toast({
|
|
description: "Measurement added!",
|
|
});
|
|
},
|
|
onError: (error) => {
|
|
toast({
|
|
description: error.message,
|
|
|
|
});
|
|
},
|
|
});
|
|
|
|
return (
|
|
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
|
<DialogContent>
|
|
<DialogHeader>
|
|
<DialogTitle>Add Measurement</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="grid" style={{ gridTemplateColumns: "repeat(6, 1fr)" }}>
|
|
{metrics.map(metric => (
|
|
<button style={{ aspectRatio: "1/1" }} key={metric.id} className="flex flex-col items-center justify-center hover:opacity-50" onClick={() => {
|
|
increment({ metricId: metric.id, hourId: hour.id, dayId: hour.dayId });
|
|
}}>
|
|
<Icon name={titleCase(metric.icon)} size={32} />
|
|
<span className="text-sm">{metric.name}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Show a dropdown menu with an option for each metric. When the user selects a metric, increment the count for that metric in the hour.
|
|
// // The dropdown should show the metric name and icon.
|
|
// // Reset the dropdown to the default value after the user selects a metric.
|
|
|
|
// <Select
|
|
// className="w-full h-2"
|
|
// unstyled={true}
|
|
// isSearchable={false}
|
|
// placeholder="Add"
|
|
// options={metrics.map(metric =>
|
|
// ({ value: metric.id, label: metric.name, icon: metric.icon }))}
|
|
// onChange={(selectedOption) => incrementCount(selectedOption.value)}
|
|
// classNames={{
|
|
// menu: (state) =>
|
|
// "bg-card px-4 py-2 text-white rounded-md shadow-lg",
|
|
// }}
|
|
// />
|
|
|
|
);
|
|
}
|