Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 32 additions & 15 deletions src/components/layouts/app-sidebar-threads.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,17 @@ export function AppSidebarThreads() {
return [];
}

const today = new Date();
today.setHours(0, 0, 0, 0);

const yesterday = new Date(today);
yesterday.setDate(yesterday.getDate() - 1);
// Get today's date at midnight in local timezone
const now = new Date();
const todayLocal = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate(),
);
const todayStart = todayLocal.getTime();

const lastWeek = new Date(today);
lastWeek.setDate(lastWeek.getDate() - 7);
const yesterdayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1).getTime();
const lastWeekStart = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 7).getTime();

const groups: ThreadGroup[] = [
{ label: t("today"), threads: [] },
Expand All @@ -125,17 +128,31 @@ export function AppSidebarThreads() {
];

displayThreadList.forEach((thread) => {
const threadDate =
(thread.lastMessageAt
? new Date(thread.lastMessageAt)
: new Date(thread.createdAt)) || new Date();
threadDate.setHours(0, 0, 0, 0);
// Get the timestamp - lastMessageAt is already a timestamp, createdAt is a Date
const threadTimestamp =
thread.lastMessageAt || new Date(thread.createdAt).getTime();

// Convert timestamp to a date in LOCAL timezone
const threadDate = new Date(threadTimestamp);

// Get the local date components (this gives us the date in user's timezone)
const localYear = threadDate.getFullYear();
const localMonth = threadDate.getMonth();
const localDay = threadDate.getDate();

// Create normalized day start using local components
const normalizedThreadDay = new Date(
localYear,
localMonth,
localDay,
).getTime();

if (threadDate.getTime() === today.getTime()) {
// Check which group this thread belongs to
if (normalizedThreadDay === todayStart) {
groups[0].threads.push(thread);
} else if (threadDate.getTime() === yesterday.getTime()) {
} else if (normalizedThreadDay === yesterdayStart) {
groups[1].threads.push(thread);
} else if (threadDate.getTime() >= lastWeek.getTime()) {
} else if (normalizedThreadDay >= lastWeekStart) {
groups[2].threads.push(thread);
} else {
groups[3].threads.push(thread);
Expand Down
13 changes: 10 additions & 3 deletions src/lib/db/pg/repositories/chat-repository.pg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,21 @@ export const pgChatRepository: ChatRepository = {
.orderBy(desc(sql`last_message_at`));

return threadWithLatestMessage.map((row) => {
let timestamp = 0;
if (row.lastMessageAt) {
// PostgreSQL returns timestamp without timezone info in format 'YYYY-MM-DD HH:MM:SS'
// We need to treat it as UTC, not local time
// Add 'Z' suffix to make it explicit UTC, or use Date.UTC
const utcTimestamp = row.lastMessageAt.replace(' ', 'T') + 'Z';
timestamp = new Date(utcTimestamp).getTime();
}

return {
id: row.threadId,
title: row.title,
userId: row.userId,
createdAt: row.createdAt,
lastMessageAt: row.lastMessageAt
? new Date(row.lastMessageAt).getTime()
: 0,
lastMessageAt: timestamp,
};
});
},
Expand Down
Loading