WACRM: historial completo con paginacion desde el origen, sync refleja eliminaciones y trae todo el historial
This commit is contained in:
@@ -17,6 +17,11 @@ interface Member {
|
||||
const WacrmMessages: FC = () => {
|
||||
const [conversations, setConversations] = useState<WacrmConversation[]>([]);
|
||||
const [messages, setMessages] = useState<WacrmMessage[]>([]);
|
||||
const [msgPage, setMsgPage] = useState(1);
|
||||
const [msgHasMore, setMsgHasMore] = useState(false);
|
||||
const [loadingOlder, setLoadingOlder] = useState(false);
|
||||
const threadRef = useRef<HTMLDivElement | null>(null);
|
||||
const convIdRef = useRef<string | null>(null);
|
||||
const [members, setMembers] = useState<Member[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [syncing, setSyncing] = useState(false);
|
||||
@@ -85,17 +90,51 @@ const WacrmMessages: FC = () => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const loadMessages = useCallback(async (conversationId: string) => {
|
||||
const scrollThreadToBottom = () => {
|
||||
requestAnimationFrame(() => {
|
||||
const el = threadRef.current;
|
||||
if (el) el.scrollTop = el.scrollHeight;
|
||||
});
|
||||
};
|
||||
|
||||
// Historial de la conversación, leído del origen (Supabase) vía el proxy,
|
||||
// paginado: página 1 = últimos 50; con "Cargar mensajes anteriores" se
|
||||
// anteponen páginas más antiguas conservando la posición del scroll.
|
||||
const loadMessages = useCallback(async (conversationId: string, page = 1) => {
|
||||
try {
|
||||
const res = await odooApi.getWacrmMessages(undefined, conversationId);
|
||||
const keepScroll = page > 1;
|
||||
const el = threadRef.current;
|
||||
const prevHeight = keepScroll && el ? el.scrollHeight : 0;
|
||||
const prevTop = keepScroll && el ? el.scrollTop : 0;
|
||||
const res = await odooApi.getWacrmConversationMessages(conversationId, page, 50);
|
||||
if (res.status === 'success') {
|
||||
setMessages(res.messages.reverse());
|
||||
convIdRef.current = conversationId;
|
||||
setMsgPage(page);
|
||||
setMsgHasMore(res.has_more);
|
||||
if (page === 1) {
|
||||
// Merge: conserva el historial antiguo ya cargado (scroll manual)
|
||||
const known = new Set(res.messages.map((m) => m.external_id));
|
||||
const minTs = res.messages.length ? res.messages[0].created_at : '';
|
||||
const older = messages.filter((m) => !known.has(m.external_id) && (m.created_at ?? '') < (minTs ?? ''));
|
||||
setMessages([...older, ...res.messages]);
|
||||
if (convIdRef.current === conversationId) scrollThreadToBottom();
|
||||
} else {
|
||||
const prev = messages;
|
||||
const known = new Set(prev.map((m) => m.external_id));
|
||||
const older = res.messages.filter((m) => !known.has(m.external_id));
|
||||
setMessages([...older, ...prev]);
|
||||
requestAnimationFrame(() => {
|
||||
if (threadRef.current) {
|
||||
threadRef.current.scrollTop = threadRef.current.scrollHeight - prevHeight + prevTop;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error('Error al cargar mensajes');
|
||||
console.error(err);
|
||||
}
|
||||
}, []);
|
||||
}, [messages]);
|
||||
|
||||
const loadMembers = useCallback(async () => {
|
||||
try {
|
||||
@@ -461,7 +500,22 @@ const WacrmMessages: FC = () => {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 overflow-y-auto p-4 space-y-3">
|
||||
<div ref={threadRef} className="flex-1 overflow-y-auto p-4 space-y-3">
|
||||
{messages.length > 0 && msgHasMore && (
|
||||
<div className="text-center">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
loading={loadingOlder}
|
||||
onClick={() => {
|
||||
setLoadingOlder(true);
|
||||
loadMessages(selected.external_id, msgPage + 1).finally(() => setLoadingOlder(false));
|
||||
}}
|
||||
>
|
||||
Cargar mensajes anteriores
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{messages.length === 0 ? (
|
||||
<p className="text-center text-sm text-theme-muted py-8">No hay mensajes en esta conversación</p>
|
||||
) : (
|
||||
|
||||
@@ -1461,6 +1461,11 @@ export const odooApi = {
|
||||
return data;
|
||||
},
|
||||
|
||||
async getWacrmConversationMessages(conversationId: string, page = 1, pageSize = 50): Promise<{ status: string; messages: WacrmMessage[]; page: number; page_size: number; has_more: boolean }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/wacrm/conversations/${conversationId}/messages`, { params: { page, page_size: pageSize } });
|
||||
return data;
|
||||
},
|
||||
|
||||
async getInventoryReport(): Promise<{ status: string; summary: InventoryReportSummary; items: InventoryItem[] }> {
|
||||
const { data } = await axios.get(`${ODOO_BASE}/skeen/frontend/v1/reports/inventory`);
|
||||
return data;
|
||||
|
||||
Reference in New Issue
Block a user