import { useGameStore } from '@/store'; import { formatNumber, formatMoney, formatPercent } from '@token-empire/shared'; import type { EnterprisePipelineStage, EnterpriseSegment } from '@token-empire/shared'; import { Building2, AlertTriangle } from 'lucide-react'; const STAGE_ORDER: EnterprisePipelineStage[] = ['lead', 'qualification', 'poc', 'negotiation']; const STAGE_LABELS: Record = { lead: 'Leads', qualification: 'Qualification', poc: 'POC', negotiation: 'Negotiation', }; const STAGE_COLORS: Record = { lead: 'bg-surface-600', qualification: 'bg-blue-600', poc: 'bg-purple-600', negotiation: 'bg-orange-600', }; const SEGMENT_BADGES: Record = { startup: { label: 'Startup', color: 'bg-green-500/20 text-green-400' }, 'mid-market': { label: 'Mid-Market', color: 'bg-blue-500/20 text-blue-400' }, enterprise: { label: 'Enterprise', color: 'bg-purple-500/20 text-purple-400' }, government: { label: 'Gov', color: 'bg-yellow-500/20 text-yellow-400' }, }; export function EnterprisePipelinePanel() { const enterprise = useGameStore((s) => s.market.enterprise); const tickCount = useGameStore((s) => s.meta.tickCount); const leadsByStage = STAGE_ORDER.map(stage => ({ stage, leads: enterprise.pipeline.filter(l => l.stage === stage), })); const totalContractValue = enterprise.activeContracts.reduce((sum, c) => sum + c.pricePerMToken * c.tokensPerTick, 0); const totalSlaViolations = enterprise.activeContracts.reduce((sum, c) => sum + c.slaViolations, 0); return (
Enterprise Pipeline
Leads: {enterprise.pipeline.length} Contracts: {enterprise.activeContracts.length} Lead Rate: {enterprise.leadGenerationRate.toFixed(3)}/t
{leadsByStage.map(({ stage, leads }) => (
{STAGE_LABELS[stage]} {leads.length}
{leads.length === 0 && (
No leads
)} {leads.map(lead => (
{lead.companyName} {SEGMENT_BADGES[lead.segment].label}
{formatMoney(lead.dealValue)}/yr Win: {formatPercent(lead.winProbability)}
))}
))}
Active Contracts {totalSlaViolations > 0 && ( {totalSlaViolations} SLA violations )}
{enterprise.activeContracts.length === 0 ? (

No active contracts. Build your sales team and model quality to attract enterprise customers.

) : (
{enterprise.activeContracts.map(c => { const remaining = Math.max(0, c.startTick + c.durationTicks - tickCount); const uptime = c.totalTicks > 0 ? c.uptimeTicks / c.totalTicks : 1; return ( ); })}
Customer Segment Tokens/s $/M tok SLA Satisfaction Remaining Renewal
{c.customerName} {SEGMENT_BADGES[c.segment].label} {formatNumber(c.tokensPerTick)} {formatMoney(c.pricePerMToken)} = c.slaUptime ? 'text-success' : 'text-danger'}> {formatPercent(uptime)} {formatPercent(c.satisfaction)} {formatNumber(remaining)}t {formatPercent(c.renewalProbability)}
)}
); }