Files
reui-blocks/blocks/settings-integrations9.tsx
T

255 lines
8.7 KiB
TypeScript

"use client";
import { ExternalLink, MoreHorizontal, RefreshCw, Trash2 } from "lucide-react";
import { useState } from "react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
interface IntegrationItem {
image: string;
title: string;
description: string;
status: "active" | "inactive" | "error";
connectedBy?: {
name: string;
avatar: string;
};
lastActivity?: string;
className?: string;
}
interface SettingsIntegrations9Props {
className?: string;
heading?: string;
subHeading?: string;
integrations?: IntegrationItem[];
}
const SettingsIntegrations9 = ({
className,
heading = "اتصال‌های فعال",
subHeading = "سرویس‌های وصل‌شده به سامانه مدیریت ارتباط با مشتری و دسترسی هر کدام را مدیریت کنید.",
integrations: initialIntegrations = [
{
image:
"/block-media/shadcnblocks/block/logos/slack-icon.svg",
title: "Slack",
description: "هشدار فروش و پشتیبانی فضای کاری",
status: "active",
connectedBy: {
name: "الهام میرزایی",
avatar:
"/block-media/shadcnblocks/block/avatar-1.webp",
},
lastActivity: "فعال · همین الان",
},
{
image:
"/block-media/shadcnblocks/block/logos/google-icon.svg",
title: "Google Drive",
description: "همگام‌سازی اسناد معامله",
status: "active",
connectedBy: {
name: "نیما کریمی",
avatar:
"/block-media/shadcnblocks/block/avatar/avatar3.webp",
},
lastActivity: "همگام‌شده · ۵ دقیقه پیش",
},
{
image:
"/block-media/shadcnblocks/block/logos/github-icon.svg",
title: "GitHub",
description: "وب‌هوک مخزن و استقرار",
status: "active",
connectedBy: {
name: "سامان احمدی",
avatar:
"/block-media/shadcnblocks/block/avatar-2.webp",
},
lastActivity: "آخرین رویداد · ۲ ساعت پیش",
className: "dark:invert",
},
{
image:
"/block-media/shadcnblocks/block/logos/notion-icon.svg",
title: "Notion",
description: "همگام‌سازی دانش فروش",
status: "error",
connectedBy: {
name: "نیلوفر کیمیایی",
avatar:
"/block-media/shadcnblocks/block/avatar-7.webp",
},
lastActivity: "همگام‌سازی ناموفق",
className: "dark:invert",
},
{
image:
"/block-media/shadcnblocks/block/logos/figma-icon.svg",
title: "Figma",
description: "وارد کردن دارایی کمپین",
status: "inactive",
connectedBy: {
name: "کاوه پارسا",
avatar:
"/block-media/shadcnblocks/block/avatar-5.webp",
},
lastActivity: "غیرفعال",
},
{
image:
"/block-media/shadcnblocks/block/logos/stripe-icon.svg",
title: "Stripe",
description: "پرداخت و صورتحساب",
status: "active",
connectedBy: {
name: "ریحانه جعفری",
avatar:
"/block-media/shadcnblocks/block/avatar-3.webp",
},
lastActivity: "۱۲ تراکنش امروز",
},
],
}: SettingsIntegrations9Props) => {
const [integrations, setIntegrations] = useState(initialIntegrations);
const handleRemove = (title: string) => {
setIntegrations((prev) => prev.filter((i) => i.title !== title));
};
const getStatusBadge = (status: IntegrationItem["status"]) => {
switch (status) {
case "active":
return (
<Badge variant="secondary" className="bg-green-100 text-green-800">
فعال
</Badge>
);
case "inactive":
return <Badge variant="secondary">غیرفعال</Badge>;
case "error":
return (
<Badge variant="secondary" className="bg-red-100 text-red-800">
خطا
</Badge>
);
}
};
return (
<section className={cn("py-32", className)}>
<div className="container max-w-4xl">
<div className="mb-8 flex items-start justify-between">
<div className="space-y-2">
<h1 className="text-3xl font-bold tracking-tight">{heading}</h1>
<p className="text-muted-foreground">{subHeading}</p>
</div>
<Button>افزودن اتصال</Button>
</div>
<div className="space-y-4">
{integrations.map((integration) => (
<div
key={integration.title}
className="group rounded-xl border bg-card p-6 transition-shadow hover:shadow-md"
>
<div className="flex items-start gap-4">
<div className="flex size-14 shrink-0 items-center justify-center rounded-xl border bg-muted/50">
<img
src={integration.image}
alt={`آیکون ${integration.title}`}
className={cn("size-8", integration.className)}
/>
</div>
<div className="flex-1 space-y-3">
<div className="flex items-start justify-between">
<div className="space-y-1">
<div className="flex items-center gap-2">
<h3 className="font-semibold">{integration.title}</h3>
{getStatusBadge(integration.status)}
</div>
<p className="text-sm text-muted-foreground">
{integration.description}
</p>
</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="ghost"
size="icon"
className="opacity-0 group-hover:opacity-100"
>
<MoreHorizontal className="size-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<ExternalLink className="me-2 size-4" />
باز کردن پیکربندی
</DropdownMenuItem>
<DropdownMenuItem>
<RefreshCw className="me-2 size-4" />
همگام‌سازی مجدد
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
className="text-destructive focus:text-destructive"
onClick={() => handleRemove(integration.title)}
>
<Trash2 className="me-2 size-4" />
حذف اتصال
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="flex items-center gap-4 text-sm text-muted-foreground">
{integration.connectedBy && (
<div className="flex items-center gap-2">
<Avatar className="size-5">
<AvatarImage src={integration.connectedBy.avatar} />
<AvatarFallback>
{integration.connectedBy.name[0]}
</AvatarFallback>
</Avatar>
<span>متصل توسط {integration.connectedBy.name}</span>
</div>
)}
{integration.lastActivity && (
<>
<span>•</span>
<span>{integration.lastActivity}</span>
</>
)}
</div>
</div>
</div>
</div>
))}
</div>
{integrations.length === 0 && (
<div className="rounded-xl border border-dashed py-12 text-center">
<p className="text-muted-foreground">
هنوز سرویسی متصل نشده است.
</p>
<Button className="mt-4">مرور سرویس‌ها</Button>
</div>
)}
</div>
</section>
);
};
export { SettingsIntegrations9 };