Skip to content

Commit

Permalink
Update date formatting and timezone handling across components
Browse files Browse the repository at this point in the history
  • Loading branch information
arjunkomath committed Jan 12, 2025
1 parent 0543615 commit 8c2e1be
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 28 deletions.
10 changes: 7 additions & 3 deletions app/(dashboard)/[tenant]/projects/[projectId]/events/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

import { calendarEvent, eventInvite } from "@/drizzle/schema";
import { generateObjectDiffMessage, logActivity } from "@/lib/activity";
import { toDateString, toEndOfDay } from "@/lib/utils/date";
import {
toDateString,
toEndOfDay,
toMachineDateString,
} from "@/lib/utils/date";
import { database } from "@/lib/utils/useDatabase";
import { getOwner, getTimezone } from "@/lib/utils/useOwner";
import { and, eq } from "drizzle-orm";
Expand Down Expand Up @@ -99,7 +103,7 @@ export async function createEvent(payload: FormData) {

revalidatePath(`/${orgSlug}/projects/${projectId}/events`);
redirect(
`/${orgSlug}/projects/${projectId}/events?on=${toDateString(start, timezone)}`,
`/${orgSlug}/projects/${projectId}/events?on=${toMachineDateString(start, timezone)}`,
);
}

Expand Down Expand Up @@ -169,7 +173,7 @@ export async function updateEvent(payload: FormData) {

revalidatePath(`/${orgSlug}/projects/${projectId}/events`);
redirect(
`/${orgSlug}/projects/${projectId}/events?on=${toDateString(start, timezone)}`,
`/${orgSlug}/projects/${projectId}/events?on=${toMachineDateString(start, timezone)}`,
);
}

Expand Down
4 changes: 3 additions & 1 deletion app/(dashboard)/[tenant]/projects/[projectId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { toDateStringWithDay } from "@/lib/utils/date";
import { getOwner, getTimezone } from "@/lib/utils/useOwner";
import { getProjectById } from "@/lib/utils/useProjects";
import { CalendarPlusIcon, ListPlusIcon, PlusIcon } from "lucide-react";
Expand Down Expand Up @@ -53,7 +54,7 @@ export default async function ProjectDetails(props: Props) {
<div className="flex space-x-2">
{project.dueDate ? (
<Badge variant="outline">
Due {project.dueDate.toLocaleDateString()}
Due {toDateStringWithDay(project.dueDate, timezone)}
</Badge>
) : null}
{project.status === "archived" ? (
Expand Down Expand Up @@ -141,6 +142,7 @@ export default async function ProjectDetails(props: Props) {
>
<TaskListHeader
orgSlug={orgSlug}
timezone={timezone}
taskList={taskList}
totalCount={taskList.tasks.length}
doneCount={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { CommentsSection } from "@/components/project/comment/comments-section";
import { TaskListItem } from "@/components/project/tasklist/tasklist";
import { Progress } from "@/components/ui/progress";
import { task, taskList, user } from "@/drizzle/schema";
import { toDateStringWithDay } from "@/lib/utils/date";
import { database } from "@/lib/utils/useDatabase";
import { getOwner } from "@/lib/utils/useOwner";
import { getOwner, getTimezone } from "@/lib/utils/useOwner";
import { and, asc, eq } from "drizzle-orm";
import { CheckCircle, ClockIcon } from "lucide-react";
import { notFound } from "next/navigation";
Expand All @@ -18,12 +19,13 @@ type Props = {
};

export default async function TaskLists(props: Props) {
const params = await props.params;
const { userId, orgSlug } = await getOwner();
const { projectId, tasklistId } = params;
const params = await props.params;
const { userId, orgSlug } = await getOwner();
const { projectId, tasklistId } = params;

const db = await database();
const list = await db.query.taskList
const timezone = await getTimezone();
const db = await database();
const list = await db.query.taskList
.findFirst({
where: and(
eq(taskList.projectId, +projectId),
Expand Down Expand Up @@ -51,27 +53,27 @@ export default async function TaskLists(props: Props) {
})
.execute();

if (!list) {
if (!list) {
return notFound();
}

const currentUser = await db.query.user.findFirst({
const currentUser = await db.query.user.findFirst({
where: eq(user.id, userId),
});

if (!currentUser) {
if (!currentUser) {
return notFound();
}

const totalCount = list.tasks.length;
const doneCount = list.tasks.filter((task) => task.status === "done").length;
const totalCount = list.tasks.length;
const doneCount = list.tasks.filter((task) => task.status === "done").length;

const completedPercent =
const completedPercent =
totalCount != null && doneCount != null
? Math.round((doneCount / totalCount) * 100)
: null;

return (
return (
<>
<PageTitle
title={list.name}
Expand Down Expand Up @@ -100,12 +102,12 @@ export default async function TaskLists(props: Props) {
) : null}

{list.dueDate ? (
<div className="flex flex-row items-center border rounded-lg py-1 px-2 space-x-2 max-w-[160px]">
<div className="flex flex-row items-center border rounded-lg py-1 px-2 space-x-2">
<ClockIcon className="w-4 h-4" />
<p className="block">
{list.dueDate ? (
<span suppressHydrationWarning>
Due {list.dueDate.toLocaleDateString()}
Due {toDateStringWithDay(list.dueDate, timezone)}
</span>
) : null}
</p>
Expand All @@ -116,6 +118,7 @@ export default async function TaskLists(props: Props) {

<div className="mx-auto -mt-8 max-w-5xl px-4">
<TaskListItem
timezone={timezone}
key={list.id}
taskList={list}
projectId={+projectId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TaskListItem } from "@/components/project/tasklist/tasklist";
import { buttonVariants } from "@/components/ui/button";
import { task, taskList } from "@/drizzle/schema";
import { database } from "@/lib/utils/useDatabase";
import { getOwner } from "@/lib/utils/useOwner";
import { getOwner, getTimezone } from "@/lib/utils/useOwner";
import { and, asc, eq, or } from "drizzle-orm";
import Link from "next/link";
import { createTask, partialUpdateTaskList } from "./actions";
Expand All @@ -24,6 +24,7 @@ export default async function TaskLists(props: Props) {
const { userId, orgSlug } = await getOwner();
const { projectId } = params;

const timezone = await getTimezone();
const filterByStatuses = searchParams.status?.split(",") ?? ["active"];
const statusFilter = filterByStatuses.map((status) =>
eq(taskList.status, status),
Expand Down Expand Up @@ -92,6 +93,7 @@ export default async function TaskLists(props: Props) {
createTask={createTask}
partialUpdateTaskList={partialUpdateTaskList}
orgSlug={orgSlug}
timezone={timezone}
compact
/>
))}
Expand Down
4 changes: 4 additions & 0 deletions app/(dashboard)/[tenant]/today/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ 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 { getTimezone } from "@/lib/utils/useOwner";
import { and, asc, lte, ne } from "drizzle-orm";
import { AlertTriangleIcon, InfoIcon } from "lucide-react";

export default async function Today() {
const db = await database();

const timezone = await getTimezone();
const tasks = await db.query.task.findMany({
where: and(lte(task.dueDate, new Date()), ne(task.status, "done")),
orderBy: [asc(task.position)],
Expand Down Expand Up @@ -68,6 +70,7 @@ export default async function Today() {
key={task.id}
task={task}
projectId={+task.taskList.projectId}
timezone={timezone}
compact
/>
))}
Expand All @@ -85,6 +88,7 @@ export default async function Today() {
key={task.id}
task={task}
projectId={+task.taskList.projectId}
timezone={timezone}
compact
/>
))}
Expand Down
2 changes: 1 addition & 1 deletion components/project/events/events-calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function EventsCalendar({
selected={new Date(currentDate)}
onDayClick={(date) => {
router.push(
`/${orgSlug}/projects/${projectId}/events?on=${currentDate}`,
`/${orgSlug}/projects/${projectId}/events?on=${date.toISOString()}`,
);
}}
/>
Expand Down
5 changes: 4 additions & 1 deletion components/project/tasklist/task/task-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { Input } from "@/components/ui/input";
import type { Task, TaskList, TaskWithDetails, User } from "@/drizzle/types";
import { cn } from "@/lib/utils";
import { toDateStringWithDay } from "@/lib/utils/date";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { AlignJustifyIcon, FileIcon } from "lucide-react";
Expand All @@ -32,10 +33,12 @@ export const TaskItem = ({
task,
projectId,
taskLists,
timezone,
compact = false,
}: {
task: TaskWithDetails;
projectId: number;
timezone: string;
taskLists?: TaskList[];
compact?: boolean;
}) => {
Expand Down Expand Up @@ -215,7 +218,7 @@ export const TaskItem = ({
<dd className="mt-1 flex items-start text-sm leading-6 sm:col-span-2 sm:mt-0">
{task.dueDate ? (
<div className="flex w-full items-center justify-between">
<p>{task.dueDate.toLocaleDateString()}</p>
<p>{toDateStringWithDay(task.dueDate, timezone)}</p>
<button
type="button"
className="text-primary hover:text-red-500"
Expand Down
9 changes: 6 additions & 3 deletions components/project/tasklist/tasklist-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Progress } from "@/components/ui/progress";
import type { TaskList } from "@/drizzle/types";
import { toDateStringWithDay } from "@/lib/utils/date";
import { CheckCircle, CircleEllipsisIcon, ClockIcon } from "lucide-react";
import Link from "next/link";
import toast from "react-hot-toast";
Expand All @@ -20,6 +21,7 @@ export const TaskListHeader = ({
doneCount,
orgSlug,
partialUpdateTaskList,
timezone,
}: {
taskList: TaskList;
totalCount?: number;
Expand All @@ -29,6 +31,7 @@ export const TaskListHeader = ({
id: number,
data: { status: string },
) => Promise<void>;
timezone: string;
}) => {
const completedPercent =
totalCount != null && doneCount != null
Expand All @@ -50,7 +53,7 @@ export const TaskListHeader = ({
</div>
</div>

<div className="flex flex-col space-y-2 md:flex-row md:space-y-0 md:space-x-2 text-gray-500 dark:text-gray-400">
<div className="flex flex-col space-y-2 text-gray-500 dark:text-gray-400">
{totalCount != null && doneCount != null ? (
<div className="flex w-[264px] flex-row items-center border rounded-lg py-1 px-2 space-x-2">
<CheckCircle className="w-4 h-4" />
Expand All @@ -71,12 +74,12 @@ export const TaskListHeader = ({
) : null}

{taskList.dueDate ? (
<div className="flex flex-row items-center border rounded-lg py-1 px-2 space-x-2 max-w-[180px]">
<div className="flex flex-row items-center border rounded-lg py-1 px-2 space-x-2 w-[264px]">
<ClockIcon className="w-4 h-4" />
<p className="block">
{taskList.dueDate ? (
<span suppressHydrationWarning>
Due {taskList.dueDate.toLocaleDateString()}
Due {toDateStringWithDay(taskList.dueDate, timezone)}
</span>
) : null}
</p>
Expand Down
11 changes: 10 additions & 1 deletion components/project/tasklist/tasklist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ export const TaskListItem = ({
orgSlug,
createTask,
partialUpdateTaskList,
timezone,
hideHeader = false,
compact = false,
}: {
taskList: TaskListWithTasks;
userId: string;
projectId: number;
orgSlug: string;
timezone: string;
createTask: (data: {
name: string;
userId: string;
Expand Down Expand Up @@ -118,6 +120,7 @@ export const TaskListItem = ({
doneCount={doneItems.length}
orgSlug={orgSlug}
partialUpdateTaskList={partialUpdateTaskList}
timezone={timezone}
/>
) : null}

Expand Down Expand Up @@ -145,6 +148,7 @@ export const TaskListItem = ({
>
{localTodoItems.map((task) => (
<TaskItem
timezone={timezone}
key={task.id}
task={task}
projectId={+projectId}
Expand Down Expand Up @@ -173,7 +177,12 @@ export const TaskListItem = ({
{compact
? null
: doneItems.map((task) => (
<TaskItem key={task.id} task={task} projectId={+projectId} />
<TaskItem
key={task.id}
task={task}
projectId={+projectId}
timezone={timezone}
/>
))}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions lib/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export function toDateTimeString(date: Date, timeZone: string) {
export function toDateStringWithDay(date: Date, timeZone: string) {
return date.toLocaleDateString("en-US", {
timeZone,
weekday: "long",
weekday: "short",
year: "numeric",
month: "long",
month: "short",
day: "numeric",
});
}
Expand Down

0 comments on commit 8c2e1be

Please sign in to comment.