From 1d44a4245558fe77d12d013bc9958611fff29bca Mon Sep 17 00:00:00 2001 From: JuanBifrost Date: Fri, 11 Sep 2026 00:52:13 -0500 Subject: [PATCH 1/3] fix(contacts): show workspace contact id in contact detail panel The Contact ID row was bound to ContactInbox.sourceId (e.g. WhatsApp wa_id) instead of the contact record id returned by the API. Co-authored-by: Cursor --- apps/builder/src/features/contacts/contact-detail.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/builder/src/features/contacts/contact-detail.tsx b/apps/builder/src/features/contacts/contact-detail.tsx index d648505bd6..dae300d4dc 100644 --- a/apps/builder/src/features/contacts/contact-detail.tsx +++ b/apps/builder/src/features/contacts/contact-detail.tsx @@ -318,7 +318,9 @@ export const ContactDetail = ({ if (conversation?.contact) { const activeContactInbox = conversation.contactInboxes[0] - const channelContactId = activeContactInbox?.sourceId + // Contact ID is the workspace contact record id — not the channel + // sourceId (e.g. WhatsApp wa_id), which has its own scoped rows below. + const contactId = conversation.contact.id // The ad the contact clicked from (any ad-attributed inbox), shown as // a link right under Contact ID. Guarded to http(s) so a non-navigable // / `javascript:` referral value never becomes an anchor href. @@ -331,10 +333,10 @@ export const ContactDetail = ({ : null const tmpContactFields: ContactEditableField[] = [ { - key: "channelContactId", + key: "contactId", icon: IdCardIcon, label: t("fields.contactId.label"), - value: channelContactId, + value: contactId, type: "shortText", readOnly: true, }, From 5f7053e78413db2da0925cbd200ace46bc3035b9 Mon Sep 17 00:00:00 2001 From: JuanBifrost Date: Fri, 11 Sep 2026 00:55:56 -0500 Subject: [PATCH 2/3] feat(contacts): surface user_id and user_code in contact detail panel Align the sidebar with ChatbotX system fields for faster API testing: - User ID ({{user_id}}) shows the workspace contact record id - User Code ({{user_code}}) shows ContactInbox.sourceId (e.g. WhatsApp wa_id) - Existing WhatsApp scoped rows still expose {{wa_user_id}} / {{wa_user_name}} Co-authored-by: Cursor --- apps/builder/messages/ar.json | 3 ++ apps/builder/messages/da.json | 3 ++ apps/builder/messages/de.json | 3 ++ apps/builder/messages/en.json | 3 ++ apps/builder/messages/es.json | 3 ++ apps/builder/messages/fi.json | 3 ++ apps/builder/messages/fr.json | 3 ++ apps/builder/messages/he.json | 3 ++ apps/builder/messages/id.json | 3 ++ apps/builder/messages/it.json | 3 ++ apps/builder/messages/ja.json | 3 ++ apps/builder/messages/nl.json | 3 ++ apps/builder/messages/pt-BR.json | 3 ++ apps/builder/messages/pt-PT.json | 3 ++ apps/builder/messages/ro.json | 3 ++ apps/builder/messages/sv.json | 3 ++ apps/builder/messages/tr.json | 3 ++ apps/builder/messages/vi.json | 3 ++ apps/builder/messages/zh-CN.json | 3 ++ apps/builder/messages/zh-TW.json | 3 ++ .../src/features/contacts/contact-detail.tsx | 37 +++++++++++++++---- 21 files changed, 89 insertions(+), 8 deletions(-) diff --git a/apps/builder/messages/ar.json b/apps/builder/messages/ar.json index ecad7d4a12..afe79620a8 100644 --- a/apps/builder/messages/ar.json +++ b/apps/builder/messages/ar.json @@ -2293,6 +2293,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "رمز المستخدم" } }, "flows": { diff --git a/apps/builder/messages/da.json b/apps/builder/messages/da.json index 287328e9fc..6f4dcdf1a5 100644 --- a/apps/builder/messages/da.json +++ b/apps/builder/messages/da.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Brugerkode" } }, "flows": { diff --git a/apps/builder/messages/de.json b/apps/builder/messages/de.json index bddc8b98c6..d48ace3f66 100644 --- a/apps/builder/messages/de.json +++ b/apps/builder/messages/de.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Benutzercode" } }, "flows": { diff --git a/apps/builder/messages/en.json b/apps/builder/messages/en.json index f30ce4be7a..aa4181df5a 100644 --- a/apps/builder/messages/en.json +++ b/apps/builder/messages/en.json @@ -2293,6 +2293,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "User Code" } }, "metaConversions": { diff --git a/apps/builder/messages/es.json b/apps/builder/messages/es.json index 3e1de64d88..84448f2f3a 100644 --- a/apps/builder/messages/es.json +++ b/apps/builder/messages/es.json @@ -2293,6 +2293,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Código de usuario" } }, "flows": { diff --git a/apps/builder/messages/fi.json b/apps/builder/messages/fi.json index 0543578f8f..77f75517ad 100644 --- a/apps/builder/messages/fi.json +++ b/apps/builder/messages/fi.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Käyttäjäkoodi" } }, "flows": { diff --git a/apps/builder/messages/fr.json b/apps/builder/messages/fr.json index 4b4b61146f..9fd81e9671 100644 --- a/apps/builder/messages/fr.json +++ b/apps/builder/messages/fr.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Code utilisateur" } }, "flows": { diff --git a/apps/builder/messages/he.json b/apps/builder/messages/he.json index 37a3f53802..9dca50feb4 100644 --- a/apps/builder/messages/he.json +++ b/apps/builder/messages/he.json @@ -4843,6 +4843,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "קוד משתמש" } }, "billing": { diff --git a/apps/builder/messages/id.json b/apps/builder/messages/id.json index c3fabd3ae0..98f84a1987 100644 --- a/apps/builder/messages/id.json +++ b/apps/builder/messages/id.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Kode pengguna" } }, "flows": { diff --git a/apps/builder/messages/it.json b/apps/builder/messages/it.json index 109d3ae25a..b2abddd5f1 100644 --- a/apps/builder/messages/it.json +++ b/apps/builder/messages/it.json @@ -1458,6 +1458,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Codice utente" } }, "actions": { diff --git a/apps/builder/messages/ja.json b/apps/builder/messages/ja.json index 519c273c31..b255f12680 100644 --- a/apps/builder/messages/ja.json +++ b/apps/builder/messages/ja.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "ユーザーコード" } }, "flows": { diff --git a/apps/builder/messages/nl.json b/apps/builder/messages/nl.json index 96cc1a2742..2256fafdd3 100644 --- a/apps/builder/messages/nl.json +++ b/apps/builder/messages/nl.json @@ -1969,6 +1969,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Gebruikerscode" } }, "condition": { diff --git a/apps/builder/messages/pt-BR.json b/apps/builder/messages/pt-BR.json index 75f37ecee0..b209312a59 100644 --- a/apps/builder/messages/pt-BR.json +++ b/apps/builder/messages/pt-BR.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Código do usuário" } }, "flows": { diff --git a/apps/builder/messages/pt-PT.json b/apps/builder/messages/pt-PT.json index da0ef23a27..cea167db29 100644 --- a/apps/builder/messages/pt-PT.json +++ b/apps/builder/messages/pt-PT.json @@ -2156,6 +2156,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Código do utilizador" } }, "flows": { diff --git a/apps/builder/messages/ro.json b/apps/builder/messages/ro.json index 6506f6f9c2..856ba6048f 100644 --- a/apps/builder/messages/ro.json +++ b/apps/builder/messages/ro.json @@ -2940,6 +2940,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Cod utilizator" } }, "channels": { diff --git a/apps/builder/messages/sv.json b/apps/builder/messages/sv.json index f09a75d30a..036b4122c9 100644 --- a/apps/builder/messages/sv.json +++ b/apps/builder/messages/sv.json @@ -2991,6 +2991,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Användarkod" } }, "flowAnalytics": { diff --git a/apps/builder/messages/tr.json b/apps/builder/messages/tr.json index efcbb13de7..3e62e744bd 100644 --- a/apps/builder/messages/tr.json +++ b/apps/builder/messages/tr.json @@ -2293,6 +2293,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Kullanıcı kodu" } }, "flows": { diff --git a/apps/builder/messages/vi.json b/apps/builder/messages/vi.json index 5e06dca0d9..1ee106ead8 100644 --- a/apps/builder/messages/vi.json +++ b/apps/builder/messages/vi.json @@ -2293,6 +2293,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "Mã người dùng" } }, "flows": { diff --git a/apps/builder/messages/zh-CN.json b/apps/builder/messages/zh-CN.json index 012b977b97..4743a96dbe 100644 --- a/apps/builder/messages/zh-CN.json +++ b/apps/builder/messages/zh-CN.json @@ -2994,6 +2994,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "用户代码" } }, "flowAnalytics": { diff --git a/apps/builder/messages/zh-TW.json b/apps/builder/messages/zh-TW.json index 64b600ed18..10621e0698 100644 --- a/apps/builder/messages/zh-TW.json +++ b/apps/builder/messages/zh-TW.json @@ -1458,6 +1458,9 @@ }, "adSource": { "label": "Ad source" + }, + "userCode": { + "label": "使用者代碼" } }, "messages": { diff --git a/apps/builder/src/features/contacts/contact-detail.tsx b/apps/builder/src/features/contacts/contact-detail.tsx index dae300d4dc..bf9a4436f8 100644 --- a/apps/builder/src/features/contacts/contact-detail.tsx +++ b/apps/builder/src/features/contacts/contact-detail.tsx @@ -163,6 +163,28 @@ const scopedIdentityRowsByChannel: Partial< ], } +// Inicia funcion (buildUserCodeField) +const buildUserCodeField = ( + contactInbox: ContactInboxResource | undefined, + t: (key: string) => string, +): ContactEditableField[] => { + const value = contactInbox?.sourceId + if (!value) { + return [] + } + return [ + { + key: "sourceId", + icon: PhoneIcon, + label: t("fields.userCode.label"), + value, + type: "shortText", + readOnly: true, + }, + ] +} +// Finaliza funcion (buildUserCodeField) + const buildScopedIdentityFields = ( contactInbox: ContactInboxResource | undefined, t: (key: string) => string, @@ -174,8 +196,7 @@ const buildScopedIdentityFields = ( const rows = scopedIdentityRowsByChannel[parsedChannel.data] ?? [] return rows.flatMap((row): ContactEditableField[] => { const value = contactInbox[row.key] - // Skip absent values, and a value that IS the Contact ID shown above - // (a scoped-id-keyed contact) — no duplicate row. + // Skip absent values, and scoped ids that duplicate {{user_code}} (sourceId). if (!value || value === contactInbox.sourceId) { return [] } @@ -318,9 +339,8 @@ export const ContactDetail = ({ if (conversation?.contact) { const activeContactInbox = conversation.contactInboxes[0] - // Contact ID is the workspace contact record id — not the channel - // sourceId (e.g. WhatsApp wa_id), which has its own scoped rows below. - const contactId = conversation.contact.id + // {{user_id}} — workspace contact record id for API calls (GET /v1/contacts/id:{id}). + const userId = conversation.contact.id // The ad the contact clicked from (any ad-attributed inbox), shown as // a link right under Contact ID. Guarded to http(s) so a non-navigable // / `javascript:` referral value never becomes an anchor href. @@ -333,13 +353,14 @@ export const ContactDetail = ({ : null const tmpContactFields: ContactEditableField[] = [ { - key: "contactId", + key: "userId", icon: IdCardIcon, - label: t("fields.contactId.label"), - value: contactId, + label: t("fields.userId.label"), + value: userId, type: "shortText", readOnly: true, }, + ...buildUserCodeField(activeContactInbox, t), ...(adSourceUrl ? [ { From 692ff5e755e7eeaae334781d348f9d6e35261a55 Mon Sep 17 00:00:00 2001 From: JuanBifrost Date: Fri, 11 Sep 2026 01:19:54 -0500 Subject: [PATCH 3/3] chore(contacts): drop non-upstream comment markers from contact detail Co-authored-by: Cursor --- apps/builder/src/features/contacts/contact-detail.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/builder/src/features/contacts/contact-detail.tsx b/apps/builder/src/features/contacts/contact-detail.tsx index bf9a4436f8..2796823711 100644 --- a/apps/builder/src/features/contacts/contact-detail.tsx +++ b/apps/builder/src/features/contacts/contact-detail.tsx @@ -163,7 +163,6 @@ const scopedIdentityRowsByChannel: Partial< ], } -// Inicia funcion (buildUserCodeField) const buildUserCodeField = ( contactInbox: ContactInboxResource | undefined, t: (key: string) => string, @@ -183,7 +182,6 @@ const buildUserCodeField = ( }, ] } -// Finaliza funcion (buildUserCodeField) const buildScopedIdentityFields = ( contactInbox: ContactInboxResource | undefined,