- 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.
89 lines
3.0 KiB
TypeScript
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 />
|
|
</>
|
|
);
|
|
}
|