Files
reui-blocks/blocks/footer18.tsx
T

471 lines
13 KiB
TypeScript

"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import {
ArrowRight,
ChevronDown,
Cookie,
Facebook,
Github,
Languages,
Linkedin,
Twitter,
} from "lucide-react";
import { Controller, useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Field, FieldLabel } from "@/components/ui/field";
import { Switch } from "@/components/ui/switch";
import { cn } from "@/lib/utils";
interface LanguageOption {
label: string;
description: string;
link: string;
}
interface CookiesOption {
title: string;
description: string;
id: string;
}
interface PrivacyDialog {
trigger: string;
title: string;
text: string;
}
interface LanguagesSelectProps {
languages: Array<LanguageOption>;
}
const HOME_LINK = "https://ShadcnBlocks";
const LOGO =
"/block-media/shadcnblocks/block/logos/ShadcnBlockscom-icon.svg";
const SOCIAL_LINKS = [
{
icon: Github,
href: "#",
},
{
icon: Linkedin,
href: "#",
},
{
icon: Facebook,
href: "#",
},
{
icon: Twitter,
href: "#",
},
];
const LANGUAGES: Array<LanguageOption> = [
{
label: "فارسی",
description: "فارسی (ایران)",
link: "#",
},
{
label: "English",
description: "انگلیسی (آمریکا)",
link: "#",
},
{
label: "Français (France)",
description: "فرانسوی",
link: "#",
},
{
label: "Deutsch",
description: "آلمانی",
link: "#",
},
{
label: "日本語",
description: "ژاپنی",
link: "#",
},
{
label: "한국어",
description: "کره‌ای",
link: "#",
},
];
const COOKIES_OPTIONS: Array<CookiesOption> = [
{
id: "1",
title: "ضروری",
description: "برای امنیت و عملکرد فضای کاری لازم است. همیشه فعال است.",
},
{
id: "2",
title: "عملکردی",
description: "ترجیحات تیم و قابلیت‌های پیشرفته همکاری را فعال می‌کند.",
},
{
id: "3",
title: "تحلیلی",
description: "نحوه استفاده تیم از ابزارها را برای بهبود محصول اندازه‌گیری می‌کند.",
},
{
id: "4",
title: "بازاریابی",
description: "به‌روزرسانی محصول و پیشنهادهای مرتبط را شخصی‌سازی می‌کند.",
},
];
const NAVIGATION = [
{
title: "شرکت",
links: [
{
name: "درباره ما",
href: "#",
},
{
name: "فرصت‌های شغلی",
href: "#",
},
{
name: "امنیت فضای کاری",
href: "#",
},
{
name: "وضعیت سرویس",
href: "#",
},
{
name: "حقوقی و حریم خصوصی",
href: "#",
},
],
},
{
title: "دانلود",
links: [
{
name: "اپ موبایل (iOS و Android)",
href: "#",
},
{
name: "اپ دسکتاپ (Mac و Windows)",
href: "#",
},
{
name: "افزونه مرورگر",
href: "#",
},
],
},
{
title: "منابع",
links: [
{
name: "مرکز راهنما",
href: "#",
},
{
name: "قیمت‌گذاری",
href: "#",
},
{
name: "وبلاگ همکاری تیمی",
href: "#",
},
{
name: "انجمن کاربران",
href: "#",
},
{
name: "یکپارچه‌سازی‌ها",
href: "#",
},
{
name: "قالب‌های پروژه",
href: "#",
},
{
name: "برنامه شرکا",
href: "#",
},
],
},
{
title: "راهکارها",
links: [
{
name: "سازمان‌های بزرگ",
href: "#",
},
{
name: "تیم‌های در حال رشد",
href: "#",
},
{
name: "فریلنسرها",
href: "#",
},
],
},
];
const PRIVACY_DIALOG: PrivacyDialog = {
trigger: "اطلاعات من را نفروشید یا به اشتراک نگذارید",
title:
"انصراف از اشتراک‌گذاری داده با شرکای تبلیغاتی ثبت شد.",
text: `
CollabSpace ممکن است برای نمایش پیشنهادهای مرتبط از کوکی و پیکسل استفاده کند.
با انصراف، داده‌تان برای تبلیغات هدفمند به اشتراک گذاشته نمی‌شود.
همچنان ممکن است پیام‌های محصول ببینید، اما شخصی‌سازی محدودتر خواهد بود.
`,
};
const FormSchema = z.object({
cookies: z.array(z.string()).refine((value) => value.some((item) => item), {
message: "",
}),
});
interface CookiesPanelProps {
cookiesOptions: Array<CookiesOption>;
}
const CookiesPanel = ({ cookiesOptions }: CookiesPanelProps) => {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
cookies: ["1"],
},
});
function onSubmit(data: z.infer<typeof FormSchema>) {
console.log(data.cookies);
}
return (
<Drawer>
<DrawerTrigger asChild>
<Button variant="outline">
<Cookie className="size-4" />
تنظیمات کوکی
</Button>
</DrawerTrigger>
<DrawerContent>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="container overflow-auto pb-4"
>
<DrawerHeader>
<div className="flex w-full flex-col items-start justify-between gap-4 md:flex-row md:items-center">
<DrawerTitle className="text-sm leading-normal font-normal">
از کوکی‌ها برای بهبود تجربه همکاری تیمی استفاده می‌کنیم. برای
جزئیات بیشتر{" "}
<Button
variant="link"
className="px-0 text-sm leading-normal font-normal underline"
>
اطلاعیه کوکی
</Button>{" "}
را ببینید.
</DrawerTitle>
<DrawerClose asChild className="w-full md:w-fit">
<Button type="submit">تمام</Button>
</DrawerClose>
</div>
</DrawerHeader>
<Controller
control={form.control}
name="cookies"
render={({ field }) => (
<Field className="grid gap-5 pt-4 lg:grid-cols-4">
{cookiesOptions.map((opt) => (
<Field
key={opt.id}
className="flex w-full items-start justify-between rounded-xl border bg-background p-3"
>
<FieldLabel className="flex w-full flex-col gap-1">
<p className="text-sm leading-normal font-medium text-foreground">
{opt.title}
</p>
<p className="text-sm leading-normal text-muted-foreground">
{opt.description}
</p>
</FieldLabel>
<Switch
checked={field.value?.includes(opt.id)}
disabled={opt.id == "1"}
onCheckedChange={(checked) => {
return checked
? field.onChange([...field.value, opt.id])
: field.onChange(
field.value?.filter((value) => value !== opt.id),
);
}}
/>
</Field>
))}
</Field>
)}
/>
</form>
</DrawerContent>
</Drawer>
);
};
const LanguagesSelect = ({ languages }: LanguagesSelectProps) => {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">
<Languages />
فارسی
<ChevronDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="start">
{languages.map((lang, i) => (
<DropdownMenuItem asChild key={`footer-lang-${i}`}>
<a
href={lang.link}
className="flex cursor-pointer flex-col items-start rounded-md px-4 py-2"
>
<div className="text-base leading-normal text-foreground">
{lang.label}
</div>
<div className="text-sm leading-normal text-muted-foreground">
{lang.description}
</div>
</a>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
);
};
const PrivacyDialog = ({ trigger, title, text }: PrivacyDialog) => {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">{trigger}</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[26.5625rem]">
<DialogHeader>
<DialogTitle className="leading-normal">{title}</DialogTitle>
<DialogDescription className="leading-normal">
{text}
</DialogDescription>
</DialogHeader>
<DialogClose asChild>
<Button variant="outline">متوجه شدم</Button>
</DialogClose>
</DialogContent>
</Dialog>
);
};
interface Footer18Props {
className?: string;
}
const Footer18 = ({ className }: Footer18Props) => {
return (
<section className={cn("py-20", className)}>
<footer className="container">
<nav className="flex flex-col gap-[2.25rem] lg:flex-row">
<div className="flex w-full flex-col gap-9 lg:w-1/4">
{/* Logo */}
<a href={HOME_LINK}>
<img
src={LOGO}
alt="لوگوی CollabSpace"
title="CollabSpace"
className="h-11"
/>
</a>
<div className="flex w-full flex-col gap-6">
<ul className="flex w-full items-center gap-0.5">
{SOCIAL_LINKS.map((link, i) => (
<li key={`social-link-${i}`}>
<Button size="icon" className="size-8" variant="ghost">
<link.icon className="size-4.5" />
</Button>
</li>
))}
</ul>
<div className="mt-4 flex flex-col items-start gap-2">
<CookiesPanel cookiesOptions={COOKIES_OPTIONS} />
<LanguagesSelect languages={LANGUAGES} />
<PrivacyDialog {...PRIVACY_DIALOG} />
</div>
</div>
</div>
<div className="grid w-full grid-cols-2 gap-6 lg:grid-cols-4">
{NAVIGATION.map((section) => (
<ul
key={`${section.title}`}
className="flex flex-col items-start gap-[.4rem]"
>
<li>
<p className="text-[0.9375rem] leading-normal font-semibold text-foreground">
{section.title}
</p>
</li>
{section.links.map((link) => (
<li key={`${section.title}-${link.name}`}>
<a
href={link.href}
className="text-[0.9375rem] leading-normal text-muted-foreground hover:underline"
>
{link.name}
</a>
</li>
))}
</ul>
))}
</div>
</nav>
<div className="mt-8 flex items-center justify-between gap-4">
<div className="flex items-center justify-between gap-4">
<p className="text-sm leading-normal font-medium text-foreground">
© ۱۴۰۴ CollabSpace
</p>
</div>
<Button variant="link" className="px-0!">
مشاهده ویژگی‌ها
<ArrowRight className="rtl:rotate-180" />
</Button>
</div>
</footer>
</section>
);
};
export { Footer18 };