121 lines
4.1 KiB
JavaScript
121 lines
4.1 KiB
JavaScript
import { useEffect, useCallback } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useChats } from "../hooks/useChats";
|
|
import { useAuthContext } from "../context/AuthContext";
|
|
import { useUnread } from "../context/UnreadContext";
|
|
import { getPostForChat } from "../stores/chatPostStore";
|
|
import { getImageUrl } from "../config/authConstants";
|
|
import { useDeleteChat } from "../hooks/useDeleteChat";
|
|
import TrashIcon from "../components/icons/TrashIcon";
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
export default function ChatListPage() {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
const { chats, loading, fetchChats } = useChats();
|
|
const { isAuthenticated } = useAuthContext();
|
|
const { updateFromChats, unreadMap } = useUnread();
|
|
const { deleteChat } = useDeleteChat();
|
|
|
|
useEffect(() => {
|
|
if (isAuthenticated) {
|
|
fetchChats();
|
|
}
|
|
}, [isAuthenticated, fetchChats]);
|
|
|
|
useEffect(() => {
|
|
if (chats.length > 0) {
|
|
updateFromChats(chats);
|
|
}
|
|
}, [chats, updateFromChats]);
|
|
|
|
const handleDeleteChat = useCallback(async (chatId) => {
|
|
if (!window.confirm(t('chat.confirmDeleteChat'))) return;
|
|
const ok = await deleteChat(chatId);
|
|
if (ok) fetchChats();
|
|
}, [t, deleteChat, fetchChats]);
|
|
|
|
if (!isAuthenticated) {
|
|
return (
|
|
<div className="f-app">
|
|
<div className="chat-page">
|
|
<div className="chat-header">
|
|
<button className="chat-back-btn" onClick={() => navigate("/feed")}>
|
|
←
|
|
</button>
|
|
<div className="chat-header-title">{t('chat.chats')}</div>
|
|
<div />
|
|
</div>
|
|
<div className="chat-empty-full">{t('chat.loginToSee')}</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="f-app">
|
|
<div className="chat-page">
|
|
<div className="chat-header">
|
|
<button className="chat-back-btn" onClick={() => navigate("/feed")}>
|
|
←
|
|
</button>
|
|
<div className="chat-header-title">{t('chat.chats')}</div>
|
|
<div />
|
|
</div>
|
|
|
|
<div className="chat-list">
|
|
{loading && (
|
|
<div className="chat-empty-full">{t('chat.loading')}</div>
|
|
)}
|
|
|
|
{!loading && chats.length === 0 && (
|
|
<div className="chat-empty-full">{t('chat.noChats')}</div>
|
|
)}
|
|
|
|
{!loading && chats.map((chat) => {
|
|
const post = getPostForChat(chat.id);
|
|
const title = post?.title || chat.otherUser?.name || t('chat.user');
|
|
const imgSrc = getImageUrl(post?.images?.[0]);
|
|
const emoji = post?.emoji;
|
|
const unreadCount = unreadMap[chat.id] ?? chat.unreadCount ?? chat.unreadMessages ?? 0;
|
|
return (
|
|
<div
|
|
key={chat.id}
|
|
className={`chat-list-item${unreadCount > 0 ? " unread" : ""}`}
|
|
onClick={() => navigate(`/chats/${chat.id}`)}
|
|
>
|
|
<div className="chat-list-avatar">
|
|
{imgSrc ? (
|
|
<img src={imgSrc} alt="" className="chat-list-avatar-img" />
|
|
) : (
|
|
emoji || chat.otherUser?.name?.[0] || "?"
|
|
)}
|
|
</div>
|
|
<div className="chat-list-info">
|
|
<div className="chat-list-name">{title}</div>
|
|
<div className="chat-list-preview">
|
|
{chat.lastMessage?.content || t('chat.noMessages')}
|
|
</div>
|
|
</div>
|
|
{unreadCount > 0 && (
|
|
<div className="chat-list-unread-badge">{unreadCount > 99 ? "99+" : unreadCount}</div>
|
|
)}
|
|
<button
|
|
className="chat-list-delete-btn"
|
|
title={t('chat.deleteChat')}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
handleDeleteChat(chat.id);
|
|
}}
|
|
>
|
|
<TrashIcon />
|
|
</button>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|