150 lines
4.6 KiB
TypeScript
150 lines
4.6 KiB
TypeScript
import { Button } from "@/components/ui/button";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface Image {
|
|
src: string;
|
|
alt: string;
|
|
}
|
|
|
|
interface TextContent {
|
|
title?: string;
|
|
paragraphs: string[];
|
|
ctaButton?: {
|
|
href: string;
|
|
text: string;
|
|
};
|
|
}
|
|
|
|
interface About28Props {
|
|
leftImages?: Image[];
|
|
leftText?: TextContent;
|
|
rightText?: TextContent;
|
|
rightImages?: Image[];
|
|
className?: string;
|
|
}
|
|
|
|
const About28 = ({
|
|
leftImages = [
|
|
{
|
|
src: "/block-media/shadcnblocks/block/placeholder-1.svg",
|
|
alt: "همکاری تیم",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/placeholder-2.svg",
|
|
alt: "فضای کاری تیم",
|
|
},
|
|
],
|
|
leftText = {
|
|
title: "تیم",
|
|
paragraphs: [
|
|
"ساخت را از ۲۱۹ آغاز کردیم و در ۲۲۲ عرضه کردیم. هر نقطه اتصال از صفر طراحی شده بدون بدهی فنی یا سیستم کهنه. برای نوآوری مدیریت پروژه در صد سال آینده ساخته شدهایم.",
|
|
"صددرصد در مالکیت بنیانگذاران و تیم است، سودآوریم و تیم را کوچک نگه میداریم. بهمرور این صفحه کاملتر میشود، اما الان تمرکزمان بر تحویل به توسعهدهندگان است.",
|
|
"اگر به ساخت آینده مدیریت پروژه علاقهمندید، موقعیتهای باز زیر را ببینید.",
|
|
],
|
|
ctaButton: {
|
|
href: "/careers",
|
|
text: "مشاهده موقعیتهای شغلی",
|
|
},
|
|
},
|
|
rightText = {
|
|
paragraphs: [
|
|
"متعهدیم نحوه برنامهریزی، اجرا و تحویل پروژهها را متحول کنیم. مأموریت ما این است که به مشتریان مزیت بیرقیب در برابر تأخیر، ناکارآمدی و بینظمی بدهیم از طریق بینشهای عملی و همکاری بیدرز.",
|
|
"مشتریمحوریم زمان میگذاریم تا هر جنبه از گردش کار شما را بفهمیم و بهتر از همیشه کار کنید. همه با هم هستیم چون موفقیت شما، موفقیت ماست.",
|
|
],
|
|
},
|
|
rightImages = [
|
|
{
|
|
src: "/block-media/shadcnblocks/block/placeholder-3.svg",
|
|
alt: "فضای کاری مدرن",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/placeholder-4.svg",
|
|
alt: "همکاری تیم",
|
|
},
|
|
],
|
|
className,
|
|
}: About28Props) => {
|
|
return (
|
|
<section
|
|
className={cn(
|
|
"container mt-10 flex max-w-5xl flex-col-reverse gap-8 md:mt-14 md:gap-14 lg:mt-20 lg:flex-row lg:items-end",
|
|
className,
|
|
)}
|
|
>
|
|
{/* Images Left - Text Right */}
|
|
<div className="flex flex-col gap-8 lg:gap-16 xl:gap-20">
|
|
<ImageSection images={leftImages} className="xl:-translate-x-10" />
|
|
<TextSection
|
|
title={leftText.title}
|
|
paragraphs={leftText.paragraphs}
|
|
ctaButton={leftText.ctaButton}
|
|
/>
|
|
</div>
|
|
|
|
{/* Text Left - Images Right */}
|
|
<div className="flex flex-col gap-8 lg:gap-16 xl:gap-20">
|
|
<TextSection paragraphs={rightText.paragraphs} />
|
|
<ImageSection
|
|
images={rightImages}
|
|
className="hidden lg:flex xl:translate-x-10"
|
|
/>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
interface ImageSectionProps {
|
|
images: Image[];
|
|
className?: string;
|
|
}
|
|
|
|
const ImageSection = ({ images, className }: ImageSectionProps) => {
|
|
return (
|
|
<div className={cn("flex flex-col gap-6", className)}>
|
|
{images.map((image, index) => (
|
|
<div
|
|
key={index}
|
|
className="relative aspect-[2/1.5] overflow-hidden rounded-2xl"
|
|
>
|
|
<img
|
|
src={image.src}
|
|
alt={image.alt}
|
|
className="absolute inset-0 size-full object-cover"
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
interface TextSectionProps {
|
|
title?: string;
|
|
paragraphs: string[];
|
|
ctaButton?: {
|
|
href: string;
|
|
text: string;
|
|
};
|
|
}
|
|
|
|
const TextSection = ({ title, paragraphs, ctaButton }: TextSectionProps) => {
|
|
return (
|
|
<div className="flex-1 space-y-4 text-lg md:space-y-6">
|
|
{title && <h2 className="text-xl text-foreground">{title}</h2>}
|
|
<div className="max-w-xl space-y-6 text-muted-foreground">
|
|
{paragraphs.map((paragraph, index) => (
|
|
<p key={index}>{paragraph}</p>
|
|
))}
|
|
</div>
|
|
{ctaButton && (
|
|
<div className="mt-8">
|
|
<Button size="lg" asChild>
|
|
<a href={ctaButton.href}>{ctaButton.text}</a>
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { About28 };
|