mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-30 07:38:12 +00:00
feat: add landing page copy and styles for English and Amharic versions
- Introduced `landing-copy.ts` containing text for the public landing page, supporting both English and Amharic languages. - Added `landing.css` for styling the landing page, ensuring scoped styles to prevent conflicts with other app styles. - Implemented smooth scrolling and animations for a better user experience.
This commit is contained in:
15
apps/portal/src/app/components/LandingRoute.tsx
Normal file
15
apps/portal/src/app/components/LandingRoute.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { LandingPage } from '@ema-platform/ui';
|
||||
import { authStorage } from '@ema-platform/auth';
|
||||
|
||||
/**
|
||||
* Public `/` — mounts the shared landing page with portal-specific routes.
|
||||
* Auth state is read the same way ProtectedRoute does (token cookie or
|
||||
* storage fallback) so the header can show "Go to dashboard" instead of
|
||||
* Login/Sign Up without gating the route itself.
|
||||
*/
|
||||
export function LandingRoute() {
|
||||
const token = authStorage.getToken() ?? Cookies.get('auth-token');
|
||||
|
||||
return <LandingPage primaryHref={token ? '/dashboard' : '/login'} signupHref="/signup" verifyHref="/verify" />;
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import { landingAm } from '@ema-platform/ui';
|
||||
import type { Translations } from './en';
|
||||
|
||||
export const am: Translations = {
|
||||
landing: landingAm,
|
||||
|
||||
app: {
|
||||
name: 'ኢባባ ፖርታል',
|
||||
authority: 'የኢትዮጵያ ባሕር ጉዳዮች ባለሥልጣን',
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { landingEn } from '@ema-platform/ui';
|
||||
|
||||
export const en = {
|
||||
landing: landingEn,
|
||||
|
||||
app: {
|
||||
name: 'EMA Portal',
|
||||
authority: 'Ethiopian Maritime Authority',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import { Provider } from 'react-redux';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { AuthBootstrap, AuthConfigProvider } from '@ema-platform/auth';
|
||||
import type { ReactNode } from 'react';
|
||||
import { store } from '../store';
|
||||
import { i18n } from '../i18n/config';
|
||||
import { MantineThemeProvider } from './MantineThemeProvider';
|
||||
import { ErrorBoundary } from '../components/ErrorBoundary';
|
||||
|
||||
@@ -26,9 +28,11 @@ export function AppProviders({ children }: { children: ReactNode }) {
|
||||
enableForgotPassword: true,
|
||||
}}
|
||||
>
|
||||
<MantineThemeProvider>
|
||||
<AuthBootstrap>{children}</AuthBootstrap>
|
||||
</MantineThemeProvider>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<MantineThemeProvider>
|
||||
<AuthBootstrap>{children}</AuthBootstrap>
|
||||
</MantineThemeProvider>
|
||||
</I18nextProvider>
|
||||
</AuthConfigProvider>
|
||||
</QueryClientProvider>
|
||||
</Provider>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { createBrowserRouter, Navigate } from "react-router-dom";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
import { i18n } from "./i18n/config";
|
||||
import { PortalLayout } from "./layouts/PortalLayout";
|
||||
import { ProtectedRoute } from "./components/ProtectedRoute";
|
||||
import { LandingRoute } from "./components/LandingRoute";
|
||||
|
||||
// Auth (standalone pages, no portal chrome)
|
||||
import {
|
||||
@@ -58,6 +57,9 @@ import { WaiverPage } from "./features/waiver/pages/WaiverPage";
|
||||
import { VesselRegistrationStatusPage } from "./features/vessel-registration/pages/VesselRegistrationStatusPage";
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
// Public landing page — institutional overview + role-based entry points.
|
||||
{ path: "/", element: <LandingRoute /> },
|
||||
|
||||
// Public auth pages
|
||||
{ path: "/login", element: <LoginPage /> },
|
||||
{ path: "/signup", element: <SignupPage /> },
|
||||
@@ -100,17 +102,14 @@ export const router = createBrowserRouter([
|
||||
{
|
||||
element: (
|
||||
<ProtectedRoute>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
{/* Asks what the applicant operates as before the rest of the
|
||||
portal, which is filtered by that answer. */}
|
||||
<RequireOperations>
|
||||
<PortalLayout />
|
||||
</RequireOperations>
|
||||
</I18nextProvider>
|
||||
{/* Asks what the applicant operates as before the rest of the
|
||||
portal, which is filtered by that answer. */}
|
||||
<RequireOperations>
|
||||
<PortalLayout />
|
||||
</RequireOperations>
|
||||
</ProtectedRoute>
|
||||
),
|
||||
children: [
|
||||
{ path: "/", element: <Navigate to="/dashboard" replace /> },
|
||||
{ path: "/dashboard", element: <DashboardPage /> },
|
||||
{ path: "/onboarding/operations", element: <OperationsOnboardingPage /> },
|
||||
|
||||
@@ -409,5 +408,7 @@ export const router = createBrowserRouter([
|
||||
element: <Navigate to="/vessel-ownership-transfer" replace />,
|
||||
},
|
||||
|
||||
{ path: "*", element: <Navigate to="/" replace /> },
|
||||
// A typo'd URL should not maroon a signed-in user on the marketing page —
|
||||
// ProtectedRoute sends anonymous visitors on to /login exactly as before.
|
||||
{ path: "*", element: <Navigate to="/dashboard" replace /> },
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user