150 lines
4.5 KiB
TypeScript
150 lines
4.5 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 };
|