Vitron-Front/app/components/thread/ThreadsPage.tsx
2026-04-29 01:44:16 +03:30

157 lines
5.2 KiB
TypeScript

import { Link } from "@remix-run/react";
import AppInput from "../AppInput";
import { useState } from "react";
import { useGetUserThreads } 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 { Search, User } from "lucide-react";
import ProfilePagesHeader from "../ProfilePagesHeader";
interface ThreadsPageProps {
type: "user" | "store";
storeId?: string;
}
export default function ThreadsPage({ type, storeId }: ThreadsPageProps) {
const [searchValue, setSearchValue] = useState("");
const { data: threads, isLoading, isError, refetch } = useGetUserThreads();
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 (
<div
className={`flex flex-col w-full ${isLoading || isFetchingProfile ? "" : "pb-20"}`}
>
<ProfilePagesHeader title="پیام‌ها" />
<div className="w-full px-4 py-2">
<div className="w-full h-[40px] flex items-center gap-2 bg-WHITE2 rounded-[10px]">
<AppInput
inputIcon={Search}
inputDir="rtl"
inputTitle={""}
className="bg-WHITE2"
inputValue={searchValue}
inputPlaceholder={"جستجو..."}
inputOnChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setSearchValue(value);
}}
/>
</div>
</div>
<UiProvider
isLoading={isLoading || isFetchingProfile}
isError={isError}
isEmpty={!!(threads && threads.length === 0)}
onRetry={refetch}
type="threads"
>
<ThreadsList
searchValue={searchValue}
threads={sortedThreads}
dataProfile={dataProfile}
type={type}
storeId={storeId}
/>
</UiProvider>
</div>
);
}
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 (
<div className="flex flex-col w-full">
{filteredThreads?.map((thread) => {
const otherParticipant = thread.participants?.find(
(participant: ThreadParticipant) =>
participant.username !== dataProfile?.username
);
const hasUnread = Number(thread.unreadCount || "0") > 0;
// Generate link based on type
const linkTo =
type === "user"
? `/profile/threads/${thread.id}`
: `/store/${storeId}/threads/${thread.id}`;
return (
<Link to={linkTo} key={thread.id} className="w-full">
<div className={`w-full h-[80px] flex items-center px-4 gap-4`}>
{thread.isCreator ? (
<SellerLogo
src={otherParticipant?.storeLogo}
alt="Participant Avatar"
/>
) : (
<User size={48} className="text-GRAY" />
)}
<div className="flex flex-col w-full">
<div className="w-full flex justify-between items-center">
<p className={`text-R14 ${hasUnread ? "font-bold" : ""}`}>
{thread.isCreator
? otherParticipant?.storeName ||
otherParticipant?.username
: otherParticipant?.name}
</p>
<div className="flex flex-col items-center justify-center">
{thread.lastMessageTime && (
<p className="text-R10 text-GRAY">
{new Date(thread.lastMessageTime).toLocaleTimeString(
"fa-IR",
{
hour: "2-digit",
minute: "2-digit",
}
)}
</p>
)}
{hasUnread && (
<div className="w-5 h-5 flex items-center justify-center bg-blue-500 text-WHITE text-R10 rounded-full">
{thread.unreadCount}
</div>
)}
</div>
</div>
<p
className={`text-R14 ${hasUnread ? "text-BLACK font-bold" : "text-GRAY"}`}
>
{thread.lastMessage?.content || "بدون پیام"}
</p>
</div>
</div>
</Link>
);
})}
</div>
);
};