mojmajstor/components/chat-list-item.tsx
2026-06-06 03:54:22 +02:00

137 lines
4.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { View, Text, Pressable } from "react-native";
import { Link } from "expo-router";
import { Ionicons } from "@expo/vector-icons";
import { useTheme } from "./theme";
import { Avatar } from "./ui/avatar";
interface ChatListItemProps {
chat: {
_id: string;
otherUser: {
_id: string;
name: string;
avatarId: string | null;
} | null;
lastMessage: {
content: string;
createdAt: number;
senderId: string;
} | null;
lastMessageAt: number;
};
currentUserId: string;
}
function formatRelativeTime(timestamp: number): string {
const now = Date.now();
const diff = now - timestamp;
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (minutes < 1) return "Сега";
if (minutes < 60) return `${minutes}м`;
if (hours < 24) return `${hours}ч`;
if (days < 7) return `${days}д`;
return new Date(timestamp).toLocaleDateString("mk-MK");
}
export function ChatListItem({ chat, currentUserId }: ChatListItemProps) {
const theme = useTheme();
const isSelfMessage = chat.lastMessage?.senderId === currentUserId;
const previewText = chat.lastMessage
? (isSelfMessage ? "Вие: " : "") +
(chat.lastMessage.content.length > 40
? chat.lastMessage.content.slice(0, 40) + "…"
: chat.lastMessage.content)
: "Нема пораки";
const isUnread = chat.lastMessage && !isSelfMessage;
return (
<Link href={`/chat/${chat._id}` as any} asChild>
<Pressable
accessible
accessibilityLabel={`Разговор со ${chat.otherUser?.name ?? "Непознат"}: ${previewText}`}
accessibilityRole="button"
style={({ pressed }) => [
{
flexDirection: "row",
alignItems: "center",
paddingVertical: theme.spacing.md,
paddingHorizontal: theme.spacing.md,
gap: theme.spacing.md,
backgroundColor: theme.colors.surface,
borderBottomWidth: 1,
borderBottomColor: theme.colors.divider,
},
pressed && { backgroundColor: theme.colors.surfaceAlt },
]}
>
<View style={{ position: "relative" }}>
<Avatar
uri={chat.otherUser?.avatarId ?? null}
name={chat.otherUser?.name ?? "Непознат"}
size={52}
/>
{isUnread && (
<View
style={{
position: "absolute",
top: -1,
right: -1,
width: 12,
height: 12,
borderRadius: 6,
backgroundColor: theme.colors.primary,
borderWidth: 2.5,
borderColor: theme.colors.surface,
}}
/>
)}
</View>
<View style={{ flex: 1, gap: 3 }}>
<View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
<Text
style={{
...theme.typography.bodyBold,
color: theme.colors.text,
fontSize: 15,
flex: 1,
}}
numberOfLines={1}
>
{chat.otherUser?.name ?? "Непознат"}
</Text>
{chat.lastMessage && (
<Text style={{ ...theme.typography.label, color: theme.colors.textTertiary, fontSize: 11 }}>
{formatRelativeTime(chat.lastMessage.createdAt)}
</Text>
)}
</View>
<View style={{ flexDirection: "row", alignItems: "center", gap: 6 }}>
{isUnread && (
<View style={{ width: 7, height: 7, borderRadius: 3.5, backgroundColor: theme.colors.primary }} />
)}
<Text
style={{
...theme.typography.caption,
color: isUnread ? theme.colors.text : theme.colors.textSecondary,
fontSize: 13,
flex: 1,
}}
numberOfLines={1}
>
{previewText}
</Text>
</View>
</View>
<Ionicons name="chevron-forward" size={16} color={theme.colors.textTertiary} />
</Pressable>
</Link>
);
}
export { formatRelativeTime };