Files
edr-platform/apps/edr-passenger-web/portal/src/app/layout.tsx

165 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { Metadata, Viewport } from 'next';
import { headers } from 'next/headers';
import './globals.css';
import { Providers } from './providers';
import AppSidebar from '@/components/AppSidebar';
import MobileTopBar from '@/components/MobileTopBar';
import BottomTabBar from '@/components/BottomTabBar';
import { LoadingIndicator } from '@/components/LoadingIndicator';
import SupportWidget from '@/features/support/SupportWidgetLazy';
import { JsonLd } from '@/components/JsonLd';
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://passenger.edrsc.com';
export const metadata: Metadata = {
metadataBase: new URL(siteUrl),
title: {
default: 'EDR Passenger Portal Book Train Tickets Online',
template: '%s | EDR Passenger Portal',
},
description:
'Book train tickets on the Ethio-Djibouti Railway. Travel between Ethiopia and Djibouti with easy online booking, seat selection, and multiple payment options.',
authors: [{ name: 'EDR Ethio-Djibouti Railway' }],
creator: 'EDR Ethio-Djibouti Railway',
publisher: 'EDR Ethio-Djibouti Railway',
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-snippet': -1,
'max-image-preview': 'large',
'max-video-preview': -1,
},
},
openGraph: {
type: 'website',
locale: 'en_US',
url: siteUrl,
siteName: 'EDR Passenger Portal',
title: 'EDR Passenger Portal Book Train Tickets Online',
description:
'Book train tickets on the Ethio-Djibouti Railway. Comfortable seats, flexible payment options, and easy online booking.',
images: [
{
url: '/edr-banner.jpg',
width: 1200,
height: 630,
alt: 'EDR Ethio-Djibouti Railway Book your train journey',
},
],
},
twitter: {
card: 'summary_large_image',
title: 'EDR Passenger Portal Book Train Tickets Online',
description:
'Book train tickets on the Ethio-Djibouti Railway. Comfortable seats, flexible payment options, and easy online booking.',
images: ['/edr-banner.jpg'],
},
icons: {
icon: '/edr-logo.png',
shortcut: '/edr-logo.png',
apple: '/edr-logo.png',
},
};
// viewportFit: 'cover' lets fixed bottom bars (e.g. the payment page's Pay
// button) read env(safe-area-inset-bottom) so they pad above the home
// indicator / gesture nav bar instead of being covered by it.
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
// Nonce set per-request by middleware; required for this inline script under the CSP.
const nonce = headers().get('x-nonce') ?? undefined;
const organizationSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Ethio-Djibouti Railway (EDR)',
url: siteUrl,
logo: `${siteUrl}/edr-logo.png`,
contactPoint: {
'@type': 'ContactPoint',
telephone: '9546',
contactType: 'customer service',
availableLanguage: ['English', 'Amharic'],
},
address: {
'@type': 'PostalAddress',
addressLocality: 'Addis Ababa',
addressCountry: 'ET',
},
sameAs: [],
};
const websiteSchema = {
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'EDR Passenger Portal',
url: siteUrl,
potentialAction: {
'@type': 'SearchAction',
target: {
'@type': 'EntryPoint',
urlTemplate: `${siteUrl}/booking/search?q={search_term_string}`,
},
'query-input': 'required name=search_term_string',
},
};
return (
<html lang="en" dir="ltr" suppressHydrationWarning>
<head>
<JsonLd data={organizationSchema} />
<JsonLd data={websiteSchema} />
</head>
<body className="font-sans antialiased">
<script
nonce={nonce}
dangerouslySetInnerHTML={{
__html: `
(function() {
try {
var theme = localStorage.getItem('theme');
var effectiveTheme = 'light';
if (theme === 'dark') {
effectiveTheme = 'dark';
} else if (theme === 'light') {
effectiveTheme = 'light';
} else if (theme === 'system' || !theme) {
effectiveTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
document.documentElement.classList.add(effectiveTheme);
} catch (e) {}
})();
`,
}}
/>
<Providers>
<LoadingIndicator />
<AppSidebar />
<div className="lg:pl-64 flex flex-col min-h-screen">
<MobileTopBar />
<main className="flex-1">
{children}
</main>
<BottomTabBar />
</div>
<SupportWidget />
</Providers>
</body>
</html>
);
}