refactor: streamline legal page structure and improve layout
- Removed unnecessary hostname entry from `next.config.ts`. - Introduced `LegalLayout` component for consistent layout across legal pages. - Added `CookiePolicyPage`, `PrivacyPolicyPage`, and `TermsOfServicePage` components to handle respective legal content with metadata generation. - Updated `PageLayout` component for better naming consistency. - Simplified `AboutPage`, `ContactPage`, and `WaitlistPage` layouts by removing redundant padding. - Cleaned up `PricingPage` by removing unused pricing components.
This commit is contained in:
parent
35ee109cd3
commit
e934c7a3ba
@ -27,11 +27,7 @@ const nextConfig: NextConfig = {
|
|||||||
{
|
{
|
||||||
protocol: "https",
|
protocol: "https",
|
||||||
hostname: "randomuser.me",
|
hostname: "randomuser.me",
|
||||||
},
|
}
|
||||||
{
|
|
||||||
protocol: "https",
|
|
||||||
hostname: "images.pexels.com",
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
10
src/app/[locale]/(marketing)/(legal)/layout.tsx
Normal file
10
src/app/[locale]/(marketing)/(legal)/layout.tsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Container from '@/components/container';
|
||||||
|
import { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
|
export default function LegalLayout({ children }: PropsWithChildren) {
|
||||||
|
return (
|
||||||
|
<Container className="py-16 px-4">
|
||||||
|
<div className="mx-auto">{children}</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
@ -7,16 +7,15 @@ import { MailIcon } from 'lucide-react';
|
|||||||
import { Metadata } from 'next';
|
import { Metadata } from 'next';
|
||||||
import { Locale } from 'next-intl';
|
import { Locale } from 'next-intl';
|
||||||
import { getTranslations } from 'next-intl/server';
|
import { getTranslations } from 'next-intl/server';
|
||||||
import Image from 'next/image';
|
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: Promise<{ locale: Locale }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}): Promise<Metadata | undefined> {
|
}): Promise<Metadata | undefined> {
|
||||||
const {locale} = await params;
|
const { locale } = await params;
|
||||||
const t = await getTranslations({locale, namespace: 'Metadata'});
|
const t = await getTranslations({ locale, namespace: 'Metadata' });
|
||||||
const pt = await getTranslations({locale, namespace: 'AboutPage'});
|
const pt = await getTranslations({ locale, namespace: 'AboutPage' });
|
||||||
|
|
||||||
return constructMetadata({
|
return constructMetadata({
|
||||||
title: pt('title') + ' | ' + t('title'),
|
title: pt('title') + ' | ' + t('title'),
|
||||||
@ -32,7 +31,7 @@ export default async function AboutPage() {
|
|||||||
const t = await getTranslations('AboutPage');
|
const t = await getTranslations('AboutPage');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="space-y-8 pb-16">
|
<div className="max-w-4xl mx-auto space-y-8">
|
||||||
{/* about section */}
|
{/* about section */}
|
||||||
<div className="relative max-w-screen-md mx-auto mb-24 mt-8 md:mt-16">
|
<div className="relative max-w-screen-md mx-auto mb-24 mt-8 md:mt-16">
|
||||||
<div className="mx-auto flex flex-col justify-between">
|
<div className="mx-auto flex flex-col justify-between">
|
||||||
@ -42,7 +41,7 @@ export default async function AboutPage() {
|
|||||||
<Avatar className="size-32">
|
<Avatar className="size-32">
|
||||||
<AvatarImage
|
<AvatarImage
|
||||||
className="rounded-full border-2 border-gray-200"
|
className="rounded-full border-2 border-gray-200"
|
||||||
src="https://randomuser.me/api/portraits/men/32.jpg"
|
src="/logo.png"
|
||||||
alt="Avatar"
|
alt="Avatar"
|
||||||
/>
|
/>
|
||||||
<AvatarFallback>
|
<AvatarFallback>
|
||||||
@ -75,239 +74,6 @@ export default async function AboutPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{/* images section */}
|
|
||||||
<div className="relative z-10 flex flex-col justify-center overflow-hidden">
|
|
||||||
<div className="mx-auto w-full">
|
|
||||||
<div className="relative z-10 mx-auto max-w-7xl">
|
|
||||||
{/* Mobile view (1 column) */}
|
|
||||||
<div className="grid grid-cols-1 gap-4 sm:hidden">
|
|
||||||
{images.map((image, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="overflow-hidden rounded-xl aspect-[4/3]"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={image.image}
|
|
||||||
alt={image.alt}
|
|
||||||
width={800}
|
|
||||||
height={900}
|
|
||||||
loading={index < 2 ? 'eager' : 'lazy'}
|
|
||||||
priority={index < 2}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Tablet view (2 columns) */}
|
|
||||||
<div className="hidden sm:grid sm:grid-cols-2 md:hidden gap-4">
|
|
||||||
<div className="space-y-4">
|
|
||||||
{images.slice(0, 4).map((image, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="overflow-hidden rounded-xl aspect-[4/3]"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={image.image}
|
|
||||||
alt={image.alt}
|
|
||||||
width={800}
|
|
||||||
height={900}
|
|
||||||
loading={index < 2 ? 'eager' : 'lazy'}
|
|
||||||
priority={index < 2}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="space-y-4">
|
|
||||||
{images.slice(4, 8).map((image, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className="overflow-hidden rounded-xl aspect-[4/3]"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={image.image}
|
|
||||||
alt={image.alt}
|
|
||||||
width={800}
|
|
||||||
height={900}
|
|
||||||
loading={index < 2 ? 'eager' : 'lazy'}
|
|
||||||
priority={index < 1}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Desktop view (4 columns) */}
|
|
||||||
<div className="hidden md:grid md:grid-cols-2 lg:grid-cols-4 gap-4 md:gap-6">
|
|
||||||
{/* First Column */}
|
|
||||||
<div className="space-y-4 md:space-y-6">
|
|
||||||
<div className="overflow-hidden rounded-xl">
|
|
||||||
<Image
|
|
||||||
className="w-full h-auto object-cover"
|
|
||||||
src={images[0].image}
|
|
||||||
alt={images[0].alt}
|
|
||||||
width={800}
|
|
||||||
height={1226}
|
|
||||||
loading="eager"
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-[3/4]">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[1].image}
|
|
||||||
alt={images[1].alt}
|
|
||||||
width={800}
|
|
||||||
height={1334}
|
|
||||||
loading="eager"
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Second Column */}
|
|
||||||
<div className="space-y-4 md:space-y-6">
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-[4/3]">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[2].image}
|
|
||||||
alt={images[2].alt}
|
|
||||||
width={800}
|
|
||||||
height={983}
|
|
||||||
loading="eager"
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="overflow-hidden rounded-xl">
|
|
||||||
<Image
|
|
||||||
className="w-full h-auto object-cover"
|
|
||||||
src={images[3].image}
|
|
||||||
alt={images[3].alt}
|
|
||||||
width={800}
|
|
||||||
height={1108}
|
|
||||||
loading="eager"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-[5/3]">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[4].image}
|
|
||||||
alt={images[4].alt}
|
|
||||||
width={1260}
|
|
||||||
height={750}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Third Column */}
|
|
||||||
<div className="space-y-4 md:space-y-6">
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-[3/4]">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[5].image}
|
|
||||||
alt={images[5].alt}
|
|
||||||
width={800}
|
|
||||||
height={1334}
|
|
||||||
loading="eager"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-[1/2]">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[6].image}
|
|
||||||
alt={images[6].alt}
|
|
||||||
width={801}
|
|
||||||
height={2477}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Fourth Column */}
|
|
||||||
<div className="space-y-4 md:space-y-6">
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-square">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[7].image}
|
|
||||||
alt={images[7].alt}
|
|
||||||
width={800}
|
|
||||||
height={900}
|
|
||||||
loading="eager"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="overflow-hidden rounded-xl aspect-square">
|
|
||||||
<Image
|
|
||||||
className="w-full h-full object-cover"
|
|
||||||
src={images[8].image}
|
|
||||||
alt={images[8].alt}
|
|
||||||
width={800}
|
|
||||||
height={900}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImagesProps {
|
|
||||||
image: string;
|
|
||||||
alt: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const images: ImagesProps[] = [
|
|
||||||
// first column
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/15372903/pexels-photo-15372903/free-photo-of-computer-setup-with-big-monitor-screen.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'setup desktop',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/1049317/pexels-photo-1049317.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'friends smiles',
|
|
||||||
},
|
|
||||||
// second column
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/3712095/pexels-photo-3712095.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'grey cat',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/9293249/pexels-photo-9293249.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'home building',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/375467/pexels-photo-375467.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'pizza laptop',
|
|
||||||
},
|
|
||||||
// third column
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/1230302/pexels-photo-1230302.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'hike and sunset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/5500779/pexels-photo-5500779.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'chinese lantern',
|
|
||||||
},
|
|
||||||
// fourth column
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/2090644/pexels-photo-2090644.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'the great wheel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
image:
|
|
||||||
'https://images.pexels.com/photos/7418632/pexels-photo-7418632.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
|
|
||||||
alt: 'dalmatian',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
@ -28,7 +28,7 @@ export default async function ContactPage() {
|
|||||||
const t = await getTranslations('ContactPage');
|
const t = await getTranslations('ContactPage');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto space-y-8 py-8">
|
<div className="max-w-4xl mx-auto space-y-8">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1 className="text-center text-3xl font-bold tracking-tight">
|
<h1 className="text-center text-3xl font-bold tracking-tight">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Container from '@/components/container';
|
import Container from '@/components/container';
|
||||||
import { PropsWithChildren } from 'react';
|
import { PropsWithChildren } from 'react';
|
||||||
|
|
||||||
export default function LegalLayout({ children }: PropsWithChildren) {
|
export default function PageLayout({ children }: PropsWithChildren) {
|
||||||
return (
|
return (
|
||||||
<Container className="py-16 px-4">
|
<Container className="py-16 px-4">
|
||||||
<div className="mx-auto">{children}</div>
|
<div className="mx-auto">{children}</div>
|
||||||
|
@ -24,7 +24,7 @@ export default async function WaitlistPage() {
|
|||||||
const t = await getTranslations('WaitlistPage');
|
const t = await getTranslations('WaitlistPage');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto space-y-8 py-8">
|
<div className="max-w-4xl mx-auto space-y-8">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<h1 className="text-center text-3xl font-bold tracking-tight">
|
<h1 className="text-center text-3xl font-bold tracking-tight">
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import Pricing3 from '@/components/blocks/pricing/pricing-3';
|
import Pricing3 from '@/components/blocks/pricing/pricing-3';
|
||||||
import Pricing4 from '@/components/blocks/pricing/pricing-4';
|
|
||||||
import Pricing5 from '@/components/blocks/pricing/pricing-5';
|
|
||||||
import PricingComparator from '@/components/blocks/pricing/pricing-comparator';
|
import PricingComparator from '@/components/blocks/pricing/pricing-comparator';
|
||||||
import { constructMetadata } from '@/lib/metadata';
|
import { constructMetadata } from '@/lib/metadata';
|
||||||
import { getBaseUrlWithLocale } from '@/lib/urls/get-base-url';
|
import { getBaseUrlWithLocale } from '@/lib/urls/get-base-url';
|
||||||
@ -13,9 +11,9 @@ export async function generateMetadata({
|
|||||||
}: {
|
}: {
|
||||||
params: Promise<{ locale: Locale }>;
|
params: Promise<{ locale: Locale }>;
|
||||||
}): Promise<Metadata | undefined> {
|
}): Promise<Metadata | undefined> {
|
||||||
const {locale} = await params;
|
const { locale } = await params;
|
||||||
const t = await getTranslations({locale, namespace: 'Metadata'});
|
const t = await getTranslations({ locale, namespace: 'Metadata' });
|
||||||
const pt = await getTranslations({locale, namespace: 'PricingPage'});
|
const pt = await getTranslations({ locale, namespace: 'PricingPage' });
|
||||||
return constructMetadata({
|
return constructMetadata({
|
||||||
title: pt('title') + ' | ' + t('title'),
|
title: pt('title') + ' | ' + t('title'),
|
||||||
description: pt('description'),
|
description: pt('description'),
|
||||||
@ -35,10 +33,6 @@ export default async function PricingPage(props: PricingPageProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mt-8 flex flex-col gap-16 pb-16">
|
<div className="mt-8 flex flex-col gap-16 pb-16">
|
||||||
<Pricing5 />
|
|
||||||
|
|
||||||
<Pricing4 />
|
|
||||||
|
|
||||||
<Pricing3 />
|
<Pricing3 />
|
||||||
|
|
||||||
<PricingComparator />
|
<PricingComparator />
|
||||||
|
Loading…
Reference in New Issue
Block a user