This commit is contained in:
debu-2 2026-10-14 06:04:27 +05:30
parent 84544e1153
commit a109df2deb
7 changed files with 51 additions and 11 deletions

View file

@ -137,7 +137,9 @@ export function CustomerWhatsAppInbox({ account, onBack }: { account: WhatsAppAc
useEffect(() => {
Promise.all([
whatsappApi.messages(account.id),
whatsappApi.templates(account.id).catch(() => ({ available: false, templates: [] as WhatsAppTemplateRow[] })),
account.status === 'disconnected'
? Promise.resolve({ available: false, templates: [] as WhatsAppTemplateRow[] })
: whatsappApi.templates(account.id).catch(() => ({ available: false, templates: [] as WhatsAppTemplateRow[] })),
])
.then(([items, templatePayload]) => {
setMessages(items)

View file

@ -193,6 +193,11 @@ export function WhatsAppSetupPage() {
useEffect(() => {
if (phase !== 'detail' || !selected) return
if (tab === 'templates') {
if (selected.status === 'disconnected') {
setTemplates([])
setTemplatesAvailable(false)
return
}
setTemplates(null)
whatsappApi.templates(selected.id)
.then((payload) => {
@ -213,7 +218,7 @@ export function WhatsAppSetupPage() {
.then(setLogs)
.catch((reason) => setError(reason instanceof Error ? reason.message : 'Unable to load logs'))
}
}, [phase, tab, selected?.id])
}, [phase, tab, selected?.id, selected?.status])
function replaceAccount(next: WhatsAppAccount) {
setAccounts((current) => current.map((account) => (account.id === next.id ? next : account)))
@ -563,9 +568,11 @@ export function WhatsAppSetupPage() {
<MessageCircle size={15} /> Chat
</button>
)}
<button className="secondary-button" onClick={() => void refreshSelected()} disabled={busy}>
<RefreshCw size={14} /> Refresh
</button>
{selected.status !== 'disconnected' && (
<button className="secondary-button" onClick={() => void refreshSelected()} disabled={busy}>
<RefreshCw size={14} /> Refresh
</button>
)}
<button className="secondary-button" onClick={() => void startEmbeddedSignup()} disabled={busy}>Reconnect</button>
<button className="secondary-button wa-biz-danger" onClick={() => setDisconnecting(selected)}>Disconnect</button>
</div>
@ -620,7 +627,7 @@ export function WhatsAppSetupPage() {
</div>
<StatusDot status={phone.status} />
<span>Quality: {phone.quality || '—'}</span>
{phone.needs_registration && !phone.needs_otp && (
{selected.status !== 'disconnected' && phone.needs_registration && !phone.needs_otp && (
<div className="wa-biz-register">
<input
inputMode="numeric"

View file

@ -69,7 +69,7 @@ export function WhatsAppTemplateWizard() {
if (!editing && !duplicateId) window.localStorage.setItem(DRAFT_KEY, JSON.stringify(draft))
}, [draft, editing, duplicateId])
const numbers = useMemo(() => accounts.flatMap((account) => (
const numbers = useMemo(() => accounts.filter((account) => account.status !== 'disconnected').flatMap((account) => (
account.phones.length
? account.phones.map((phone) => ({ account, phone: phone as WhatsAppAccount['phones'][number] | null }))
: [{ account, phone: null as WhatsAppAccount['phones'][number] | null }]

View file

@ -129,7 +129,7 @@ export function WhatsAppTemplatesPage() {
<input value={search} onChange={(event) => setSearch(event.target.value)} placeholder="Search by name or ID" aria-label="Search templates" />
<select value={accountId} onChange={(event) => { setAccountId(event.target.value); load(event.target.value) }} aria-label="WhatsApp account">
<option value="">All accounts</option>
{accounts.map((account) => {
{accounts.filter((account) => account.status !== 'disconnected').map((account) => {
const numbers = account.phones.map((phone) => phone.display_phone).filter(Boolean).join(', ')
return <option key={account.id} value={account.id}>{numbers ? `${account.name} · ${numbers}` : account.name}</option>
})}

View file

@ -2035,6 +2035,7 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
.wa-tpl-preview > p { margin: 0 0 8px; font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #8a95a7; }
.wa-tpl-phone { background: #efe7dc; border-radius: 16px; padding: 16px; }
.wa-tpl-bubble { display: grid; gap: 6px; background: white; border-radius: 12px; padding: 10px 12px; color: #14233b; }
.wa-tpl-bubble span, .wa-tpl-bubble strong, .wa-tpl-bubble small { white-space: pre-wrap; overflow-wrap: anywhere; }
.wa-tpl-bubble img, .wa-tpl-media { width: 100%; border-radius: 8px; background: #d9e2ec; min-height: 84px; object-fit: cover; }
.wa-tpl-media { display: grid; place-items: center; color: #526176; font-size: 13px; }
.wa-tpl-bubble small { color: #718096; }
@ -2052,7 +2053,7 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
.wa-tpl-review { display: grid; gap: 8px; margin: 0; }
.wa-tpl-review div { display: grid; grid-template-columns: 160px 1fr; gap: 8px; }
.wa-tpl-review dt { color: #718096; }
.wa-tpl-review dd { margin: 0; }
.wa-tpl-review dd { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.wa-tpl-checks { margin: 12px 0 0; padding-left: 18px; }
.wa-tpl-reason { margin-top: 16px; padding: 12px; border-radius: 10px; background: #fff4f2; color: #8d2b26; }
.wa-tpl-tabs { display: flex; gap: 8px; }