452 lines
14 KiB
TypeScript
452 lines
14 KiB
TypeScript
import Header from "@/components/Header";
|
||
import Footer from "@/components/Footer";
|
||
import ProducerCard from "@/components/ProducerCard";
|
||
import {
|
||
aboutBullets,
|
||
featuredCategories,
|
||
featuredProducers,
|
||
type Producer,
|
||
} from "@/data/home";
|
||
import {
|
||
getWebsiteHomeMedia,
|
||
type WebsiteMediaItem,
|
||
} from "@/lib/website-media";
|
||
import {
|
||
carouselBusinessToProducer,
|
||
getWebsiteCarousels,
|
||
type WebsiteCarousel,
|
||
} from "@/lib/website-carousels";
|
||
import styles from "./home.module.css";
|
||
|
||
function SectionHeading({
|
||
title,
|
||
subtitle,
|
||
exploreHref,
|
||
}: {
|
||
title: string;
|
||
subtitle?: string;
|
||
exploreHref: string;
|
||
}) {
|
||
return (
|
||
<div className={styles.sectionHead}>
|
||
<div className={styles.arrows}>
|
||
<button
|
||
className={`tile-hover ${styles.arrowBtn}`}
|
||
type="button"
|
||
aria-label="Previous"
|
||
>
|
||
<img
|
||
className={styles.arrowPrev}
|
||
src="/images/icons/chevron.svg"
|
||
alt=""
|
||
width={8}
|
||
height={14}
|
||
/>
|
||
</button>
|
||
<button
|
||
className={`tile-hover ${styles.arrowBtn}`}
|
||
type="button"
|
||
aria-label="Next"
|
||
>
|
||
<img src="/images/icons/chevron.svg" alt="" width={8} height={14} />
|
||
</button>
|
||
</div>
|
||
<div className={styles.sectionTitles}>
|
||
<h2 className={styles.sectionTitle}>{title}</h2>
|
||
<p className={styles.sectionSubtitle}>
|
||
{subtitle || "some of our most crowded categories"}
|
||
</p>
|
||
</div>
|
||
<a className={`tile-hover ${styles.explore}`} href={exploreHref}>
|
||
Explore all
|
||
<img src="/images/icons/menu.svg" alt="" width={22} height={22} />
|
||
</a>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
function BusinessCarouselSection({
|
||
carousel,
|
||
fallbackProducers,
|
||
}: {
|
||
carousel?: WebsiteCarousel;
|
||
fallbackProducers?: Producer[];
|
||
}) {
|
||
if (!carousel) return null;
|
||
|
||
const producers =
|
||
carousel.businesses.length > 0
|
||
? carousel.businesses.map(carouselBusinessToProducer)
|
||
: (fallbackProducers ?? []);
|
||
|
||
if (!producers.length) return null;
|
||
|
||
return (
|
||
<section
|
||
className={`${styles.section} ${styles.carousel}`}
|
||
id={carousel.slug || carousel.id}
|
||
>
|
||
<SectionHeading
|
||
title={carousel.title}
|
||
subtitle={carousel.subtext || undefined}
|
||
exploreHref="/businesses"
|
||
/>
|
||
<div className={styles.producerGrid}>
|
||
{producers.map((producer) => (
|
||
<ProducerCard
|
||
key={`${carousel.id}-${producer.slug}`}
|
||
producer={producer}
|
||
/>
|
||
))}
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|
||
|
||
function TitleLines({ text }: { text: string }) {
|
||
const lines = text.includes("\n")
|
||
? text.split("\n")
|
||
: (() => {
|
||
const parts = text.trim().split(/\s+/);
|
||
if (parts.length <= 1) return [text];
|
||
return [parts[0], parts.slice(1).join(" ")];
|
||
})();
|
||
|
||
return (
|
||
<>
|
||
{lines.map((line, index) => (
|
||
<span key={`${line}-${index}`}>
|
||
{index > 0 ? <br /> : null}
|
||
{line}
|
||
</span>
|
||
))}
|
||
</>
|
||
);
|
||
}
|
||
|
||
function fallbackMedia() {
|
||
return {
|
||
slider: [
|
||
{
|
||
id: "slider-1",
|
||
imageUrl: "/images/hero/furniture.png",
|
||
linkUrl: "#producers",
|
||
title: "Iranian modern art",
|
||
cta: "browse furniture producers",
|
||
},
|
||
] satisfies WebsiteMediaItem[],
|
||
standingBanners: [
|
||
{
|
||
id: "standing-1",
|
||
imageUrl: "/images/hero/ice-cream.png",
|
||
linkUrl: "#producers",
|
||
title: "food industry",
|
||
cta: "browse producers",
|
||
},
|
||
{
|
||
id: "standing-2",
|
||
imageUrl: "/images/hero/rug.png",
|
||
linkUrl: "#producers",
|
||
title: "original & pure art",
|
||
cta: "browse producers",
|
||
},
|
||
] satisfies WebsiteMediaItem[],
|
||
categories: featuredCategories.map((category, index) => ({
|
||
id: `cat-${index + 1}`,
|
||
imageUrl: category.image,
|
||
linkUrl: "#producers",
|
||
title: category.title,
|
||
subtitle: category.description,
|
||
})),
|
||
menuImages: [],
|
||
aboutUs: {
|
||
id: "about-1",
|
||
imageUrl: "/images/banners/ship.png",
|
||
linkUrl: "/about",
|
||
} satisfies WebsiteMediaItem,
|
||
banners: [
|
||
{
|
||
id: "banner-1",
|
||
imageUrl: "/images/banners/tv.png",
|
||
linkUrl: "#producers",
|
||
title: "Iranian modern art",
|
||
cta: "browse furniture producers",
|
||
},
|
||
{
|
||
id: "banner-2",
|
||
imageUrl: "/images/banners/pistachio.png",
|
||
linkUrl: "#producers",
|
||
title: "food industry",
|
||
cta: "browse producers",
|
||
},
|
||
{
|
||
id: "banner-3",
|
||
imageUrl: "/images/banners/shampoo.png",
|
||
linkUrl: "#producers",
|
||
title: "food industry",
|
||
cta: "browse producers",
|
||
},
|
||
{
|
||
id: "banner-4",
|
||
imageUrl: "/images/banners/saffron.png",
|
||
linkUrl: "#producers",
|
||
title: "original & pure art",
|
||
cta: "browse producers",
|
||
},
|
||
{
|
||
id: "banner-5",
|
||
imageUrl: "/images/banners/plane.png",
|
||
linkUrl: "/register",
|
||
title: "let's export",
|
||
cta: "begin",
|
||
},
|
||
] satisfies WebsiteMediaItem[],
|
||
};
|
||
}
|
||
|
||
export default async function Home() {
|
||
const [mediaResult, carousels] = await Promise.all([
|
||
getWebsiteHomeMedia(),
|
||
getWebsiteCarousels(),
|
||
]);
|
||
const media = mediaResult ?? fallbackMedia();
|
||
const slide = media.slider[0];
|
||
const standing = media.standingBanners;
|
||
const collectionBanners = media.banners.slice(0, 4);
|
||
const exportBanner =
|
||
media.banners[4] ?? media.banners[media.banners.length - 1];
|
||
|
||
const [firstCarousel, secondCarousel, ...restCarousels] = carousels;
|
||
|
||
return (
|
||
<div className={styles.page} id="top">
|
||
<Header />
|
||
|
||
<main>
|
||
<section className={styles.section} aria-label="Featured collections">
|
||
<div className={styles.hero}>
|
||
<article className={`tile-hover ${styles.heroCard} ${styles.heroMain}`}>
|
||
<button
|
||
className={`${styles.heroNav} ${styles.heroPrev}`}
|
||
type="button"
|
||
aria-label="Previous slide"
|
||
>
|
||
<img src="/images/icons/chevron.svg" alt="" width={11} height={22} />
|
||
</button>
|
||
<div className={styles.heroCopy}>
|
||
<h1 className={styles.heroTitle}>
|
||
<TitleLines text={slide?.title || "Iranian modern art"} />
|
||
</h1>
|
||
<a
|
||
className={`outline-btn ${styles.heroBtn}`}
|
||
href={slide?.linkUrl || "#producers"}
|
||
>
|
||
{slide?.cta || "browse furniture producers"}
|
||
</a>
|
||
</div>
|
||
<img
|
||
className={`${styles.heroImage} ${styles.heroFurniture}`}
|
||
src={slide?.imageUrl || "/images/hero/furniture.png"}
|
||
alt={slide?.title || "Iranian modern furniture"}
|
||
/>
|
||
<button
|
||
className={`${styles.heroNav} ${styles.heroNext}`}
|
||
type="button"
|
||
aria-label="Next slide"
|
||
>
|
||
<img src="/images/icons/chevron.svg" alt="" width={11} height={22} />
|
||
</button>
|
||
</article>
|
||
|
||
{standing.slice(0, 2).map((banner, index) => (
|
||
<article key={banner.id} className={`tile-hover ${styles.heroCard}`}>
|
||
<img
|
||
className={`${styles.heroImage} ${
|
||
index === 0 ? styles.heroIceCream : styles.heroRug
|
||
}`}
|
||
src={banner.imageUrl}
|
||
alt={banner.title || ""}
|
||
/>
|
||
<h2 className={`${styles.heroTitle} ${styles.heroTitleSmall}`}>
|
||
<TitleLines text={banner.title || "Browse"} />
|
||
</h2>
|
||
<a
|
||
className={`outline-btn ${styles.heroBtnSmall}`}
|
||
href={banner.linkUrl || "#producers"}
|
||
>
|
||
{banner.cta || "browse producers"}
|
||
</a>
|
||
</article>
|
||
))}
|
||
</div>
|
||
</section>
|
||
|
||
<section className={styles.section} id="join">
|
||
<a href="/register" className={`tile-hover ${styles.join}`}>
|
||
<img
|
||
className={styles.joinIcon}
|
||
src="/images/icons/join-add.svg"
|
||
alt=""
|
||
width={62}
|
||
height={62}
|
||
/>
|
||
<span className={styles.joinCopy}>
|
||
<span className={styles.joinTitle}>Join our club</span>
|
||
<span className={styles.joinText}>
|
||
we will show your business to verity
|
||
<br />
|
||
of visitor around the world
|
||
</span>
|
||
</span>
|
||
</a>
|
||
</section>
|
||
|
||
<section className={`${styles.section} ${styles.container}`} id="categories">
|
||
<div className={styles.sectionHeadCentered}>
|
||
<h2 className={styles.sectionTitle}>Featured categories</h2>
|
||
<p className={styles.sectionSubtitle}>
|
||
some of our most crowded categories
|
||
</p>
|
||
</div>
|
||
<div className={styles.categoryGrid}>
|
||
{media.categories.map((category) => (
|
||
<a
|
||
key={category.id}
|
||
href={category.linkUrl || "#producers"}
|
||
className={styles.categoryCard}
|
||
>
|
||
<div className={`tile-hover ${styles.categoryStage}`}>
|
||
<img
|
||
className={styles.categoryImage}
|
||
src={category.imageUrl}
|
||
alt=""
|
||
/>
|
||
<h3 className={styles.categoryTitle}>
|
||
{category.title || "Category"}
|
||
</h3>
|
||
<p className={styles.categoryCopy}>
|
||
{category.subtitle || ""}
|
||
</p>
|
||
</div>
|
||
</a>
|
||
))}
|
||
</div>
|
||
</section>
|
||
|
||
<BusinessCarouselSection
|
||
carousel={firstCarousel}
|
||
fallbackProducers={featuredProducers}
|
||
/>
|
||
|
||
<section className={`${styles.section} ${styles.container}`} id="about">
|
||
<div className={styles.about}>
|
||
<div>
|
||
<h2 className={styles.aboutKicker}>
|
||
IranBay<span>,</span>
|
||
</h2>
|
||
<p className={styles.aboutLead}>
|
||
We are a gate to iran’s market place
|
||
</p>
|
||
<p className={styles.aboutBody}>
|
||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
|
||
enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
||
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
|
||
reprehenderit in voluptate velit esse cillum dolore eu fugiat
|
||
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
|
||
sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||
</p>
|
||
<ul className={styles.aboutList}>
|
||
{aboutBullets.map((item, index) => (
|
||
<li key={`${item}-${index}`}>
|
||
<img src="/images/icons/bullet.svg" alt="" width={11} height={11} />
|
||
<span>{item}</span>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
<a
|
||
className={`outline-btn ${styles.aboutBtn}`}
|
||
href={media.aboutUs.linkUrl || "/about"}
|
||
>
|
||
know more about us
|
||
</a>
|
||
</div>
|
||
<div className={styles.aboutVisual}>
|
||
<div className={styles.aboutFrame} />
|
||
<img
|
||
className={styles.aboutShip}
|
||
src={media.aboutUs.imageUrl}
|
||
alt="Cargo ship entering the market"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<BusinessCarouselSection
|
||
carousel={secondCarousel}
|
||
fallbackProducers={featuredProducers}
|
||
/>
|
||
|
||
<section className={`${styles.section} ${styles.bannerBlock}`} aria-label="Browse collections">
|
||
<div className={styles.bannerRow}>
|
||
{collectionBanners.map((banner, index) => (
|
||
<article
|
||
key={banner.id}
|
||
className={`tile-hover ${styles.bannerCard} ${
|
||
index === 0 ? styles.bannerWide : ""
|
||
}`}
|
||
>
|
||
<img
|
||
className={styles.bannerImage}
|
||
src={banner.imageUrl}
|
||
alt={banner.title || ""}
|
||
/>
|
||
<h2 className={styles.bannerTitle}>
|
||
<TitleLines text={banner.title || "Browse"} />
|
||
</h2>
|
||
<a
|
||
className={`outline-btn ${styles.bannerBtn} ${
|
||
index === 0 ? styles.bannerBtnWide : ""
|
||
}`}
|
||
href={banner.linkUrl || "#producers"}
|
||
>
|
||
{banner.cta || "browse producers"}
|
||
</a>
|
||
</article>
|
||
))}
|
||
</div>
|
||
{exportBanner ? (
|
||
<div className={`tile-hover ${styles.exportCta}`}>
|
||
<img
|
||
className={styles.plane}
|
||
src={exportBanner.imageUrl}
|
||
alt=""
|
||
/>
|
||
<h2 className={styles.exportTitle}>
|
||
<TitleLines text={exportBanner.title || "let's export"} />
|
||
</h2>
|
||
<a
|
||
className={`outline-btn ${styles.beginBtn}`}
|
||
href={exportBanner.linkUrl || "/register"}
|
||
>
|
||
{exportBanner.cta || "begin"}
|
||
<img src="/images/icons/chevron.svg" alt="" width={9} height={16} />
|
||
</a>
|
||
</div>
|
||
) : null}
|
||
</section>
|
||
|
||
{restCarousels.map((carousel, index) => (
|
||
<BusinessCarouselSection
|
||
key={carousel.id}
|
||
carousel={carousel}
|
||
fallbackProducers={index === 0 ? featuredProducers : undefined}
|
||
/>
|
||
))}
|
||
</main>
|
||
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|