UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

221 lines (219 loc) 7.37 kB
import { CHATBOT_MESSAGE_ROLES } from "./chunk-QIXFV54A.mjs"; // src/hooks/useChatbot.ts import { useCallback, useEffect, useRef, useState } from "react"; var DEFAULT_CONVERSATIONS_PAGE_SIZE = 20; var DEFAULT_MESSAGES_PAGE_SIZE = 50; var placeholderCounter = 0; function generatePlaceholderId() { const globalCrypto = globalThis.crypto; if (globalCrypto && typeof globalCrypto.randomUUID === "function") { return `pending-${globalCrypto.randomUUID()}`; } placeholderCounter += 1; return `pending-${Date.now()}-${placeholderCounter}`; } function replacePlaceholder(prev, placeholderId, result) { return [ ...prev.filter((m) => m.id !== placeholderId), result.userMessage, result.assistantMessage ]; } function removePlaceholder(prev, placeholderId) { return prev.filter((m) => m.id !== placeholderId); } function removeById(items, id) { return items.filter((item) => item.id !== id); } function toUserErrorMessage(_err, fallback) { return fallback; } function createUseChatbot(resolver) { const resolveClient = typeof resolver === "function" ? resolver : () => resolver; return function useChatbot() { const [isOpen, setIsOpen] = useState(false); const [isSending, setIsSending] = useState(false); const [isLoadingHistory, setIsLoadingHistory] = useState(false); const [isLoadingMessages, setIsLoadingMessages] = useState(false); const [errorMessage, setErrorMessage] = useState(null); const [conversations, setConversations] = useState( [] ); const [activeConversationId, setActiveConversationId] = useState(null); const [messages, setMessages] = useState([]); const apiClientRef = useRef(resolveClient()); apiClientRef.current = resolveClient(); const mountedRef = useRef(false); useEffect(() => { mountedRef.current = true; return () => { mountedRef.current = false; }; }, []); const conversationsSeqRef = useRef(0); const messagesSeqRef = useRef(0); const isSendingRef = useRef(false); const invalidateMessagesLoad = () => { messagesSeqRef.current += 1; setIsLoadingMessages(false); }; const loadConversations = useCallback(async () => { const seq = ++conversationsSeqRef.current; setIsLoadingHistory(true); setErrorMessage(null); try { const result = await apiClientRef.current.listConversations({ page: 1, limit: DEFAULT_CONVERSATIONS_PAGE_SIZE }); if (!mountedRef.current || seq !== conversationsSeqRef.current) return; setConversations(result.conversations); } catch (err) { if (!mountedRef.current || seq !== conversationsSeqRef.current) return; setErrorMessage(toUserErrorMessage(err, "Falha ao carregar conversas")); } finally { if (mountedRef.current && seq === conversationsSeqRef.current) { setIsLoadingHistory(false); } } }, []); const loadMessages = useCallback(async (conversationId) => { const seq = ++messagesSeqRef.current; setIsLoadingMessages(true); setErrorMessage(null); try { const result = await apiClientRef.current.getMessages(conversationId, { page: 1, limit: DEFAULT_MESSAGES_PAGE_SIZE }); if (!mountedRef.current || seq !== messagesSeqRef.current) return; setMessages(result.messages); } catch (err) { if (!mountedRef.current || seq !== messagesSeqRef.current) return; setErrorMessage(toUserErrorMessage(err, "Falha ao carregar mensagens")); } finally { if (mountedRef.current && seq === messagesSeqRef.current) { setIsLoadingMessages(false); } } }, []); const openPanel = useCallback(() => { setIsOpen(true); void loadConversations(); }, [loadConversations]); const closePanel = useCallback(() => { setIsOpen(false); }, []); const togglePanel = useCallback(() => { setIsOpen((prev) => { if (!prev) void loadConversations(); return !prev; }); }, [loadConversations]); const selectConversation = useCallback( (id) => { setActiveConversationId(id); if (id) { void loadMessages(id); } else { invalidateMessagesLoad(); setMessages([]); } }, [loadMessages] ); const startNewConversation = useCallback(() => { invalidateMessagesLoad(); setActiveConversationId(null); setMessages([]); }, []); const sendMessage = useCallback( async (text, currentContext) => { const trimmed = text.trim(); if (!trimmed || isSendingRef.current) return; isSendingRef.current = true; const sendSeq = messagesSeqRef.current; const placeholderId = generatePlaceholderId(); const placeholder = { id: placeholderId, conversationId: activeConversationId ?? "", role: CHATBOT_MESSAGE_ROLES.USER, content: trimmed, createdAt: /* @__PURE__ */ new Date() }; setMessages((prev) => [...prev, placeholder]); setIsSending(true); setErrorMessage(null); try { const result = await apiClientRef.current.sendMessage({ message: trimmed, conversationId: activeConversationId ?? void 0, currentContext }); if (!mountedRef.current) return; if (sendSeq !== messagesSeqRef.current) { void loadConversations(); return; } setMessages( (prev) => replacePlaceholder(prev, placeholderId, result) ); setActiveConversationId(result.conversationId); void loadConversations(); } catch (err) { if (!mountedRef.current) return; if (sendSeq !== messagesSeqRef.current) return; setMessages((prev) => removePlaceholder(prev, placeholderId)); setErrorMessage(toUserErrorMessage(err, "Falha ao enviar mensagem")); } finally { isSendingRef.current = false; if (mountedRef.current) setIsSending(false); } }, [activeConversationId, loadConversations] ); const deleteConversation = useCallback( async (id) => { setErrorMessage(null); try { await apiClientRef.current.deleteConversation(id); if (!mountedRef.current) return; setConversations((prev) => removeById(prev, id)); if (activeConversationId === id) { invalidateMessagesLoad(); setActiveConversationId(null); setMessages([]); } } catch (err) { if (!mountedRef.current) return; setErrorMessage(toUserErrorMessage(err, "Falha ao excluir conversa")); } }, [activeConversationId] ); return { isOpen, isSending, isLoadingHistory, isLoadingMessages, errorMessage, conversations, activeConversationId, messages, openPanel, closePanel, togglePanel, selectConversation, startNewConversation, sendMessage, deleteConversation, reloadConversations: loadConversations }; }; } export { createUseChatbot }; //# sourceMappingURL=chunk-L57VCDNM.mjs.map