mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 19:12:50 +00:00
193 lines
6.1 KiB
TypeScript
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 }} />
|
|
</>
|
|
);
|
|
}
|