471 lines
13 KiB
TypeScript
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 };
|