diff --git a/frontend/app/components/workspace/CrmWorkspaceApp.vue b/frontend/app/components/workspace/CrmWorkspaceApp.vue index 76e9922..f55764d 100644 --- a/frontend/app/components/workspace/CrmWorkspaceApp.vue +++ b/frontend/app/components/workspace/CrmWorkspaceApp.vue @@ -170,6 +170,10 @@ type ClientTimelineItem = { const selectedTab = ref("communications"); const peopleLeftMode = ref("contacts"); +function safeTrim(value: unknown) { + return String(value ?? "").trim(); +} + function dayKey(date: Date) { const y = date.getFullYear(); const m = String(date.getMonth() + 1).padStart(2, "0"); @@ -817,7 +821,7 @@ function normalizePilotTimeline(messages: PilotMessage[]) { const renderedPilotMessages = computed(() => { const items = normalizePilotTimeline(pilotMessages.value).filter((m) => m.role !== "system"); const hasPersistedLiveUser = items.some( - (m) => m.role === "user" && m.text.trim() === livePilotUserText.value.trim(), + (m) => m.role === "user" && safeTrim(m.text) === livePilotUserText.value.trim(), ); if (livePilotUserText.value && !hasPersistedLiveUser) { @@ -1172,7 +1176,7 @@ function startCrmRealtime() { } async function sendPilotText(rawText: string) { - const text = rawText.trim(); + const text = safeTrim(rawText); if (!text || pilotSending.value) return; const contextPayload = buildContextPayload(); @@ -1396,7 +1400,7 @@ async function startPilotMeter(stream: MediaStream) { } function appendPilotTranscript(text: string) { - const next = text.trim(); + const next = safeTrim(text); if (!next) return ""; const merged = pilotInput.value.trim() ? `${pilotInput.value.trim()} ${next}` : next; pilotInput.value = merged; @@ -1831,7 +1835,7 @@ function parseCalendarYearToken(token: string | null | undefined) { } function normalizedConversationId() { - return (selectedChatId.value || authMe.value?.conversation.id || "pilot").trim(); + return safeTrim(selectedChatId.value || authMe.value?.conversation.id || "pilot"); } function currentUiPath() { @@ -4041,8 +4045,8 @@ const selectedWorkspaceDeal = computed(() => { }); function formatDealHeadline(deal: Deal) { - const title = deal.title.trim(); - const amountRaw = deal.amount.trim(); + const title = safeTrim(deal.title); + const amountRaw = safeTrim(deal.amount); if (!amountRaw) return title; const normalized = amountRaw.replace(/\s+/g, "").replace(",", "."); @@ -4066,7 +4070,7 @@ function getDealCurrentStep(deal: Deal) { } function getDealCurrentStepLabel(deal: Deal) { - return getDealCurrentStep(deal)?.title?.trim() || deal.nextStep.trim() || deal.stage.trim() || "Без шага"; + return safeTrim(getDealCurrentStep(deal)?.title) || safeTrim(deal.nextStep) || safeTrim(deal.stage) || "Без шага"; } function parseDateFromText(input: string) { @@ -4584,7 +4588,7 @@ async function createCommDocument() { return; } - const title = commDocumentForm.value.title.trim() || buildCommDocumentTitle(summary, selectedCommThread.value.contact); + const title = safeTrim(commDocumentForm.value.title) || buildCommDocumentTitle(summary, selectedCommThread.value.contact); const scope = buildContactDocumentScope(selectedCommThread.value.id, selectedCommThread.value.contact); const body = summary;