analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
221 lines (219 loc) • 7.37 kB
JavaScript
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