From f31e75c3def822c745cd713ff2fd49116b71fcf0 Mon Sep 17 00:00:00 2001 From: estifanos Date: Fri, 14 Aug 2026 11:35:34 +0000 Subject: [PATCH] feat: implement PageLoader component and register maritime loader as the default theme loader --- apps/backoffice/index.html | 67 +++++++++++++++++++ .../pages/SeafarerRegistryPage/index.tsx | 4 +- .../VesselRegistrationQueuePage/index.tsx | 2 +- .../app/providers/MantineThemeProvider.tsx | 7 +- apps/portal/index.html | 60 +++++++++++++++++ .../licensing/components/DocumentSlots.tsx | 2 +- .../licensing/components/StaffEvidence.tsx | 2 +- .../components/OperationsFormContent.tsx | 2 +- .../profile/components/ProfileFormContent.tsx | 7 +- .../seafarer/pages/MySeaRecordsPage/index.tsx | 2 +- .../app/providers/MantineThemeProvider.tsx | 7 +- .../auth/src/lib/components/AuthBootstrap.tsx | 3 +- libs/ui/src/index.ts | 3 + libs/ui/src/lib/components/MaritimeLoader.tsx | 30 +++------ libs/ui/src/lib/feedback/PageLoader.tsx | 26 +++++++ .../ui/src/lib/theme/maritime-loader-theme.ts | 31 +++++++++ 16 files changed, 219 insertions(+), 36 deletions(-) create mode 100644 libs/ui/src/lib/feedback/PageLoader.tsx create mode 100644 libs/ui/src/lib/theme/maritime-loader-theme.ts diff --git a/apps/backoffice/index.html b/apps/backoffice/index.html index 8d1d8072c..f473aea4c 100644 --- a/apps/backoffice/index.html +++ b/apps/backoffice/index.html @@ -6,9 +6,76 @@ EMA Backoffice + +
+ +
+ +
diff --git a/apps/backoffice/src/app/features/seafarer-registry/pages/SeafarerRegistryPage/index.tsx b/apps/backoffice/src/app/features/seafarer-registry/pages/SeafarerRegistryPage/index.tsx index c39f5c95f..34f6b3dab 100644 --- a/apps/backoffice/src/app/features/seafarer-registry/pages/SeafarerRegistryPage/index.tsx +++ b/apps/backoffice/src/app/features/seafarer-registry/pages/SeafarerRegistryPage/index.tsx @@ -137,7 +137,7 @@ function SeafarerDetailDrawer({ {loadingSea ? ( - + ) : (seaService ?? []).length === 0 ? ( {t('seafarerRegistry.drawer.noSeaService', 'No sea-service records.')} @@ -184,7 +184,7 @@ function SeafarerDetailDrawer({ {loadingMedical ? ( - + ) : (medical ?? []).length === 0 ? ( {t('seafarerRegistry.drawer.noMedical', 'No medical certificates.')} diff --git a/apps/backoffice/src/app/features/vessel-registration/pages/VesselRegistrationQueuePage/index.tsx b/apps/backoffice/src/app/features/vessel-registration/pages/VesselRegistrationQueuePage/index.tsx index 2df4cd9a6..f7a504651 100644 --- a/apps/backoffice/src/app/features/vessel-registration/pages/VesselRegistrationQueuePage/index.tsx +++ b/apps/backoffice/src/app/features/vessel-registration/pages/VesselRegistrationQueuePage/index.tsx @@ -109,7 +109,7 @@ function VesselDetailDrawer({ {loadingIncidents ? ( - + ) : (incidents ?? []).length === 0 ? ( No incidents recorded. diff --git a/apps/backoffice/src/app/providers/MantineThemeProvider.tsx b/apps/backoffice/src/app/providers/MantineThemeProvider.tsx index 54bd52447..b28c844c0 100644 --- a/apps/backoffice/src/app/providers/MantineThemeProvider.tsx +++ b/apps/backoffice/src/app/providers/MantineThemeProvider.tsx @@ -1,11 +1,14 @@ -import { MantineProvider } from '@mantine/core'; +import { MantineProvider, mergeThemeOverrides } from '@mantine/core'; import { Notifications } from '@mantine/notifications'; import { emaTheme } from '@ema-platform/shared'; +import { maritimeLoaderTheme } from '@ema-platform/ui'; import type { ReactNode } from 'react'; +const theme = mergeThemeOverrides(emaTheme, maritimeLoaderTheme); + export function MantineThemeProvider({ children }: { children: ReactNode }) { return ( - + {children} diff --git a/apps/portal/index.html b/apps/portal/index.html index aaa28d481..66a56efb0 100644 --- a/apps/portal/index.html +++ b/apps/portal/index.html @@ -13,9 +13,69 @@ document.documentElement.setAttribute('data-mantine-color-scheme', s); } catch (e) {} +
+ +
+ +
diff --git a/apps/portal/src/app/features/licensing/components/DocumentSlots.tsx b/apps/portal/src/app/features/licensing/components/DocumentSlots.tsx index 2f28c6635..85a36d046 100644 --- a/apps/portal/src/app/features/licensing/components/DocumentSlots.tsx +++ b/apps/portal/src/app/features/licensing/components/DocumentSlots.tsx @@ -175,7 +175,7 @@ export function DocumentSlots({ variant={uploaded ? 'light' : 'filled'} leftSection={ busy === requirement.key ? ( - + ) : ( ) diff --git a/apps/portal/src/app/features/licensing/components/StaffEvidence.tsx b/apps/portal/src/app/features/licensing/components/StaffEvidence.tsx index 8ef08a415..672b1cf73 100644 --- a/apps/portal/src/app/features/licensing/components/StaffEvidence.tsx +++ b/apps/portal/src/app/features/licensing/components/StaffEvidence.tsx @@ -74,7 +74,7 @@ export function StaffEvidence({ staffId, evidence, readOnly, onUploaded }: Props disabled={readOnly || busy === item.docKey} leftSection={ busy === item.docKey ? ( - + ) : uploaded ? ( ) : undefined diff --git a/apps/portal/src/app/features/profile/components/OperationsFormContent.tsx b/apps/portal/src/app/features/profile/components/OperationsFormContent.tsx index 75699d5fb..63247b262 100644 --- a/apps/portal/src/app/features/profile/components/OperationsFormContent.tsx +++ b/apps/portal/src/app/features/profile/components/OperationsFormContent.tsx @@ -92,7 +92,7 @@ export function OperationsFormContent({ } if (loadingTypes || loadingMine) { - return ; + return ; } const removedNames = options diff --git a/apps/portal/src/app/features/profile/components/ProfileFormContent.tsx b/apps/portal/src/app/features/profile/components/ProfileFormContent.tsx index 41323e747..4540554a9 100644 --- a/apps/portal/src/app/features/profile/components/ProfileFormContent.tsx +++ b/apps/portal/src/app/features/profile/components/ProfileFormContent.tsx @@ -1,6 +1,7 @@ import { Loader, Select, SimpleGrid, TextInput } from '@mantine/core'; import type { FieldErrors, UseFormRegister, UseFormSetValue, UseFormWatch, UseFormTrigger } from 'react-hook-form'; import { z } from 'zod'; +import { useTranslation } from 'react-i18next'; import { AmharicDatePicker } from '@ema-platform/ui'; export const profileSchema = z.object({ @@ -39,11 +40,13 @@ export function ProfileFormContent({ professionsLoading, professionOptions, }: ProfileFormContentProps) { + const { t } = useTranslation(); + return (