UI finish

This commit is contained in:
debu-2 2026-10-07 12:15:48 +05:30
parent 614cf1e7f5
commit b469a09cde
2 changed files with 552 additions and 231 deletions

View file

@ -1,4 +1,4 @@
import { MessageSquareText, RefreshCw, Settings2 } from 'lucide-react'
import { MessageSquareText, RefreshCw, Search, Send, Settings2, X } from 'lucide-react'
import { useEffect, useMemo, useRef, useState } from 'react'
import type { FormEvent } from 'react'
import { API_BASE_URL } from '../../lib/apiBase'
@ -26,6 +26,42 @@ function mediaUrl(mediaId: string) {
return `${API_BASE_URL}/api/v1/admin/whatsapp/media/${mediaId}`
}
function peerInitials(value: string) {
const digits = value.replace(/\D/g, '')
return digits.slice(-2) || 'WA'
}
function formatChatTime(value: string) {
const date = new Date(value)
const now = new Date()
const sameDay = date.toDateString() === now.toDateString()
if (sameDay) {
return date.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })
}
const yesterday = new Date(now)
yesterday.setDate(now.getDate() - 1)
if (date.toDateString() === yesterday.toDateString()) return 'Yesterday'
return date.toLocaleDateString([], { month: 'short', day: 'numeric' })
}
function formatDayLabel(value: string) {
const date = new Date(value)
const now = new Date()
if (date.toDateString() === now.toDateString()) return 'Today'
const yesterday = new Date(now)
yesterday.setDate(now.getDate() - 1)
if (date.toDateString() === yesterday.toDateString()) return 'Yesterday'
return date.toLocaleDateString([], { weekday: 'short', month: 'short', day: 'numeric' })
}
const SEND_MODES: { id: SendMode; label: string }[] = [
{ id: 'text', label: 'Text' },
{ id: 'template', label: 'Template' },
{ id: 'media', label: 'Media' },
{ id: 'buttons', label: 'Buttons' },
{ id: 'reaction', label: 'Reaction' },
]
export function AdminWhatsAppPage() {
const [config, setConfig] = useState<AdminWhatsAppConfig | null>(null)
const [messages, setMessages] = useState<AdminWhatsAppMessage[]>([])
@ -57,8 +93,10 @@ export function AdminWhatsAppPage() {
const [buttonThree, setButtonThree] = useState('')
const [reactionEmoji, setReactionEmoji] = useState('👍')
const [reactionTarget, setReactionTarget] = useState('')
const [threadQuery, setThreadQuery] = useState('')
const chatEndRef = useRef<HTMLDivElement | null>(null)
const replyRef = useRef<HTMLTextAreaElement | null>(null)
async function loadMessages(peer?: string | null) {
const items = await adminApi.listWhatsAppMessages(300, peer || undefined)
@ -104,12 +142,24 @@ export function AdminWhatsAppPage() {
.sort((a, b) => (b.latest?.created_at ?? '').localeCompare(a.latest?.created_at ?? ''))
}, [messages])
const visibleThreads = useMemo(() => {
const query = threadQuery.trim().toLowerCase()
if (!query) return threads
return threads.filter(({ peer, latest }) => {
const haystack = `${formatWaNumber(peer)} ${peer} ${latest.body ?? ''} ${latest.message_type}`.toLowerCase()
return haystack.includes(query)
})
}, [threads, threadQuery])
const activeThread = useMemo(() => {
if (!selectedPeer) return []
const found = threads.find((item) => item.peer === selectedPeer)
return found?.thread ?? []
}, [threads, selectedPeer])
const activeLatest = activeThread[activeThread.length - 1]
const activeFirst = activeThread[0]
useEffect(() => {
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [activeThread.length, selectedPeer])
@ -271,18 +321,28 @@ export function AdminWhatsAppPage() {
)}
<div className="admin-whatsapp-messenger">
<aside className="panel admin-whatsapp-sidebar">
<div className="panel-heading">
<aside className="admin-whatsapp-sidebar">
<div className="admin-whatsapp-sidebar-head">
<div>
<h2>Conversations</h2>
<p>{threads.length} active threads</p>
<p>{threads.length} active {threads.length === 1 ? 'thread' : 'threads'}</p>
</div>
</div>
<label className="admin-whatsapp-search">
<Search size={14} />
<input
value={threadQuery}
onChange={(event) => setThreadQuery(event.target.value)}
placeholder="Search by name, phone or message…"
/>
</label>
{threads.length === 0 ? (
<p className="admin-whatsapp-empty">No messages yet. Ask someone to message +91 94112 57916 or scan your Meta QR.</p>
<p className="admin-whatsapp-empty">No messages yet. Ask someone to message {config ? formatWaNumber(config.business_phone) : '+91 94112 57916'} or scan your Meta QR.</p>
) : visibleThreads.length === 0 ? (
<p className="admin-whatsapp-empty">No conversations match that search.</p>
) : (
<div className="admin-whatsapp-thread-list compact">
{threads.map(({ peer, latest, thread }) => (
{visibleThreads.map(({ peer, latest, thread }) => (
<button
key={peer}
type="button"
@ -293,32 +353,50 @@ export function AdminWhatsAppPage() {
if (lastInbound) markRead(lastInbound)
}}
>
<span className="admin-whatsapp-avatar">{peerInitials(peer)}</span>
<span className="admin-whatsapp-thread-copy">
<strong>{formatWaNumber(peer)}</strong>
<span>{latest.body || `[${latest.message_type}]`}</span>
<small>{new Date(latest.created_at).toLocaleString()}</small>
</span>
<small>{formatChatTime(latest.created_at)}</small>
</button>
))}
</div>
)}
</aside>
<section className="panel admin-whatsapp-chat">
<section className="admin-whatsapp-chat">
<div className="admin-whatsapp-chat-head">
{selectedPeer ? (
<>
<span className="admin-whatsapp-avatar">{peerInitials(selectedPeer)}</span>
<div>
<strong>{formatWaNumber(selectedPeer)}</strong>
<small>{activeThread.length} messages · {activeLatest ? formatChatTime(activeLatest.created_at) : 'No activity'}</small>
</div>
</>
) : (
<div>
<strong>Select a conversation</strong>
<small>Or start one with a new recipient below.</small>
</div>
)}
</div>
<div className="admin-whatsapp-chat-body">
{!selectedPeer ? (
<div className="admin-whatsapp-chat-empty">
<p>Select a conversation to view messages and reply.</p>
<MessageSquareText size={28} />
<p>Choose a thread on the left to read it and reply from the box below.</p>
</div>
) : (
<>
<div className="admin-whatsapp-chat-head">
<strong>{formatWaNumber(selectedPeer)}</strong>
<small>{activeThread.length} messages</small>
</div>
<div className="admin-whatsapp-chat-body">
{activeThread.map((item) => (
<div
key={item.id}
className={`admin-whatsapp-bubble ${item.direction === 'inbound' ? 'inbound' : 'outbound'}`}
>
activeThread.map((item, index) => {
const previous = activeThread[index - 1]
const showDay = !previous || new Date(previous.created_at).toDateString() !== new Date(item.created_at).toDateString()
return (
<div key={item.id} className="admin-whatsapp-message-row">
{showDay && <div className="admin-whatsapp-day">{formatDayLabel(item.created_at)}</div>}
<div className={`admin-whatsapp-bubble ${item.direction === 'inbound' ? 'inbound' : 'outbound'}`}>
{item.media?.id && ['image', 'sticker'].includes(item.message_type) && (
<img src={mediaUrl(item.media.id)} alt={item.message_type} className="admin-whatsapp-media" />
)}
@ -333,11 +411,23 @@ export function AdminWhatsAppPage() {
)}
<span>{item.body || `[${item.message_type} · ${item.status}]`}</span>
<small>
{new Date(item.created_at).toLocaleTimeString()}
{new Date(item.created_at).toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' })}
{item.status ? ` · ${item.status}` : ''}
{item.wa_message_id ? ` · ${item.wa_message_id.slice(0, 12)}…` : ''}
</small>
{item.direction === 'inbound' && item.wa_message_id && (
<span className="admin-whatsapp-bubble-actions">
<button
type="button"
className="link-button"
onClick={() => {
setSendMode('text')
setReplyTo(item.wa_message_id || '')
replyRef.current?.focus()
}}
>
Reply
</button>
<button
type="button"
className="link-button"
@ -348,35 +438,30 @@ export function AdminWhatsAppPage() {
>
React
</button>
</span>
)}
</div>
))}
</div>
)
})
)}
<div ref={chatEndRef} />
</div>
</>
)}
</section>
<section className="panel admin-whatsapp-compose-panel">
<div className="panel-heading">
<div>
<h2>Send</h2>
<p>Supported: text, template, media, buttons, reaction, read receipts.</p>
</div>
</div>
<form className="admin-whatsapp-composer" onSubmit={sendMessage}>
<div className="admin-whatsapp-mode-tabs">
{(['text', 'template', 'media', 'buttons', 'reaction'] as SendMode[]).map((mode) => (
{SEND_MODES.map((mode) => (
<button
key={mode}
key={mode.id}
type="button"
className={sendMode === mode ? 'active' : ''}
onClick={() => setSendMode(mode)}
className={sendMode === mode.id ? 'active' : ''}
onClick={() => setSendMode(mode.id)}
>
{mode}
{mode.label}
</button>
))}
</div>
<form className="admin-whatsapp-form" onSubmit={sendMessage}>
<div className="admin-whatsapp-form">
{!selectedPeer && (
<label>
<span>New recipient</span>
@ -390,9 +475,24 @@ export function AdminWhatsAppPage() {
{sendMode === 'text' && (
<>
{replyTo && (
<div className="admin-whatsapp-reply-chip">
<span>Replying to {replyTo.slice(0, 18)}…</span>
<button type="button" onClick={() => setReplyTo('')} aria-label="Clear reply">
<X size={12} />
</button>
</div>
)}
<label>
<span>Message</span>
<textarea value={textBody} onChange={(e) => setTextBody(e.target.value)} rows={5} required />
<textarea
ref={replyRef}
value={textBody}
onChange={(e) => setTextBody(e.target.value)}
rows={3}
placeholder="Type a message…"
required
/>
</label>
<label>
<span>Reply to message ID (optional)</span>
@ -447,6 +547,10 @@ export function AdminWhatsAppPage() {
<input value={mediaFilename} onChange={(e) => setMediaFilename(e.target.value)} />
</label>
)}
<label>
<span>Reply to message ID (optional)</span>
<input value={replyTo} onChange={(e) => setReplyTo(e.target.value)} placeholder="wamid…" />
</label>
</>
)}
@ -454,11 +558,15 @@ export function AdminWhatsAppPage() {
<>
<label>
<span>Body</span>
<textarea value={buttonBody} onChange={(e) => setButtonBody(e.target.value)} rows={4} required />
<textarea value={buttonBody} onChange={(e) => setButtonBody(e.target.value)} rows={3} required />
</label>
<label><span>Button 1</span><input value={buttonOne} onChange={(e) => setButtonOne(e.target.value)} required /></label>
<label><span>Button 2</span><input value={buttonTwo} onChange={(e) => setButtonTwo(e.target.value)} /></label>
<label><span>Button 3</span><input value={buttonThree} onChange={(e) => setButtonThree(e.target.value)} /></label>
<label>
<span>Reply to message ID (optional)</span>
<input value={replyTo} onChange={(e) => setReplyTo(e.target.value)} placeholder="wamid…" />
</label>
</>
)}
@ -476,12 +584,62 @@ export function AdminWhatsAppPage() {
)}
{error && <p className="auth-error">{error}</p>}
<div className="admin-whatsapp-composer-footer">
<small>Within 24h of a customer message: free-form text, media, and buttons. Outside that window, use a template.</small>
<button className="primary-button" type="submit" disabled={sending || !readyToSend || (!selectedPeer && !newPeer.trim())}>
<Send size={14} />
{sending ? 'Sending…' : 'Send'}
</button>
<small>Within 24h of customer message: free-form text/media/buttons. Outside window: use template.</small>
</div>
</div>
</form>
</section>
<aside className="admin-whatsapp-details">
<div className="admin-whatsapp-details-hero">
<span className="admin-whatsapp-avatar large">{selectedPeer ? peerInitials(selectedPeer) : 'WA'}</span>
<strong>{selectedPeer ? formatWaNumber(selectedPeer) : 'No contact selected'}</strong>
<small>{selectedPeer ? 'WhatsApp conversation' : 'Pick a thread to see details'}</small>
</div>
<dl className="admin-whatsapp-details-list">
<div>
<dt>Phone</dt>
<dd>{selectedPeer ? formatWaNumber(selectedPeer) : '—'}</dd>
</div>
<div>
<dt>Messages</dt>
<dd>{selectedPeer ? activeThread.length : threads.length}</dd>
</div>
<div>
<dt>First seen</dt>
<dd>{activeFirst ? new Date(activeFirst.created_at).toLocaleString() : '—'}</dd>
</div>
<div>
<dt>Last message</dt>
<dd>{activeLatest ? new Date(activeLatest.created_at).toLocaleString() : '—'}</dd>
</div>
<div>
<dt>Last status</dt>
<dd>{activeLatest?.status || '—'}</dd>
</div>
<div>
<dt>Source</dt>
<dd>{activeLatest ? (activeLatest.direction === 'inbound' ? 'Customer' : 'Business') : '—'}</dd>
</div>
<div>
<dt>Business line</dt>
<dd>{config ? formatWaNumber(config.business_phone) : '+91 94112 57916'}</dd>
</div>
</dl>
<div className="admin-whatsapp-quick">
<h3>Quick actions</h3>
{SEND_MODES.map((mode) => (
<button key={mode.id} type="button" onClick={() => setSendMode(mode.id)}>
{mode.label === 'Text' ? 'Reply with text' : `Send ${mode.label.toLowerCase()}`}
</button>
))}
</div>
</aside>
</div>
</div>
)

View file

@ -857,6 +857,7 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
color: white;
}
.admin-content, .admin-login-page { padding: 28px; }
.admin-content.admin-whatsapp-page { max-width: none; padding: 18px 20px 24px; }
.admin-login-page { min-height: calc(100vh - 72px); display: grid; place-items: center; }
.admin-login-card { width: min(420px, 100%); }
.admin-kyc-card { margin-bottom: 18px; }
@ -954,21 +955,22 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
.admin-whatsapp-bubble {
display: grid;
gap: 4px;
max-width: 88%;
padding: 8px 10px;
border-radius: 10px;
font-size: 11px;
max-width: min(78%, 460px);
padding: 10px 12px;
border-radius: 14px;
font-size: 13px;
line-height: 1.45;
box-shadow: 0 1px 1px rgba(18, 31, 54, .04);
}
.admin-whatsapp-bubble.inbound {
justify-self: start;
background: white;
border: 1px solid #dfe5ed;
border-bottom-left-radius: 4px;
}
.admin-whatsapp-bubble.outbound {
justify-self: end;
background: #e8f2ff;
border: 1px solid #c8ddff;
background: #d9fdd3;
border-bottom-right-radius: 4px;
}
.admin-whatsapp-bubble small { color: #8a95a7; font-size: 9px; }
.admin-whatsapp-form {
@ -995,7 +997,7 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
color: #1f2a3d;
background: white;
}
.admin-whatsapp-form textarea { resize: vertical; min-height: 120px; }
.admin-whatsapp-form textarea { resize: vertical; min-height: 72px; }
.admin-whatsapp-form small {
color: #8a95a7;
font-size: 10px;
@ -1004,12 +1006,13 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
@media (max-width: 960px) {
.admin-whatsapp-grid { grid-template-columns: 1fr; }
}
.admin-whatsapp-page { max-width: 1400px; }
.admin-whatsapp-page { max-width: none; }
.admin-whatsapp-heading {
display: flex;
justify-content: space-between;
gap: 16px;
align-items: flex-start;
margin-bottom: 14px;
}
.admin-whatsapp-heading-actions {
display: flex;
@ -1019,99 +1022,257 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
}
.admin-whatsapp-messenger {
display: grid;
grid-template-columns: 260px minmax(0, 1fr) 320px;
gap: 16px;
align-items: start;
grid-template-columns: 300px minmax(0, 1fr) 280px;
min-height: calc(100vh - 210px);
background: white;
border: 1px solid var(--border);
border-radius: 16px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(18, 31, 54, .06);
}
.admin-whatsapp-sidebar,
.admin-whatsapp-chat,
.admin-whatsapp-compose-panel {
min-height: 640px;
.admin-whatsapp-details {
min-height: 0;
background: white;
}
.admin-whatsapp-sidebar {
display: flex;
flex-direction: column;
border-right: 1px solid #edf1f6;
background: #fbfcfe;
}
.admin-whatsapp-sidebar-head {
padding: 18px 16px 8px;
}
.admin-whatsapp-sidebar-head h2 {
margin: 0;
font-size: 15px;
letter-spacing: -.02em;
color: #17253e;
}
.admin-whatsapp-sidebar-head p {
margin: 4px 0 0;
color: #8a95a7;
font-size: 11px;
}
.admin-whatsapp-search {
display: flex;
align-items: center;
gap: 8px;
margin: 8px 14px 12px;
padding: 0 12px;
border: 1px solid #e4eaf2;
border-radius: 999px;
background: white;
color: #8a95a7;
}
.admin-whatsapp-search input {
width: 100%;
border: 0;
background: transparent;
padding: 10px 0;
font: inherit;
font-size: 12px;
color: #1f2a3d;
outline: none;
}
.admin-whatsapp-thread-list.compact {
display: grid;
gap: 8px;
max-height: 560px;
align-content: start;
gap: 2px;
padding: 0 8px 12px;
overflow: auto;
}
.admin-whatsapp-thread-item {
display: grid;
gap: 4px;
grid-template-columns: 38px minmax(0, 1fr) auto;
gap: 10px;
align-items: center;
text-align: left;
border: 1px solid #e6ebf2;
border-radius: 10px;
padding: 10px 12px;
background: white;
border: 0;
border-radius: 12px;
padding: 10px;
background: transparent;
cursor: pointer;
}
.admin-whatsapp-thread-item.active {
border-color: #1475ff;
background: #f3f8ff;
}
.admin-whatsapp-thread-item:hover { background: #f3f6fb; }
.admin-whatsapp-thread-item.active { background: #eaf2ff; }
.admin-whatsapp-thread-copy { display: grid; min-width: 0; gap: 2px; }
.admin-whatsapp-thread-item strong { font-size: 12px; color: #1f2a3d; }
.admin-whatsapp-thread-item span {
.admin-whatsapp-thread-copy > span {
font-size: 11px;
color: #607089;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.admin-whatsapp-thread-item small { font-size: 10px; color: #8a95a7; }
.admin-whatsapp-thread-item small { font-size: 10px; color: #8a95a7; align-self: start; margin-top: 2px; }
.admin-whatsapp-avatar {
display: grid;
place-items: center;
width: 38px;
height: 38px;
border-radius: 50%;
background: linear-gradient(160deg, #2f6bff, #163a8a);
color: white;
font-size: 11px;
font-weight: 700;
letter-spacing: .02em;
}
.admin-whatsapp-avatar.large { width: 64px; height: 64px; font-size: 16px; }
.admin-whatsapp-chat {
display: grid;
grid-template-rows: auto 1fr;
grid-template-rows: auto minmax(0, 1fr) auto;
min-height: 680px;
background: #f7f4ef;
}
.admin-whatsapp-chat-empty {
display: grid;
place-items: center;
min-height: 520px;
justify-items: center;
align-content: center;
gap: 8px;
min-height: 240px;
color: #8a95a7;
font-size: 12px;
text-align: center;
padding: 24px;
}
.admin-whatsapp-chat-empty p { margin: 0; max-width: 280px; line-height: 1.5; }
.admin-whatsapp-chat-head {
display: flex;
justify-content: space-between;
gap: 10px;
padding-bottom: 12px;
border-bottom: 1px solid #e6ebf2;
margin-bottom: 12px;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: white;
border-bottom: 1px solid #edf1f6;
}
.admin-whatsapp-chat-head strong { font-size: 13px; }
.admin-whatsapp-chat-head small { color: #8a95a7; font-size: 10px; }
.admin-whatsapp-chat-head strong { display: block; font-size: 14px; color: #17253e; }
.admin-whatsapp-chat-head small { display: block; margin-top: 2px; color: #8a95a7; font-size: 11px; }
.admin-whatsapp-chat-body {
display: grid;
gap: 10px;
gap: 8px;
align-content: start;
max-height: 560px;
overflow: auto;
padding-right: 4px;
padding: 18px 18px 8px;
}
.admin-whatsapp-message-row { display: grid; gap: 8px; }
.admin-whatsapp-day {
justify-self: center;
margin: 6px 0;
padding: 4px 10px;
border-radius: 999px;
background: rgba(255, 255, 255, .85);
color: #6d7b90;
font-size: 10px;
font-weight: 700;
letter-spacing: .04em;
text-transform: uppercase;
}
.admin-whatsapp-media {
max-width: 100%;
border-radius: 8px;
margin-bottom: 6px;
}
.admin-whatsapp-bubble-actions { display: flex; gap: 10px; }
.admin-whatsapp-composer {
padding: 10px 12px 12px;
background: white;
border-top: 1px solid #edf1f6;
}
.admin-whatsapp-mode-tabs {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 12px;
margin-bottom: 10px;
}
.admin-whatsapp-mode-tabs button {
border: 1px solid #dfe5ed;
background: white;
border: 1px solid #e4eaf2;
background: #f7f9fc;
color: #607089;
border-radius: 8px;
padding: 7px 10px;
font-size: 10px;
border-radius: 999px;
padding: 6px 12px;
font-size: 11px;
font-weight: 600;
text-transform: capitalize;
}
.admin-whatsapp-mode-tabs button.active {
background: #1475ff;
border-color: #1475ff;
color: white;
}
.admin-whatsapp-reply-chip {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 8px 10px;
border-left: 3px solid #1475ff;
border-radius: 8px;
background: #f3f8ff;
color: #35527a;
font-size: 11px;
}
.admin-whatsapp-reply-chip button {
display: grid;
place-items: center;
border: 0;
background: transparent;
color: #607089;
padding: 2px;
}
.admin-whatsapp-composer-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.admin-whatsapp-composer-footer .primary-button { flex: 0 0 auto; }
.admin-whatsapp-details {
display: flex;
flex-direction: column;
gap: 16px;
padding: 20px 16px;
border-left: 1px solid #edf1f6;
background: #fbfcfe;
overflow: auto;
}
.admin-whatsapp-details-hero {
display: grid;
justify-items: center;
gap: 8px;
text-align: center;
padding-bottom: 8px;
}
.admin-whatsapp-details-hero strong { font-size: 14px; color: #17253e; }
.admin-whatsapp-details-hero small { color: #8a95a7; font-size: 11px; }
.admin-whatsapp-details-list { margin: 0; display: grid; gap: 10px; }
.admin-whatsapp-details-list div {
display: grid;
gap: 2px;
padding-bottom: 10px;
border-bottom: 1px solid #edf1f6;
}
.admin-whatsapp-details-list dt {
color: #8a95a7;
font-size: 10px;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
}
.admin-whatsapp-details-list dd { margin: 0; color: #1f2a3d; font-size: 12px; }
.admin-whatsapp-quick { display: grid; gap: 8px; }
.admin-whatsapp-quick h3 { margin: 0 0 2px; font-size: 12px; color: #17253e; }
.admin-whatsapp-quick button {
text-align: left;
border: 1px solid #e4eaf2;
background: white;
border-radius: 10px;
padding: 9px 12px;
color: #35435a;
font-size: 12px;
font-weight: 600;
}
.admin-whatsapp-quick button:hover { border-color: #1475ff; color: #1475ff; }
.admin-whatsapp-setup-form {
display: grid;
gap: 12px;
@ -1158,10 +1319,12 @@ main { padding: 30px clamp(20px, 3vw, 44px) 50px; }
justify-self: start;
}
@media (max-width: 1100px) {
.admin-whatsapp-messenger { grid-template-columns: 1fr; }
.admin-whatsapp-sidebar,
.admin-whatsapp-chat,
.admin-whatsapp-compose-panel { min-height: auto; }
.admin-whatsapp-messenger { grid-template-columns: 1fr; min-height: auto; }
.admin-whatsapp-sidebar { border-right: 0; border-bottom: 1px solid #edf1f6; }
.admin-whatsapp-details { border-left: 0; border-top: 1px solid #edf1f6; }
.admin-whatsapp-chat { min-height: 560px; }
.admin-whatsapp-thread-list.compact { max-height: 280px; }
.admin-whatsapp-composer-footer { align-items: stretch; flex-direction: column; }
}
/* UrmiOTP */