import { Link } from "@remix-run/react"; import AppInput from "../AppInput"; import { useState } from "react"; import { useGetUserThreads, useGetStoreThreads, } from "../../requestHandler/use-chat-hooks"; import { ThreadList, ThreadParticipant, UserProfile, } from "../../../src/api/types"; import { useServiceGetProfile } from "../../requestHandler/use-profile-hooks"; import UiProvider from "../UiProvider"; import SellerLogo from "../SellerLogo"; import { CheckCheck, MessageCircleWarning, Search, User } from "lucide-react"; import ProfilePagesHeader from "../ProfilePagesHeader"; // Persian-style relative timestamp for the inbox list. Older messages need a // day label so the seller can tell "today's message" from "3 months ago" // without reading the date. function formatThreadTimestamp(iso: string | null | undefined): string { if (!iso) return ""; const d = new Date(iso); if (isNaN(d.getTime())) return ""; const now = new Date(); const startOfDay = (x: Date) => new Date(x.getFullYear(), x.getMonth(), x.getDate()).getTime(); const dayDiff = Math.round( (startOfDay(now) - startOfDay(d)) / (1000 * 60 * 60 * 24), ); const timePart = d.toLocaleTimeString("fa-IR", { hour: "2-digit", minute: "2-digit", }); if (dayDiff <= 0) return timePart; // today: just HH:MM if (dayDiff === 1) return `دیروز ${timePart}`; if (dayDiff < 7) return `${dayDiff} روز پیش`; // Older than a week: show the date in Persian calendar. return d.toLocaleDateString("fa-IR"); } interface ThreadsPageProps { type: "user" | "store"; storeId?: string; } export default function ThreadsPage({ type, storeId }: ThreadsPageProps) { const [searchValue, setSearchValue] = useState(""); // Seller dashboard shows the STORE's inbox; the profile page shows the user's // personal (buyer) chats. Two different endpoints so the two never mix. const userThreads = useGetUserThreads(); const storeThreads = useGetStoreThreads(type === "store" ? storeId : undefined); const { data: threads, isLoading, isError, refetch, } = type === "store" ? storeThreads : userThreads; const sortedThreads = threads?.sort((a, b) => { const dateA = new Date(a.lastMessageTime || "2025-01-18T00:00:00.000Z"); const dateB = new Date(b.lastMessageTime || "2025-01-18T00:00:00.000Z"); return dateB.getTime() - dateA.getTime(); }); const { data: dataProfile, isFetching: isFetchingProfile } = useServiceGetProfile(); return (
) => { const value = e.target.value; setSearchValue(value); }} />
); } const ThreadsList = ({ searchValue, threads, dataProfile, type, storeId, }: { searchValue: string; threads: ThreadList[] | undefined; dataProfile: UserProfile | undefined; type: "user" | "store"; storeId?: string; }) => { const filteredThreads = threads?.filter((thread) => { return thread.participants?.some((participant: ThreadParticipant) => participant.username?.toLowerCase().includes(searchValue.toLowerCase()) ); }); return (
{filteredThreads?.map((thread) => { const otherParticipant = thread.participants?.find( (participant: ThreadParticipant) => participant.username !== dataProfile?.username ); const hasUnread = Number(thread.unreadCount || "0") > 0; // Seller-inbox only. Shows what state the thread is in so the team // can see at a glance which chats need attention. // - "needs-reply" → last message is from the customer (or nobody // on the team has replied yet). // - "unread-by-customer" → team replied, customer hasn't seen it. // - "seen" → team replied and the customer opened it. const showStatus = type === "store"; const lastFromTeam = !!thread.lastMessageFromTeam; const otherSeen = !!thread.otherPartySeenLast; const status: "needs-reply" | "unread-by-customer" | "seen" | null = !showStatus ? null : !lastFromTeam ? "needs-reply" : otherSeen ? "seen" : "unread-by-customer"; // Generate link based on type const linkTo = type === "user" ? `/profile/threads/${thread.id}` : `/store/${storeId}/threads/${thread.id}`; return (
{thread.isCreator ? ( ) : ( )}
{status === "needs-reply" && ( )} {status === "seen" && ( )}

{thread.isCreator ? otherParticipant?.storeName || otherParticipant?.username : otherParticipant?.name}

{thread.lastMessageTime && (

{formatThreadTimestamp(thread.lastMessageTime)}

)} {hasUnread && (
{thread.unreadCount}
)}

{thread.lastMessage?.content || (thread.lastMessage?.imageUrl ? "📷 تصویر" : thread.lastMessage?.product ? `🛍 ${thread.lastMessage.product.title || "محصول"}` : "بدون پیام")}

); })}
); };