diff --git a/app/(dashboard)/[tenant]/projects/[projectId]/events/actions.ts b/app/(dashboard)/[tenant]/projects/[projectId]/events/actions.ts
index a4f177e..4e9b8fc 100644
--- a/app/(dashboard)/[tenant]/projects/[projectId]/events/actions.ts
+++ b/app/(dashboard)/[tenant]/projects/[projectId]/events/actions.ts
@@ -2,55 +2,74 @@
import { calendarEvent, eventInvite } from "@/drizzle/schema";
import { generateObjectDiffMessage, logActivity } from "@/lib/activity";
+import { toDateString, toEndOfDay } from "@/lib/utils/date";
import { database } from "@/lib/utils/useDatabase";
import { getOwner, getTimezone } from "@/lib/utils/useOwner";
-import dayjs from "dayjs";
-import timezone from "dayjs/plugin/timezone";
-import utc from "dayjs/plugin/utc";
import { and, eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { type Frequency, RRule } from "rrule";
-dayjs.extend(timezone);
-dayjs.extend(utc);
-
-export async function createEvent(payload: FormData) {
- const { userId, orgSlug } = await getOwner();
- const projectId = +(payload.get("projectId") as string);
+function handleEventPayload(payload: FormData): {
+ name: string;
+ description: string;
+ start: Date;
+ end: Date | null;
+ allDay: boolean;
+ repeatRule?: string;
+ invites: string[];
+} {
const name = payload.get("name") as string;
const description = payload.get("description") as string;
- const start = dayjs.utc(payload.get("start") as string);
+ const start = new Date(payload.get("start") as string);
const allDay = (payload.get("allDay") as string) === "on";
const repeat = payload.get("repeat") as string;
const invites = ((payload.get("invites") as string) ?? "")
.split(",")
.filter(Boolean);
- let end = payload.get("end") ? dayjs.utc(payload.get("end") as string) : null;
+ let end = payload.get("end") ? new Date(payload.get("end") as string) : null;
if (allDay && end) {
- end = end.endOf("day");
+ end = toEndOfDay(end);
}
const repeatRule = repeat
? new RRule({
freq: repeat as unknown as Frequency,
- dtstart: start.toDate(),
- until: end ? end.toDate() : null,
+ dtstart: start,
+ until: end ?? null,
tzid: "UTC",
})
: undefined;
+ return {
+ name,
+ description,
+ start,
+ end,
+ allDay,
+ repeatRule: repeatRule?.toString(),
+ invites,
+ };
+}
+
+export async function createEvent(payload: FormData) {
+ const { userId, orgSlug } = await getOwner();
+ const projectId = +(payload.get("projectId") as string);
+
+ const { name, description, start, end, allDay, repeatRule, invites } =
+ handleEventPayload(payload);
+
const db = await database();
- const createdEvent = await db
+ const createdEvent = db
.insert(calendarEvent)
.values({
name,
description,
- start: start.toDate(),
- end: end?.toDate(),
+ start,
+ end,
allDay,
- repeatRule: repeatRule?.toString(),
+ repeatRule,
projectId,
createdByUser: userId,
createdAt: new Date(),
@@ -60,8 +79,7 @@ export async function createEvent(payload: FormData) {
.get();
for (const userId of invites) {
- await db
- .insert(eventInvite)
+ db.insert(eventInvite)
.values({
eventId: createdEvent.id,
userId,
@@ -81,43 +99,23 @@ export async function createEvent(payload: FormData) {
revalidatePath(`/${orgSlug}/projects/${projectId}/events`);
redirect(
- `/${orgSlug}/projects/${projectId}/events?on=${start.tz(timezone).format("YYYY-MM-DD")}`,
+ `/${orgSlug}/projects/${projectId}/events?on=${toDateString(start, timezone)}`,
);
}
export async function updateEvent(payload: FormData) {
const { orgSlug } = await getOwner();
const id = +(payload.get("id") as string);
- const name = payload.get("name") as string;
- const description = payload.get("description") as string;
- const start = dayjs.utc(payload.get("start") as string);
- const allDay = (payload.get("allDay") as string) === "on";
- const repeat = payload.get("repeat") as string;
- const projectId = payload.get("projectId") as string;
- const invites = ((payload.get("invites") as string) ?? "")
- .split(",")
- .filter(Boolean);
-
- let end = payload.get("end") ? dayjs.utc(payload.get("end") as string) : null;
- if (allDay && end) {
- end = end.endOf("day");
- }
+ const projectId = +(payload.get("projectId") as string);
- const repeatRule = repeat
- ? new RRule({
- freq: repeat as unknown as Frequency,
- dtstart: start.toDate(),
- until: end ? end.toDate() : null,
- tzid: "UTC",
- })
- : undefined;
+ const { name, description, start, end, allDay, repeatRule, invites } =
+ handleEventPayload(payload);
const db = await database();
- await db.delete(eventInvite).where(eq(eventInvite.eventId, id)).run();
+ db.delete(eventInvite).where(eq(eventInvite.eventId, id)).run();
for (const userId of invites) {
- await db
- .insert(eventInvite)
+ db.insert(eventInvite)
.values({
eventId: id,
userId,
@@ -135,13 +133,12 @@ export async function updateEvent(payload: FormData) {
})
.execute();
- await db
- .update(calendarEvent)
+ db.update(calendarEvent)
.set({
name,
description,
- start: start.toDate(),
- end: end?.toDate(),
+ start,
+ end,
allDay,
repeatRule: repeatRule?.toString(),
updatedAt: new Date(),
@@ -160,8 +157,8 @@ export async function updateEvent(payload: FormData) {
{
name,
description,
- start: start.toDate(),
- end: end?.toDate(),
+ start,
+ end,
allDay,
},
)}`,
@@ -172,7 +169,7 @@ export async function updateEvent(payload: FormData) {
revalidatePath(`/${orgSlug}/projects/${projectId}/events`);
redirect(
- `/${orgSlug}/projects/${projectId}/events?on=${start.tz(timezone).format("YYYY-MM-DD")}`,
+ `/${orgSlug}/projects/${projectId}/events?on=${toDateString(start, timezone)}`,
);
}
@@ -182,7 +179,7 @@ export async function deleteEvent(payload: FormData) {
const projectId = payload.get("projectId") as string;
const db = await database();
- const eventDetails = await db
+ const eventDetails = db
.delete(calendarEvent)
.where(eq(calendarEvent.id, id))
.returning()
diff --git a/app/(dashboard)/[tenant]/projects/[projectId]/events/page.tsx b/app/(dashboard)/[tenant]/projects/[projectId]/events/page.tsx
index 768bca3..c61c730 100644
--- a/app/(dashboard)/[tenant]/projects/[projectId]/events/page.tsx
+++ b/app/(dashboard)/[tenant]/projects/[projectId]/events/page.tsx
@@ -4,11 +4,13 @@ import { CommentsSection } from "@/components/project/comment/comments-section";
import EventsCalendar from "@/components/project/events/events-calendar";
import { buttonVariants } from "@/components/ui/button";
import { calendarEvent } from "@/drizzle/schema";
+import {
+ toDateStringWithDay,
+ toEndOfDay,
+ toStartOfDay,
+} from "@/lib/utils/date";
import { database } from "@/lib/utils/useDatabase";
import { getOwner, getTimezone } from "@/lib/utils/useOwner";
-import dayjs from "dayjs";
-import timezone from "dayjs/plugin/timezone";
-import utc from "dayjs/plugin/utc";
import {
and,
asc,
@@ -32,9 +34,6 @@ type Props = {
}>;
};
-dayjs.extend(utc);
-dayjs.extend(timezone);
-
export default async function EventDetails(props: Props) {
const searchParams = await props.searchParams;
const params = await props.params;
@@ -44,11 +43,11 @@ export default async function EventDetails(props: Props) {
const timezone = await getTimezone();
- const selectedDate = on ? dayjs(new Date(on)) : dayjs().tz(timezone);
- const dayCommentId = `${projectId}${selectedDate.year()}${selectedDate.month()}${selectedDate.date()}`;
+ const selectedDate = on ? new Date(on) : new Date();
+ const dayCommentId = `${projectId}${selectedDate.getFullYear()}${selectedDate.getMonth()}${selectedDate.getDay()}`;
- const startOfDay = selectedDate.startOf("day").toDate();
- const endOfDay = selectedDate.endOf("day").toDate();
+ const startOfDay = toStartOfDay(selectedDate);
+ const endOfDay = toEndOfDay(selectedDate);
const db = await database();
const events = await db.query.calendarEvent
@@ -98,7 +97,7 @@ export default async function EventDetails(props: Props) {
actionLink={`/${orgSlug}/projects/${projectId}/events/new`}
>
- {selectedDate.tz(timezone).format("dddd, MMMM D, YYYY")}
+ {toDateStringWithDay(selectedDate, timezone)}
diff --git a/app/(dashboard)/[tenant]/projects/page.tsx b/app/(dashboard)/[tenant]/projects/page.tsx
index 3fc6923..410c9f2 100644
--- a/app/(dashboard)/[tenant]/projects/page.tsx
+++ b/app/(dashboard)/[tenant]/projects/page.tsx
@@ -4,7 +4,7 @@ import PageTitle from "@/components/layout/page-title";
import { ProjecItem } from "@/components/project/project-item";
import { buttonVariants } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
-import { getOwner } from "@/lib/utils/useOwner";
+import { getOwner, getTimezone } from "@/lib/utils/useOwner";
import { getProjectsForOwner } from "@/lib/utils/useProjects";
import Link from "next/link";
@@ -19,6 +19,7 @@ export default async function Projects(props: Props) {
const searchParams = await props.searchParams;
const { orgSlug } = await getOwner();
const statuses = searchParams?.status?.split(",") ?? ["active"];
+ const timezone = await getTimezone();
const { projects, archivedProjects } = await getProjectsForOwner({
search: searchParams.search,
@@ -66,7 +67,11 @@ export default async function Projects(props: Props) {
{projects.map((project) => (
-
+
))}
diff --git a/app/(dashboard)/[tenant]/today/page.tsx b/app/(dashboard)/[tenant]/today/page.tsx
index 67c8dc5..472eec0 100644
--- a/app/(dashboard)/[tenant]/today/page.tsx
+++ b/app/(dashboard)/[tenant]/today/page.tsx
@@ -3,95 +3,95 @@ import PageSection from "@/components/core/section";
import PageTitle from "@/components/layout/page-title";
import { TaskItem } from "@/components/project/tasklist/task/task-item";
import { task } from "@/drizzle/schema";
+import { isSameDate } from "@/lib/utils/date";
import { database } from "@/lib/utils/useDatabase";
-import dayjs from "dayjs";
import { and, asc, lte, ne } from "drizzle-orm";
import { AlertTriangleIcon, InfoIcon } from "lucide-react";
export default async function Today() {
- const db = await database();
+ const db = await database();
- const tasks = await db.query.task.findMany({
- where: and(lte(task.dueDate, new Date()), ne(task.status, "done")),
- orderBy: [asc(task.position)],
- with: {
- taskList: {
- columns: {
- projectId: true,
- },
- },
- creator: {
- columns: {
- firstName: true,
- imageUrl: true,
- },
- },
- assignee: {
- columns: {
- firstName: true,
- imageUrl: true,
- },
- },
- },
- });
+ const tasks = await db.query.task.findMany({
+ where: and(lte(task.dueDate, new Date()), ne(task.status, "done")),
+ orderBy: [asc(task.position)],
+ with: {
+ taskList: {
+ columns: {
+ projectId: true,
+ },
+ },
+ creator: {
+ columns: {
+ firstName: true,
+ imageUrl: true,
+ },
+ },
+ assignee: {
+ columns: {
+ firstName: true,
+ imageUrl: true,
+ },
+ },
+ },
+ });
- const dueToday = tasks
- .filter((t) => Boolean(t.dueDate))
- .filter((t) => dayjs(new Date(t.dueDate!)).isSame(new Date(), "day"));
+ const dueToday = tasks
+ .filter((t) => !!t.dueDate)
+ .filter((t) => isSameDate(t.dueDate!, new Date()));
- const overDue = tasks
- .filter((t) => Boolean(t.dueDate))
- .filter((t) => dayjs(new Date(t.dueDate!)).isBefore(new Date(), "day"));
+ const overDue = tasks
+ .filter((t) => !!t.dueDate)
+ .filter((t) => t.dueDate! < new Date());
- const summary = `You've got ${dueToday.length > 0 ? dueToday.length : "no"} tasks due today & ${overDue.length > 0 ? overDue.length : "no"} overdue tasks.`;
+ const summary = `You've got ${dueToday.length > 0 ? dueToday.length : "no"} tasks due today & ${overDue.length > 0 ? overDue.length : "no"} overdue tasks.`;
- return (
- <>
-
+ return (
+ <>
+
-
-
- , {summary}
-
-
+
+
+ , {summary}
+
+
- {overDue.length || dueToday.length ? (
-
- {overDue.length ? (
- <>
-
-
- Overdue
-
- {overDue.map((task) => (
-
- ))}
- >
- ) : null}
+ {overDue.length || dueToday.length ? (
+
+ {overDue.length ? (
+ <>
+
+
+ Overdue
+
+ {overDue.map((task) => (
+
+ ))}
+ >
+ ) : null}
- {dueToday.length ? (
- <>
-
-
- Due Today
-
- {dueToday.map((task) => (
-
- ))}
- >
- ) : null}
-
- ) : null}
- >
- );
+ {dueToday.length ? (
+ <>
+
+
+ Due Today
+
+ {dueToday.map((task) => (
+
+ ))}
+ >
+ ) : null}
+
+ ) : null}
+ >
+ );
}
diff --git a/components/core/greeting.tsx b/components/core/greeting.tsx
index 4b080a8..85f2df3 100644
--- a/components/core/greeting.tsx
+++ b/components/core/greeting.tsx
@@ -1,6 +1,5 @@
"use client";
-import dayjs from "dayjs";
import { useEffect, useState } from "react";
export function Greeting() {
@@ -8,7 +7,7 @@ export function Greeting() {
useEffect(() => {
const getCurrentGreeting = () => {
- const currentHour = dayjs().hour();
+ const currentHour = new Date().getHours();
if (currentHour >= 5 && currentHour < 12) {
return "Good morning";
}
diff --git a/components/core/report-timezone.tsx b/components/core/report-timezone.tsx
index d96ee6e..ea90a41 100644
--- a/components/core/report-timezone.tsx
+++ b/components/core/report-timezone.tsx
@@ -1,19 +1,12 @@
"use client";
import { saveUserTimezone } from "@/app/(dashboard)/[tenant]/settings/actions";
-import dayjs from "dayjs";
-import timezone from "dayjs/plugin/timezone";
-import utc from "dayjs/plugin/utc";
import { useEffect } from "react";
-dayjs.extend(utc);
-dayjs.extend(timezone);
-
export function ReportTimezone() {
useEffect(() => {
- const timeZone = dayjs.tz.guess();
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (timeZone) {
- console.log("Timezone: ", timeZone);
saveUserTimezone(timeZone);
}
}, []);
diff --git a/components/form/event.tsx b/components/form/event.tsx
index 71ed18c..8f9a4d9 100644
--- a/components/form/event.tsx
+++ b/components/form/event.tsx
@@ -2,7 +2,6 @@
import { Input } from "@/components/ui/input";
import type { EventWithInvites, User } from "@/drizzle/types";
-import dayjs from "dayjs";
import { Trash2Icon } from "lucide-react";
import { useState } from "react";
import { RRule, rrulestr } from "rrule";
@@ -33,9 +32,7 @@ export default function EventForm({
item?.invites?.map((invite) => invite.userId) ?? [],
);
- const start = item?.start
- ? new Date(item.start)
- : dayjs(new Date()).add(2, "hours").startOf("hour").toDate();
+ const start = item?.start ? new Date(item.start) : new Date();
const end = item?.end ? new Date(item.end) : undefined;
diff --git a/components/project/events/date-time-picker.tsx b/components/project/events/date-time-picker.tsx
index 5d7923a..9a7c585 100644
--- a/components/project/events/date-time-picker.tsx
+++ b/components/project/events/date-time-picker.tsx
@@ -10,6 +10,7 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
+import { toStartOfDay } from "@/lib/utils/date";
import {
type Period,
type TimePickerType,
@@ -18,7 +19,6 @@ import {
setDateByType,
} from "@/lib/utils/time";
import { add, format } from "date-fns";
-import dayjs from "dayjs";
import { Calendar as CalendarIcon, Clock } from "lucide-react";
import * as React from "react";
@@ -221,13 +221,13 @@ export function DateTimePicker({
if (!newDay) return;
if (dateOnly) {
- onSelect?.(dayjs(newDay).utc().startOf("day").toDate());
+ onSelect?.(toStartOfDay(new Date(newDay)));
setDate(newDay);
return;
}
if (!date) {
- setDate(dayjs(newDay).utc().startOf("day").toDate());
+ setDate(toStartOfDay(newDay));
return;
}
@@ -235,7 +235,7 @@ export function DateTimePicker({
const diffInDays = diff / (1000 * 60 * 60 * 24);
const newDateFull = add(date, { days: Math.ceil(diffInDays) });
setDate(newDateFull);
- onSelect?.(dayjs(newDateFull).utc().toDate());
+ onSelect?.(new Date(newDateFull));
};
return (
diff --git a/components/project/events/events-calendar.tsx b/components/project/events/events-calendar.tsx
index eed6425..5e4db31 100644
--- a/components/project/events/events-calendar.tsx
+++ b/components/project/events/events-calendar.tsx
@@ -2,7 +2,7 @@
import { Calendar } from "@/components/ui/calendar";
import type { EventWithInvites } from "@/drizzle/types";
-import dayjs from "dayjs";
+import { toDateString } from "@/lib/utils/date";
import { useRouter } from "next/navigation";
import EventsList from "./events-list";
@@ -10,7 +10,7 @@ export default function EventsCalendar({
projectId,
userId,
events,
- selectedDate = dayjs().format("YYYY-MM-DD"),
+ selectedDate,
compact = false,
timezone,
orgSlug,
@@ -25,15 +25,20 @@ export default function EventsCalendar({
}) {
const router = useRouter();
+ const currentDate = toDateString(
+ selectedDate ? new Date(selectedDate) : new Date(),
+ timezone,
+ );
+
return (
{
router.push(
- `/${orgSlug}/projects/${projectId}/events?on=${dayjs(date).format("YYYY-MM-DD")}`,
+ `/${orgSlug}/projects/${projectId}/events?on=${currentDate}`,
);
}}
/>
@@ -43,7 +48,7 @@ export default function EventsCalendar({
events={events}
projectId={projectId}
userId={userId}
- date={selectedDate}
+ date={currentDate}
compact={compact}
timezone={timezone}
/>
diff --git a/components/project/events/events-list.tsx b/components/project/events/events-list.tsx
index 692c5e4..0dff5d8 100644
--- a/components/project/events/events-list.tsx
+++ b/components/project/events/events-list.tsx
@@ -12,22 +12,22 @@ import {
} from "@/components/ui/dropdown-menu";
import type { EventWithInvites } from "@/drizzle/types";
import { cn } from "@/lib/utils";
-import dayjs from "dayjs";
-import timezone from "dayjs/plugin/timezone";
-import utc from "dayjs/plugin/utc";
+import {
+ toDateString,
+ toDateTimeString,
+ toEndOfDay,
+ toStartOfDay,
+} from "@/lib/utils/date";
import { CircleEllipsisIcon } from "lucide-react";
import Link from "next/link";
import { rrulestr } from "rrule";
import { Assignee } from "../shared/assigee";
-dayjs.extend(utc);
-dayjs.extend(timezone);
-
const filterByRepeatRule = (event: EventWithInvites, date: Date) => {
if (event.repeatRule) {
const rrule = rrulestr(event.repeatRule);
- const start = dayjs.utc(date).startOf("day").toDate();
- const end = dayjs.utc(date).endOf("day").toDate();
+ const start = toStartOfDay(date);
+ const end = toEndOfDay(date);
return rrule.between(start, end, true).length > 0;
}
@@ -83,17 +83,13 @@ export default function EventsList({
suppressHydrationWarning
>
{event.allDay
- ? dayjs(event.start).tz(timezone).format("MMM D, YYYY")
- : dayjs(event.start)
- .tz(timezone)
- .format("MMM D, YYYY, h:mm A")}
+ ? toDateString(event.start, timezone)
+ : toDateTimeString(event.start, timezone)}
{event.end
? ` - ${
event.allDay
- ? dayjs(event.end).tz(timezone).format("MMM D, YYYY")
- : dayjs(event.end)
- .tz(timezone)
- .format("MMM D, YYYY, h:mm A")
+ ? toDateString(event.end, timezone)
+ : toDateTimeString(event.end, timezone)
}`
: null}
{event.repeatRule
diff --git a/components/project/project-item.tsx b/components/project/project-item.tsx
index 4bc0978..731890e 100644
--- a/components/project/project-item.tsx
+++ b/components/project/project-item.tsx
@@ -1,19 +1,17 @@
import type { ProjectWithCreator } from "@/drizzle/types";
import { cn } from "@/lib/utils";
+import { toDateStringWithDay } from "@/lib/utils/date";
import { convertMarkdownToPlainText } from "@/lib/utils/useMarkdown";
-import dayjs from "dayjs";
-import timezone from "dayjs/plugin/timezone";
import Link from "next/link";
import { UserAvatar } from "../core/user-avatar";
-import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar";
import { Badge } from "../ui/badge";
-dayjs.extend(timezone);
-
export const ProjecItem = ({
project: { id, name, description, creator, dueDate },
+ timezone,
}: {
project: ProjectWithCreator;
+ timezone: string;
}) => {
return (
{dueDate ? (
- Due {dayjs(dueDate).format("dddd, MMMM D, YYYY")}
+ Due {toDateStringWithDay(dueDate, timezone)}
) : null}
diff --git a/lib/activity/index.ts b/lib/activity/index.ts
index d0102b5..46d7b11 100644
--- a/lib/activity/index.ts
+++ b/lib/activity/index.ts
@@ -1,7 +1,7 @@
import { activity } from "@/drizzle/schema";
-import dayjs from "dayjs";
+import { guessTimezone, toDateStringWithDay } from "../utils/date";
import { database } from "../utils/useDatabase";
-import { getOwner, getTimezone } from "../utils/useOwner";
+import { getOwner } from "../utils/useOwner";
type GenericObject = {
[key: string]:
@@ -54,7 +54,7 @@ function toDateString(date: any) {
return "-";
}
- return dayjs(date).format("YYYY-MM-DD HH:mm:ss");
+ return toDateStringWithDay(date, guessTimezone);
}
export function generateObjectDiffMessage(
diff --git a/lib/utils/date.ts b/lib/utils/date.ts
new file mode 100644
index 0000000..c2a8f09
--- /dev/null
+++ b/lib/utils/date.ts
@@ -0,0 +1,55 @@
+export function toStartOfDay(date: Date) {
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
+}
+
+export function toEndOfDay(date: Date) {
+ return new Date(
+ date.getFullYear(),
+ date.getMonth(),
+ date.getDate(),
+ 23,
+ 59,
+ 59,
+ 999,
+ );
+}
+
+export function toDateString(date: Date, timeZone: string) {
+ return date.toLocaleDateString("en-US", {
+ timeZone,
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ });
+}
+
+export function toDateTimeString(date: Date, timeZone: string) {
+ return date.toLocaleString("en-US", {
+ timeZone,
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit",
+ hour: "2-digit",
+ minute: "2-digit",
+ });
+}
+
+export function toDateStringWithDay(date: Date, timeZone: string) {
+ return date.toLocaleDateString("en-US", {
+ timeZone,
+ weekday: "long",
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ });
+}
+
+export function isSameDate(a: Date, b: Date) {
+ return (
+ a.getFullYear() === b.getFullYear() &&
+ a.getMonth() === b.getMonth() &&
+ a.getDate() === b.getDate()
+ );
+}
+
+export const guessTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
diff --git a/lib/utils/useOwner.ts b/lib/utils/useOwner.ts
index cdf5813..e5ebee4 100644
--- a/lib/utils/useOwner.ts
+++ b/lib/utils/useOwner.ts
@@ -2,16 +2,10 @@ import { logtoConfig } from "@/app/logto";
import { user } from "@/drizzle/schema";
import type { User } from "@/drizzle/types";
import { getLogtoContext } from "@logto/next/server-actions";
-import dayjs from "dayjs";
-import timezone from "dayjs/plugin/timezone";
-import utc from "dayjs/plugin/utc";
import { eq } from "drizzle-orm";
import { cookies } from "next/headers";
import { database } from "./useDatabase";
-dayjs.extend(utc);
-dayjs.extend(timezone);
-
type Result = {
ownerId: string;
userId: string;
@@ -63,5 +57,8 @@ export async function getOwner(): Promise {
export async function getTimezone() {
const cookieStore = await cookies();
- return cookieStore.get("userTimezone")?.value ?? dayjs.tz.guess();
+ return (
+ cookieStore.get("userTimezone")?.value ??
+ Intl.DateTimeFormat().resolvedOptions().timeZone
+ );
}
diff --git a/lib/utils/useProjects.ts b/lib/utils/useProjects.ts
index b4410e1..8decdd1 100644
--- a/lib/utils/useProjects.ts
+++ b/lib/utils/useProjects.ts
@@ -1,7 +1,7 @@
import { calendarEvent, document, project, taskList } from "@/drizzle/schema";
import type { ProjectWithCreator, ProjectWithData } from "@/drizzle/types";
-import dayjs from "dayjs";
import { and, between, eq, isNotNull, isNull, like, or } from "drizzle-orm";
+import { toEndOfDay, toStartOfDay } from "./date";
import { database } from "./useDatabase";
export async function getProjectsForOwner({
@@ -45,8 +45,8 @@ export async function getProjectById(
): Promise {
const db = await database();
- const startOfDay = dayjs().startOf("day").toDate();
- const endOfDay = dayjs().endOf("day").toDate();
+ const startOfDay = toStartOfDay(new Date());
+ const endOfDay = toEndOfDay(new Date());
const data = await db.query.project
.findFirst({
diff --git a/package.json b/package.json
index 6e7f4d1..eafe3a8 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,6 @@
"clsx": "^1.2.1",
"cmdk": "0.2.0",
"date-fns": "^2.30.0",
- "dayjs": "^1.11.12",
"drizzle-orm": "^0.38.2",
"easymde": "^2.18.0",
"eslint-config-next": "15.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 83d3fe7..ca00dc8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -87,9 +87,6 @@ importers:
date-fns:
specifier: ^2.30.0
version: 2.30.0
- dayjs:
- specifier: ^1.11.12
- version: 1.11.12
drizzle-orm:
specifier: ^0.38.2
version: 0.38.2(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.12)(@types/react@19.0.1)(better-sqlite3@11.7.0)(react@19.0.0)
@@ -7374,7 +7371,8 @@ snapshots:
dependencies:
'@babel/runtime': 7.25.0
- dayjs@1.11.12: {}
+ dayjs@1.11.12:
+ optional: true
debug@3.2.7:
dependencies: