Files
emaui/apps/backoffice/src/app/features/user-management/UserManagementPage.tsx

193 lines
6.1 KiB
TypeScript

import { useCallback, useEffect, useRef } from 'react';
import { createRoot, type Root } from 'react-dom/client';
import { useNavigate } from 'react-router-dom';
import { UserManagementApp } from '@tria-plc/iamui';
import type { DesignConfig, UserManagementSessionOptions } from '@tria-plc/iamui';
import '@tria-plc/iamui/style.css';
const UM_OVERRIDES = `
.um-theme-light {
--background: #ffffff !important;
--foreground: #1f2937 !important;
--card: #ffffff !important;
--card-foreground: #1f2937 !important;
--popover: #ffffff !important;
--popover-foreground: #1f2937 !important;
--secondary: #f1f5f9 !important;
--secondary-foreground: #1e293b !important;
--muted: #f1f5f9 !important;
--muted-foreground: #64748b !important;
--accent: var(--primary) !important;
--accent-foreground: var(--primary-foreground) !important;
--border: #e2e8f0 !important;
--input: #e2e8f0 !important;
--sidebar: #ffffff !important;
--sidebar-foreground: #1e293b !important;
--sidebar-accent: #f1f5f9 !important;
--sidebar-accent-foreground: #1e293b !important;
--sidebar-border: #e2e8f0 !important;
--sidebar-ring: var(--primary) !important;
--color-amber-50: #eff6ff !important;
--color-amber-100: #dbeafe !important;
--color-yellow-50: #eff6ff !important;
--color-yellow-100: #dbeafe !important;
}
[class*="bg-[#f7efe8]"] { background-color: #f1f5f9 !important; }
[class*="bg-[#f2ece8]"] { background-color: #f1f5f9 !important; }
[class*="hover:bg-[#f7efe8]"]:hover { background-color: #f1f5f9 !important; }
[class*="hover:bg-[#f2ece8]"]:hover { background-color: #f1f5f9 !important; }
[class*="border-[#e6d8cc]"] { border-color: #e2e8f0 !important; }
[class*="bg-[#fffdfa]"] { background-color: #ffffff !important; }
[class*="bg-[#fcf7f3]"] { background-color: #f8fafc !important; }
[class*="bg-[#fffaf6]"] { background-color: #f8fafc !important; }
[class*="text-[#432319]"] { color: #1e293b !important; }
[class*="text-[#7a6a61]"] { color: #64748b !important; }
[class*="text-[#6b4a3d]"] { color: #475569 !important; }
.um-theme-light [class*="dark:border-gray-900"],
.um-theme-light [class*="dark:border-gray-800"],
.um-theme-light [class*="dark:border-gray-700"],
.um-theme-light [class*="dark:border-gray-600"],
.um-theme-light [class*="dark:border-slate-800"],
.um-theme-light [class*="dark:border-slate-700"] {
border-color: #e2e8f0 !important;
}
`;
const UM_CONFIG: DesignConfig = {
brand: {
appName: 'Ethiopian Maritime Licence',
logoUrl: '/assets/emaLogo.jpg',
},
colors: {
primary: '#2563eb',
sidebar: '#ffffff',
background: '#f8fafc',
foreground: '#1e293b',
border: '#e2e8f0',
mutedForeground: '#94a3b8',
card: '#ffffff',
},
typography: {
fontFamily: 'Inter, ui-sans-serif, system-ui, sans-serif',
},
layout: {
userManagementView: 'classic',
sidebarBrandLabel: 'Ethiopian Maritime Authority',
sidebarBrandSublabel: 'User Management',
sidebarBackground: '#ffffff',
sidebarColor: '#1e293b',
sidebarMutedColor: '#94a3b8',
sidebarActiveBackground: '#eff6ff',
sidebarActiveColor: '#2563eb',
sidebarHoverBackground: '#f8fafc',
sidebarBorder: '#e2e8f0',
sidebarWidth: '280px',
sidebarCollapsedWidth: '80px',
modalAccentColor: '#2563eb',
modalHeaderBackground: '#f8fafc',
modalHeaderEditBackground: '#eff6ff',
modalIconBackground: '#eff6ff',
modalIconColor: '#2563eb',
modalTitleColor: '#1e293b',
modalFocusColor: '#2563eb',
modalSurface: '#ffffff',
},
};
const UM_RUNTIME = {
basename: '/um',
apiUrl: import.meta.env.VITE_BASE_API_URL,
};
const buttonStyle: React.CSSProperties = {
position: 'fixed',
top: 12,
left: 12,
zIndex: 9999,
display: 'flex',
alignItems: 'center',
gap: 6,
padding: '8px 16px',
border: '1px solid #e2e8f0',
borderRadius: 8,
background: '#ffffff',
color: '#2563eb',
fontSize: 14,
fontWeight: 600,
cursor: 'pointer',
fontFamily: 'Inter, ui-sans-serif, system-ui, sans-serif',
boxShadow: '0 1px 3px rgba(0,0,0,0.08)',
transition: 'all 150ms ease',
};
export default function UserManagementPage() {
const containerRef = useRef<HTMLDivElement>(null);
const rootRef = useRef<Root | null>(null);
const navigate = useNavigate();
const handleReturn = useCallback(() => {
navigate('/dashboard');
}, [navigate]);
useEffect(() => {
if (!containerRef.current) return;
const style = document.createElement('style');
style.textContent = UM_OVERRIDES;
document.head.appendChild(style);
const readCookie = (name: string) => {
const m = document.cookie.match(new RegExp('(?:^|;\\s*)' + name + '=([^;]*)'));
return m ? decodeURIComponent(m[1]) : undefined;
};
const token = readCookie('ema-backoffice-auth-token') ?? '';
const refreshToken = readCookie('ema-backoffice-refresh-token');
const session: UserManagementSessionOptions = {
initialSession: token
? { token, refreshToken, rememberMe: true }
: null,
enableEmbeddedAuthBridge: false,
};
rootRef.current = createRoot(containerRef.current);
rootRef.current.render(
<UserManagementApp config={UM_CONFIG} runtime={UM_RUNTIME} session={session} />,
);
return () => {
if (rootRef.current) {
rootRef.current.unmount();
rootRef.current = null;
}
style.remove();
};
}, []);
return (
<>
<button
onClick={handleReturn}
style={buttonStyle}
onMouseEnter={(e) => {
e.currentTarget.style.background = '#f8fafc';
e.currentTarget.style.boxShadow = '0 1px 6px rgba(0,0,0,0.12)';
}}
onMouseLeave={(e) => {
e.currentTarget.style.background = '#ffffff';
e.currentTarget.style.boxShadow = '0 1px 3px rgba(0,0,0,0.08)';
}}
>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="m12 19-7-7 7-7" />
<path d="M19 12H5" />
</svg>
Return to EMA
</button>
<div ref={containerRef} style={{ position: 'fixed', inset: 0 }} />
</>
);
}