feat/#24 WebOS Completion (#25)
#24 WebOS Completion Co-authored-by: Sayan Datta <sayan@Sayans-MacBook-Air.local> Reviewed-on: #25
This commit was merged in pull request #25.
This commit is contained in:
@@ -17,6 +17,7 @@ import type {
|
||||
OracleEnvelope,
|
||||
CanvasPageRevision,
|
||||
} from '../types/canvas';
|
||||
import { VELOCITY_TOKEN_KEY } from '@/lib/velocityPlatformClient';
|
||||
|
||||
const BASE_URL = (import.meta.env.VITE_ORACLE_API_URL as string | undefined) ?? '';
|
||||
const WS_URL = (import.meta.env.VITE_ORACLE_WS_URL as string | undefined) ?? '';
|
||||
@@ -39,7 +40,7 @@ async function apiFetch<T>(
|
||||
...(options?.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : {}),
|
||||
};
|
||||
|
||||
const token = localStorage.getItem('oracle_jwt');
|
||||
const token = localStorage.getItem('oracle_jwt') ?? localStorage.getItem(VELOCITY_TOKEN_KEY);
|
||||
if (token) headers.Authorization = `Bearer ${token}`;
|
||||
|
||||
const res = await fetch(apiUrl(path), { ...options, headers });
|
||||
|
||||
@@ -1,455 +0,0 @@
|
||||
/**
|
||||
* Oracle Demo Data — In-memory seed canvas used when backend is not available.
|
||||
* Preserves visual richness while the system is in development/demo mode.
|
||||
* These objects conform exactly to the CanvasPage/CanvasComponent contract.
|
||||
*/
|
||||
|
||||
import type { CanvasPage, UserProfile, CanvasComponent } from '../types/canvas';
|
||||
|
||||
// ── Demo user profile ─────────────────────────────────────────────────────────
|
||||
|
||||
export const IN_MEMORY_ME: UserProfile = {
|
||||
userId: 'user_sales_director_001',
|
||||
tenantId: 'tenant_binghatti_demo',
|
||||
email: 'ahmed.alfarsi@binghatti.ae',
|
||||
displayName: 'Ahmed Al-Farsi',
|
||||
role: 'sales_director',
|
||||
timezone: 'Asia/Dubai',
|
||||
locale: 'en-AE',
|
||||
defaultPageId: 'page_01_main_broker',
|
||||
canvasPreferences: {
|
||||
defaultDensity: 'comfortable',
|
||||
defaultPlacementMode: 'append_after_last_visible_component',
|
||||
showLineageBadges: true,
|
||||
},
|
||||
policyProfileId: 'policy_sales_director_standard_v4',
|
||||
createdAt: '2026-01-15T09:00:00Z',
|
||||
updatedAt: '2026-04-09T00:00:00Z',
|
||||
};
|
||||
|
||||
// ── Default style signature ───────────────────────────────────────────────────
|
||||
|
||||
const VELOCITY_GLASS_STYLE = {
|
||||
theme: 'velocity_glass',
|
||||
paletteToken: 'ocean_signal',
|
||||
motionProfile: 'calm_reveal',
|
||||
density: 'comfortable' as const,
|
||||
radiusScale: 'lg',
|
||||
typographyScale: 'balanced',
|
||||
};
|
||||
|
||||
// ── Demo components ───────────────────────────────────────────────────────────
|
||||
|
||||
const PIPELINE_BOARD: CanvasComponent = {
|
||||
componentId: 'cmp_demo_pipeline_board',
|
||||
type: 'pipelineBoard',
|
||||
title: 'Active Pipeline by Stage',
|
||||
description: 'Current deal distribution across funnel stages for Q2 2026.',
|
||||
dataSourceDescriptor: {
|
||||
descriptorId: 'dsd_demo_pipeline',
|
||||
sourceType: 'postgres',
|
||||
connectorId: 'velocity-core-postgres',
|
||||
dataset: 'deals',
|
||||
authContextRef: 'authctx_sales_director_team_scope',
|
||||
queryTemplate: 'SELECT stage, COUNT(*) as count, SUM(value) as value FROM deals WHERE tenant_id = :tenant_id GROUP BY stage',
|
||||
queryParameters: { tenant_id: 'tenant_binghatti_demo' },
|
||||
rowLimit: 100,
|
||||
freshnessSlaSeconds: 120,
|
||||
cachePolicy: { mode: 'ttl', ttlSeconds: 120 },
|
||||
privacyTier: 'standard',
|
||||
lineageRefs: [],
|
||||
},
|
||||
visualizationParameters: {
|
||||
stages: ['New Leads', 'Qualified', 'Proposal Sent', 'Negotiation'],
|
||||
showValue: true,
|
||||
colorByStage: true,
|
||||
},
|
||||
dataBindings: {
|
||||
dimensions: ['stage'],
|
||||
measures: ['count', 'value'],
|
||||
series: [],
|
||||
filters: [],
|
||||
},
|
||||
version: 1,
|
||||
provenance: {
|
||||
originType: 'catalog',
|
||||
templateId: 'tpl_pipeline_board_v2',
|
||||
promptExecutionId: 'pex_demo_seed_001',
|
||||
createdBy: 'user_sales_director_001',
|
||||
createdAt: '2026-04-09T08:00:00Z',
|
||||
},
|
||||
renderingHints: {
|
||||
estimatedHeightPx: 400,
|
||||
skeletonVariant: 'pipeline',
|
||||
virtualizationPriority: 9,
|
||||
},
|
||||
layout: {
|
||||
orderIndex: 100,
|
||||
sectionId: 'sec_pipeline',
|
||||
widthMode: 'full',
|
||||
minHeightPx: 380,
|
||||
stickyHeader: false,
|
||||
},
|
||||
accessControls: {
|
||||
visibilityScope: 'private',
|
||||
allowedRoles: ['senior_broker', 'sales_director'],
|
||||
redactionPolicy: 'none',
|
||||
},
|
||||
styleSignature: VELOCITY_GLASS_STYLE,
|
||||
validationState: {
|
||||
schema: 'pass',
|
||||
policy: 'pass',
|
||||
a11y: 'pass',
|
||||
performance: 'pass',
|
||||
status: 'validated',
|
||||
},
|
||||
auditLog: ['aud_demo_create_001'],
|
||||
dataRows: [
|
||||
{ stage: 'New Leads', count: 14, value: 18500000, leads: [
|
||||
{ id: 'l1', name: 'Mohammed Al-Rashid', company: 'Rashid Group', value: 'AED 15M', avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&w=80&q=80' },
|
||||
{ id: 'l2', name: 'Sarah Chen', company: 'Chen Capital', value: 'AED 8M', avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&w=80&q=80' },
|
||||
{ id: 'l3', name: 'James Wilson', company: 'Wilson RE', value: 'AED 4.5M', avatar: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?auto=format&fit=crop&w=80&q=80' },
|
||||
]},
|
||||
{ stage: 'Qualified', count: 9, value: 42000000, leads: [
|
||||
{ id: 'l4', name: 'Fatima Hassan', company: 'Hassan Holdings', value: 'AED 22M', avatar: 'https://images.unsplash.com/photo-1554151228-14d9def656e4?auto=format&fit=crop&w=80&q=80' },
|
||||
{ id: 'l5', name: 'David Kumar', company: 'Kumar RE', value: 'AED 20M', avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&w=80&q=80' },
|
||||
]},
|
||||
{ stage: 'Proposal Sent', count: 5, value: 28000000, leads: [
|
||||
{ id: 'l6', name: 'Elena Rostova', company: 'Rostova Ventures', value: 'AED 12M', avatar: 'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?auto=format&fit=crop&w=80&q=80' },
|
||||
{ id: 'l7', name: 'Oliver Park', company: 'Park Investments', value: 'AED 16M', avatar: 'https://images.unsplash.com/photo-1560250097-0b93528c311a?auto=format&fit=crop&w=80&q=80' },
|
||||
]},
|
||||
{ stage: 'Negotiation', count: 3, value: 65000000, leads: [
|
||||
{ id: 'l8', name: 'Priya Sharma', company: 'Sharma Family Office', value: 'AED 32M', avatar: 'https://images.unsplash.com/photo-1542206395-9feb3edaa68d?auto=format&fit=crop&w=80&q=80' },
|
||||
{ id: 'l9', name: 'Carlos Mendez', company: 'Mendez Capital', value: 'AED 33M', avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=80&q=80' },
|
||||
]},
|
||||
],
|
||||
};
|
||||
|
||||
const WHALE_LEADS_BAR: CanvasComponent = {
|
||||
componentId: 'cmp_demo_whale_bar',
|
||||
type: 'barChart',
|
||||
title: 'Whale Leads by Source This Week',
|
||||
description: 'Compares QD-weighted whale lead volume across lead sources in the current week.',
|
||||
dataSourceDescriptor: {
|
||||
descriptorId: 'dsd_demo_whale_bar',
|
||||
sourceType: 'postgres',
|
||||
connectorId: 'velocity-core-postgres',
|
||||
dataset: 'lead_daily_snapshot',
|
||||
authContextRef: 'authctx_sales_director_team_scope',
|
||||
queryTemplate: "SELECT source, SUM(qd_weighted_score) as qd_weighted_volume FROM lead_daily_snapshot WHERE tenant_id = :tenant_id AND lead_class = 'whale' GROUP BY source ORDER BY qd_weighted_volume DESC",
|
||||
queryParameters: { tenant_id: 'tenant_binghatti_demo' },
|
||||
rowLimit: 20,
|
||||
freshnessSlaSeconds: 120,
|
||||
cachePolicy: { mode: 'ttl', ttlSeconds: 120 },
|
||||
privacyTier: 'standard',
|
||||
lineageRefs: ['lin_demo_leadsnap'],
|
||||
},
|
||||
visualizationParameters: {
|
||||
xAxis: 'source',
|
||||
yAxis: 'qd_weighted_volume',
|
||||
sort: 'desc',
|
||||
showLabels: true,
|
||||
colorScale: ['#0EA5E9', '#22D3EE', '#3B82F6'],
|
||||
legend: false,
|
||||
},
|
||||
dataBindings: {
|
||||
dimensions: ['source'],
|
||||
measures: ['qd_weighted_volume'],
|
||||
series: [],
|
||||
filters: [{ field: 'lead_class', operator: '=', value: 'whale' }],
|
||||
},
|
||||
version: 1,
|
||||
provenance: {
|
||||
originType: 'prompt_generated',
|
||||
templateId: 'tpl_bar_source_quality_v3',
|
||||
promptExecutionId: 'pex_demo_seed_002',
|
||||
createdBy: 'user_sales_director_001',
|
||||
createdAt: '2026-04-09T10:00:00Z',
|
||||
},
|
||||
renderingHints: {
|
||||
estimatedHeightPx: 340,
|
||||
skeletonVariant: 'chart',
|
||||
virtualizationPriority: 8,
|
||||
},
|
||||
layout: {
|
||||
orderIndex: 200,
|
||||
sectionId: 'sec_leads',
|
||||
widthMode: 'half',
|
||||
minHeightPx: 320,
|
||||
stickyHeader: false,
|
||||
},
|
||||
accessControls: {
|
||||
visibilityScope: 'private',
|
||||
allowedRoles: ['senior_broker', 'sales_director', 'marketing_operator'],
|
||||
redactionPolicy: 'aggregate_only',
|
||||
},
|
||||
styleSignature: { ...VELOCITY_GLASS_STYLE, paletteToken: 'ocean_signal' },
|
||||
validationState: { schema: 'pass', policy: 'pass', a11y: 'pass', performance: 'pass', status: 'validated' },
|
||||
auditLog: ['aud_demo_create_002'],
|
||||
dataRows: [
|
||||
{ source: 'WhatsApp', qd_weighted_volume: 182.4 },
|
||||
{ source: 'Website', qd_weighted_volume: 149.2 },
|
||||
{ source: 'Walk-in', qd_weighted_volume: 93.7 },
|
||||
{ source: 'Referral', qd_weighted_volume: 87.1 },
|
||||
{ source: 'Instagram', qd_weighted_volume: 54.3 },
|
||||
],
|
||||
};
|
||||
|
||||
const INVESTOR_GEO_MAP: CanvasComponent = {
|
||||
componentId: 'cmp_demo_geo_investor',
|
||||
type: 'geoMap',
|
||||
title: 'Investor Interest Density by Dubai District',
|
||||
description: 'Maps high-intent leads with at least one positive Sentinel spike in the last 30 days.',
|
||||
dataSourceDescriptor: {
|
||||
descriptorId: 'dsd_demo_geo',
|
||||
sourceType: 'derived_dataset',
|
||||
connectorId: 'velocity-core-postgres',
|
||||
dataset: 'lead_geo_interest_rollup',
|
||||
authContextRef: 'authctx_sales_director_team_scope',
|
||||
queryTemplate: 'SELECT district, lat, lng, lead_count, avg_qd_score FROM lead_geo_interest_rollup WHERE tenant_id = :tenant_id AND activity_window = :window',
|
||||
queryParameters: { tenant_id: 'tenant_binghatti_demo', window: '30d' },
|
||||
rowLimit: 100,
|
||||
freshnessSlaSeconds: 300,
|
||||
cachePolicy: { mode: 'ttl', ttlSeconds: 300 },
|
||||
privacyTier: 'restricted',
|
||||
lineageRefs: ['lin_demo_rollup', 'lin_demo_sentinel'],
|
||||
},
|
||||
visualizationParameters: {
|
||||
mapStyle: 'dubai_district_heat',
|
||||
intensityField: 'lead_count',
|
||||
tooltipFields: ['district', 'lead_count', 'avg_qd_score'],
|
||||
interactive: true,
|
||||
},
|
||||
dataBindings: {
|
||||
dimensions: ['district'],
|
||||
measures: ['lead_count', 'avg_qd_score'],
|
||||
series: ['district'],
|
||||
filters: [{ field: 'activity_window', operator: '=', value: '30d' }],
|
||||
},
|
||||
version: 1,
|
||||
provenance: {
|
||||
originType: 'catalog',
|
||||
templateId: 'tpl_geo_investor_heat_v2',
|
||||
promptExecutionId: 'pex_demo_seed_002',
|
||||
createdBy: 'user_sales_director_001',
|
||||
createdAt: '2026-04-09T10:00:01Z',
|
||||
},
|
||||
renderingHints: {
|
||||
estimatedHeightPx: 420,
|
||||
skeletonVariant: 'map',
|
||||
virtualizationPriority: 9,
|
||||
},
|
||||
layout: {
|
||||
orderIndex: 300,
|
||||
sectionId: 'sec_leads',
|
||||
widthMode: 'half',
|
||||
minHeightPx: 400,
|
||||
stickyHeader: false,
|
||||
},
|
||||
accessControls: {
|
||||
visibilityScope: 'private',
|
||||
allowedRoles: ['senior_broker', 'sales_director'],
|
||||
redactionPolicy: 'district_level_only',
|
||||
},
|
||||
styleSignature: { ...VELOCITY_GLASS_STYLE, paletteToken: 'aqua_signal' },
|
||||
validationState: { schema: 'pass', policy: 'pass', a11y: 'pass', performance: 'pass', status: 'validated' },
|
||||
auditLog: ['aud_demo_create_003'],
|
||||
dataRows: [
|
||||
{ district: 'Downtown Dubai', lat: 25.1972, lng: 55.2744, lead_count: 38, avg_qd_score: 87.2, x: 52, y: 48 },
|
||||
{ district: 'Dubai Marina', lat: 25.0777, lng: 55.1386, lead_count: 29, avg_qd_score: 82.1, x: 28, y: 68 },
|
||||
{ district: 'Palm Jumeirah', lat: 25.1124, lng: 55.1390, lead_count: 24, avg_qd_score: 91.4, x: 22, y: 60 },
|
||||
{ district: 'Business Bay', lat: 25.1850, lng: 55.2617, lead_count: 19, avg_qd_score: 74.8, x: 48, y: 44 },
|
||||
{ district: 'Dubai Hills', lat: 25.1124, lng: 55.2454, lead_count: 15, avg_qd_score: 71.3, x: 44, y: 58 },
|
||||
{ district: 'JBR', lat: 25.0794, lng: 55.1322, lead_count: 11, avg_qd_score: 68.9, x: 26, y: 70 },
|
||||
{ district: 'DIFC', lat: 25.2048, lng: 55.2708, lead_count: 9, avg_qd_score: 79.5, x: 50, y: 38 },
|
||||
],
|
||||
};
|
||||
|
||||
const BROKER_PERFORMANCE: CanvasComponent = {
|
||||
componentId: 'cmp_demo_broker_perf',
|
||||
type: 'table',
|
||||
title: 'Broker Performance Leaderboard',
|
||||
description: 'Ranked by QD-adjusted deal value closed this month.',
|
||||
dataSourceDescriptor: {
|
||||
descriptorId: 'dsd_demo_brokers',
|
||||
sourceType: 'postgres',
|
||||
connectorId: 'velocity-core-postgres',
|
||||
dataset: 'broker_performance',
|
||||
authContextRef: 'authctx_sales_director_team_scope',
|
||||
queryTemplate: 'SELECT broker_id, name, deals_closed, revenue_generated, avg_response_time_min FROM broker_performance WHERE tenant_id = :tenant_id ORDER BY revenue_generated DESC',
|
||||
queryParameters: { tenant_id: 'tenant_binghatti_demo' },
|
||||
rowLimit: 20,
|
||||
freshnessSlaSeconds: 300,
|
||||
cachePolicy: { mode: 'ttl', ttlSeconds: 300 },
|
||||
privacyTier: 'standard',
|
||||
lineageRefs: [],
|
||||
},
|
||||
visualizationParameters: {
|
||||
columns: ['name', 'deals_closed', 'revenue_generated', 'avg_response_time_min'],
|
||||
rankBy: 'revenue_generated',
|
||||
showTopBadge: true,
|
||||
},
|
||||
dataBindings: {
|
||||
dimensions: ['name'],
|
||||
measures: ['deals_closed', 'revenue_generated'],
|
||||
series: [],
|
||||
filters: [],
|
||||
},
|
||||
version: 1,
|
||||
provenance: {
|
||||
originType: 'catalog',
|
||||
templateId: 'tpl_broker_performance_v1',
|
||||
promptExecutionId: 'pex_demo_seed_003',
|
||||
createdBy: 'user_sales_director_001',
|
||||
createdAt: '2026-04-09T11:00:00Z',
|
||||
},
|
||||
renderingHints: {
|
||||
estimatedHeightPx: 320,
|
||||
skeletonVariant: 'table',
|
||||
virtualizationPriority: 7,
|
||||
},
|
||||
layout: {
|
||||
orderIndex: 400,
|
||||
sectionId: 'sec_team',
|
||||
widthMode: 'full',
|
||||
minHeightPx: 300,
|
||||
stickyHeader: true,
|
||||
},
|
||||
accessControls: {
|
||||
visibilityScope: 'private',
|
||||
allowedRoles: ['sales_director'],
|
||||
redactionPolicy: 'none',
|
||||
},
|
||||
styleSignature: { ...VELOCITY_GLASS_STYLE, paletteToken: 'indigo_signal' },
|
||||
validationState: { schema: 'pass', policy: 'pass', a11y: 'pass', performance: 'pass', status: 'validated' },
|
||||
auditLog: ['aud_demo_create_004'],
|
||||
dataRows: [
|
||||
{ name: 'Elena Rostova', deals_closed: 12, revenue_generated: 'AED 28.4M', avg_response_time_min: 8, rank: 1, avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&w=80&q=80' },
|
||||
{ name: 'Priya Sharma', deals_closed: 10, revenue_generated: 'AED 24.1M', avg_response_time_min: 11, rank: 2, avatar: 'https://images.unsplash.com/photo-1554151228-14d9def656e4?auto=format&fit=crop&w=80&q=80' },
|
||||
{ name: 'Carlos Mendez', deals_closed: 9, revenue_generated: 'AED 19.7M', avg_response_time_min: 14, rank: 3, avatar: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?auto=format&fit=crop&w=80&q=80' },
|
||||
{ name: 'Ravi Kapoor', deals_closed: 7, revenue_generated: 'AED 15.2M', avg_response_time_min: 22, rank: 4, avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&w=80&q=80' },
|
||||
{ name: 'Minati Ganrison', deals_closed: 6, revenue_generated: 'AED 11.8M', avg_response_time_min: 19, rank: 5, avatar: 'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?auto=format&fit=crop&w=80&q=80' },
|
||||
],
|
||||
};
|
||||
|
||||
const FOLLOWUP_QUEUE: CanvasComponent = {
|
||||
componentId: 'cmp_demo_followup_queue',
|
||||
type: 'activityStream',
|
||||
title: 'Follow-up Gap Queue',
|
||||
description: 'High-scoring leads with no contact in the last 72 hours.',
|
||||
dataSourceDescriptor: {
|
||||
descriptorId: 'dsd_demo_queue',
|
||||
sourceType: 'postgres',
|
||||
connectorId: 'velocity-core-postgres',
|
||||
dataset: 'lead_follow_up_gaps',
|
||||
authContextRef: 'authctx_sales_director_team_scope',
|
||||
queryTemplate: 'SELECT lead_id, name, last_contact_hours_ago, qd_score, assigned_broker FROM lead_follow_up_gaps WHERE tenant_id = :tenant_id AND last_contact_hours_ago > 72 ORDER BY qd_score DESC',
|
||||
queryParameters: { tenant_id: 'tenant_binghatti_demo' },
|
||||
rowLimit: 10,
|
||||
freshnessSlaSeconds: 60,
|
||||
cachePolicy: { mode: 'ttl', ttlSeconds: 60 },
|
||||
privacyTier: 'restricted',
|
||||
lineageRefs: ['lin_demo_sentinel'],
|
||||
},
|
||||
visualizationParameters: {
|
||||
showUrgencyIndicator: true,
|
||||
enableQuickAction: true,
|
||||
quickActions: ['call', 'whatsapp', 'email', 'assign'],
|
||||
},
|
||||
dataBindings: {
|
||||
dimensions: ['name', 'assigned_broker'],
|
||||
measures: ['qd_score', 'last_contact_hours_ago'],
|
||||
series: [],
|
||||
filters: [{ field: 'last_contact_hours_ago', operator: '>', value: 72 }],
|
||||
},
|
||||
version: 1,
|
||||
provenance: {
|
||||
originType: 'catalog',
|
||||
templateId: 'tpl_followup_queue_v1',
|
||||
promptExecutionId: 'pex_demo_seed_004',
|
||||
createdBy: 'user_sales_director_001',
|
||||
createdAt: '2026-04-09T12:00:00Z',
|
||||
},
|
||||
renderingHints: {
|
||||
estimatedHeightPx: 380,
|
||||
skeletonVariant: 'table',
|
||||
virtualizationPriority: 10,
|
||||
},
|
||||
layout: {
|
||||
orderIndex: 500,
|
||||
sectionId: 'sec_actions',
|
||||
widthMode: 'full',
|
||||
minHeightPx: 360,
|
||||
stickyHeader: false,
|
||||
},
|
||||
accessControls: {
|
||||
visibilityScope: 'private',
|
||||
allowedRoles: ['senior_broker', 'sales_director'],
|
||||
redactionPolicy: 'team_scope',
|
||||
},
|
||||
styleSignature: { ...VELOCITY_GLASS_STYLE, paletteToken: 'amber_signal' },
|
||||
validationState: { schema: 'pass', policy: 'pass', a11y: 'pass', performance: 'pass', status: 'validated' },
|
||||
auditLog: ['aud_demo_create_005'],
|
||||
dataRows: [
|
||||
{ lead_id: 'l10', name: 'Alexander Petrov', last_contact_hours_ago: 96, qd_score: 88.4, assigned_broker: 'Elena Rostova', urgency: 'critical', avatar: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=80&q=80' },
|
||||
{ lead_id: 'l11', name: 'Nadia Okafor', last_contact_hours_ago: 84, qd_score: 81.2, assigned_broker: 'Priya Sharma', urgency: 'high', avatar: 'https://images.unsplash.com/photo-1542206395-9feb3edaa68d?auto=format&fit=crop&w=80&q=80' },
|
||||
{ lead_id: 'l12', name: 'Tariq Al-Mansoori', last_contact_hours_ago: 78, qd_score: 76.9, assigned_broker: 'Carlos Mendez', urgency: 'medium', avatar: 'https://images.unsplash.com/photo-1560250097-0b93528c311a?auto=format&fit=crop&w=80&q=80' },
|
||||
{ lead_id: 'l13', name: 'Sophie Leclerc', last_contact_hours_ago: 73, qd_score: 72.1, assigned_broker: 'Ravi Kapoor', urgency: 'medium', avatar: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?auto=format&fit=crop&w=80&q=80' },
|
||||
],
|
||||
};
|
||||
|
||||
// ── Demo Canvas Page ──────────────────────────────────────────────────────────
|
||||
|
||||
export const IN_MEMORY_DEMO_PAGE: CanvasPage = {
|
||||
pageId: 'page_01_main_broker',
|
||||
tenantId: 'tenant_binghatti_demo',
|
||||
ownerId: 'user_sales_director_001',
|
||||
branchId: 'branch_main',
|
||||
branchName: 'main',
|
||||
pageType: 'main',
|
||||
title: 'Oracle — Pipeline & Investor Signals',
|
||||
createdAt: '2026-04-09T08:00:00Z',
|
||||
updatedAt: '2026-04-09T12:00:00Z',
|
||||
isShared: false,
|
||||
forks: [],
|
||||
mainBranchPointer: {
|
||||
pageId: 'page_01_main_broker',
|
||||
branchId: 'branch_main',
|
||||
revision: 5,
|
||||
},
|
||||
baseRevision: 0,
|
||||
headRevision: 5,
|
||||
sharingPolicy: {
|
||||
shareMode: 'direct_fork_only',
|
||||
allowReshare: false,
|
||||
defaultForkVisibility: 'private',
|
||||
},
|
||||
presence: {
|
||||
activeViewers: 1,
|
||||
activeEditors: 1,
|
||||
lastPresenceAt: new Date().toISOString(),
|
||||
},
|
||||
lineage: [
|
||||
{
|
||||
lineageRecordId: 'lin_demo_seed',
|
||||
tenantId: 'tenant_binghatti_demo',
|
||||
sourceKind: 'prompt',
|
||||
sourceId: 'pex_demo_seed_001',
|
||||
transformationType: 'prompt_to_component_bundle',
|
||||
producedKind: 'page_revision',
|
||||
producedId: 'page_01_main_broker:5',
|
||||
createdAt: '2026-04-09T12:00:00Z',
|
||||
},
|
||||
],
|
||||
audit: {
|
||||
lastAuditEventId: 'aud_demo_rev5',
|
||||
eventCount: 12,
|
||||
},
|
||||
components: [
|
||||
PIPELINE_BOARD,
|
||||
WHALE_LEADS_BAR,
|
||||
INVESTOR_GEO_MAP,
|
||||
BROKER_PERFORMANCE,
|
||||
FOLLOWUP_QUEUE,
|
||||
],
|
||||
};
|
||||
Reference in New Issue
Block a user