"use client"; import * as z from "zod"; import axios from "axios"; import qs from "query-string"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Member, MemberRole, Profile } from "@prisma/client"; import { Edit, FileIcon, ShieldAlert, ShieldCheck, Trash } from "lucide-react"; import Image from "next/image"; import { useEffect, useState } from "react"; import { useRouter, useParams } from "next/navigation"; import { UserAvatar } from "@/components/user-avatar"; import { ActionTooltip } from "@/components/action-tooltip"; import { cn } from "@/lib/utils"; import { Form, FormControl, FormField, FormItem, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { useModal } from "@/hooks/use-modal-store"; interface ChatItemProps { id: string; content: string; member: Member & { profile: Profile; }; timestamp: string fileUrl: string | null; deleted: boolean; currentMember: Member; isUpdated: boolean; socketUrl: string; socketQuery: Record; } const roleIconMap = { "GUEST": null, "MODERATOR": , "ADMIN": , } const formSchema = z.object({ content: z.string().min(1), }) export const ChatItem = ({ id, content, member, timestamp, fileUrl, deleted, currentMember, isUpdated, socketUrl, socketQuery, }: ChatItemProps) => { const [isEditing, setIsEditing] = useState(false); const { onOpen } = useModal(); const params = useParams(); const router = useRouter(); const onMemberClick = () => { if (member.id === currentMember.id) { return; } router.push(`/servers/${params?.serverId}/conversations/${member.id}`); } useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "Escape" || event.keyCode === 27) { setIsEditing(false); } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, []); const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { content: content } }); const isLoading = form.formState.isSubmitting; const onSubmit = async (values: z.infer) => { try { const url = qs.stringifyUrl({ url: `${socketUrl}/${id}`, query: socketQuery, }); await axios.patch(url, values); form.reset(); setIsEditing(false); } catch (error) { console.log(error); } } useEffect(() => { form.reset({ content: content, }) }, [content]); const filetype = fileUrl?.split(".").pop(); const isAdmin = currentMember.role === MemberRole.ADMIN; const isModerator = currentMember.role === MemberRole.MODERATOR; const isOwner = currentMember.id === member.id; const canDeleteMessage = !deleted && (isAdmin || isModerator || isOwner); const canEditMessage = !deleted && isOwner && !fileUrl; const isPDF = filetype == "pdf" && fileUrl; const isImage = !isPDF && fileUrl; return (

{member.profile.name}

{roleIconMap[member.role]}
{timestamp}
{isImage && ( {content} )} {isPDF && ( )} {!fileUrl && !isEditing && (

{content} {isUpdated && ( (edited) )}

)} {!fileUrl && isEditing && (
(
)} /> Press escape to cancel, enter to save )}
{canDeleteMessage && (
{canEditMessage && ( setIsEditing(true)} className="cursor-pointer ml-auto w-4 h-4 text-zinc-500 hover:text-zinc-600 dark:hove:text-zinc-300 transition" /> )} onOpen("deleteMessage", { apiUrl: `${socketUrl}/${id}`, query: socketQuery, })} className="cursor-pointer ml-auto w-4 h-4 text-zinc-500 hover:text-zinc-600 dark:hove:text-zinc-300 transition" />
)}
) }