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:
2026-04-18 18:59:04 +05:30
parent 857e0b88e6
commit 84e439712c
459 changed files with 11713 additions and 3853 deletions

View File

@@ -49,7 +49,7 @@ export const useCurrencyStore = create<CurrencyState>()(
const { currency, option } = get();
const { locale } = option();
// Base assumption: Raw numbers in mock data are in AED.
// Base assumption: inventory and campaign amounts are stored in AED.
let convertedAmount = amount;
if (currency === 'USD') convertedAmount = amount * 0.272; // AED -> USD
if (currency === 'INR') convertedAmount = amount * 25.135112; // AED -> INR (0.272 * 92.4085)

View File

@@ -5,139 +5,8 @@ import type {
AdInsight,
LiveOptimizationEvent,
CatalystSettings,
LiveEventType,
} from '@/types';
// ── Mock Data ─────────────────────────────────────────────────────────────────
const mockCampaigns: Campaign[] = [
{
id: 'c1',
name: '3BHK Prestige Launch — Dubai Marina',
objective: 'OUTCOME_LEADS',
status: 'ACTIVE',
dailyBudget: 50000, // AED 500
lifetimeSpend: 2340000,
impressions: 487200,
clicks: 9744,
ctr: 2.0,
cpa: 240,
roi: 18.5,
createdAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 7),
updatedAt: new Date(),
},
{
id: 'c2',
name: 'Penthouse Whale Retarget — Instagram',
objective: 'OUTCOME_SALES',
status: 'ACTIVE',
dailyBudget: 100000, // AED 1000
lifetimeSpend: 5800000,
impressions: 92400,
clicks: 2772,
ctr: 3.0,
cpa: 2094,
roi: 42.1,
createdAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 14),
updatedAt: new Date(),
},
{
id: 'c3',
name: '1BHK Investment — Lookalike Audience',
objective: 'OUTCOME_TRAFFIC',
status: 'PAUSED',
dailyBudget: 25000, // AED 250
lifetimeSpend: 980000,
impressions: 213000,
clicks: 4260,
ctr: 2.0,
cpa: 230,
roi: 8.2,
createdAt: new Date(Date.now() - 1000 * 60 * 60 * 24 * 3),
updatedAt: new Date(),
},
];
const mockAssets: MarketingAsset[] = [
{
id: 'a1',
name: 'Penthouse Cinematic — Sea View',
type: 'video',
status: 'ready',
localUrl: '/assets/renders/penthouse_wan22_001.mp4',
metaAssetId: 'meta_vid_83920',
language: 'en',
createdAt: new Date(Date.now() - 1000 * 60 * 60 * 2),
},
{
id: 'a2',
name: 'Arabic Poster — 3BHK (Qwen-2512)',
type: 'image',
status: 'uploaded',
localUrl: '/assets/renders/3bhk_qwen_ar.png',
metaAssetId: 'meta_img_74811',
language: 'ar',
createdAt: new Date(Date.now() - 1000 * 60 * 60 * 5),
},
{
id: 'a3',
name: 'Amenity Deck Reel — Wan 2.2 14B',
type: 'video',
status: 'rendering',
renderMessage: 'Wan 2.2 is compositing the infinity pool reflection...',
language: 'en',
createdAt: new Date(),
},
{
id: 'a4',
name: 'English Poster — Penthouse Launch',
type: 'image',
status: 'queued',
renderMessage: 'Qwen-Image 2512 queued for cinematic poster render...',
language: 'en',
createdAt: new Date(),
},
];
const mockInsights: AdInsight[] = Array.from({ length: 14 }, (_, i) => {
const d = new Date(Date.now() - 1000 * 60 * 60 * 24 * (13 - i));
return {
adSetId: `as_${i}`,
adSetName: i % 2 === 0 ? '3BHK — Dubai Marina' : 'Penthouse Retarget',
spend: 800 + Math.floor(Math.random() * 400),
impressions: 18000 + Math.floor(Math.random() * 10000),
clicks: 360 + Math.floor(Math.random() * 200),
ctr: 1.8 + Math.random() * 1.5,
cpa: 190 + Math.floor(Math.random() * 120),
roi: 14 + Math.random() * 20,
date: d.toISOString().split('T')[0],
};
});
function makeLiveEvent(
type: LiveEventType,
message: string,
campaignName?: string,
value?: string
): LiveOptimizationEvent {
return {
id: `ev_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
type,
message,
campaignName,
timestamp: new Date(),
value,
};
}
const mockLiveEvents: LiveOptimizationEvent[] = [
makeLiveEvent('pause', 'Paused Ad Set B due to CPA exceeding AED 500 threshold.', '3BHK Prestige Launch', 'CPA: AED 512'),
makeLiveEvent('shift', 'Shifted AED 200/day budget from Ad Set B to Ad Set A (lower CPA).', '3BHK Prestige Launch', '+AED 200'),
makeLiveEvent('rotate', 'Rotated in Penthouse Cinematic (sea view) as new creative for A/B test.', 'Penthouse Whale Retarget'),
makeLiveEvent('optimize', 'Expanded Lookalike Audience to 2% similarity — 48k new reach.', '1BHK Investment', '+48k reach'),
makeLiveEvent('create', 'Created new Ad Set targeting High-Net-Worth Lookalike from 23 new CRM Closed/Won leads.', 'Penthouse Whale Retarget'),
];
// ── Store Types ────────────────────────────────────────────────────────────────
interface MarketingState {
@@ -162,10 +31,10 @@ interface MarketingState {
// ── Store ─────────────────────────────────────────────────────────────────────
export const useMarketingStore = create<MarketingState>()((set) => ({
campaigns: mockCampaigns,
activeAssets: mockAssets,
adInsights: mockInsights,
liveEvents: mockLiveEvents,
campaigns: [],
activeAssets: [],
adInsights: [],
liveEvents: [],
activeTab: 'studio',
settings: {

View File

@@ -61,6 +61,7 @@ interface DashboardState {
metrics: DashboardMetrics;
velocityData: LeadVelocityData[];
updateMetrics: (metrics: Partial<DashboardMetrics>) => void;
setVelocityData: (data: LeadVelocityData[]) => void;
addVelocityDataPoint: (data: LeadVelocityData) => void;
}
@@ -69,6 +70,7 @@ interface InventoryState {
units: Unit[];
selectedUnitId: string | null;
filterStatus: Unit['status'] | 'all';
setUnits: (units: Unit[]) => void;
setSelectedUnit: (unitId: string | null) => void;
setFilterStatus: (status: Unit['status'] | 'all') => void;
}
@@ -101,160 +103,6 @@ interface StoreState extends
SystemState,
NotificationState { }
// Mock Data
const mockLeads: Lead[] = [
{
id: '1',
name: 'Mohammed Al-Rashid',
phone: '+971 55 123 4567',
source: 'whatsapp',
status: 'hot',
lastMessage: 'Can we schedule a viewing for the penthouse tomorrow?',
lastActive: new Date(Date.now() - 1000 * 60 * 5),
unreadCount: 2,
qualification: 'whale',
budget: 'AED 15M+',
interest: 'Penthouse Suite',
},
{
id: '2',
name: 'Sarah Chen',
phone: '+971 50 987 6543',
source: 'walkin',
status: 'engaged',
lastMessage: 'Thank you for the brochure. I will review with my partner.',
lastActive: new Date(Date.now() - 1000 * 60 * 30),
unreadCount: 0,
qualification: 'potential',
budget: 'AED 5-8M',
interest: '2 Bedroom Sea View',
},
{
id: '3',
name: 'James Wilson',
phone: '+971 52 456 7890',
source: 'website',
status: 'new',
lastMessage: 'Interested in investment opportunities.',
lastActive: new Date(Date.now() - 1000 * 60 * 60 * 2),
unreadCount: 1,
qualification: 'potential',
budget: 'AED 3-5M',
interest: '1 Bedroom Investment',
},
{
id: '4',
name: 'Fatima Hassan',
phone: '+971 54 321 0987',
source: 'whatsapp',
status: 'qualified',
lastMessage: 'What are the payment plan options?',
lastActive: new Date(Date.now() - 1000 * 60 * 60 * 4),
unreadCount: 0,
qualification: 'whale',
budget: 'AED 12M+',
interest: '3 Bedroom + Maid',
},
{
id: '5',
name: 'David Kumar',
phone: '+971 56 789 0123',
source: 'walkin',
status: 'closed',
lastMessage: 'Contract signed. Thank you!',
lastActive: new Date(Date.now() - 1000 * 60 * 60 * 24),
unreadCount: 0,
qualification: 'whale',
budget: 'AED 20M',
interest: 'Full Floor',
},
];
const mockMessages: Record<string, ChatMessage[]> = {
'1': [
{
id: 'm1',
sender: 'user',
content: 'Hi, I am interested in the penthouse units.',
timestamp: new Date(Date.now() - 1000 * 60 * 60 * 2),
},
{
id: 'm2',
sender: 'oracle',
content: 'Welcome! Our penthouse collection features 4 exclusive units with panoramic sea views. Prices start at AED 15M. Would you like to know more about specific floor plans?',
timestamp: new Date(Date.now() - 1000 * 60 * 60 * 2 + 1000 * 30),
},
{
id: 'm3',
sender: 'user',
content: 'Can we schedule a viewing for the penthouse tomorrow?',
timestamp: new Date(Date.now() - 1000 * 60 * 5),
},
],
'2': [
{
id: 'm4',
sender: 'oracle',
content: 'Hello Sarah! Thank you for visiting our Experience Center today. Here is the digital brochure for the 2-bedroom units we discussed.',
timestamp: new Date(Date.now() - 1000 * 60 * 60 * 4),
},
{
id: 'm5',
sender: 'user',
content: 'Thank you for the brochure. I will review with my partner.',
timestamp: new Date(Date.now() - 1000 * 60 * 30),
},
],
};
const mockVisitors: Visitor[] = [
{
id: 'v1',
faceId: 'face_001',
sentiment: 'excited',
confidence: 0.92,
dwellTime: 450,
zone: 'Penthouse Showroom',
timestamp: new Date(),
},
{
id: 'v2',
faceId: 'face_002',
sentiment: 'interested',
confidence: 0.87,
dwellTime: 320,
zone: 'Amenity Deck VR',
timestamp: new Date(),
},
{
id: 'v3',
faceId: 'face_003',
sentiment: 'neutral',
confidence: 0.78,
dwellTime: 180,
zone: 'Reception',
timestamp: new Date(),
},
];
const mockVelocityData: LeadVelocityData[] = Array.from({ length: 12 }, (_, i) => ({
time: `${9 + Math.floor(i / 2)}:${i % 2 === 0 ? '00' : '30'}`,
generated: Math.floor(Math.random() * 8) + 2,
closed: Math.floor(Math.random() * 3),
}));
const mockUnits: Unit[] = [
{ id: 'u1', unitNumber: 'PH-01', type: 'penthouse', floor: 45, area: 520, price: 25000000, status: 'available', view: 'Panoramic Sea', lastUpdated: new Date() },
{ id: 'u2', unitNumber: 'PH-02', type: 'penthouse', floor: 45, area: 480, price: 22000000, status: 'reserved', view: 'Sea & Marina', lastUpdated: new Date() },
{ id: 'u3', unitNumber: '4501', type: '3br', floor: 45, area: 280, price: 12000000, status: 'available', view: 'Sea View', lastUpdated: new Date() },
{ id: 'u4', unitNumber: '4502', type: '3br', floor: 45, area: 265, price: 11500000, status: 'sold', view: 'Marina View', lastUpdated: new Date() },
{ id: 'u5', unitNumber: '4401', type: '2br', floor: 44, area: 180, price: 7500000, status: 'available', view: 'Sea View', lastUpdated: new Date() },
{ id: 'u6', unitNumber: '4402', type: '2br', floor: 44, area: 175, price: 7200000, status: 'hold', view: 'City View', lastUpdated: new Date() },
{ id: 'u7', unitNumber: '4301', type: '1br', floor: 43, area: 95, price: 4200000, status: 'available', view: 'Sea View', lastUpdated: new Date() },
{ id: 'u8', unitNumber: '4302', type: '1br', floor: 43, area: 92, price: 4000000, status: 'available', view: 'City View', lastUpdated: new Date() },
];
export const useStore = create<StoreState>()(
persist(
(set) => ({
@@ -272,9 +120,9 @@ export const useStore = create<StoreState>()(
setSidebarExpanded: (expanded) => set({ sidebarExpanded: expanded }),
// Oracle State
leads: mockLeads,
leads: [],
activeLeadId: null,
messages: mockMessages,
messages: {},
isOracleThinking: false,
setLeads: (leads) => set({ leads }),
replaceMessages: (messages) => set({ messages }),
@@ -293,7 +141,7 @@ export const useStore = create<StoreState>()(
})),
// Sentinel State
visitors: mockVisitors,
visitors: [],
isAlertActive: false,
alertMessage: '',
addVisitor: (visitor) => set((state) => ({
@@ -307,37 +155,39 @@ export const useStore = create<StoreState>()(
// Dashboard State
metrics: {
activeVisitors: 12,
todayLeads: 24,
closedDeals: 3,
conversionRate: 12.5,
sentiment: 78,
activeVisitors: 0,
todayLeads: 0,
closedDeals: 0,
conversionRate: 0,
sentiment: 0,
systemHealth: {
cpu: 34,
gpu: 28,
memory: 42,
temperature: 58,
cpu: 0,
gpu: 0,
memory: 0,
temperature: 0,
},
},
velocityData: mockVelocityData,
velocityData: [],
updateMetrics: (metrics) => set((state) => ({
metrics: { ...state.metrics, ...metrics },
})),
setVelocityData: (data) => set({ velocityData: data }),
addVelocityDataPoint: (data) => set((state) => ({
velocityData: [...state.velocityData.slice(1), data],
})),
// Inventory State
units: mockUnits,
units: [],
selectedUnitId: null,
filterStatus: 'all',
setUnits: (units) => set({ units }),
setSelectedUnit: (unitId) => set({ selectedUnitId: unitId }),
setFilterStatus: (status) => set({ filterStatus: status }),
// System State
status: {
isConnected: true,
serverStatus: 'online',
isConnected: false,
serverStatus: 'syncing',
lastSync: new Date(),
version: '2.1.0',
},