Update WhatsApp Concierge UI

This commit is contained in:
Tanuja Pansare 2026-10-19 12:47:07 +05:30
parent beebf1dfb7
commit d4247fe8a7
3 changed files with 15 additions and 4 deletions

View File

@ -74,6 +74,7 @@ function receptionFromBot(bot: ConciergeBotRecord): ConciergeBotReception {
allowNonRegistered: Boolean(r.allowNonRegistered),
prefillText: r.prefillText || "Hi",
welcomeMessage: r.welcomeMessage || DEFAULT_WELCOME,
welcomeCtas: Array.isArray(r.welcomeCtas) ? r.welcomeCtas : [],
unmatchedBadgePrompt: r.unmatchedBadgePrompt || DEFAULT_BADGE,
staffHandoffMessage: r.staffHandoffMessage || DEFAULT_STAFF,
dripAudience: r.dripAudience === "all_inbound" ? "all_inbound" : "matched",
@ -180,7 +181,9 @@ export function WhatsAppReceptionTab({
setSaving(true);
setMsg(null);
let dripsPayload: ConciergeReceptionDrip[];
let welcomeCtas: WhatsAppCtaItem[];
try {
welcomeCtas = normalizeCtasForSave((reception.welcomeCtas || []) as WhatsAppCtaItem[]);
dripsPayload = (reception.drips || []).map((d) => {
const ctas =
d.contentKind === "upcoming_agenda" ? [] : normalizeCtasForSave((d.ctas || []) as WhatsAppCtaItem[]);
@ -209,6 +212,7 @@ export function WhatsAppReceptionTab({
const res = await conciergeBotsApi.update(bot._id, {
reception: {
...reception,
welcomeCtas,
drips: dripsPayload,
},
});
@ -400,6 +404,12 @@ export function WhatsAppReceptionTab({
<p style={{ fontSize: 11, color: "var(--muted-foreground)", margin: "4px 0 10px" }}>
Placeholders: {"{firstName}"}, {"{profileName}"}, {"{eventName}"}, {"{engagementUrl}"}
</p>
<div style={{ marginBottom: 12 }}>
<WhatsAppCtaEditor
value={(reception.welcomeCtas || []) as WhatsAppCtaItem[]}
onChange={(welcomeCtas) => patch({ welcomeCtas })}
/>
</div>
<label>
If not matched — ask for badge photo
<textarea

View File

@ -53,8 +53,8 @@ export function normalizeCtasForSave(ctas: WhatsAppCtaItem[] | undefined): Whats
}
if (type === "url") {
if (rows.length > 1) throw new Error("Only one URL button is allowed per message.");
if (!/^https?:\/\//i.test(rows[0].value) && !/\{engagementUrl\}/i.test(rows[0].value)) {
throw new Error("URL buttons must start with http:// or https://, or use {engagementUrl}");
if (!/^https?:\/\//i.test(rows[0].value) && !/\{(?:url|engagementUrl)\}/i.test(rows[0].value)) {
throw new Error("URL buttons must start with http:// or https://, or use {Url}");
}
return [{ type: "url", label: rows[0].label, value: rows[0].value.slice(0, 2000) }];
}
@ -106,7 +106,7 @@ export function WhatsAppCtaEditor({
<span style={{ fontSize: compact ? 12 : "var(--text-sm)", fontWeight: 500 }}>Buttons (optional)</span>
<span style={{ fontSize: 11, color: "var(--muted)", lineHeight: 1.4 }}>
Up to 3 Reply buttons, or one URL button — not both. Only sent inside the 24-hour chat window.
For unique participant links, set the URL to exactly {"{engagementUrl}"} (the visitor must already be
For unique participant links, set the URL to exactly {"{Url}"} (the visitor must already be
identified so we can build their link).
</span>
</div>
@ -163,7 +163,7 @@ export function WhatsAppCtaEditor({
style={IS}
value={row.value}
disabled={disabled}
placeholder={row.type === "url" ? "{engagementUrl} or https://…" : "Same as label if empty"}
placeholder={row.type === "url" ? "{Url} or https://…" : "Same as label if empty"}
onChange={(e) => patchRow(i, { value: e.target.value })}
/>
</label>

View File

@ -31,6 +31,7 @@ export interface ConciergeBotReception {
allowNonRegistered?: boolean;
prefillText?: string;
welcomeMessage?: string;
welcomeCtas?: Array<{ type: "reply" | "url"; label: string; value: string }>;
unmatchedBadgePrompt?: string;
staffHandoffMessage?: string;
dripAudience?: "matched" | "all_inbound";