UI finish

This commit is contained in:
debu-2 2026-10-07 12:31:57 +05:30
parent b469a09cde
commit 6e295dd4b3
3 changed files with 1162 additions and 472 deletions

View file

@ -1,4 +1,19 @@
import { ChevronRight, LockKeyhole, MessageSquareText, Network, Phone, ShieldCheck } from 'lucide-react'
import {
BarChart3,
ChevronRight,
Contact,
LayoutTemplate,
LockKeyhole,
Megaphone,
MessageSquareText,
Network,
Phone,
ScrollText,
Send,
Settings,
ShieldCheck,
Workflow,
} from 'lucide-react'
import { useEffect, useState } from 'react'
import type { FormEvent } from 'react'
import {
@ -390,9 +405,23 @@ function AdminCompliance() {
)
}
const WORKSPACE_NAV = [
{ id: 'conversations', label: 'Conversations', icon: MessageSquareText },
{ id: 'compose', label: 'Send message', icon: Send },
{ id: 'templates', label: 'Templates', icon: LayoutTemplate },
{ id: 'contacts', label: 'Contacts', icon: Contact },
{ id: 'campaigns', label: 'Campaigns', icon: Megaphone },
{ id: 'automations', label: 'Automations', icon: Workflow },
{ id: 'analytics', label: 'Analytics', icon: BarChart3 },
{ id: 'logs', label: 'Webhook logs', icon: ScrollText },
{ id: 'numbers', label: 'Phone numbers', icon: Phone },
] as const
export function AdminApp() {
const [authenticated, setAuthenticated] = useState<boolean | null>(null)
const [section, setSection] = useState<'compliance' | 'whatsapp'>('whatsapp')
const [focus, setFocus] = useState<'inbox' | 'templates' | 'compose'>('inbox')
const [nav, setNav] = useState<string>('conversations')
useEffect(() => {
adminApi.me().then(() => setAuthenticated(true)).catch(() => setAuthenticated(false))
@ -403,39 +432,74 @@ export function AdminApp() {
setAuthenticated(false)
}
function openWorkspace(id: string) {
setSection('whatsapp')
setNav(id)
if (id === 'templates') setFocus('templates')
else if (id === 'compose') setFocus('compose')
else setFocus('inbox')
}
if (authenticated === null) return <div className="auth-loading">Checking admin session…</div>
if (!authenticated) {
return (
<div className="admin-shell">
<header className="admin-topbar">
<div><img src="/urmi-logo.png" alt="Urmi" /><strong>Admin portal</strong></div>
</header>
<main>
<AdminLogin onSuccess={() => setAuthenticated(true)} />
</main>
</div>
)
}
return (
<div className="admin-shell">
<header className="admin-topbar">
<div><img src="/urmi-logo.png" alt="Urmi" /><strong>Admin portal</strong></div>
{authenticated && (
<div className="admin-topbar-actions">
<nav className="admin-main-nav">
<div className="wa-shell">
<aside className="wa-nav">
<div className="wa-nav-brand"><img src="/urmi-logo.png" alt="Urmi" /></div>
<nav>
{WORKSPACE_NAV.map((item) => {
const Icon = item.icon
return (
<button
key={item.id}
type="button"
className={section === 'whatsapp' ? 'active' : ''}
onClick={() => setSection('whatsapp')}
className={section === 'whatsapp' && nav === item.id ? 'active' : ''}
onClick={() => openWorkspace(item.id)}
>
WhatsApp Business
<Icon size={16} />
{item.label}
</button>
<button
type="button"
className={section === 'compliance' ? 'active' : ''}
onClick={() => setSection('compliance')}
>
Compliance
</button>
</nav>
<button className="secondary-button" onClick={logout}>Log out</button>
</div>
)}
</header>
<main>
{authenticated
? (section === 'whatsapp' ? <AdminWhatsAppPage /> : <AdminCompliance />)
: <AdminLogin onSuccess={() => setAuthenticated(true)} />}
</main>
)
})}
<button
type="button"
className={section === 'compliance' ? 'active' : ''}
onClick={() => { setSection('compliance'); setNav('settings') }}
>
<Settings size={16} />
Settings
</button>
</nav>
<div className="wa-nav-foot">
<strong>Business line</strong>
<span>WhatsApp connected</span>
</div>
</aside>
<div className="wa-shell-main">
{section === 'whatsapp'
? <AdminWhatsAppPage onLogout={logout} focus={focus} />
: (
<>
<header className="wa-topbar plain">
<strong>Settings</strong>
<button className="wa-ghost" type="button" onClick={logout}>Log out</button>
</header>
<AdminCompliance />
</>
)}
</div>
</div>
)
}

File diff suppressed because it is too large Load diff