import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import {
User,
Bell,
Shield,
Database,
Monitor,
RefreshCw,
Power,
Server,
Smartphone,
Wifi,
Copy,
Check,
ChevronDown,
LogOut,
type LucideIcon,
} from 'lucide-react';
import { useStore } from '@/store/useStore';
import { useCurrency, CURRENCY_OPTIONS } from '@/store/useCurrencyStore';
import type { CurrencyCode } from '@/store/useCurrencyStore';
import { API_URL } from '@/lib/api';
import { VELOCITY_TOKEN_KEY, clearVelocityToken, getVelocityToken, normalizeVelocityRole } from '@/lib/velocityPlatformClient';
// ── Design tokens (matching inventory glassmorphism) ─────────────────────────
const GLASS = {
background: 'rgba(14, 16, 21, 0.72)',
border: '1px solid rgba(255,255,255,0.08)',
backdropFilter: 'blur(18px)',
WebkitBackdropFilter: 'blur(18px)',
} as const;
const INNER_SURFACE = {
background: 'rgba(255,255,255,0.04)',
border: '1px solid rgba(255,255,255,0.07)',
} as const;
// ── Shared primitives ────────────────────────────────────────────────────────
function GlassCard({
children,
delay = 0,
className = '',
}: {
children: React.ReactNode;
delay?: number;
className?: string;
}) {
return (
{children}
);
}
function SectionHeader({ icon: Icon, title, accent = 'hsl(var(--accent))' }: { icon: LucideIcon; title: string; accent?: string }) {
return (
{open && (
{options.map((opt) => (
))}
)}
{open &&
setOpen(false)} />}
);
}
// ── Ghost button ─────────────────────────────────────────────────────────────
function GhostButton({ children, onClick, danger = false }: { children: React.ReactNode; onClick?: () => void; danger?: boolean }) {
return (
{children}
);
}
// ── Text input ───────────────────────────────────────────────────────────────
function DarkInput({ type = 'text', defaultValue, placeholder }: { type?: string; defaultValue?: string; placeholder?: string }) {
return (
{ e.currentTarget.style.border = '1px solid hsl(var(--accent) / 0.4)'; }}
onBlur={(e) => { e.currentTarget.style.border = '1px solid rgba(255,255,255,0.07)'; }}
/>
);
}
// ── System Status ────────────────────────────────────────────────────────────
function SystemStatusCard() {
const { status, updateStatus } = useStore();
const lastSync = status.lastSync instanceof Date ? status.lastSync : new Date(status.lastSync);
return (
{/* Connection pill */}
Backend Connection
{status.isConnected ? 'Connected to live Velocity backend' : 'Connection unavailable'}
{status.serverStatus.toUpperCase()}
{/* Version / sync grid */}
{[
{ label: 'Version', value: status.version },
{ label: 'Last Sync', value: Number.isNaN(lastSync.getTime()) ? 'Unavailable' : lastSync.toLocaleTimeString() },
].map(({ label, value }) => (
))}
{/* Actions */}
{
updateStatus({ serverStatus: 'syncing' });
window.location.reload();
}}
>
Sync Now
window.location.reload()}
>
Restart
);
}
// ── iOS Device Connection ────────────────────────────────────────────────────
function CompanionSurfacesCard() {
const [copied, setCopied] = useState(false);
const token = getVelocityToken();
const maskedToken = token ? `${token.slice(0, 8)}...${token.slice(-6)}` : 'No active bearer token';
const handleCopy = (text: string) => {
void navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 1800);
};
return (
WebOS Session Token
{token ? 'Reusable by Oracle and protected WebOS routes.' : 'No authenticated backend session is currently present.'}
{token
?
ACTIVE
:
}
Runtime Access
{maskedToken}
Mobile and tablet pairing is intentionally deferred until the next delivery phase. This WebOS pass does not simulate device pairing.
window.location.reload()}
className="flex-1 py-2.5 rounded-xl text-sm font-semibold flex items-center justify-center gap-2 transition-all"
style={{ background: 'hsl(var(--accent))', color: 'hsl(var(--accent-fg))' }}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.97 }}
>
<> Refresh WebOS>
handleCopy(API_URL)}>Copy API URL
);
}
// ── Profile ──────────────────────────────────────────────────────────────────
function ProfileSettings() {
const { user } = useStore();
const initials = user?.name.split(' ').map((n) => n[0]).join('') ?? 'AU';
const roleLabel = normalizeVelocityRole(user?.role)
.toLowerCase()
.split('_')
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(' ') || 'Authenticated User';
return (
{user?.name ?? 'Unavailable'}
{user?.id ?? 'Unavailable'}
{roleLabel}
);
}
// ── Notifications ────────────────────────────────────────────────────────────
function NotificationSettings() {
const [s, setS] = useState({ newLeads: true, sentimentAlerts: true, viewings: true, systemUpdates: false, emailDigest: true });
const rows: { key: keyof typeof s; label: string; desc: string }[] = [
{ key: 'newLeads', label: 'New Lead Alerts', desc: 'Get notified when a new lead is captured' },
{ key: 'sentimentAlerts', label: 'Sentiment Alerts', desc: 'Alert when visitor sentiment drops' },
{ key: 'viewings', label: 'Viewing Reminders', desc: 'Reminders for scheduled viewings' },
{ key: 'systemUpdates', label: 'System Updates', desc: 'Notifications about system maintenance' },
{ key: 'emailDigest', label: 'Daily Email Digest', desc: 'Summary of daily activity' },
];
return (
{rows.map(({ key, label, desc }) => (
setS({ ...s, [key]: v })} />
))}
);
}
// ── Security ─────────────────────────────────────────────────────────────────
function SecuritySettings() {
const [timeout, setTimeout_] = useState('30');
const { logout } = useStore();
const token = getVelocityToken();
return (
{token ? 'Present' : 'Missing'}
Managed outside WebOS
{
clearVelocityToken();
logout();
}}
>
Sign Out
);
}
// ── Display ──────────────────────────────────────────────────────────────────
function DisplaySettings() {
const [reducedMotion, setReducedMotion] = useState(false);
const [compactMode, setCompactMode] = useState(false);
const [language, setLanguage] = useState('en');
const [timezone, setTimezone] = useState('dxb');
const { currency, setCurrency } = useCurrency();
return (
{/* ── Currency ── */}
setCurrency(v as CurrencyCode)}
options={CURRENCY_OPTIONS.map((o) => ({
value: o.code,
label: `${o.flag} ${o.symbol} — ${o.label}`,
}))}
/>
);
}
// ── Data & Privacy ───────────────────────────────────────────────────────────
function DataSettings() {
const [retention, setRetention] = useState('90');
const { leads, messages, units, status } = useStore();
const exportSnapshot = () => {
const blob = new Blob([
JSON.stringify(
{
exported_at: new Date().toISOString(),
status,
lead_count: leads.length,
message_threads: Object.keys(messages).length,
inventory_count: units.length,
leads,
messages,
units,
},
null,
2,
),
], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = url;
anchor.download = `velocity-webos-export-${Date.now()}.json`;
anchor.click();
URL.revokeObjectURL(url);
};
const clearUiCache = () => {
localStorage.removeItem('velocity-webos-storage');
localStorage.removeItem('pv-currency');
window.location.reload();
};
return (
Backend managed
Export
Clear
);
}
// ── About ────────────────────────────────────────────────────────────────────
function AboutSection() {
const token = getVelocityToken();
return (
V
Velocity WebOS
Real Estate Operating System
Version 2.1.0
•
{token ? 'Authenticated session active' : 'No active session'}
Backend origin: {API_URL}
);
}
// ── Main ─────────────────────────────────────────────────────────────────────
export function Settings() {
return (
{/* Row 1: System + iOS */}
{/* Row 2: Profile + Notifications */}
{/* Row 3: Security + Display */}
{/* Row 4: Data + About */}
);
}