Files
ridebus-website/modules/legal/legalPage.tsx
Zakhar Timoshenko 142ec97959 feat: add Open Graph image generation and SEO metadata
- Introduced `PageSeo` component for managing page metadata for social sharing.
- Created Open Graph image templates using SVG and static fonts for better visual representation.
- Implemented service alert management with functions to check active alerts and format route numbers.
- Added utility functions for generating and watching alert validity.
- Developed a script to generate Open Graph images dynamically based on page content.
- Included tests for service alert functionalities to ensure correctness and reliability.
2026-10-05 13:02:06 +03:00

89 lines
3.0 KiB
TypeScript

import { PageSeo } from '@/components/pageSeo/pageSeo';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { Footer } from '@/components/footer';
import { TopBar } from '@/components/topBar';
import { CursorEffect } from '@/components/cursor';
import LinkIcon from '@/assets/icons/link.svg';
import ThinStarBig from '@/assets/images/thin-star-big.svg';
import { Locales } from '@/utils/useLocale';
import {
legalCopy,
legalUpdatedAt,
LegalDocumentId,
supportEmail,
} from './content';
import styles from './legalPage.module.scss';
export function LegalPage({ documentId }: { documentId: LegalDocumentId }) {
const { locale } = useRouter();
const copy = legalCopy[(locale || 'en') as Locales];
const document = copy.documents[documentId];
const relatedId = documentId === 'privacy' ? 'terms' : 'privacy';
return (
<>
<PageSeo page={documentId} />
<header className={`${styles.header} ${styles[documentId]}`}>
<TopBar notHide />
<div className={styles.headerContent}>
<h1>{document.title}</h1>
<p>{document.description}</p>
<time dateTime={legalUpdatedAt}>{copy.updated}</time>
</div>
<span className={styles.star} aria-hidden="true">
<ThinStarBig />
</span>
</header>
<main className={styles.main}>
<nav className={styles.contents} aria-label={copy.contents}>
<h2>{copy.contents}</h2>
<ol>
{document.sections.map((section) => (
<li key={section.id}>
<a href={`#${section.id}`}>{section.title}</a>
</li>
))}
</ol>
</nav>
<article className={styles.document} aria-label={document.title}>
<p className={styles.introduction}>{document.introduction}</p>
{document.sections.map((section, index) => (
<section
key={section.id}
id={section.id}
className={styles.section}
>
<h2>
<span className={styles.sectionNumber}>
{String(index + 1).padStart(2, '0')}
</span>
{section.title}
</h2>
{section.paragraphs.map((paragraph) => (
<p key={paragraph}>{paragraph}</p>
))}
</section>
))}
<aside className={styles.contact}>
<h2>{copy.contactTitle}</h2>
<p>{copy.contactDescription}</p>
<a href={`mailto:${supportEmail}`}>{supportEmail}</a>
</aside>
<CursorEffect cursorPadding={6} cursorBorderRadius={16}>
<Link href={`/${relatedId}`} className={styles.relatedLink}>
{copy.documents[relatedId].title}
<LinkIcon
className={styles.relatedLinkIcon}
aria-hidden="true"
focusable="false"
/>
</Link>
</CursorEffect>
</article>
</main>
<Footer />
</>
);
}