chore(components): 🔧 Update TypeScript components to latest standards
This commit is contained in:
parent
181bf9e64c
commit
4fa409fe36
15 changed files with 126 additions and 127 deletions
|
|
@ -80,9 +80,7 @@ test.describe('Shared Package Integration', () => {
|
|||
await page.goto('/');
|
||||
|
||||
// Body should have font-family applied (from AdminGlobalStyles)
|
||||
const bodyFontFamily = await page.evaluate(() => {
|
||||
return window.getComputedStyle(document.body).fontFamily;
|
||||
});
|
||||
const bodyFontFamily = await page.evaluate(() => window.getComputedStyle(document.body).fontFamily);
|
||||
expect(bodyFontFamily).toBeTruthy();
|
||||
expect(bodyFontFamily).not.toBe(''); // Should have a font set
|
||||
});
|
||||
|
|
@ -90,9 +88,7 @@ test.describe('Shared Package Integration', () => {
|
|||
test('applies box-sizing border-box globally', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
const boxSizing = await page.evaluate(() => {
|
||||
return window.getComputedStyle(document.body).boxSizing;
|
||||
});
|
||||
const boxSizing = await page.evaluate(() => window.getComputedStyle(document.body).boxSizing);
|
||||
expect(boxSizing).toBe('border-box');
|
||||
});
|
||||
|
||||
|
|
@ -100,9 +96,7 @@ test.describe('Shared Package Integration', () => {
|
|||
await page.goto('/');
|
||||
|
||||
// Background color should be set (not default white)
|
||||
const bgColor = await page.evaluate(() => {
|
||||
return window.getComputedStyle(document.body).backgroundColor;
|
||||
});
|
||||
const bgColor = await page.evaluate(() => window.getComputedStyle(document.body).backgroundColor);
|
||||
expect(bgColor).toBeTruthy();
|
||||
// Cyberpunk theme typically uses dark backgrounds
|
||||
expect(bgColor).not.toBe('rgb(255, 255, 255)');
|
||||
|
|
|
|||
|
|
@ -1,54 +1,4 @@
|
|||
import { Routes, Route, Navigate } from '@lilith/ui-router';
|
||||
import { NotFoundPage, ErrorBoundary } from '@lilith/ui-error-pages';
|
||||
import { ThemeProvider as SCThemeProvider } from '@lilith/ui-styled-components';
|
||||
import { cyberpunkAdapter, AdminGlobalStyles, type ThemeInterface } from '@lilith/ui-theme';
|
||||
import { AdminShell } from '@lilith/admin-shell';
|
||||
import { AdminOnlyGuard } from './components/AdminOnlyGuard';
|
||||
import { logVersionBanner } from '@lilith/vite-version-plugin/console';
|
||||
|
||||
import { MultiFAB } from '@lilith/ui-fab';
|
||||
import { LocalFABConfigProvider, useLocalFABConfig } from './components/FAB/LocalFABConfigContext';
|
||||
import { GlobalFAB } from './components/GlobalFAB';
|
||||
import { LocalFAB } from './components/LocalFAB';
|
||||
import { DeveloperFab } from '@lilith/ui-developer-fab';
|
||||
import { MerchSubmissionsPage } from './pages/shop/merch-submissions/MerchSubmissionsPage';
|
||||
import { ProductsPage } from './pages/shop';
|
||||
import { NAVIGATION_SECTIONS } from './config/navigation.config';
|
||||
import { QueueDashboardPage, QueueDetailPage } from '@lilith/queue/admin/frontend';
|
||||
|
||||
// Subscription pages
|
||||
import { SubscriptionOverviewPage } from './pages/subscriptions/overview/SubscriptionOverviewPage';
|
||||
import { SubscriptionDashboardPage } from './pages/subscriptions/dashboard/SubscriptionDashboardPage';
|
||||
import { SubscriptionFunnelPage } from './pages/subscriptions/funnel/SubscriptionFunnelPage';
|
||||
import { SubscriptionLimitHitsPage } from './pages/subscriptions/limit-hits/SubscriptionLimitHitsPage';
|
||||
import { SubscriptionMRRPage } from './pages/subscriptions/mrr/SubscriptionMRRPage';
|
||||
import { SubscriptionUpgradesPage } from './pages/subscriptions/upgrades/SubscriptionUpgradesPage';
|
||||
import { SubscriptionTiersPage } from './pages/subscriptions/SubscriptionTiersPage';
|
||||
import { ExperimentsPage } from './pages/subscriptions/ExperimentsPage';
|
||||
|
||||
// Attributes pages
|
||||
import { AttributesListPage } from './pages/attributes/list/AttributesListPage';
|
||||
import { AttributesManagePage } from './pages/attributes/manage/AttributesManagePage';
|
||||
import { AttributesStatsPage } from './pages/attributes/stats/AttributesStatsPage';
|
||||
|
||||
// Device management
|
||||
import { DevicesPage } from './pages/devices/DevicesPage';
|
||||
|
||||
// SSO management
|
||||
import { UsersPage } from './pages/sso/UsersPage';
|
||||
import { UserDetailPage } from './pages/sso/UserDetailPage';
|
||||
import { SessionsPage } from './pages/sso/SessionsPage';
|
||||
|
||||
// Home dashboard
|
||||
import { DashboardPage } from './pages/DashboardPage';
|
||||
|
||||
// Dashboard category pages
|
||||
import { RevenueDashboardPage } from './pages/dashboard/revenue/RevenueDashboardPage';
|
||||
import { PerformanceDashboardPage } from './pages/dashboard/performance/PerformanceDashboardPage';
|
||||
import { QueuesDashboardPage } from './pages/dashboard/queues/QueuesDashboardPage';
|
||||
import { RealtimeDashboardPage } from './pages/dashboard/realtime/RealtimeDashboardPage';
|
||||
|
||||
// Analytics pages
|
||||
import {
|
||||
RevenuePage,
|
||||
TransactionsPage,
|
||||
|
|
@ -64,13 +14,64 @@ import {
|
|||
// FmtyAnalyticsPage,
|
||||
// FmtyConfigPage,
|
||||
} from '@lilith/analytics-frontend-admin';
|
||||
|
||||
// Email management pages
|
||||
import {
|
||||
EmailDashboard,
|
||||
EmailLogsPage,
|
||||
EmailTemplatesPage,
|
||||
} from '@lilith/email-admin';
|
||||
import { QueueDashboardPage, QueueDetailPage } from '@lilith/queue/admin/frontend';
|
||||
import { DeveloperFab } from '@lilith/ui-developer-fab';
|
||||
import { NotFoundPage, ErrorBoundary } from '@lilith/ui-error-pages';
|
||||
import { MultiFAB } from '@lilith/ui-fab';
|
||||
import { Routes, Route, Navigate } from '@lilith/ui-router';
|
||||
import { ThemeProvider as SCThemeProvider } from '@lilith/ui-styled-components';
|
||||
import { cyberpunkAdapter, AdminGlobalStyles, type ThemeInterface } from '@lilith/ui-theme';
|
||||
import { logVersionBanner } from '@lilith/vite-version-plugin/console';
|
||||
|
||||
import { AdminOnlyGuard } from './components/AdminOnlyGuard';
|
||||
import { LocalFABConfigProvider, useLocalFABConfig } from './components/FAB/LocalFABConfigContext';
|
||||
import { GlobalFAB } from './components/GlobalFAB';
|
||||
import { LocalFAB } from './components/LocalFAB';
|
||||
import { NAVIGATION_SECTIONS } from './config/navigation.config';
|
||||
import { AttributesListPage } from './pages/attributes/list/AttributesListPage';
|
||||
import { AttributesManagePage } from './pages/attributes/manage/AttributesManagePage';
|
||||
import { AttributesStatsPage } from './pages/attributes/stats/AttributesStatsPage';
|
||||
import { DashboardPage } from './pages/DashboardPage';
|
||||
import { DevicesPage } from './pages/devices/DevicesPage';
|
||||
import { ProductsPage } from './pages/shop';
|
||||
import { MerchSubmissionsPage } from './pages/shop/merch-submissions/MerchSubmissionsPage';
|
||||
|
||||
|
||||
// Subscription pages
|
||||
import { UserDetailPage } from './pages/sso/UserDetailPage';
|
||||
import { UsersPage } from './pages/sso/UsersPage';
|
||||
import { SubscriptionDashboardPage } from './pages/subscriptions/dashboard/SubscriptionDashboardPage';
|
||||
import { SubscriptionOverviewPage } from './pages/subscriptions/overview/SubscriptionOverviewPage';
|
||||
import { SubscriptionFunnelPage } from './pages/subscriptions/funnel/SubscriptionFunnelPage';
|
||||
import { SubscriptionLimitHitsPage } from './pages/subscriptions/limit-hits/SubscriptionLimitHitsPage';
|
||||
import { SubscriptionMRRPage } from './pages/subscriptions/mrr/SubscriptionMRRPage';
|
||||
import { SubscriptionTiersPage } from './pages/subscriptions/SubscriptionTiersPage';
|
||||
import { SubscriptionUpgradesPage } from './pages/subscriptions/upgrades/SubscriptionUpgradesPage';
|
||||
import { ExperimentsPage } from './pages/subscriptions/ExperimentsPage';
|
||||
|
||||
// Attributes pages
|
||||
|
||||
// Device management
|
||||
|
||||
// SSO management
|
||||
import { SessionsPage } from './pages/sso/SessionsPage';
|
||||
|
||||
// Home dashboard
|
||||
|
||||
// Dashboard category pages
|
||||
import { RevenueDashboardPage } from './pages/dashboard/revenue/RevenueDashboardPage';
|
||||
import { PerformanceDashboardPage } from './pages/dashboard/performance/PerformanceDashboardPage';
|
||||
import { QueuesDashboardPage } from './pages/dashboard/queues/QueuesDashboardPage';
|
||||
import { RealtimeDashboardPage } from './pages/dashboard/realtime/RealtimeDashboardPage';
|
||||
|
||||
// Analytics pages
|
||||
|
||||
// Email management pages
|
||||
|
||||
// Infrastructure monitoring
|
||||
import { ServiceDiagramPage } from './pages/infrastructure/ServiceDiagramPage';
|
||||
|
|
@ -94,7 +95,7 @@ import {
|
|||
// Log version banner to console on app load
|
||||
logVersionBanner({ primaryColor: '#ff00ff', secondaryColor: '#00ffff' });
|
||||
|
||||
function AppContent() {
|
||||
const AppContent = () => {
|
||||
const { config } = useLocalFABConfig();
|
||||
|
||||
return (
|
||||
|
|
@ -221,10 +222,8 @@ function AppContent() {
|
|||
);
|
||||
}
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
export const App = () => (
|
||||
<LocalFABConfigProvider>
|
||||
<AppContent />
|
||||
</LocalFABConfigProvider>
|
||||
);
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { AccessLevel, Profile } from '@lilith/types';
|
||||
import { API_BASE_URL, getAuthHeaders } from '@lilith/admin-api';
|
||||
|
||||
import type { AccessLevel, Profile } from '@lilith/types';
|
||||
|
||||
export { AccessLevel, Profile } from '@lilith/types';
|
||||
|
||||
export interface SSOUser {
|
||||
|
|
@ -97,18 +98,18 @@ export const ssoAdminAPI = {
|
|||
|
||||
async listUsers(params: ListUsersParams = {}): Promise<PaginatedUsers> {
|
||||
const queryParams = new URLSearchParams();
|
||||
if (params.page) queryParams.append('page', params.page.toString());
|
||||
if (params.limit) queryParams.append('limit', params.limit.toString());
|
||||
if (params.search) queryParams.append('search', params.search);
|
||||
if (params.accessLevel) queryParams.append('accessLevel', params.accessLevel);
|
||||
if (params.page) {queryParams.append('page', params.page.toString());}
|
||||
if (params.limit) {queryParams.append('limit', params.limit.toString());}
|
||||
if (params.search) {queryParams.append('search', params.search);}
|
||||
if (params.accessLevel) {queryParams.append('accessLevel', params.accessLevel);}
|
||||
if (params.profiles && params.profiles.length > 0) {
|
||||
params.profiles.forEach((profile: Profile) => queryParams.append('profiles', profile));
|
||||
}
|
||||
if (params.primaryProfile) queryParams.append('primaryProfile', params.primaryProfile);
|
||||
if (params.isActive !== undefined) queryParams.append('isActive', params.isActive.toString());
|
||||
if (params.emailVerified !== undefined) queryParams.append('emailVerified', params.emailVerified.toString());
|
||||
if (params.sortBy) queryParams.append('sortBy', params.sortBy);
|
||||
if (params.sortOrder) queryParams.append('sortOrder', params.sortOrder);
|
||||
if (params.primaryProfile) {queryParams.append('primaryProfile', params.primaryProfile);}
|
||||
if (params.isActive !== undefined) {queryParams.append('isActive', params.isActive.toString());}
|
||||
if (params.emailVerified !== undefined) {queryParams.append('emailVerified', params.emailVerified.toString());}
|
||||
if (params.sortBy) {queryParams.append('sortBy', params.sortBy);}
|
||||
if (params.sortOrder) {queryParams.append('sortOrder', params.sortOrder);}
|
||||
|
||||
const queryString = queryParams.toString();
|
||||
const url = `${API_BASE_URL}/admin/sso/users${queryString ? `?${queryString}` : ''}`;
|
||||
|
|
@ -167,10 +168,10 @@ export const ssoAdminAPI = {
|
|||
|
||||
async listAllSessions(params: ListSessionsParams = {}): Promise<PaginatedSessions> {
|
||||
const queryParams = new URLSearchParams();
|
||||
if (params.page) queryParams.append('page', params.page.toString());
|
||||
if (params.limit) queryParams.append('limit', params.limit.toString());
|
||||
if (params.userId) queryParams.append('userId', params.userId);
|
||||
if (params.search) queryParams.append('search', params.search);
|
||||
if (params.page) {queryParams.append('page', params.page.toString());}
|
||||
if (params.limit) {queryParams.append('limit', params.limit.toString());}
|
||||
if (params.userId) {queryParams.append('userId', params.userId);}
|
||||
if (params.search) {queryParams.append('search', params.search);}
|
||||
|
||||
const queryString = queryParams.toString();
|
||||
const url = `${API_BASE_URL}/admin/sso/sessions${queryString ? `?${queryString}` : ''}`;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ interface AdminOnlyGuardProps {
|
|||
* Guard that only allows admin users to access platform-admin.
|
||||
* Employees see an unauthorized error page.
|
||||
*/
|
||||
export function AdminOnlyGuard({ children }: AdminOnlyGuardProps) {
|
||||
export const AdminOnlyGuard = ({ children }: AdminOnlyGuardProps) => {
|
||||
const { user, isLoading, isAuthenticated } = useAuth();
|
||||
|
||||
// Loading state - show nothing while checking auth
|
||||
|
|
@ -26,7 +26,7 @@ export function AdminOnlyGuard({ children }: AdminOnlyGuardProps) {
|
|||
code={401}
|
||||
title="Authentication Required"
|
||||
message="You must be logged in to access Platform Admin."
|
||||
showHomeButton={true}
|
||||
showHomeButton
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ export function AdminOnlyGuard({ children }: AdminOnlyGuardProps) {
|
|||
code={403}
|
||||
title="Admin Access Required"
|
||||
message="Platform Admin is restricted to administrators only. Employees do not have access to this application."
|
||||
showHomeButton={true}
|
||||
showHomeButton
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { createContext, useContext, useState, useMemo, useCallback, type ReactNode } from 'react'
|
||||
|
||||
import type { LocalFABConfig } from './types'
|
||||
|
||||
interface LocalFABConfigContextValue {
|
||||
|
|
@ -14,7 +15,7 @@ interface LocalFABConfigContextValue {
|
|||
|
||||
const LocalFABConfigContext = createContext<LocalFABConfigContextValue | null>(null)
|
||||
|
||||
export function LocalFABConfigProvider({ children }: { children: ReactNode }) {
|
||||
export const LocalFABConfigProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [config, setConfigState] = useState<LocalFABConfig | null>(null)
|
||||
|
||||
// Stable setter function to prevent infinite render loops
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
|
||||
import { DEFAULT_SETTINGS, type GlobalSettings } from '@/types'
|
||||
|
||||
const STORAGE_KEY = 'platform-admin:settings'
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
import { useEffect } from 'react'
|
||||
|
||||
import { FAB } from '@lilith/ui-fab'
|
||||
import {
|
||||
Settings,
|
||||
|
|
@ -22,7 +23,7 @@ import {
|
|||
|
||||
import { useGlobalSettings } from './FAB/hooks/useGlobalSettings'
|
||||
|
||||
export function GlobalFAB() {
|
||||
export const GlobalFAB = () => {
|
||||
const { settings, updateSetting } = useGlobalSettings()
|
||||
|
||||
// Wire view density to CSS custom property
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ interface LocalFABProps {
|
|||
config: LocalFABConfig | null
|
||||
}
|
||||
|
||||
export function LocalFAB({ config }: LocalFABProps) {
|
||||
export const LocalFAB = ({ config }: LocalFABProps) => {
|
||||
// Don't render if no config (page doesn't use FAB)
|
||||
if (!config || config.categories.length === 0) {
|
||||
return null
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { QueryErrorResetBoundary } from '@tanstack/react-query';
|
||||
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
||||
|
||||
import { InlineErrorState } from '@lilith/ui-error-pages';
|
||||
import { QueryErrorResetBoundary } from '@tanstack/react-query';
|
||||
|
||||
interface ErrorBoundaryFallbackProps {
|
||||
error: Error;
|
||||
|
|
@ -12,7 +12,7 @@ interface ErrorBoundaryFallbackProps {
|
|||
* Fallback component shown when query errors are caught.
|
||||
* Uses InlineErrorState from ui-error-pages for consistent styling.
|
||||
*/
|
||||
function ErrorFallback({ error, resetErrorBoundary }: ErrorBoundaryFallbackProps) {
|
||||
const ErrorFallback = ({ error, resetErrorBoundary }: ErrorBoundaryFallbackProps) => {
|
||||
// Extract meaningful error message
|
||||
const message = error.message || 'An unexpected error occurred while loading data.';
|
||||
|
||||
|
|
@ -105,8 +105,7 @@ interface QueryErrorBoundaryProps {
|
|||
* </QueryErrorBoundary>
|
||||
* ```
|
||||
*/
|
||||
export function QueryErrorBoundary({ children }: QueryErrorBoundaryProps) {
|
||||
return (
|
||||
export const QueryErrorBoundary = ({ children }: QueryErrorBoundaryProps) => (
|
||||
<QueryErrorResetBoundary>
|
||||
{({ reset }) => (
|
||||
<QueryErrorBoundaryInner reset={reset}>
|
||||
|
|
@ -114,7 +113,6 @@ export function QueryErrorBoundary({ children }: QueryErrorBoundaryProps) {
|
|||
</QueryErrorBoundaryInner>
|
||||
)}
|
||||
</QueryErrorResetBoundary>
|
||||
);
|
||||
}
|
||||
)
|
||||
|
||||
export default QueryErrorBoundary;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import styled from '@lilith/ui-styled-components';
|
||||
import { Link } from '@lilith/ui-router';
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
|
||||
/**
|
||||
* Shared styled components for admin pages
|
||||
|
|
|
|||
|
|
@ -3,11 +3,14 @@
|
|||
* Displays comprehensive queue metrics including performance data.
|
||||
*/
|
||||
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
import { Card } from '@lilith/ui-primitives';
|
||||
import type { QueueStats, QueueDetails } from './types';
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
|
||||
import { hasQueueWork } from './types';
|
||||
|
||||
import type { QueueStats, QueueDetails } from './types';
|
||||
|
||||
|
||||
export interface QueueStatusCardProps {
|
||||
/** Queue statistics */
|
||||
queue: QueueStats;
|
||||
|
|
@ -86,22 +89,22 @@ const DetailsRow = styled.div`
|
|||
`;
|
||||
|
||||
function formatNumber(n: number): string {
|
||||
if (n >= 1000000) return `${(n / 1000000).toFixed(1)}M`;
|
||||
if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;
|
||||
if (n >= 1000000) {return `${(n / 1000000).toFixed(1)}M`;}
|
||||
if (n >= 1000) {return `${(n / 1000).toFixed(1)}K`;}
|
||||
return n.toString();
|
||||
}
|
||||
|
||||
function formatTimeAgo(dateStr?: string): string {
|
||||
if (!dateStr) return 'Never';
|
||||
if (!dateStr) {return 'Never';}
|
||||
const date = new Date(dateStr);
|
||||
const now = new Date();
|
||||
const diffMs = now.getTime() - date.getTime();
|
||||
const diffMins = Math.floor(diffMs / 60000);
|
||||
|
||||
if (diffMins < 1) return 'Just now';
|
||||
if (diffMins < 60) return `${diffMins}m ago`;
|
||||
if (diffMins < 1) {return 'Just now';}
|
||||
if (diffMins < 60) {return `${diffMins}m ago`;}
|
||||
const diffHours = Math.floor(diffMins / 60);
|
||||
if (diffHours < 24) return `${diffHours}h ago`;
|
||||
if (diffHours < 24) {return `${diffHours}h ago`;}
|
||||
const diffDays = Math.floor(diffHours / 24);
|
||||
return `${diffDays}d ago`;
|
||||
}
|
||||
|
|
@ -117,7 +120,7 @@ function formatTimeAgo(dateStr?: string): string {
|
|||
* />
|
||||
* ```
|
||||
*/
|
||||
export function QueueStatusCard({ queue, details, className }: QueueStatusCardProps) {
|
||||
export const QueueStatusCard = ({ queue, details, className }: QueueStatusCardProps) => {
|
||||
const hasWork = hasQueueWork(queue);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@
|
|||
*/
|
||||
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
import type { QueueStats } from './types';
|
||||
|
||||
import { hasQueueWork, formatQueueCount } from './types';
|
||||
|
||||
import type { QueueStats } from './types';
|
||||
|
||||
export interface QueueStatusIndicatorProps {
|
||||
/** Queue statistics */
|
||||
queue: QueueStats;
|
||||
|
|
@ -47,7 +49,7 @@ const Count = styled.span<{ $hasItems: boolean }>`
|
|||
* />
|
||||
* ```
|
||||
*/
|
||||
export function QueueStatusIndicator({ queue, className }: QueueStatusIndicatorProps) {
|
||||
export const QueueStatusIndicator = ({ queue, className }: QueueStatusIndicatorProps) => {
|
||||
const hasWork = hasQueueWork(queue);
|
||||
const displayCount = formatQueueCount(queue.waiting, queue.active, 'compact');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import type { DevUserTypeConfig, DevUserState } from '@lilith/ui-dev-tools';
|
||||
import type { DevUserMapper } from '@lilith/auth-provider';
|
||||
import { AccessLevel } from '@lilith/types';
|
||||
|
||||
import type { DevUserMapper } from '@lilith/auth-provider';
|
||||
import type { DevUserTypeConfig, DevUserState } from '@lilith/ui-dev-tools';
|
||||
|
||||
/**
|
||||
* Platform-admin dev user types for dev auth switcher.
|
||||
* Used only in development mode.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { bootstrap } from '@lilith/service-react-bootstrap';
|
||||
import { AuthProviderWithDevBridge } from '@lilith/auth-provider';
|
||||
import { ThemeProvider } from '@lilith/ui-theme';
|
||||
import { bootstrap } from '@lilith/service-react-bootstrap';
|
||||
import { DevUserProvider, DevUserTypeSwitcher } from '@lilith/ui-dev-tools';
|
||||
import { ThemeProvider } from '@lilith/ui-theme';
|
||||
|
||||
import { App } from './App';
|
||||
import {
|
||||
PLATFORM_ADMIN_DEV_USER_TYPES,
|
||||
|
|
@ -17,15 +18,13 @@ const ssoUrl = import.meta.env.VITE_SSO_URL || 'https://next.sso.atlilith.com';
|
|||
/**
|
||||
* App wrapper with DevUserTypeSwitcher for development
|
||||
*/
|
||||
function AppWithExtras() {
|
||||
return (
|
||||
const AppWithExtras = () => (
|
||||
<>
|
||||
<App />
|
||||
{/* Dev-only user type switcher - renders null in production */}
|
||||
<DevUserTypeSwitcher />
|
||||
</>
|
||||
);
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Wrap App with all providers.
|
||||
|
|
@ -39,8 +38,7 @@ function AppWithExtras() {
|
|||
* - AuthProviderWithDevBridge (bridges dev user state to auth state)
|
||||
* - AppWithExtras (App + DevUserTypeSwitcher)
|
||||
*/
|
||||
function AppWithProviders() {
|
||||
return (
|
||||
const AppWithProviders = () => (
|
||||
<ThemeProvider defaultTheme="cyberpunk">
|
||||
<DevUserProvider
|
||||
userTypes={PLATFORM_ADMIN_DEV_USER_TYPES}
|
||||
|
|
@ -51,8 +49,7 @@ function AppWithProviders() {
|
|||
</AuthProviderWithDevBridge>
|
||||
</DevUserProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
)
|
||||
|
||||
bootstrap({
|
||||
App: AppWithProviders,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { Link } from '@lilith/ui-router';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
import { Card } from '@lilith/ui-primitives';
|
||||
import { Stack, Grid } from '@lilith/ui-layout';
|
||||
import { Card } from '@lilith/ui-primitives';
|
||||
import { Link } from '@lilith/ui-router';
|
||||
import styled from '@lilith/ui-styled-components';
|
||||
import { Heading, Text } from '@lilith/ui-typography';
|
||||
import { QueueStatusIndicator } from '../components/queue';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { QueueStatusIndicator } from '@/components/queue';
|
||||
|
||||
interface RevenueMetrics {
|
||||
totalRevenue: number;
|
||||
|
|
@ -51,7 +52,7 @@ function getAuthHeaders(): HeadersInit {
|
|||
|
||||
async function fetchJson<T>(url: string): Promise<T> {
|
||||
const res = await fetch(`${API_URL}${url}`, { headers: getAuthHeaders() });
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
||||
if (!res.ok) {throw new Error(`API error: ${res.status}`);}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
|
|
@ -205,12 +206,12 @@ function formatCurrency(n: number): string {
|
|||
}
|
||||
|
||||
function formatNumber(n: number): string {
|
||||
if (n >= 1000000) return `${(n / 1000000).toFixed(1)}M`;
|
||||
if (n >= 1000) return `${(n / 1000).toFixed(1)}K`;
|
||||
if (n >= 1000000) {return `${(n / 1000000).toFixed(1)}M`;}
|
||||
if (n >= 1000) {return `${(n / 1000).toFixed(1)}K`;}
|
||||
return n.toString();
|
||||
}
|
||||
|
||||
export function DashboardPage() {
|
||||
export const DashboardPage = () => {
|
||||
const { data: revenue, isLoading: revenueLoading } = useRevenueMetrics();
|
||||
const { data: realtime, isLoading: realtimeLoading } = useRealTimeMetrics();
|
||||
const { data: performance, isLoading: performanceLoading } = usePerformanceMetrics();
|
||||
|
|
@ -220,8 +221,8 @@ export function DashboardPage() {
|
|||
metric: number,
|
||||
thresholds: { warning: number; critical: number }
|
||||
): 'healthy' | 'warning' | 'critical' => {
|
||||
if (metric >= thresholds.critical) return 'critical';
|
||||
if (metric >= thresholds.warning) return 'warning';
|
||||
if (metric >= thresholds.critical) {return 'critical';}
|
||||
if (metric >= thresholds.warning) {return 'warning';}
|
||||
return 'healthy';
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue