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

273 lines
8.1 KiB
TypeScript

"use client";
import { CornerDownLeft, MoreHorizontalIcon, Search } from "lucide-react";
import { useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogFooter,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";
interface User {
name: string;
email: string;
accessLevel: string;
status?: string;
image?: string;
}
interface Cta {
title: string;
ctaText: string;
ctaLink: string;
}
interface SettingsMembers2Props {
heading?: string;
subHeading?: Cta;
users?: User[];
className?: string;
}
const SettingsMembers2 = ({
heading = "اعضای فضای کاری",
subHeading = {
title:
"همکاران فروش و پشتیبانی را دعوت کنید و سطح دسترسی هر عضو به CRM را تعیین کنید.",
ctaText: "راهنمای نقش‌ها و دسترسی‌ها",
ctaLink: "#",
},
users = [
{
name: "سارا مرتضوی",
email: "sofia.m@example.com",
accessLevel: "مالک فضای کاری",
image:
"/block-media/shadcnblocks/block/avatar/avatar2.jpg",
},
{
name: "امیر چناری",
email: "alex.c@example.com",
accessLevel: "فروشنده",
status: "دعوت در انتظار",
},
{
name: "ژوبین بلاکی",
email: "jordan.b@example.com",
accessLevel: "فقط مشاهده",
image:
"/block-media/shadcnblocks/block/avatar/avatar3.jpg",
},
{
name: "مریم رئیسی",
email: "morgan.r@example.com",
accessLevel: "فروشنده",
status: "دعوت در انتظار",
},
],
className,
}: SettingsMembers2Props) => {
const [searchValue, setSearchValue] = useState("");
const filteredUsers = useMemo(() => {
return users.filter((user) => {
return (
user.name.toLowerCase().includes(searchValue.toLowerCase()) ||
user.email.toLowerCase().includes(searchValue.toLowerCase())
);
});
}, [users, searchValue]);
return (
<section dir="rtl" lang="fa" className={cn("w-full py-32", className)}>
<div className="w-full px-4 sm:px-6 lg:px-8">
<div className="flex w-full flex-col gap-6">
<div className="space-y-4">
<h3 className="text-xl font-semibold tracking-tight">{heading}</h3>
<CtaText cta={subHeading} />
</div>
<div className="space-y-4">
<div className="flex items-center justify-between gap-3">
<div className="relative w-full max-w-56 min-w-20">
<Search className="absolute top-1/2 start-2 size-4 -translate-y-1/2 text-muted-foreground" />
<Input
placeholder="جستجوی عضو…"
className="ps-7"
value={searchValue}
onChange={(e) => setSearchValue(e.target.value)}
/>
</div>
<InviteUserForm />
</div>
<p className="text-xs font-semibold text-muted-foreground">
{filteredUsers.length.toLocaleString("fa-IR")} عضو فعال
</p>
<UsersList users={filteredUsers} />
</div>
</div>
</div>
</section>
);
};
export { SettingsMembers2 };
const InviteUserForm = () => {
return (
<Dialog>
<DialogTrigger asChild>
<Button>دعوت عضو</Button>
</DialogTrigger>
<DialogContent className="gap-0 overflow-hidden p-0">
<DialogTitle className="flex items-center gap-2 border-b p-4 text-sm font-medium">
دعوت به فضای کاری
</DialogTitle>
<form
autoComplete="off"
onSubmit={(e) => e.preventDefault()}
className="flex flex-col gap-4 bg-muted pt-4"
>
<div className="flex flex-col gap-4 px-4">
<div className="space-y-1">
<Label className="text-xs">ایمیل سازمانی</Label>
<Input
placeholder="name@yourcompany.com"
className="bg-background"
/>
</div>
<div className="space-y-1">
<Label className="text-xs">انتخاب نقش</Label>
<Select defaultValue="editor">
<SelectTrigger className="w-full bg-background">
<SelectValue placeholder="انتخاب نقش" />
</SelectTrigger>
<SelectContent>
<SelectItem value="owner">مالک فضای کاری</SelectItem>
<SelectItem value="editor">فروشنده</SelectItem>
<SelectItem value="viewer">فقط مشاهده</SelectItem>
</SelectContent>
</Select>
</div>
</div>
<DialogFooter className="border-t bg-background px-4 py-3">
<Button size="sm" type="submit">
ارسال دعوتنامه <CornerDownLeft className="rtl:rotate-180" />
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
};
interface CtaTextProps {
cta: Cta;
}
const CtaText = ({ cta }: CtaTextProps) => {
return (
<p className="text-xs text-muted-foreground sm:text-sm">
{cta.title}{" "}
<a href={cta.ctaLink} className="whitespace-nowrap underline">
{cta.ctaText}
</a>
</p>
);
};
interface UserCardProps {
user: User;
}
const UserCard = ({ user }: UserCardProps) => {
return (
<div className="flex w-full items-center justify-between">
<div className="flex items-center gap-2 sm:flex-2/3">
<div className="flex size-10 items-center justify-center overflow-hidden rounded-full bg-muted">
{user.image ? (
<img
src={user.image}
alt={`آواتار ${user.name}`}
className="size-full object-cover"
/>
) : (
<span className="text-sm font-medium">{user.name.charAt(0)}</span>
)}
</div>
<div className="text-sm font-medium">
<p>{user.name}</p>
<p className="text-xs text-muted-foreground">{user.email}</p>
</div>
</div>
<div className="flex items-center justify-between gap-3 sm:flex-1/3">
<Select defaultValue={user.accessLevel}>
<SelectTrigger className="min-w-24">
<SelectValue placeholder="انتخاب نقش" />
</SelectTrigger>
<SelectContent>
<SelectItem value="مالک فضای کاری">مالک فضای کاری</SelectItem>
<SelectItem value="فروشنده">فروشنده</SelectItem>
<SelectItem value="فقط مشاهده">فقط مشاهده</SelectItem>
</SelectContent>
</Select>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" aria-label="گزینه‌های بیشتر" size="icon-sm">
<MoreHorizontalIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-fit max-w-56" align="end">
<DropdownMenuItem>انتقال مالکیت فضای کاری</DropdownMenuItem>
<DropdownMenuItem>حذف از فضای کاری</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
);
};
interface UsersListProps {
users: User[];
}
const UsersList = ({ users }: UsersListProps) => {
return (
<ul className="overflow-x-auto">
{users.map((user, i) => {
return (
<li
key={`user-card-${i}`}
className="w-full min-w-80 shrink-0 border-b py-3 first:pt-0"
>
<UserCard user={user} />
</li>
);
})}
</ul>
);
};