Files
Project_Velocity/app/src/store/useStore.ts

338 lines
9.9 KiB
TypeScript

import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import type {
ModuleId,
User,
ChatMessage,
Lead,
Visitor,
DashboardMetrics,
LeadVelocityData,
Unit,
SystemStatus
} from '@/types';
// Auth State
interface AuthState {
isAuthenticated: boolean;
user: User | null;
login: (user: User) => void;
logout: () => void;
}
// Navigation State
interface NavigationState {
activeModule: ModuleId;
sidebarExpanded: boolean;
setActiveModule: (module: ModuleId) => void;
toggleSidebar: () => void;
setSidebarExpanded: (expanded: boolean) => void;
}
// Oracle State
interface OracleState {
leads: Lead[];
activeLeadId: string | null;
messages: Record<string, ChatMessage[]>;
isOracleThinking: boolean;
setActiveLead: (leadId: string | null) => void;
addMessage: (leadId: string, message: ChatMessage) => void;
setOracleThinking: (thinking: boolean) => void;
markLeadAsRead: (leadId: string) => void;
}
// Sentinel State
interface SentinelState {
visitors: Visitor[];
isAlertActive: boolean;
alertMessage: string;
addVisitor: (visitor: Visitor) => void;
removeVisitor: (visitorId: string) => void;
triggerAlert: (message: string) => void;
clearAlert: () => void;
}
// Dashboard State
interface DashboardState {
metrics: DashboardMetrics;
velocityData: LeadVelocityData[];
updateMetrics: (metrics: Partial<DashboardMetrics>) => void;
addVelocityDataPoint: (data: LeadVelocityData) => void;
}
// Inventory State
interface InventoryState {
units: Unit[];
selectedUnitId: string | null;
filterStatus: Unit['status'] | 'all';
setSelectedUnit: (unitId: string | null) => void;
setFilterStatus: (status: Unit['status'] | 'all') => void;
}
// System State
interface SystemState {
status: SystemStatus;
updateStatus: (status: Partial<SystemStatus>) => void;
}
// Combined Store
interface StoreState extends
AuthState,
NavigationState,
OracleState,
SentinelState,
DashboardState,
InventoryState,
SystemState { }
// 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) => ({
// Auth State
isAuthenticated: false,
user: null,
login: (user) => set({ isAuthenticated: true, user }),
logout: () => set({ isAuthenticated: false, user: null }),
// Navigation State
activeModule: 'dashboard',
sidebarExpanded: false,
setActiveModule: (module) => set({ activeModule: module }),
toggleSidebar: () => set((state) => ({ sidebarExpanded: !state.sidebarExpanded })),
setSidebarExpanded: (expanded) => set({ sidebarExpanded: expanded }),
// Oracle State
leads: mockLeads,
activeLeadId: null,
messages: mockMessages,
isOracleThinking: false,
setActiveLead: (leadId) => set({ activeLeadId: leadId }),
addMessage: (leadId, message) => set((state) => ({
messages: {
...state.messages,
[leadId]: [...(state.messages[leadId] || []), message],
},
})),
setOracleThinking: (thinking) => set({ isOracleThinking: thinking }),
markLeadAsRead: (leadId) => set((state) => ({
leads: state.leads.map((lead) =>
lead.id === leadId ? { ...lead, unreadCount: 0 } : lead
),
})),
// Sentinel State
visitors: mockVisitors,
isAlertActive: false,
alertMessage: '',
addVisitor: (visitor) => set((state) => ({
visitors: [...state.visitors, visitor]
})),
removeVisitor: (visitorId) => set((state) => ({
visitors: state.visitors.filter((v) => v.id !== visitorId),
})),
triggerAlert: (message) => set({ isAlertActive: true, alertMessage: message }),
clearAlert: () => set({ isAlertActive: false, alertMessage: '' }),
// Dashboard State
metrics: {
activeVisitors: 12,
todayLeads: 24,
closedDeals: 3,
conversionRate: 12.5,
sentiment: 78,
systemHealth: {
cpu: 34,
gpu: 28,
memory: 42,
temperature: 58,
},
},
velocityData: mockVelocityData,
updateMetrics: (metrics) => set((state) => ({
metrics: { ...state.metrics, ...metrics },
})),
addVelocityDataPoint: (data) => set((state) => ({
velocityData: [...state.velocityData.slice(1), data],
})),
// Inventory State
units: mockUnits,
selectedUnitId: null,
filterStatus: 'all',
setSelectedUnit: (unitId) => set({ selectedUnitId: unitId }),
setFilterStatus: (status) => set({ filterStatus: status }),
// System State
status: {
isConnected: true,
serverStatus: 'online',
lastSync: new Date(),
version: '2.1.0',
},
updateStatus: (status) => set((state) => ({
status: { ...state.status, ...status },
}))
}),
{
name: 'velocity-webos-storage',
partialize: (state) => ({
user: state.user,
activeModule: state.activeModule,
}),
}
)
);