diff --git a/Frontend/app.vue b/Frontend/app.vue
index 053021c..8d180ff 100644
--- a/Frontend/app.vue
+++ b/Frontend/app.vue
@@ -8,6 +8,7 @@ import logoutMutation from "./graphql/operations/logout.graphql?raw";
import logPilotNoteMutation from "./graphql/operations/log-pilot-note.graphql?raw";
import createCalendarEventMutation from "./graphql/operations/create-calendar-event.graphql?raw";
import createCommunicationMutation from "./graphql/operations/create-communication.graphql?raw";
+import updateCommunicationTranscriptMutation from "./graphql/operations/update-communication-transcript.graphql?raw";
import updateFeedDecisionMutation from "./graphql/operations/update-feed-decision.graphql?raw";
import chatConversationsQuery from "./graphql/operations/chat-conversations.graphql?raw";
import createChatConversationMutation from "./graphql/operations/create-chat-conversation.graphql?raw";
@@ -1982,6 +1983,13 @@ async function transcribeCallItem(item: CommItem) {
const itemId = item.id;
if (callTranscriptLoading.value[itemId]) return;
if (callTranscriptText.value[itemId]) return;
+ if (Array.isArray(item.transcript) && item.transcript.length) {
+ const persisted = item.transcript.map((line) => String(line ?? "").trim()).filter(Boolean).join("\n");
+ if (persisted) {
+ callTranscriptText.value[itemId] = persisted;
+ return;
+ }
+ }
const audioUrl = getCallAudioUrl(item);
if (!audioUrl) {
@@ -2003,6 +2011,11 @@ async function transcribeCallItem(item: CommItem) {
});
const text = String(result?.text ?? "").trim();
callTranscriptText.value[itemId] = text || "(empty transcript)";
+ await gqlFetch<{ updateCommunicationTranscript: { ok: boolean; id: string } }>(updateCommunicationTranscriptMutation, {
+ id: itemId,
+ transcript: text ? [text] : [],
+ });
+ await refreshCrmData();
} catch (error: any) {
callTranscriptError.value[itemId] = String(error?.message ?? error ?? "Transcription failed");
} finally {
@@ -3221,6 +3234,7 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
+ {{ latestPinnedLabel }}
{{ selectedCommPinnedStream.length }}
@@ -3231,8 +3245,7 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
>
- Pinned note
- {{ entry.text }}
+ {{ entry.text }}
diff --git a/Frontend/graphql/operations/update-communication-transcript.graphql b/Frontend/graphql/operations/update-communication-transcript.graphql
new file mode 100644
index 0000000..2555d63
--- /dev/null
+++ b/Frontend/graphql/operations/update-communication-transcript.graphql
@@ -0,0 +1,6 @@
+mutation UpdateCommunicationTranscriptMutation($id: ID!, $transcript: [String!]!) {
+ updateCommunicationTranscript(id: $id, transcript: $transcript) {
+ ok
+ id
+ }
+}
diff --git a/Frontend/server/graphql/schema.ts b/Frontend/server/graphql/schema.ts
index 7016089..5857dc5 100644
--- a/Frontend/server/graphql/schema.ts
+++ b/Frontend/server/graphql/schema.ts
@@ -552,6 +552,29 @@ async function createCommunication(auth: AuthContext | null, input: {
return { ok: true, id: created.id };
}
+async function updateCommunicationTranscript(auth: AuthContext | null, id: string, transcript: string[]) {
+ const ctx = requireAuth(auth);
+ const messageId = String(id ?? "").trim();
+ if (!messageId) throw new Error("id is required");
+
+ const lines = Array.isArray(transcript)
+ ? transcript.map((line) => String(line ?? "").trim()).filter(Boolean)
+ : [];
+
+ const updated = await prisma.contactMessage.updateMany({
+ where: {
+ id: messageId,
+ contact: { teamId: ctx.teamId },
+ },
+ data: {
+ transcriptJson: lines,
+ },
+ });
+
+ if (!updated.count) throw new Error("communication not found");
+ return { ok: true, id: messageId };
+}
+
async function updateFeedDecision(auth: AuthContext | null, id: string, decision: "accepted" | "rejected" | "pending", decisionNote?: string) {
const ctx = requireAuth(auth);
@@ -769,6 +792,7 @@ export const crmGraphqlSchema = buildSchema(`
toggleContactPin(contact: String!, text: String!): PinToggleResult!
createCalendarEvent(input: CreateCalendarEventInput!): CalendarEvent!
createCommunication(input: CreateCommunicationInput!): MutationWithIdResult!
+ updateCommunicationTranscript(id: ID!, transcript: [String!]!): MutationWithIdResult!
updateFeedDecision(id: ID!, decision: String!, decisionNote: String): MutationWithIdResult!
}
@@ -1027,6 +1051,11 @@ export const crmGraphqlRoot = {
context: GraphQLContext,
) => createCommunication(context.auth, args.input),
+ updateCommunicationTranscript: async (
+ args: { id: string; transcript: string[] },
+ context: GraphQLContext,
+ ) => updateCommunicationTranscript(context.auth, args.id, args.transcript),
+
updateFeedDecision: async (
args: { id: string; decision: "accepted" | "rejected" | "pending"; decisionNote?: string },
context: GraphQLContext,