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

267 lines
8.1 KiB
TypeScript

"use client";
import {
CornerDownLeft,
Search,
SlidersHorizontal,
UserRoundPlus,
} from "lucide-react";
import { useMemo, useState } from "react";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Dialog,
DialogContent,
DialogFooter,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { cn } from "@/lib/utils";
interface User {
name?: string;
email: string;
accessLevel: string;
status?: string;
}
interface UsersTableProps {
users: User[];
}
const UsersTable = ({ users }: UsersTableProps) => {
return (
<Table>
<TableHeader>
<TableRow>
<TableHead>عضو</TableHead>
<TableHead>سطح دسترسی</TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
{users.map((user) => (
<TableRow key={user.email}>
<TableCell className="flex max-w-56 items-center gap-2 font-medium">
<span className="flex size-6 shrink-0 items-center justify-center rounded-full bg-primary text-background">
{user.name ? user.name.charAt(0) : "?"}
</span>
{user.name}
<span className="text-muted-foreground">{user.email}</span>
</TableCell>
<TableCell>
<Badge variant="secondary">{user.accessLevel}</Badge>
</TableCell>
<TableCell>
{user.status === "دعوت در انتظار" && (
<Badge className="bg-blue-100 text-blue-800">
{user.status}
</Badge>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
);
};
const InviteUserForm = () => {
return (
<Dialog>
<DialogTrigger asChild>
<Button>
<UserRoundPlus /> دعوت عضو
</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">
<UserRoundPlus className="size-4" />
دعوت عضو جدید
</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="colleague@company.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 SettingsMembers1Props {
heading?: string;
subHeading?: string;
className?: string;
users?: User[];
}
const SettingsMembers1 = ({
heading = "اعضای فضای کاری",
subHeading = "دسترسی همکاران به CRM را مدیریت کنید و نقش هر عضو را تنظیم کنید.",
users = [
{
name: "الهام حسینی",
email: "emily.w@acme.io",
accessLevel: "مالک فضای کاری",
},
{
email: "john.d@acme.io",
accessLevel: "فروشنده",
status: "دعوت در انتظار",
},
{
name: "مهدی پارسا",
email: "michael.p@acme.io",
accessLevel: "فقط مشاهده",
},
{
email: "lisa.t@acme.io",
accessLevel: "فروشنده",
status: "دعوت در انتظار",
},
],
className,
}: SettingsMembers1Props) => {
const [searchValue, setSearchValue] = useState("");
const [selectedAccessLevels, setSelectedAccessLevels] = useState<string[]>(
[],
);
const accessLevels = useMemo(() => {
return Array.from(new Set(users.map((user) => user.accessLevel)));
}, [users]);
const filteredUsers = useMemo(() => {
return users.filter((user) => {
const isAccessLevelSelected =
selectedAccessLevels.length === 0 ||
selectedAccessLevels.includes(user.accessLevel);
const isSearchMatch =
user.name?.toLowerCase().includes(searchValue.toLowerCase()) ||
user.email.toLowerCase().includes(searchValue.toLowerCase());
return isAccessLevelSelected && isSearchMatch;
});
}, [users, selectedAccessLevels, searchValue]);
const toggleAccessLevel = (accessLevel: string) => {
setSelectedAccessLevels((prev) => {
if (prev.includes(accessLevel)) {
return prev.filter((level) => level !== accessLevel);
}
return [...prev, accessLevel];
});
};
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-8">
<div className="space-y-3 border-b pb-8">
<h3 className="text-xl font-semibold tracking-tight">{heading}</h3>
<p className="text-sm font-medium text-muted-foreground">
{subHeading}
</p>
</div>
<div className="flex flex-wrap items-center gap-3 sm:flex-nowrap">
<div className="relative w-full 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>
<Popover>
<PopoverTrigger asChild>
<Button variant="outline">
<SlidersHorizontal />
فیلتر نقش
</Button>
</PopoverTrigger>
<PopoverContent align="end" className="w-56">
<div className="space-y-3">
<p className="text-sm font-medium">سطح دسترسی</p>
<div className="space-y-2">
{accessLevels.map((accessLevel) => (
<Label
key={accessLevel}
className="cursor-pointer font-normal"
>
<Checkbox
checked={selectedAccessLevels.includes(accessLevel)}
onCheckedChange={() => toggleAccessLevel(accessLevel)}
/>
<span className="text-sm">{accessLevel}</span>
</Label>
))}
</div>
</div>
</PopoverContent>
</Popover>
<InviteUserForm />
</div>
<UsersTable users={filteredUsers} />
</div>
</div>
</section>
);
};
export { SettingsMembers1 };