MingruiZhang's picture
feat: Minor updates and introducing shadcn (#54)
78ebb49 unverified
raw
history blame
2.48 kB
'use client';
import { PropsWithChildren } from 'react';
import Link from 'next/link';
import { useParams, usePathname, useRouter } from 'next/navigation';
import { cn } from '@/lib/utils';
import Image from 'next/image';
import clsx from 'clsx';
import Img from '../ui/Img';
import { format } from 'date-fns';
import { cleanInputMessage } from '@/lib/messageUtils';
import { IconClose } from '../ui/Icons';
import { ChatWithMessages } from '@/lib/db/types';
import { dbDeleteChat } from '@/lib/db/functions';
type ChatCardProps = PropsWithChildren<{
chat: ChatWithMessages;
isAdminView?: boolean;
}>;
export const ChatCardLayout: React.FC<
PropsWithChildren<{ link: string; classNames?: clsx.ClassValue }>
> = ({ link, children, classNames }) => {
return (
<Link
className={cn(
'p-2 bg-background max-h-[100px] rounded-xl shadow-md flex items-center border border-transparent hover:border-gray-500 transition-all cursor-pointer w-full',
classNames,
)}
href={link}
>
{children}
</Link>
);
};
const ChatCard: React.FC<ChatCardProps> = ({ chat, isAdminView }) => {
const { id: chatIdFromParam } = useParams();
const { id, mediaUrl, messages, userId, updatedAt } = chat;
if (!id) {
return null;
}
const firstMessage = cleanInputMessage(messages?.[0]?.content ?? '');
const title = firstMessage
? firstMessage.length > 50
? firstMessage.slice(0, 50) + '...'
: firstMessage
: '(No messages yet)';
return (
<ChatCardLayout
link={isAdminView ? `/all/chat/${id}` : `/chat/${id}`}
classNames={chatIdFromParam === id && 'border-gray-500'}
>
<div className="overflow-hidden flex items-center size-full group">
<Img src={mediaUrl} alt={`chat-${id}-card-image`} className="w-1/4" />
<div className="flex items-start flex-col h-full ml-3 w-3/4">
<p className="text-sm mb-1">{title}</p>
<p className="text-xs text-gray-500">
{updatedAt ? format(Number(updatedAt), 'yyyy-MM-dd') : '-'}
</p>
{isAdminView && <p className="text-xs text-gray-500">{userId}</p>}
<IconClose
onClick={async e => {
e.stopPropagation();
await dbDeleteChat(id);
}}
className="absolute right-4 opacity-0 group-hover:opacity-100 top-1/2 -translate-y-1/2"
/>
</div>
</div>
</ChatCardLayout>
);
};
export default ChatCard;