/* global React, Icon, KpiCard, StageChip, ChannelIcon, fmtAED, Avatar, EmptyState */ const { useState } = React; /* ============================================================ DASHBOARD Two layout variations (toggle via Tweaks): 1. "modular" — original brief: 12-col grid, KPI cards on top 2. "ops" — left-rail today/calendar focus, right side metrics ============================================================ */ function Dashboard({ layout = 'modular', goto }) { return layout === 'ops' ? : ; } /* ----- Variation 1: Modular ----- */ function DashboardModular({ goto }) { return (
Tuesday · 28 Apr 2026

Good morning, Sebastiano.

Pipeline weighted total · AED 187,400
{/* Top row: 4 KPI cards */}
{/* Row 2: Pipeline by stage + Today */}
{/* Row 3: Account health full-width */}
{/* Row 4: Funnels, Campaigns, Payments */}
); } /* ----- Variation 2: Ops ----- */ function DashboardOps({ goto }) { return (
Tuesday · 28 Apr 2026

Today.

Pipeline
AED 187,400
Open
14
Replies
4
{/* 2-col split: Today (left, larger) + everything else stacked right */}
); } /* ============================================================ CARDS ============================================================ */ function PipelineCard({ goto }) { const stages = window.STAGES_OUTBOUND; const counts = {}; const values = {}; window.PIPELINE_OUTBOUND.forEach(d => { counts[d.stage] = (counts[d.stage] || 0) + 1; if (d.value) values[d.stage] = (values[d.stage] || 0) + d.value; }); const maxCount = Math.max(...Object.values(counts), 1); const totalAed = Object.values(values).reduce((a,b) => a+b, 0); const weightedAed = 187400; return (

This Week's Pipeline

AED {fmtAED(totalAed)} total
AED {fmtAED(weightedAed)} weighted
{stages.filter(s => counts[s.id]).map(s => (
{s.label}
{counts[s.id]}
{values[s.id] ? `AED ${fmtAED(values[s.id])}` : '—'}
))}
); } function TodayCard({ goto, expanded = false }) { const events = window.CALENDAR_EVENTS.filter(e => e.day === 1); const tasks = [ { id: 1, text: 'Send proposal to Globex', done: false, due: '11:00' }, { id: 2, text: 'Follow up · Initech pricing', done: false, due: '14:30' }, { id: 3, text: 'Recap deck · Acme tweaks', done: false, due: 'EOD' }, { id: 4, text: 'Review LinkedIn responses', done: true, due: 'morning' }, ]; return (

Today

Calls
{events.length === 0 && (
No calls scheduled
)} {events.map(e => (
goto('calendar')}>
{String(Math.floor(e.start)).padStart(2,'0')}:{String(Math.round((e.start%1)*60)).padStart(2,'0')}
{e.title}
{e.type === 'discovery' ? 'Discovery' : 'Strategy'}
))}
Tasks · {tasks.filter(t => !t.done).length} due
{tasks.map(t => (
{t.done && }
{t.text}
{t.due}
))}
4 unread messages across LinkedIn, WhatsApp, IG
); } function AccountHealthCard({ goto }) { const channels = window.CHANNELS.filter(c => c.kind !== 'email'); return (

Account Health · Messaging

Account
Channel
Sends today
Ramp
{channels.map(ch => { const dotClass = ch.status === 'active' ? 'dot-green' : ch.status === 'paused' ? 'dot-yellow' : 'dot-red'; const pct = (ch.sendsToday / ch.cap) * 100; return (
{ch.label}
{ch.errorMsg &&
{ch.errorMsg}
}
{ch.kind}
90 ? 'var(--orange)' : 'var(--accent)' }}>
{ch.sendsToday}/{ch.cap}
W{ch.rampWeek}
); })}
); } function FunnelsCard({ goto }) { const funnels = window.FUNNELS.filter(f => f.status === 'live').slice(0, 5); return (

Funnels · This Week

{funnels.map(f => (
{f.name}
/{f.slug}
{f.submissions}
{f.conversion}%
))}
); } function CampaignsCard({ goto }) { const active = window.CAMPAIGNS.filter(c => c.status === 'active'); return (

Campaigns · Active

{active.map(c => (
{c.name}
{c.sent}
sent
{c.opens}%
opens
{c.replies}%
replies
1 ? 'var(--orange)' : 'var(--text)' }}>{c.bounces}%
bounces
))}
); } function PaymentsCard({ goto }) { const newPayments = window.PAYMENTS.filter(p => p.status === 'paid').slice(0, 3); const expected = 26000; const mrr = 53000; return (

Payments · This Week

Expected
AED {fmtAED(expected)}
MRR proj.
AED {fmtAED(mrr)}
{newPayments.map(p => (
{p.deal}
{fmtAED(p.amount)}
))}
); } Object.assign(window, { Dashboard });