diff --git a/frontend/app/components/workspace/CrmWorkspaceApp.vue b/frontend/app/components/workspace/CrmWorkspaceApp.vue index 8372271..35ecd4f 100644 --- a/frontend/app/components/workspace/CrmWorkspaceApp.vue +++ b/frontend/app/components/workspace/CrmWorkspaceApp.vue @@ -844,17 +844,17 @@ async function sendCommMessage() { const text = commDraft.value.trim(); if (!text || commSending.value || !selectedCommThread.value) return; commSending.value = true; + const contactId = selectedCommThreadId.value; + const contactName = selectedCommThread.value.contact; try { const channel = commSendChannel.value; if (!channel) return; const { useMutation } = await import("@vue/apollo-composable"); - const { CreateCommunicationMutationDocument, CommunicationsQueryDocument, ContactInboxesQueryDocument } = await import("~~/graphql/generated"); - const { mutate: doCreateCommunication } = useMutation(CreateCommunicationMutationDocument, { - refetchQueries: [{ query: CommunicationsQueryDocument }, { query: ContactInboxesQueryDocument }], - }); - await doCreateCommunication({ + const { CreateCommunicationMutationDocument } = await import("~~/graphql/generated"); + const { mutate: doCreateCommunication } = useMutation(CreateCommunicationMutationDocument); + const result = await doCreateCommunication({ input: { - contact: selectedCommThread.value.contact, + contact: contactName, channel, kind: "message", direction: "out", @@ -862,7 +862,36 @@ async function sendCommMessage() { }, }); commDraft.value = ""; - openCommunicationThread(selectedCommThread.value.contact); + + // Optimistically append the sent message to timeline (no full reload) + const newId = result?.data?.createCommunication?.id ?? `temp-${Date.now()}`; + const now = new Date().toISOString(); + clientTimelineItems.value = [ + ...clientTimelineItems.value, + { + id: newId, + contactId, + contentType: "message", + contentId: newId, + datetime: now, + message: { + id: newId, + at: now, + contact: contactName, + contactInboxId: "", + sourceExternalId: "", + sourceTitle: "", + channel: channel as CommItem["channel"], + kind: "message", + direction: "out", + text, + }, + }, + ]; + scrollCommThreadToBottom(); + + // Refresh sidebar preview (lastMessageText) — lightweight + void refetchContacts(); } finally { commSending.value = false; } @@ -1145,9 +1174,9 @@ function scrollCommThreadToBottom() { }); } -// Scroll to bottom whenever timeline items change (thread switch or new message) -watch(clientTimelineItems, (items) => { - if (items.length) scrollCommThreadToBottom(); +// Scroll to bottom when a new thread loads (items go from [] → [items]) +watch(clientTimelineItems, (items, oldItems) => { + if (items.length && (!oldItems || oldItems.length === 0)) scrollCommThreadToBottom(); }); // ---------------------------------------------------------------------------