import { desc, eq, inArray, or } from "drizzle-orm"; import Link from "next/link"; import { redirect } from "next/navigation"; import { getTranslations } from "next-intl/server"; import type { CSSProperties } from "react"; import { acceptFriend, declineFriendRequest, sendOfflineMessage, } from "@/actions/messenger"; import { ContentCard, EmptyState } from "@/components/public/ui"; import { auth } from "@/lib/auth"; import { db, MessengerFriendrequests, MessengerFriendships, MessengerOffline, User, } from "@/lib/db"; import { avatarImageUrl } from "@/lib/format"; import { formatDate } from "@/lib/format-date"; type SearchParams = Promise<{ accepted?: string; declined?: string; sent?: string; error?: string; send_error?: string; }>; function feedbackStyle(tone: "success" | "error"): CSSProperties { const accent = tone === "error" ? "var(--color-danger)" : "var(--color-primary)"; return { margin: 0, padding: "0.85rem 1rem", borderRadius: "var(--radius-md)", border: `1px solid ${accent}`, color: "var(--color-text-readable, var(--color-text))", fontSize: "0.9rem", fontWeight: 600, background: "var(--color-surface)", borderLeft: `4px solid ${accent}`, }; } export default async function MessagesPage({ searchParams, }: { searchParams: SearchParams; }) { const t = await getTranslations("pages.messages"); const session = await auth(); if (!session?.user?.id) redirect("/login"); const userId = Number(session.user.id); const { accepted, declined, sent, error, send_error } = await searchParams; let requests: { id: number; userFromId: number }[] = []; let messages: { id: number; userFromId: number; message: string; sendedOn: number; }[] = []; let friendships: { userOneId: number; userTwoId: number }[] = []; try { const [reqRows, msgRows, friendRows] = await Promise.all([ db .select({ id: MessengerFriendrequests.id, userFromId: MessengerFriendrequests.userFromId, }) .from(MessengerFriendrequests) .where(eq(MessengerFriendrequests.userToId, userId)) .orderBy(desc(MessengerFriendrequests.id)) .limit(100), db .select({ id: MessengerOffline.id, userFromId: MessengerOffline.userFromId, message: MessengerOffline.message, sendedOn: MessengerOffline.sendedOn, }) .from(MessengerOffline) .where(eq(MessengerOffline.userId, userId)) .orderBy(desc(MessengerOffline.sendedOn)) .limit(50), db .select({ userOneId: MessengerFriendships.userOneId, userTwoId: MessengerFriendships.userTwoId, }) .from(MessengerFriendships) .where( or( eq(MessengerFriendships.userOneId, userId), eq(MessengerFriendships.userTwoId, userId), ), ), ]); requests = reqRows; messages = msgRows; friendships = friendRows; } catch { requests = []; messages = []; friendships = []; } const friendIds = Array.from( new Set( friendships.map((f) => f.userOneId === userId ? f.userTwoId : f.userOneId, ), ), ).filter((id) => id > 0 && id !== userId); const otherIds = Array.from( new Set([ ...requests.map((r) => r.userFromId), ...messages.map((m) => m.userFromId), ...friendIds, ]), ).filter((id) => id && id > 0); let userById = new Map< number, { id: number; username: string; look: string } >(); if (otherIds.length > 0) { try { const users = await db .select({ id: User.id, username: User.username, look: User.look, }) .from(User) .where(inArray(User.id, otherIds)); userById = new Map(users.map((u) => [u.id, u])); } catch { userById = new Map(); } } const friendsForSelect = friendIds .map((id) => userById.get(id)) .filter((u): u is { id: number; username: string; look: string } => Boolean(u), ) .sort((a, b) => a.username.localeCompare(b.username)); const errorMessage = error === "not_found" ? t("errors.notFound") : error === "unauthorized" ? t("errors.unauthorized") : error === "invalid" ? t("errors.invalid") : error ? t("errors.error") : null; const sendErrorMessage = send_error === "not_friend" ? t("errors.notFriend") : send_error === "empty" ? t("errors.emptyMessage") : send_error === "rate_limited" ? t("errors.rateLimited") : send_error === "invalid" ? t("errors.invalid") : send_error ? t("errors.error") : null; return (
{accepted === "1" ? (
{t("success.accepted")}
) : null} {declined === "1" ? (
{t("success.declined")}
) : null} {sent === "1" ? (
{t("success.sent")}
) : null} {errorMessage ? (
{errorMessage}
) : null} {sendErrorMessage ? (
{sendErrorMessage}
) : null} {friendsForSelect.length === 0 ? ( {t("composeEmptyFriends")} ) : (