'use client'
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import { InfiniteScrollList } from '@/components/ui/infinite-scroll-list'
import RenderContactStatusText from './components/RenderContactStatusText'
import { useHeartbeatRelationListInfinite } from '@/hooks/useIm'
import { HeartbeatRelationListOutput } from '@/services/im/types'
import { useMemo } from 'react'
import { useRouter } from 'next/navigation'
import AIRelationTag from '@/components/features/AIRelationTag'
import Link from 'next/link'
import { usePrefetchRoutes } from '@/hooks/useGlobalPrefetchRoutes'
import Image from 'next/image'
// 联系人数据类型现在使用API返回的数据结构
type ContactItem = HeartbeatRelationListOutput
// 联系人卡片组件
const ContactCard = ({ contact }: { contact: ContactItem }) => {
const router = useRouter()
// 计算年龄
const age = useMemo(() => {
if (!contact.birthday) return null
const birthYear = new Date(contact.birthday).getFullYear()
const currentYear = new Date().getFullYear()
return currentYear - birthYear
}, [contact.birthday])
// 跳转到聊天页面
const handleChatClick = () => {
if (contact.aiId) {
router.push(`/chat/${contact.aiId}`)
}
}
return (
{/* 用户信息部分 */}
{/* 头像 */}
{(contact.nickname || contact.roleName || 'A').charAt(0)}
{/* 用户详细信息 */}
{/* 名字和标签 */}
{contact.nickname || contact.roleName}
{contact.heartbeatLevel && contact.isShow && (
)}
{/* 心动值和用户信息 */}
{/* 心动值 */}
{contact.heartbeatVal || 0}°
{/* 分隔线 */}
{/* 用户详细信息 */}
{[age && `${age}`, contact.characterName, contact.tagName]
.filter(Boolean)
.join(' · ')}
{/* 聊天按钮 */}
)
}
const ContactsPage = () => {
// 使用无限查询获取心动关系列表
const { data, fetchNextPage, hasNextPage, isLoading, isFetchingNextPage, error } =
useHeartbeatRelationListInfinite()
// 扁平化所有页面的数据
const allContacts = useMemo(() => {
return data?.pages.flatMap((page) => page.datas || []) || []
}, [data])
const chatRoutes = useMemo(
() =>
allContacts.slice(0, 20).map((contact) => (contact?.aiId ? `/chat/${contact.aiId}` : null)),
[allContacts]
)
usePrefetchRoutes(chatRoutes)
// 加载状态骨架屏组件
const ContactSkeleton = () => (
)
// 空状态组件
const EmptyState = () => (
No crushes found
Start chatting with AI characters to build your crushes
)
return (
{/* 页面标题 */}
My Crushes
{/* 心动值统计信息栏 */}
0} />
{/* 联系人列表 */}
items={allContacts}
renderItem={(contact) => }
getItemKey={(contact) => contact.aiId?.toString() || 'unknown'}
hasNextPage={!!hasNextPage}
isLoading={isLoading || isFetchingNextPage}
fetchNextPage={fetchNextPage}
columns={1}
gap={4}
className="!grid-cols-1" // 强制单列布局
LoadingSkeleton={ContactSkeleton}
EmptyComponent={EmptyState}
hasError={!!error}
onRetry={() => window.location.reload()}
/>
)
}
export default ContactsPage