initial commit
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import type {Metadata} from 'next';
|
||||
import {DemoBrowser} from '@/components/DemoBrowser';
|
||||
import {SectionHeader} from '@/components/SectionHeader';
|
||||
import {demoContent} from '@/config/content';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Dema konfiguratorów 3D | Ultifide',
|
||||
description: 'Lista interaktywnych dem konfiguratorów 3D Ultifide z podglądem biurka, wnętrz i drzwi.'
|
||||
};
|
||||
|
||||
export default function DemosPage() {
|
||||
const demos = [demoContent.desk, demoContent.room, demoContent.door];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<section className="sectionBand sectionBand--light demosPage">
|
||||
<div className="container demosContainer">
|
||||
<SectionHeader
|
||||
eyebrow="Dema konfiguratorów"
|
||||
title="Sprawdź konfiguratory 3D w jednym miejscu"
|
||||
description="Wybierz demo z listy, przetestuj je od razu w podglądzie, a potem przejdź do strony z opisem zastosowania i korzyści."
|
||||
/>
|
||||
<DemoBrowser demos={demos} />
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type {Metadata} from 'next';
|
||||
import {DemoPage} from '@/components/DemoPage';
|
||||
import {demoContent} from '@/config/content';
|
||||
import messages from '../../../../messages/pl.json';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: messages.metadata.doorTitle,
|
||||
description:
|
||||
'Poznaj konfigurator 3D drzwi, który pozwala klientom dobrać model, kolor, przeszklenie, klamkę i detale w czasie rzeczywistym.'
|
||||
};
|
||||
|
||||
export default function DoorDemoPage() {
|
||||
return <DemoPage demo={demoContent.door} />;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type {Metadata} from 'next';
|
||||
import {DemoPage} from '@/components/DemoPage';
|
||||
import {demoContent} from '@/config/content';
|
||||
import messages from '../../../../messages/pl.json';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: messages.metadata.roomTitle,
|
||||
description:
|
||||
'Poznaj konfigurator 3D, który pozwala klientom projektować całe pomieszczenia i zestawy mebli w czasie rzeczywistym.'
|
||||
};
|
||||
|
||||
export default function RoomDemoPage() {
|
||||
return <DemoPage demo={demoContent.room} />;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import type {Metadata} from 'next';
|
||||
import {DemoPage} from '@/components/DemoPage';
|
||||
import {demoContent} from '@/config/content';
|
||||
import messages from '../../../../messages/pl.json';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: messages.metadata.deskTitle,
|
||||
description:
|
||||
'Poznaj konfigurator 3D, który zwiększa konwersję i pozwala klientom tworzyć własne biurka regulowane w czasie rzeczywistym.'
|
||||
};
|
||||
|
||||
export default function DeskDemoPage() {
|
||||
return <DemoPage demo={demoContent.desk} />;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import type {Metadata} from 'next';
|
||||
import {Poppins} from 'next/font/google';
|
||||
import {NextIntlClientProvider} from 'next-intl';
|
||||
import {getMessages} from 'next-intl/server';
|
||||
import {notFound} from 'next/navigation';
|
||||
import {Footer} from '@/components/Footer';
|
||||
import {Header} from '@/components/Header';
|
||||
import {routing} from '@/i18n/routing';
|
||||
|
||||
type LocaleLayoutProps = {
|
||||
children: React.ReactNode;
|
||||
params: Promise<{locale: string}>;
|
||||
};
|
||||
|
||||
const poppins = Poppins({
|
||||
subsets: ['latin', 'latin-ext'],
|
||||
weight: ['400', '600', '700'],
|
||||
display: 'swap'
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
default: 'Konfiguratory 3D | Ultifide',
|
||||
template: '%s'
|
||||
}
|
||||
};
|
||||
|
||||
export function generateStaticParams() {
|
||||
return routing.locales.map(locale => ({locale}));
|
||||
}
|
||||
|
||||
export default async function LocaleLayout({children, params}: LocaleLayoutProps) {
|
||||
const {locale} = await params;
|
||||
|
||||
if (!routing.locales.includes(locale as never)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const messages = await getMessages();
|
||||
|
||||
return (
|
||||
<html lang={locale}>
|
||||
<body className={poppins.className}>
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<Header />
|
||||
{children}
|
||||
<Footer />
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
import {ArrowRight, Box, CheckCircle2, DoorOpen, Layers3, Plug, Settings2, ShoppingCart, Workflow} from 'lucide-react';
|
||||
import type {Metadata} from 'next';
|
||||
import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import {ButtonLink} from '@/components/ButtonLink';
|
||||
import {Faq} from '@/components/Faq';
|
||||
import {HeroVisual} from '@/components/HeroVisual';
|
||||
import {SectionHeader} from '@/components/SectionHeader';
|
||||
import {Stats} from '@/components/Stats';
|
||||
import {contact} from '@/config/contact';
|
||||
import {demoContent, homeContent, marketingFaq} from '@/config/content';
|
||||
import messages from '../../../messages/pl.json';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: messages.metadata.homeTitle,
|
||||
description: messages.metadata.homeDescription
|
||||
};
|
||||
|
||||
const platformIcons = [Settings2, Workflow, Plug, ShoppingCart];
|
||||
const industryIcons = [Box, Layers3, CheckCircle2];
|
||||
|
||||
export default function HomePage() {
|
||||
const demos = [demoContent.desk, demoContent.room, demoContent.door];
|
||||
|
||||
return (
|
||||
<main>
|
||||
<section className="hero sectionBand sectionBand--light">
|
||||
<div className="container hero__grid">
|
||||
<div className="hero__content">
|
||||
<p className="eyebrow">{homeContent.hero.eyebrow}</p>
|
||||
<h1>{homeContent.hero.title}</h1>
|
||||
<p>{homeContent.hero.description}</p>
|
||||
<div className="buttonRow">
|
||||
<ButtonLink href="/pl/dema">{homeContent.hero.primaryCta}</ButtonLink>
|
||||
<ButtonLink href={contact.url} variant="secondary" isExternal>
|
||||
{homeContent.hero.secondaryCta}
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</div>
|
||||
<HeroVisual />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="sectionBand statsBand">
|
||||
<div className="container">
|
||||
<Stats stats={homeContent.stats} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="dema" className="sectionBand">
|
||||
<div className="container">
|
||||
<SectionHeader title={homeContent.demosTitle} description={homeContent.demosDescription} />
|
||||
<div className="demoCards">
|
||||
{demos.map(demo => (
|
||||
<article className="demoCard" key={demo.slug}>
|
||||
{demo.imageUrl ? (
|
||||
<Image src={demo.imageUrl} alt="" width={420} height={420} />
|
||||
) : (
|
||||
<div className="demoCard__visual" aria-hidden="true">
|
||||
<DoorOpen size={72} />
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<p className="eyebrow">{demo.eyebrow}</p>
|
||||
<h3>{demo.title}</h3>
|
||||
<p>{demo.intro}</p>
|
||||
<Link href={`/pl/dema?demo=${demo.slug}`}>
|
||||
{demo.openLabel}
|
||||
<ArrowRight size={18} />
|
||||
</Link>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="platforma" className="sectionBand sectionBand--tint">
|
||||
<div className="container splitSection">
|
||||
<SectionHeader title={homeContent.benefitsTitle} description={homeContent.benefitsDescription} />
|
||||
<div className="featureGrid">
|
||||
{homeContent.benefits.map((item, index) => {
|
||||
const Icon = platformIcons[index];
|
||||
return (
|
||||
<article className="featureItem" key={item.title}>
|
||||
<Icon size={24} />
|
||||
<h3>{item.title}</h3>
|
||||
<p>{item.description}</p>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="sectionBand">
|
||||
<div className="container">
|
||||
<SectionHeader title={homeContent.industriesTitle} />
|
||||
<div className="featureGrid featureGrid--three">
|
||||
{homeContent.industries.map((item, index) => {
|
||||
const Icon = industryIcons[index];
|
||||
return (
|
||||
<article className="featureItem" key={item.title}>
|
||||
<Icon size={24} />
|
||||
<h3>{item.title}</h3>
|
||||
<p>{item.description}</p>
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="funkcje" className="sectionBand sectionBand--dark">
|
||||
<div className="container splitSection splitSection--dark">
|
||||
<SectionHeader title={homeContent.featuresTitle} />
|
||||
<ul className="checkList">
|
||||
{homeContent.features.map(feature => (
|
||||
<li key={feature}>
|
||||
<CheckCircle2 size={20} />
|
||||
{feature}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="sectionBand">
|
||||
<div className="container">
|
||||
<SectionHeader title={homeContent.processTitle} />
|
||||
<div className="processGrid">
|
||||
{homeContent.process.map((item, index) => (
|
||||
<article key={item.title}>
|
||||
<span>{index + 1}</span>
|
||||
<h3>{item.title}</h3>
|
||||
<p>{item.description}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="faq" className="sectionBand sectionBand--tint">
|
||||
<div className="container narrow">
|
||||
<SectionHeader title="FAQ" />
|
||||
<Faq items={marketingFaq} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="sectionBand">
|
||||
<div className="container finalCta">
|
||||
<h2>{homeContent.finalCta.title}</h2>
|
||||
<p>{homeContent.finalCta.description}</p>
|
||||
<ButtonLink href={contact.url} isExternal>
|
||||
{homeContent.finalCta.button}
|
||||
</ButtonLink>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,12 @@
|
||||
import type {Metadata} from 'next';
|
||||
import './globals.scss';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL('https://ultifide.com'),
|
||||
title: 'Konfiguratory 3D | Ultifide',
|
||||
description: 'Konfiguratory 3D dla produktów, wnętrz i sprzedaży B2B.'
|
||||
};
|
||||
|
||||
export default function RootLayout({children}: Readonly<{children: React.ReactNode}>) {
|
||||
return children;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function NotFound() {
|
||||
return (
|
||||
<main className="notFound">
|
||||
<h1>Nie znaleziono strony</h1>
|
||||
<Link className="button button--primary" href="/pl">
|
||||
Wróć do strony głównej
|
||||
</Link>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import {redirect} from 'next/navigation';
|
||||
|
||||
export default function RootPage() {
|
||||
redirect('/pl');
|
||||
}
|
||||
Reference in New Issue
Block a user