import { ActionIcon, Avatar, Box, Group, Loader, Paper, ScrollArea, Stack, Text, Textarea, Tooltip, } from "@mantine/core"; import { IconSend, IconTrash } from "@tabler/icons-react"; import { notifications } from "@mantine/notifications"; import { KeyboardEvent, useCallback, useEffect, useRef, useState } from "react"; import * as api from "../api"; import type { CardMessage, User } from "../types"; import { tagColor } from "./colors"; import { formatDateTimeShort } from "./format"; interface Props { cardId: string; users: User[]; currentUserId?: string; onMessagesChange?: (messages: CardMessage[]) => void; } export function CardChatPanel({ cardId, users, currentUserId, onMessagesChange }: Props) { const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(true); const [body, setBody] = useState(""); const [sending, setSending] = useState(false); const viewportRef = useRef(null); const usersById = new Map(users.map((u) => [u.id, u])); const reload = useCallback(async () => { try { const ms = await api.listCardMessages(cardId); setMessages(ms); onMessagesChange?.(ms); } catch (e) { notifications.show({ color: "red", message: (e as Error).message }); } finally { setLoading(false); } }, [cardId, onMessagesChange]); useEffect(() => { reload(); }, [reload]); useEffect(() => { if (viewportRef.current) { viewportRef.current.scrollTo({ top: viewportRef.current.scrollHeight, behavior: "smooth" }); } }, [messages.length]); const send = async () => { const text = body.trim(); if (!text || sending) return; setSending(true); try { const m = await api.createCardMessage(cardId, text); const next = [...messages, m]; setMessages(next); onMessagesChange?.(next); setBody(""); } catch (e) { notifications.show({ color: "red", message: (e as Error).message }); } finally { setSending(false); } }; const remove = async (mid: string) => { try { await api.deleteCardMessage(cardId, mid); const next = messages.filter((m) => m.id !== mid); setMessages(next); onMessagesChange?.(next); } catch (e) { notifications.show({ color: "red", message: (e as Error).message }); } }; const onKeyDown = (e: KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } }; return ( {loading ? ( ) : messages.length === 0 ? ( Sin mensajes aun. Escribe el primero. ) : ( {messages.map((m) => { const author = m.author_id ? usersById.get(m.author_id) : null; const isMe = m.author_id && m.author_id === currentUserId; const label = author ? author.display_name || author.username : "Anonimo"; return ( {label.slice(0, 2).toUpperCase()} {label} {formatDateTimeShort(m.created_at)} {isMe && ( remove(m.id)}> )} {m.body} ); })} )}