Files
reui-blocks/blocks/book-a-demo2.tsx
T

504 lines
17 KiB
TypeScript

"use client";
import { AnimatePresence, motion } from "framer-motion";
import { ArrowLeft, ArrowRight, MousePointer2 } from "lucide-react";
import React, { useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { cn } from "@/lib/utils";
interface Avatar {
image: string;
avatarClassName: string;
cursorClassName: string;
className?: string;
delay?: number;
}
const BookADemo2Avatar = ({
image,
avatarClassName,
cursorClassName,
className,
delay,
}: Avatar) => {
return (
<div className={cn("relative", className)}>
<motion.div
animate={{
x: [0, 10, 10, 0, 0],
y: [0, 0, -10, -10, 0],
}}
transition={{
duration: 10,
ease: "linear",
repeat: Infinity,
repeatType: "loop",
delay: delay ?? 0,
}}
className={cn(
"relative size-10 rounded-full border-2 p-[1px]",
avatarClassName,
)}
>
<MousePointer2
className={cn(
"absolute start-full bottom-full shrink-0 translate-x-2/5 translate-y-2/5 !delay-0",
cursorClassName,
)}
size={18}
/>
<img
src={image}
alt="آواتار"
className="size-full rounded-full object-cover"
/>
</motion.div>
</div>
);
};
interface Description {
text: string;
hyperlink: string;
url: string;
}
interface Header {
heading: string;
description: Description;
avatars: Avatar[];
}
const BookADemo2Header = ({ heading, description, avatars }: Header) => {
return (
<div className="relative flex w-full max-w-2xl flex-col items-center gap-4 text-center">
<h3 className="text-xl font-semibold sm:text-2xll md:text-2xll">
{heading}
</h3>
<p className="font-medium text-muted-foreground sm:text-lg md:text-xl">
<span>{description.text.split(description.hyperlink)[0]}</span>
<span className="text-foreground">
<a href={description.url} className="underline">
{description.hyperlink}
</a>
</span>
<span>{description.text.split(description.hyperlink)[1]}</span>
</p>
<div className="pointer-events-none absolute inset-0 hidden lg:block">
<BookADemo2Avatar
className="absolute bottom-full start-full"
{...avatars[0]}
/>
<BookADemo2Avatar
className="absolute top-full end-full"
delay={1}
{...avatars[1]}
/>
</div>
</div>
);
};
interface FormGroupProps {
children: React.ReactNode;
className?: string;
}
const FormGroup = ({ children, className }: FormGroupProps) => {
return <div className={cn("flex flex-col gap-2", className)}>{children}</div>;
};
const BookADemo2ContactForm = () => {
return (
<div className="border-b p-8 lg:border-e lg:border-b-0">
<form className="grid grid-cols-2 gap-x-3 gap-y-6">
<FormGroup className="col-span-2 sm:col-span-1">
<Label>نام</Label>
<Input type="text" placeholder="علی" />
</FormGroup>
<FormGroup className="col-span-2 sm:col-span-1">
<Label>نام خانوادگی</Label>
<Input type="text" placeholder="محمدی" />
</FormGroup>
<FormGroup className="col-span-2">
<Label>ایمیل کاری</Label>
<Input
type="email"
placeholder="example@company.com"
dir="rtl"
className="text-start"
/>
</FormGroup>
<FormGroup className="col-span-2 sm:col-span-1">
<Label>تعداد اعضای تیم</Label>
<Select>
<SelectTrigger className="w-full">
<SelectValue placeholder="۱–۱۰ نفر" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1-10">۱–۱۰ نفر</SelectItem>
<SelectItem value="11-50">۱۱–۵۰ نفر</SelectItem>
<SelectItem value="51-100">۵۱–۱۰۰ نفر</SelectItem>
<SelectItem value="101-500">۱۱–۵۰۰ نفر</SelectItem>
<SelectItem value="501-1000">۵۱–۱۰۰۰ نفر</SelectItem>
</SelectContent>
</Select>
</FormGroup>
<FormGroup className="col-span-2 sm:col-span-1">
<Label>سمت شغلی</Label>
<Select>
<SelectTrigger className="w-full">
<SelectValue placeholder="سمت شغلی خود را انتخاب کنید" />
</SelectTrigger>
<SelectContent>
<SelectItem value="CEO">مدیرعامل</SelectItem>
<SelectItem value="CTO">مدیر فناوری</SelectItem>
<SelectItem value="CFO">مدیر مالی</SelectItem>
<SelectItem value="Other">سایر</SelectItem>
</SelectContent>
</Select>
</FormGroup>
<FormGroup className="col-span-2">
<Label>توضیحات</Label>
<Textarea
placeholder="درباره پروژه، چالش‌ها، نیازها و انتظارات خود از این جلسه دمو توضیح دهید."
className="min-h-32"
/>
</FormGroup>
<Button type="submit" className="col-span-2 gap-2" size="lg">
ثبت درخواست
<ArrowRight className="rtl:rotate-180" />
</Button>
</form>
</div>
);
};
interface Author {
name: string;
designation: string;
profilePicture: string;
}
interface Quote {
fullQuote: string;
highlightedWords: string[];
}
interface Testimonial {
companyLogo: string;
quote: Quote;
author: Author;
}
interface TestimonialsProps {
testimonials: Testimonial[];
}
const BookADemo2Testimonials = ({ testimonials }: TestimonialsProps) => {
const [activeTestimonial, setActiveTestimonial] = useState(0);
return (
<div className="relative flex h-full p-8">
<div className="absolute top-8 end-8 flex items-center gap-2">
<Button
size="sm"
aria-label="نظر قبلی"
onClick={() =>
setActiveTestimonial(
(activeTestimonial + testimonials.length - 1) %
testimonials.length,
)
}
>
<ArrowLeft className="rtl:rotate-180" />
</Button>
<Button
size="sm"
aria-label="نظر بعدی"
onClick={() =>
setActiveTestimonial((activeTestimonial + 1) % testimonials.length)
}
>
<ArrowRight className="rtl:rotate-180" />
</Button>
</div>
<AnimatePresence mode="wait">
{testimonials.map((testimonial, index) => {
if (index !== activeTestimonial) return null;
return (
<motion.div
initial={{
opacity: 0,
}}
animate={{
opacity: 1,
}}
exit={{
opacity: 0,
}}
transition={{
duration: 0.3,
ease: "easeInOut",
}}
key={`testimonial-${index}`}
className="flex h-full flex-col justify-between gap-12"
>
<div className="flex items-center gap-3">
<img
src={testimonial.companyLogo}
alt={`لوگوی شرکت ${testimonial.author.name}`}
className="h-6 w-auto object-contain md:h-8 dark:invert"
/>
</div>
<div className="space-y-6">
<blockquote className="leading-snug text-muted-foreground sm:text-lg lg:max-w-md">
&quot;
{testimonial.quote.fullQuote
.split(" ")
.map((word, wordIndex) => {
const isHighlighted =
testimonial.quote.highlightedWords.some((highlighted) =>
word
.toLowerCase()
.includes(highlighted.toLowerCase()),
);
return (
<span
key={wordIndex}
className={
isHighlighted ? "font-medium text-foreground" : ""
}
>
{word}{" "}
</span>
);
})}
&quot;
</blockquote>
<div className="flex items-center gap-3">
<img
src={testimonial.author.profilePicture}
alt={testimonial.author.name}
className="size-9 rounded-full object-cover"
/>
<div>
<div className="text-sm font-medium">
{testimonial.author.name}
</div>
<div className="text-sm text-muted-foreground">
{testimonial.author.designation}
</div>
</div>
</div>
</div>
</motion.div>
);
})}
</AnimatePresence>
</div>
);
};
interface Footer {
heading: string;
logos: string[];
}
const BookADemo2Footer = ({ heading, logos }: Footer) => {
return (
<div className="flex w-full max-w-6xl flex-col items-center gap-14 text-center">
<h3 className="text-sm font-medium text-muted-foreground">{heading}</h3>
<div className="flex w-full flex-wrap items-center justify-center gap-10 md:grid md:grid-cols-5">
{logos.map((logo, index) => {
return (
<img
key={`bookademo2-footer-logo-${index}`}
src={logo}
alt={`لوگوی شرکت ${index + 1}`}
className={cn(
"h-6 place-self-center object-contain md:h-8 dark:invert",
index > 5 && "hidden md:block",
)}
/>
);
})}
</div>
</div>
);
};
interface BookADemo2Props {
className?: string;
header: Header;
testimonials: Testimonial[];
footer: Footer;
}
const BookADemo2 = ({
header = {
heading: "درخواست دمو",
description: {
text: "برای آشنایی با قابلیت‌های پلتفرم، مشاهده سناریوهای واقعی و دریافت مشاوره تخصصی، درخواست دمو ثبت کنید. کارشناسان ما در کوتاه‌ترین زمان با شما تماس خواهند گرفت.",
hyperlink: "با تیم ما در تماس باشید",
url: "https://ShadcnBlocks",
},
avatars: [
{
image:
"/block-media/shadcnblocks/block/portraits/christian-buehner-DItYlc26zVI-unsplash 1.jpg",
avatarClassName: "border-orange-500",
cursorClassName: "text-orange-500 fill-orange-500",
},
{
image:
"/block-media/shadcnblocks/block/portraits/christian-buehner-DItYlc26zVI-unsplash 1.jpg",
avatarClassName: "border-blue-500",
cursorClassName: "text-blue-500 fill-blue-500",
},
],
},
testimonials = [
{
companyLogo:
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-1.svg",
quote: {
fullQuote:
"این پلتفرم گردش کار توسعه ما را متحول کرده است. افزایش بهره‌وری فوق‌العاده بوده است.",
highlightedWords: ["متحول", "بهره‌وری", "فوق‌العاده"],
},
author: {
name: "علی رضایی",
designation: "توسعه‌دهنده ارشد",
profilePicture:
"/block-media/shadcnblocks/block/portraits/alexander-hipp-iEEBWgY_6lA-unsplash.jpg",
},
},
{
companyLogo:
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-2.svg",
quote: {
fullQuote:
"یکپارچه‌سازی بی‌دردسر بود و تیم ما در چند دقیقه آماده شد. برای استارتاپ ما یک تغییردهنده بازی بود.",
highlightedWords: ["بی‌دردسر", "دقیقه", "تغییردهنده"],
},
author: {
name: "محمد حسینی",
designation: "مدیر فناوری",
profilePicture:
"/block-media/shadcnblocks/block/portraits/christian-buehner-DItYlc26zVI-unsplash 1.jpg",
},
},
{
companyLogo:
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-3.svg",
quote: {
fullQuote:
"از زمان استفاده از این راه‌حل، زمان توسعه را ۴۰٪ کاهش داده‌ایم. به‌شدت توصیه می‌کنم.",
highlightedWords: ["کاهش", "۴۰٪", "توصیه"],
},
author: {
name: "سارا احمدی",
designation: "مدیر مهندسی",
profilePicture:
"/block-media/shadcnblocks/block/portraits/good-faces-xmSWVeGEnJw-unsplash.jpg",
},
},
{
companyLogo:
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-4.svg",
quote: {
fullQuote:
"تجربه توسعه‌دهنده فوق‌العاده است. پذیرش توسط تیم آنی بود و منحنی یادگیری بسیار کوتاه.",
highlightedWords: ["فوق‌العاده", "آنی", "کوتاه"],
},
author: {
name: "داوود کریمی",
designation: "توسعه‌دهنده ارشد",
profilePicture:
"/block-media/shadcnblocks/block/portraits/joseph-gonzalez-iFgRcqHznqg-unsplash.jpg",
},
},
{
companyLogo:
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-5.svg",
quote: {
fullQuote:
"از زمان مهاجرت به این پلتفرم، فرکانس استقرار را ۶۰٪ بهبود داده‌ایم. واقعاً تحول‌آفرین است.",
highlightedWords: ["۶۰٪", "بهبود", "تحول‌آفرین"],
},
author: {
name: "مریم محمدی",
designation: "مهندس DevOps",
profilePicture:
"/block-media/shadcnblocks/block/portraits/good-faces-xmSWVeGEnJw-unsplash.jpg",
},
},
{
companyLogo:
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-6.svg",
quote: {
fullQuote:
"قابلیت‌های همکاری نحوه کار تیم دورکار ما را متحول کرده است. انگار کل تیم در یک اتاق حضور دارند.",
highlightedWords: ["همکاری", "متحول", "اتاق"],
},
author: {
name: "امیر نوری",
designation: "مدیر محصول",
profilePicture:
"/block-media/shadcnblocks/block/portraits/nima-motaghian-nejad-_omdf_EgRUo-unsplash.jpg",
},
},
],
footer = {
heading: "انتخاب تیم‌های توسعه نرم‌افزار در سراسر جهان",
logos: [
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-1.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-2.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-3.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-4.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-5.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-6.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-7.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-8.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-9.svg",
"/block-media/shadcnblocks/block/logos/company/fictional-company-logo-10.svg",
],
},
className,
}: BookADemo2Props) => {
return (
<section dir="rtl" lang="fa" className={cn("py-32", className)}>
<div className="container">
<div className="flex flex-col items-center gap-12 lg:gap-24">
<BookADemo2Header {...header} />
<div className="grid max-w-6xl grid-cols-1 rounded-lg border lg:grid-cols-2">
<BookADemo2ContactForm />
<BookADemo2Testimonials testimonials={testimonials} />
</div>
<BookADemo2Footer {...footer} />
</div>
</div>
</section>
);
};
export { BookADemo2 };