- Web3 authentication with MetaMask, WalletConnect, Coinbase wallet options - Demo mode for testing without wallet - Overview dashboard with KPI cards, asset allocation, positions, accounts, alerts - Transaction Builder module (full IDE-style drag-and-drop canvas with 28 gap fixes) - Accounts module with multi-account/subaccount hierarchical structures - Treasury Management module with positions table and 14-day cash forecast - Financial Reporting module with IPSAS, US GAAP, IFRS compliance - Compliance & Risk module with KYC/AML/Sanctions monitoring - Settlement & Clearing module with DVP/FOP/PVP operations - Settings with role-based permissions and enterprise controls - Dark theme professional UI with Solace Bank branding - HashRouter for static hosting compatibility Co-Authored-By: Nakamoto, S <defi@defi-oracle.io>
244 lines
7.5 KiB
TypeScript
244 lines
7.5 KiB
TypeScript
import { Routes, Route, Navigate } from 'react-router-dom';
|
|
import { useAuth } from './contexts/AuthContext';
|
|
import LoginPage from './pages/LoginPage';
|
|
import DashboardPage from './pages/DashboardPage';
|
|
import AccountsPage from './pages/AccountsPage';
|
|
import TreasuryPage from './pages/TreasuryPage';
|
|
import ReportingPage from './pages/ReportingPage';
|
|
import CompliancePage from './pages/CompliancePage';
|
|
import SettlementsPage from './pages/SettlementsPage';
|
|
import PortalLayout from './components/portal/PortalLayout';
|
|
import App from './App';
|
|
|
|
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
|
const { isAuthenticated, loading } = useAuth();
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="portal-loading">
|
|
<div className="portal-loading-spinner" />
|
|
<span>Initializing secure session...</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!isAuthenticated) {
|
|
return <Navigate to="/login" replace />;
|
|
}
|
|
|
|
return <>{children}</>;
|
|
}
|
|
|
|
export default function Portal() {
|
|
const { isAuthenticated, loading } = useAuth();
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="portal-loading">
|
|
<div className="portal-loading-spinner" />
|
|
<span>Initializing secure session...</span>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Routes>
|
|
<Route
|
|
path="/login"
|
|
element={isAuthenticated ? <Navigate to="/dashboard" replace /> : <LoginPage />}
|
|
/>
|
|
|
|
<Route
|
|
path="/dashboard"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<DashboardPage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/transaction-builder"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<div className="transaction-builder-module">
|
|
<App />
|
|
</div>
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/accounts"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<AccountsPage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/treasury"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<TreasuryPage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/reporting"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<ReportingPage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/compliance"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<CompliancePage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/settlements"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<SettlementsPage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route
|
|
path="/settings"
|
|
element={
|
|
<ProtectedRoute>
|
|
<PortalLayout>
|
|
<SettingsPage />
|
|
</PortalLayout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
|
|
<Route path="*" element={<Navigate to={isAuthenticated ? '/dashboard' : '/login'} replace />} />
|
|
</Routes>
|
|
);
|
|
}
|
|
|
|
function SettingsPage() {
|
|
const { user, wallet } = useAuth();
|
|
return (
|
|
<div className="settings-page">
|
|
<div className="page-header">
|
|
<h1>Settings</h1>
|
|
<p className="page-subtitle">Portal configuration and user preferences</p>
|
|
</div>
|
|
<div className="settings-grid">
|
|
<div className="dashboard-card">
|
|
<div className="card-header"><h3>Profile</h3></div>
|
|
<div className="settings-section">
|
|
<div className="setting-row">
|
|
<span className="setting-label">Display Name</span>
|
|
<span className="setting-value">{user?.displayName || '—'}</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Role</span>
|
|
<span className="setting-value">{user?.role?.replace('_', ' ') || '—'}</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Institution</span>
|
|
<span className="setting-value">{user?.institution || '—'}</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Department</span>
|
|
<span className="setting-value">{user?.department || '—'}</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Wallet Address</span>
|
|
<span className="setting-value mono">{wallet?.address || '—'}</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Chain ID</span>
|
|
<span className="setting-value">{wallet?.chainId || '—'}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="dashboard-card">
|
|
<div className="card-header"><h3>Permissions</h3></div>
|
|
<div className="settings-section">
|
|
<div className="permissions-list">
|
|
{user?.permissions?.map(p => (
|
|
<span key={p} className="permission-badge">{p}</span>
|
|
)) || <span>No permissions</span>}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="dashboard-card">
|
|
<div className="card-header"><h3>Reporting Preferences</h3></div>
|
|
<div className="settings-section">
|
|
<div className="setting-row">
|
|
<span className="setting-label">Default Standard</span>
|
|
<span className="setting-value">IFRS</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Base Currency</span>
|
|
<span className="setting-value">USD</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Fiscal Year End</span>
|
|
<span className="setting-value">December 31</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Auto-generate Reports</span>
|
|
<span className="setting-value">Monthly</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="dashboard-card">
|
|
<div className="card-header"><h3>Enterprise Controls</h3></div>
|
|
<div className="settings-section">
|
|
<div className="setting-row">
|
|
<span className="setting-label">Multi-signature Required</span>
|
|
<span className="setting-value">Yes (2-of-3)</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Transaction Limit</span>
|
|
<span className="setting-value">$10,000,000</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Approval Workflow</span>
|
|
<span className="setting-value">Dual Authorization</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Session Timeout</span>
|
|
<span className="setting-value">30 minutes</span>
|
|
</div>
|
|
<div className="setting-row">
|
|
<span className="setting-label">Audit Logging</span>
|
|
<span className="setting-value">Enabled (Full)</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|