"use client"; import { usePathname, useRouter } from "next/navigation"; import { toast } from "@/components/ui/use-toast"; import { cn } from "@/lib/utils"; import React, { useState, useEffect, useRef } from 'react'; import { useUpdateHour } from "@lifetracker/shared-react/hooks/days"; import { EditableText } from "@/components/dashboard/EditableText"; import { format } from "date-fns"; import { TZDate } from "@date-fns/tz"; import { ZHour } from "@lifetracker/shared/types/days"; import { MessageCircle, Pencil, Plus } from "lucide-react"; import { ButtonWithTooltip } from "@/components/ui/button"; import { EditableHourCode } from "./EditableHourCode"; import { EditableHourComment } from "./EditableHourComment"; import spacetime from 'spacetime'; import { eq, is } from "drizzle-orm"; import HourMeasurementsDialog from "@/components/dashboard/hours/HourMeasurementsDialog"; import { ActionButtonWithTooltip } from "@/components/ui/action-button"; 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"; export default function EditableHour({ hour: initialHour, i, j, hourGroup, metrics, isConsecutiveHour = false, className, }: { hour: ZHour, i: number, j: number, hourGroup: ZHour[], metrics: ZMetric[], isConsecutiveHour?: boolean, className?: string; }) { const [hour, setHour] = useState(initialHour); const { mutate: updateHour, isPending } = useUpdateHour({ onSuccess: (res, req, meta) => { const { categoryCode: oldCode, comment: oldComment } = hour; const newHour = { categoryCode: parseInt(req.code!), comment: oldComment, ...res, }; setHour(newHour); // Only show toast if client screen is larger than mobile if (window.innerWidth > 640) { toast({ description: "Hour updated!", }); } }, }); const { mutate: decrementCount } = useDecrementCount({ onSuccess: (res, req) => { const oldMeasurementIndex = hour.measurements.findIndex(m => m.metricId === req.metricId); let newMeasurements; if (oldMeasurementIndex !== -1) { if (res === undefined) { // Remove the measurement if res is undefined newMeasurements = [ ...hour.measurements.slice(0, oldMeasurementIndex), ...hour.measurements.slice(oldMeasurementIndex + 1) ]; } else { // Update the measurement newMeasurements = [ ...hour.measurements.slice(0, oldMeasurementIndex), res, ...hour.measurements.slice(oldMeasurementIndex + 1) ]; } } else { // Add the new measurement newMeasurements = [...hour.measurements, res]; } const newHour = { ...hour, measurements: newMeasurements, }; setHour(newHour); toast({ description: res === undefined ? "Measurement removed!" : "Measurement updated!", }); } }); const tzOffset = spacetime().offset() / 60; const localDateTime = (h) => { return spacetime(h.date).add(h.time + tzOffset, "hour").format('{hour} {ampm}'); } hour.datetime = localDateTime(hour); useEffect(() => { // console.log(hour.categoryDesc); }, [hour]); function isActiveHour(hour: ZHour) { const now = new TZDate(); const isCurrentHour = ((now.getHours() - localDateTime.hour()) == 0); const isToday = (localDateTime.format("iso-short") == format(now, "yyyy-MM-dd")); return isToday && isCurrentHour; } function reload(newHour: ZHour) { setHour(newHour); } return (
640 ? "50px 100px 3fr 2fr" : "50px 100px 1fr", // Known issue: This won't work if the screen is resized, only on reload }} > {hourGroup.length > 1 ? (
{hour.datetime} | {localDateTime(hourGroup[hourGroup.length - 1])}
) :
{hour.datetime}
}
{hour.categoryCode != undefined ? : ""}
{hour.categoryName}
{hour.categoryCode != undefined ?
{ hour.measurements?.map(m => Array.from({ length: m.value }).map((_, index) =>
{ decrementCount({ metricId: m.metricId, hourId: hour.id }); }}>
) )} {(hour.measurements.length > 0) ? ( {/* {JSON.stringify(hour.measurements.length)} */} | ) : "" }
: ""}
); }