Checkpoint: Can actually log time (track life, if you will) using CLI and Web.
This commit is contained in:
parent
a85e8f294a
commit
d0c07fd8b8
@ -66,9 +66,9 @@ export const daysCmd = new Command()
|
||||
const day = (await api.days.get.query({ dateQuery: dateQuery, timezone: timezone }));
|
||||
|
||||
console.log(`Snagged day with id '${day.id}'`);
|
||||
if (getGlobalOptions().json) {
|
||||
printObject(day);
|
||||
} else {
|
||||
// if (getGlobalOptions().json) {
|
||||
// printObject(day);
|
||||
// } else {
|
||||
|
||||
const moodStr = moodToStars(day.mood);
|
||||
const dateStr = format(day.date, "EEEE, MMMM do", { in: utc });
|
||||
@ -76,6 +76,8 @@ export const daysCmd = new Command()
|
||||
[`Time (${timezones[timezone]})`, "Category", "Comment"]
|
||||
];
|
||||
|
||||
console.log(day.hours.map((h) => h.date));
|
||||
|
||||
day.hours.forEach((h, i) => {
|
||||
data.push([
|
||||
getHourFromTime(i, 'twelves', `(${timezones[timezone]})`),
|
||||
@ -85,7 +87,7 @@ export const daysCmd = new Command()
|
||||
})
|
||||
|
||||
if (flags?.hour) {
|
||||
doHour(day.hours, day, flags.hour, timezone);
|
||||
doHour(day, flags.hour, timezone);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -100,7 +102,7 @@ export const daysCmd = new Command()
|
||||
return (lineIndex < 1 || lineIndex === 2 || lineIndex === 3 || lineIndex === rowCount);
|
||||
},
|
||||
}));
|
||||
}
|
||||
// }
|
||||
}
|
||||
} catch (error) {
|
||||
printErrorMessageWithReason("Failed", error as object);
|
||||
|
||||
@ -26,11 +26,12 @@ export const hoursCmd = new Command()
|
||||
return "Hello";
|
||||
});
|
||||
|
||||
export async function doHour(hours: ZHour[], day: ZDay, hourFlags: string[], timezone = "UTC") {
|
||||
export async function doHour(day: ZDay, hourFlags: string[], timezone = "UTC") {
|
||||
const hourNum = getTimeFromHour(hourFlags.shift()!);
|
||||
const hour = hours[hourNum];
|
||||
const hour = day.hours[hourNum];
|
||||
|
||||
if (hourFlags.length == 0) {
|
||||
console.log("No new values to set; printing hour.")
|
||||
printHour(hour, hourNum, day, timezone);
|
||||
}
|
||||
else {
|
||||
@ -48,6 +49,7 @@ export async function doHour(hours: ZHour[], day: ZDay, hourFlags: string[], tim
|
||||
}
|
||||
}
|
||||
const props = { dateQuery: hour.date!, time: hour.time, code: hourFlags[0], comment: hourFlags[1] || null };
|
||||
// console.log(props);
|
||||
res = await api.hours.update.mutate({ ...props });
|
||||
printHour(res as ZHour, hourNum, day, timezone);
|
||||
|
||||
|
||||
@ -2,6 +2,8 @@ import { notFound } from "next/navigation";
|
||||
import { api } from "@/server/api/client";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import DayView from "@/components/dashboard/days/DayView";
|
||||
import spacetime from "spacetime";
|
||||
import { useTimezone } from "@lifetracker/shared-react/hooks/timezones";
|
||||
|
||||
export default async function DayPage({
|
||||
params,
|
||||
@ -9,9 +11,12 @@ export default async function DayPage({
|
||||
params: { dateQuery: string };
|
||||
}) {
|
||||
let day;
|
||||
const tzName = await api.users.getTimezone();
|
||||
console.log(`Displaying ${spacetime.now(tzName).format()} in ${tzName}.`);
|
||||
try {
|
||||
day = await api.days.get({
|
||||
dateQuery: params.dateQuery,
|
||||
dateQuery: spacetime(params.dateQuery, tzName).format(),
|
||||
timezone: tzName,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof TRPCError) {
|
||||
@ -23,8 +28,10 @@ export default async function DayPage({
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DayView
|
||||
day={day}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
export default function DemoModeBanner() {
|
||||
return (
|
||||
<div className="h-min w-full rounded bg-yellow-100 px-4 py-2 text-center text-black">
|
||||
Demo mode is on. All modifications are disabled.
|
||||
YO
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -12,6 +12,9 @@ import Link from "next/link";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ArrowLeftSquare, ArrowRightSquare } from "lucide-react";
|
||||
import { UTCDate, utc } from "@date-fns/utc";
|
||||
import spacetime from "spacetime";
|
||||
import EditableHour from "@/components/hours/EditableHour";
|
||||
|
||||
export default async function DayView({
|
||||
day,
|
||||
}: {
|
||||
@ -22,8 +25,8 @@ export default async function DayView({
|
||||
redirect("/");
|
||||
}
|
||||
|
||||
const prevDay = format(addDays(day.date, -1), "yyyy-MM-dd");
|
||||
const nextDay = format(addDays(day.date, 1), "yyyy-MM-dd");
|
||||
const prevDay = spacetime(day.date).subtract(1, "day").format("iso-short");
|
||||
const nextDay = spacetime(day.date).add(1, "day").format("iso-short");
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
@ -41,7 +44,7 @@ export default async function DayView({
|
||||
</div>
|
||||
</Link>
|
||||
<span className="text-2xl flex-1">
|
||||
{format(day.date, "EEEE, MMMM do", { in: utc })}
|
||||
{spacetime(day.date).format("{day}, {month} {date}, {year}")}
|
||||
</span>
|
||||
<Link
|
||||
href={`/dashboard/day/${nextDay}`}
|
||||
@ -70,9 +73,29 @@ export default async function DayView({
|
||||
<Separator />
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<div className={cn(
|
||||
"p-4 grid justify-between",
|
||||
)}
|
||||
style={{
|
||||
fontFamily: "inherit",
|
||||
gridTemplateColumns: "100px 1fr 200px"
|
||||
}}
|
||||
>
|
||||
<span className="text-right">
|
||||
Time
|
||||
</span>
|
||||
<span className="text-center">
|
||||
Category
|
||||
</span>
|
||||
<div className="text-right">
|
||||
Actions
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{day.hours.map((hour) => (
|
||||
<li key={hour.time}>
|
||||
{hour.time}: {hour.categoryName} {hour.comment}
|
||||
<li key={hour.time} id={"hour-" + hour.time.toString()}>
|
||||
<EditableHour hour={hour} />
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@ -8,50 +8,73 @@ import { useTimezone } from "@lifetracker/shared-react/hooks/timezones";
|
||||
import LoadingSpinner from "@/components/ui/spinner";
|
||||
import { db } from "@lifetracker/db";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import spacetime from "spacetime";
|
||||
|
||||
|
||||
|
||||
export default function TimezoneDisplay() {
|
||||
|
||||
const dbTimezone = useTimezone();
|
||||
const [timezone, setTimezone] = useState(dbTimezone);
|
||||
|
||||
// Update timezone state when dbTimezone changes
|
||||
useEffect(() => {
|
||||
if (dbTimezone !== undefined) {
|
||||
setTimezone(dbTimezone);
|
||||
}
|
||||
}, [dbTimezone]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleTzChange = (event) => {
|
||||
setTimezone(event.detail.timezone);
|
||||
};
|
||||
|
||||
window.addEventListener('timezoneUpdated', handleTzChange);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('timezoneUpdated', handleTzChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
|
||||
if (timezone === undefined) {
|
||||
return (
|
||||
<div className="flex flex-col items-center w-full">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const clientTime = spacetime.now();
|
||||
return (
|
||||
<div className="text-center w-full">
|
||||
<Link href="/settings/app">
|
||||
<b className="whitespace-nowrap">{format(TZDate.tz(timezone), 'MMM dd, hh:mm aa')}</b>
|
||||
<b className="whitespace-nowrap">
|
||||
{clientTime.format('nice')}
|
||||
</b>
|
||||
<br />
|
||||
<span>in </span>
|
||||
<span className="whitespace-nowrap">
|
||||
<b>{timezones[timezone]}</b>
|
||||
<b>
|
||||
{timezones[clientTime.timezone().name] || clientTime.timezone().name}
|
||||
</b>
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// export default function TimezoneDisplay() {
|
||||
|
||||
// const dbTimezone = useTimezone();
|
||||
// const [timezone, setTimezone] = useState(dbTimezone);
|
||||
|
||||
// // Update timezone state when dbTimezone changes
|
||||
// useEffect(() => {
|
||||
// if (dbTimezone !== undefined) {
|
||||
// setTimezone(dbTimezone);
|
||||
// }
|
||||
// }, [dbTimezone]);
|
||||
|
||||
// useEffect(() => {
|
||||
// const handleTzChange = (event) => {
|
||||
// setTimezone(event.detail.timezone);
|
||||
// };
|
||||
|
||||
// window.addEventListener('timezoneUpdated', handleTzChange);
|
||||
|
||||
// return () => {
|
||||
// window.removeEventListener('timezoneUpdated', handleTzChange);
|
||||
// };
|
||||
// }, []);
|
||||
|
||||
|
||||
|
||||
// if (timezone === undefined) {
|
||||
// return (
|
||||
// <div className="flex flex-col items-center w-full">
|
||||
// <LoadingSpinner />
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
// return (
|
||||
// <div className="text-center w-full">
|
||||
// <Link href="/settings/app">
|
||||
// <b className="whitespace-nowrap">{format(TZDate.tz(timezone), 'MMM dd, hh:mm aa')}</b>
|
||||
// <br />
|
||||
// <span>in </span>
|
||||
// <span className="whitespace-nowrap">
|
||||
// <b>{timezones[timezone]}</b>
|
||||
// </span>
|
||||
// </Link>
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
137
apps/web/components/hours/EditableHour.tsx
Normal file
137
apps/web/components/hours/EditableHour.tsx
Normal file
@ -0,0 +1,137 @@
|
||||
"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 "../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 EditMode({
|
||||
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 == "") {
|
||||
newCode = null;
|
||||
}
|
||||
// console.log(hour);
|
||||
onSubmit({
|
||||
dateQuery: hour.date,
|
||||
time: hour.time,
|
||||
code: newCode,
|
||||
})
|
||||
document.getElementById("hour-" + (hour.time + 1).toString())?.getElementsByClassName("edit-hour-code")[0].focus();
|
||||
};
|
||||
|
||||
return (
|
||||
<input
|
||||
className="w-8 border-b-2 text-center edit-hour-code"
|
||||
ref={ref}
|
||||
value={originalText}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
submit();
|
||||
}
|
||||
}}
|
||||
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">
|
||||
<EditMode
|
||||
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>
|
||||
);
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { timezones } from '@/lib/timezones';
|
||||
import { timezones } from "@lifetracker/shared/utils/timezones";
|
||||
import TimezoneSelect, { type ITimezone } from 'react-timezone-select'
|
||||
import { useUpdateUserTimezone } from "@lifetracker/shared-react/hooks/timezones";
|
||||
|
||||
|
||||
@ -77,6 +77,7 @@
|
||||
"remark-gfm": "^4.0.0",
|
||||
"request-ip": "^3.3.0",
|
||||
"sharp": "^0.33.3",
|
||||
"spacetime": "^7.6.2",
|
||||
"superjson": "^2.2.1",
|
||||
"tailwind-merge": "^2.2.1",
|
||||
"title-case": "^4.3.2",
|
||||
|
||||
@ -10,7 +10,7 @@ import dbConfig from "./drizzle.config";
|
||||
const sqlite = new Database(dbConfig.dbCredentials.url);
|
||||
export const db = drizzle(sqlite, {
|
||||
schema,
|
||||
logger: false
|
||||
logger: false,
|
||||
});
|
||||
|
||||
export function getInMemoryDB(runMigrations: boolean) {
|
||||
|
||||
@ -4,6 +4,7 @@ export function useUpdateDay(
|
||||
...opts: Parameters<typeof api.days.update.useMutation>
|
||||
) {
|
||||
const apiUtils = api.useUtils();
|
||||
// console.log("UPDATING DAY");
|
||||
return api.days.update.useMutation({
|
||||
...opts[0],
|
||||
onSuccess: (res, req, meta) => {
|
||||
@ -13,30 +14,15 @@ export function useUpdateDay(
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteLabel(
|
||||
...opts: Parameters<typeof api.labels.delete.useMutation>
|
||||
export function useUpdateHour(
|
||||
...opts: Parameters<typeof api.hours.update.useMutation>
|
||||
) {
|
||||
const apiUtils = api.useUtils();
|
||||
|
||||
return api.labels.delete.useMutation({
|
||||
// console.log(opts[0]);
|
||||
return api.hours.update.useMutation({
|
||||
...opts[0],
|
||||
onSuccess: (res, req, meta) => {
|
||||
apiUtils.labels.list.invalidate();
|
||||
// apiUtils.bookmarks.getBookmark.invalidate();
|
||||
return opts[0]?.onSuccess?.(res, req, meta);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useDeleteUnusedTags(
|
||||
...opts: Parameters<typeof api.tags.deleteUnused.useMutation>
|
||||
) {
|
||||
const apiUtils = api.useUtils();
|
||||
|
||||
return api.tags.deleteUnused.useMutation({
|
||||
...opts[0],
|
||||
onSuccess: (res, req, meta) => {
|
||||
apiUtils.tags.list.invalidate();
|
||||
apiUtils.days.get.invalidate({ dateQuery: req.dateQuery });
|
||||
return opts[0]?.onSuccess?.(res, req, meta);
|
||||
},
|
||||
});
|
||||
|
||||
@ -12,6 +12,7 @@ export function useUpdateUserTimezone(
|
||||
}
|
||||
|
||||
export function useTimezone() {
|
||||
const res = api.users.getTimezone.useQuery().data;
|
||||
const res = api.users.getTimezone.useQuery();
|
||||
console.log("react hook useTimezone", res);
|
||||
return res;
|
||||
}
|
||||
@ -12,6 +12,8 @@ export const zHourSchema = z.object({
|
||||
categoryName: z.string().nullish(),
|
||||
categoryDesc: z.string().nullish(),
|
||||
comment: z.string().nullish(),
|
||||
background: z.string().nullish(),
|
||||
foreground: z.string().nullish(),
|
||||
});
|
||||
export type ZHour = z.infer<typeof zHourSchema>;
|
||||
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
"bcryptjs": "^2.4.3",
|
||||
"date-fns": "^4.1.0",
|
||||
"drizzle-orm": "^0.33.0",
|
||||
"spacetime": "^7.6.2",
|
||||
"superjson": "^2.2.1",
|
||||
"tiny-invariant": "^1.3.3",
|
||||
"title-case": "^4.3.2",
|
||||
|
||||
@ -13,6 +13,9 @@ import { dateFromInput, hoursListInUTC } from "@lifetracker/shared/utils/days";
|
||||
import { closestIndexTo, format } from "date-fns";
|
||||
import { TZDate } from "@date-fns/tz";
|
||||
import { hoursAppRouter } from "./hours";
|
||||
import spacetime from "spacetime";
|
||||
import { getHourFromTime, getTimeFromHour } from "@lifetracker/shared/utils/hours";
|
||||
import { hourColors } from "./hours";
|
||||
|
||||
async function createDay(date: string, ctx: Context) {
|
||||
return await ctx.db.transaction(async (trx) => {
|
||||
@ -87,7 +90,9 @@ async function getDay(input: { dateQuery: string }, ctx: Context, date: string)
|
||||
dayId: hours.dayId,
|
||||
time: hours.time,
|
||||
userId: hours.userId,
|
||||
date: days.date
|
||||
}).from(hours)
|
||||
.leftJoin(days, eq(days.id, hours.dayId)) // Ensure days table is joined first
|
||||
.where(and(
|
||||
eq(hours.userId, ctx.user!.id),
|
||||
eq(hours.dayId, day.id),
|
||||
@ -132,7 +137,7 @@ export const daysAppRouter = router({
|
||||
}
|
||||
}));
|
||||
|
||||
const dayHours = await Promise.all(allHours.map(async function (map: { date, time }) {
|
||||
const dayHours = await Promise.all(allHours.map(async function (map: { date, time }, i) {
|
||||
const dayId = allDayIds.find((dayIds: { id, date }) => map.date == dayIds.date)!.id;
|
||||
|
||||
const hourMatch = await ctx.db.select({
|
||||
@ -144,8 +149,10 @@ export const daysAppRouter = router({
|
||||
categoryName: categories.name,
|
||||
categoryDesc: categories.description,
|
||||
comment: hours.comment,
|
||||
date: days.date
|
||||
}).from(hours)
|
||||
.leftJoin(categories, eq(categories.id, hours.categoryId))
|
||||
.leftJoin(days, eq(days.id, hours.dayId))
|
||||
.where(and(
|
||||
eq(hours.time, map.time),
|
||||
eq(hours.dayId, dayId)));
|
||||
@ -155,15 +162,20 @@ export const daysAppRouter = router({
|
||||
// });
|
||||
// console.log("Search values:: ", `allDayIds: ${allDayIds}, d: ${date}, t: ${time}, dayId: ${dayId}`)
|
||||
// console.log("hourMatch", hourMatch[0]);
|
||||
// console.log(hourMatch[0].categoryDesc);
|
||||
|
||||
const dayHour = {
|
||||
...hourMatch[0],
|
||||
|
||||
...(await hourColors(hourMatch[0], ctx)),
|
||||
};
|
||||
|
||||
|
||||
const localDateTime = spacetime(date, timezone).add(i, "hour");
|
||||
|
||||
return {
|
||||
...dayHour,
|
||||
date: map.date,
|
||||
datetime: `${localDateTime.format('{hour} {ampm}')}`,
|
||||
// datetime: `${localDateTime.format('{nice}')} ${timezone} (${localDateTime.goto("UTC").format('{nice}')} UTC)`,
|
||||
};
|
||||
}));
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { and, desc, eq, inArray, notExists } from "drizzle-orm";
|
||||
import { date, z } from "zod";
|
||||
|
||||
import { SqliteError } from "@lifetracker/db";
|
||||
import { categories, days, hours, } from "@lifetracker/db/schema";
|
||||
import { categories, days, hours, colors } from "@lifetracker/db/schema";
|
||||
import {
|
||||
zDaySchema, ZDay, ZHour, zHourSchema
|
||||
} from "@lifetracker/shared/types/days";
|
||||
@ -13,6 +13,32 @@ import { format } from "date-fns";
|
||||
import { TZDate } from "@date-fns/tz";
|
||||
import { dateFromInput } from "@lifetracker/shared/utils/days";
|
||||
|
||||
|
||||
export async function hourColors(hour: ZHour, ctx: Context) {
|
||||
|
||||
const categoryColor = await ctx.db.select()
|
||||
.from(colors)
|
||||
.leftJoin(categories, eq(categories.id, hour.categoryId))
|
||||
.where(and(
|
||||
eq(colors.id, categories.colorId),
|
||||
eq(colors.userId, ctx.user!.id)
|
||||
))
|
||||
|
||||
// console.log(categoryColor);
|
||||
if (!categoryColor[0]) {
|
||||
return {
|
||||
background: "inherit",
|
||||
foreground: "inherit"
|
||||
}
|
||||
}
|
||||
else {
|
||||
return {
|
||||
background: categoryColor[0].color.hexcode,
|
||||
foreground: categoryColor[0].color.inverse,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const hoursAppRouter = router({
|
||||
get: authedProcedure
|
||||
.input(z.object({
|
||||
@ -30,6 +56,7 @@ export const hoursAppRouter = router({
|
||||
categoryId: hours.categoryId,
|
||||
categoryCode: categories.code,
|
||||
categoryName: categories.name,
|
||||
categoryDesc: categories.description,
|
||||
comment: hours.comment,
|
||||
})
|
||||
.from(hours)
|
||||
@ -44,6 +71,8 @@ export const hoursAppRouter = router({
|
||||
update: authedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
hourId: z.string().optional(),
|
||||
dayId: z.string().optional(),
|
||||
dateQuery: z.string(),
|
||||
time: z.number(),
|
||||
code: z.string().optional(),
|
||||
@ -53,7 +82,13 @@ export const hoursAppRouter = router({
|
||||
.output(zHourSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { dateQuery, time, code, ...updatedProps } = input;
|
||||
var date = dateFromInput({ dateQuery: dateQuery });
|
||||
let dateCondition;
|
||||
if (input.dayId) {
|
||||
dateCondition = eq(days.id, input.dayId)
|
||||
}
|
||||
else {
|
||||
dateCondition = eq(days.date, dateFromInput({ dateQuery: dateQuery }));
|
||||
}
|
||||
|
||||
const category =
|
||||
code == "" ? [{
|
||||
@ -64,6 +99,7 @@ export const hoursAppRouter = router({
|
||||
{
|
||||
id: categories.id,
|
||||
name: categories.name,
|
||||
description: categories.description
|
||||
}
|
||||
)
|
||||
.from(categories)
|
||||
@ -74,14 +110,11 @@ export const hoursAppRouter = router({
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
const day = await ctx.db.select(
|
||||
{ id: days.id }
|
||||
)
|
||||
const day = await ctx.db.select()
|
||||
.from(days)
|
||||
.where(
|
||||
and(
|
||||
eq(days.date, date),
|
||||
dateCondition,
|
||||
eq(days.userId, ctx.user!.id),
|
||||
)
|
||||
);
|
||||
@ -107,8 +140,9 @@ export const hoursAppRouter = router({
|
||||
.returning();
|
||||
|
||||
return {
|
||||
date: format(date, "yyyy-MM-dd"),
|
||||
date: format(day[0].date, "yyyy-MM-dd"),
|
||||
categoryName: category[0].name,
|
||||
categoryDesc: category[0].description,
|
||||
...hourRes[0]
|
||||
}
|
||||
}),
|
||||
|
||||
@ -180,7 +180,6 @@ export const usersAppRouter = router({
|
||||
)
|
||||
.query(async ({ ctx }) => {
|
||||
const res = await ctx.db.select({ timezone: users.timezone }).from(users).where(eq(users.id, ctx.user.id));
|
||||
|
||||
return res[0].timezone;
|
||||
}),
|
||||
changeTimezone: authedProcedure
|
||||
|
||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@ -337,6 +337,9 @@ importers:
|
||||
sharp:
|
||||
specifier: ^0.33.3
|
||||
version: 0.33.5
|
||||
spacetime:
|
||||
specifier: ^7.6.2
|
||||
version: 7.6.2
|
||||
superjson:
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1
|
||||
@ -616,6 +619,9 @@ importers:
|
||||
drizzle-orm:
|
||||
specifier: ^0.33.0
|
||||
version: 0.33.0(@types/better-sqlite3@7.6.11)(@types/react@18.2.61)(better-sqlite3@11.5.0)(expo-sqlite@14.0.6(expo@51.0.36(@babel/core@7.26.0)(@babel/preset-env@7.25.7(@babel/core@7.26.0))(encoding@0.1.13)))(react@18.3.1)(sqlite3@5.1.7)
|
||||
spacetime:
|
||||
specifier: ^7.6.2
|
||||
version: 7.6.2
|
||||
superjson:
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user