lifetracker/apps/web/components/dashboard/hours/EditableHour.tsx

158 lines
4.8 KiB
TypeScript

"use client";
import { usePathname, useRouter } from "next/navigation";
import { toast } from "@/components/ui/use-toast";
import { cn } from "@/lib/utils";
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 { useEffect, useRef } from "react";
function selectNext(time: number) {
document.getElementById("hour-" + (time).toString())?.getElementsByClassName("edit-hour-code")[0].focus();
}
function EditCode({
originalText,
hour,
onSubmit
}) {
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
if (ref.current) {
ref.current.value = originalText;
}
}, [ref]);
const submit = () => {
let newCode: string | null = ref.current?.value ?? null;
if (originalText == newCode) {
// Nothing to do here
return;
}
if (newCode == "") {
if (originalText == null) {
// Set value to previous hour's value
newCode = document.getElementById("hour-" + (hour.time - 1).toString())?.getElementsByClassName("edit-hour-code")[0].value;
console.log(newCode);
}
else {
newCode = null;
}
}
// console.log(hour);
onSubmit({
dateQuery: hour.date,
time: hour.time,
code: newCode,
})
selectNext(hour.time + 1);
};
return (
<input
className="w-8 border-b-2 text-center edit-hour-code"
style={{
background: hour.background, color: hour.foreground, fontFamily: "inherit",
}}
ref={ref}
defaultValue={originalText}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
submit();
}
if (e.key == "ArrowDown") {
e.preventDefault();
selectNext(hour.time + 1);
}
if (e.key == "ArrowUp") {
e.preventDefault();
selectNext(hour.time - 1);
}
}}
onClick={(e) => {
const range = document.createRange();
range.selectNodeContents(ref.current);
const selection = window.getSelection();
if (selection) {
selection.removeAllRanges();
selection.addRange(range);
}
}}
/>
// <input type="text"
// className="w-10 bg-inherit border-b-2 text-center"
// style={{ color: "inherit", borderColor: "inherit" }}
// onKeyDown={(e) => {
// if (e.key === "Enter") {
// e.preventDefault();
// onSave();
// }
// }}
// value={originalText.originalText ?? ""}
// />
);
}
export default function EditableHour({
hour,
className,
}: {
hour: ZHour,
className?: string;
}) {
const router = useRouter();
const currentPath = usePathname();
const { mutate: updateHour, isPending } = useUpdateHour({
onSuccess: () => {
toast({
description: "Hour updated!",
});
if (currentPath.includes("dashboard")) {
router.refresh();
}
},
});
function isActiveHour(hour: ZHour) {
const now = new TZDate();
return (hour.date == format(now, "yyyy-MM-dd")) && (((now.getHours()) + (now.getTimezoneOffset() / 60) - (parseInt(hour.time))) == 0)
}
return (
<div className={cn(
"p-4 grid justify-between",
)}
style={{
background: hour.background, color: hour.foreground, fontFamily: "inherit",
gridTemplateColumns: "100px 100px 1fr 200px"
}}
>
<span className="text-right">
{isActiveHour(hour) && "--> "}
{hour.datetime}
</span>
<div className="flex justify-center">
<EditCode
originalText={hour.categoryCode}
hour={hour}
onSubmit={updateHour}
/>
</div>
<span>
{hour.categoryDesc || " "}
</span>
<div className="text-right">
<EditableText
originalText={hour.comment || " "}
viewClassName="text-right"
/>
</div>
</div>
);
}