mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-15 17:16:16 +08:00
feat(admin): init project (#7197)
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
import { Badge } from '@affine/admin/components/ui/badge';
|
||||
import { Button } from '@affine/admin/components/ui/button';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@affine/admin/components/ui/card';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@affine/admin/components/ui/dropdown-menu';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@affine/admin/components/ui/table';
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from '@affine/admin/components/ui/tabs';
|
||||
import { useQuery } from '@affine/core/hooks/use-query';
|
||||
import { listUsersQuery } from '@affine/graphql';
|
||||
import {
|
||||
CircleUser,
|
||||
File,
|
||||
ListFilter,
|
||||
MoreHorizontal,
|
||||
PlusCircle,
|
||||
} from 'lucide-react';
|
||||
|
||||
import { Nav } from '../nav';
|
||||
|
||||
export function Users() {
|
||||
const {
|
||||
data: { users },
|
||||
} = useQuery({
|
||||
query: listUsersQuery,
|
||||
variables: {
|
||||
filter: {
|
||||
first: 10,
|
||||
skip: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const usersCells = users.map(user => {
|
||||
const avatar = user.avatarUrl ? (
|
||||
<img
|
||||
alt="User avatar"
|
||||
className="aspect-square rounded-md object-cover"
|
||||
height="64"
|
||||
src={user.avatarUrl}
|
||||
width="64"
|
||||
/>
|
||||
) : (
|
||||
<CircleUser size={36} />
|
||||
);
|
||||
return (
|
||||
<TableRow key={user.id}>
|
||||
<TableCell className="hidden sm:table-cell">{avatar}</TableCell>
|
||||
<TableCell className="hidden md:table-cell">{user.id}</TableCell>
|
||||
<TableCell className="font-medium">{user.name}</TableCell>
|
||||
<TableCell>
|
||||
<Badge variant="outline">
|
||||
{user.emailVerified ? 'Email Verified' : 'Not yet verified'}
|
||||
</Badge>
|
||||
</TableCell>
|
||||
<TableCell>{user.email}</TableCell>
|
||||
<TableCell className="hidden md:table-cell">
|
||||
{user.hasPassword ? '✅' : '❌'}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button aria-haspopup="true" size="icon" variant="ghost">
|
||||
<MoreHorizontal className="h-4 w-4" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Actions</DropdownMenuLabel>
|
||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||
<DropdownMenuItem>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Nav>
|
||||
<main className="flex flex-1 flex-col gap-4 p-4 md:gap-8 md:p-8">
|
||||
<Tabs defaultValue="all">
|
||||
<div className="flex items-center">
|
||||
<TabsList>
|
||||
<TabsTrigger value="all">All</TabsTrigger>
|
||||
<TabsTrigger value="active">Active</TabsTrigger>
|
||||
<TabsTrigger value="draft">Draft</TabsTrigger>
|
||||
<TabsTrigger value="archived" className="hidden sm:flex">
|
||||
Archived
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" size="sm" className="h-7 gap-1">
|
||||
<ListFilter className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
||||
Filter
|
||||
</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Filter by</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuCheckboxItem checked>
|
||||
Active
|
||||
</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem>Draft</DropdownMenuCheckboxItem>
|
||||
<DropdownMenuCheckboxItem>Archived</DropdownMenuCheckboxItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button size="sm" variant="outline" className="h-7 gap-1">
|
||||
<File className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
||||
Export
|
||||
</span>
|
||||
</Button>
|
||||
<Button size="sm" className="h-7 gap-1">
|
||||
<PlusCircle className="h-3.5 w-3.5" />
|
||||
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
||||
Add User
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<TabsContent value="all">
|
||||
<Card x-chunk="dashboard-06-chunk-0">
|
||||
<CardHeader>
|
||||
<CardTitle>Users</CardTitle>
|
||||
<CardDescription>
|
||||
Manage your users and edit their properties.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="hidden w-[100px] sm:table-cell">
|
||||
<span className="sr-only">Image</span>
|
||||
</TableHead>
|
||||
<TableHead className="hidden md:table-cell">Id</TableHead>
|
||||
<TableHead>Name</TableHead>
|
||||
<TableHead>Status</TableHead>
|
||||
<TableHead>Email</TableHead>
|
||||
<TableHead className="hidden md:table-cell">
|
||||
Has password
|
||||
</TableHead>
|
||||
<TableHead>
|
||||
<span className="sr-only">Actions</span>
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>{usersCells}</TableBody>
|
||||
</Table>
|
||||
</CardContent>
|
||||
<CardFooter>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Showing <strong>1-10</strong> of <strong>32</strong> products
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</main>
|
||||
</Nav>
|
||||
);
|
||||
}
|
||||
|
||||
export { Users as Component };
|
||||
Reference in New Issue
Block a user