MIF_E31222379_WEB/app/routes/sys-rijig-adminpanel.dashbo...

212 lines
7.7 KiB
TypeScript

import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Users, UserCheck, UserX, MoreHorizontal, Eye, Edit, Trash2 } from "lucide-react";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "~/components/ui/card";
import { Button } from "~/components/ui/button";
import { Badge } from "~/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "~/components/ui/table";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
export const loader = async () => {
const userData = {
summary: {
totalUsers: 1234,
activeUsers: 1100,
pendingVerification: 15,
collectors: 45
},
users: [
{
id: 1,
name: "Ahmad Rizki",
email: "ahmad.rizki@example.com",
role: "Masyarakat",
status: "active",
joinDate: "2024-01-15",
totalTransactions: 25,
avatar: ""
},
{
id: 2,
name: "Siti Nurhaliza",
email: "siti.nurhaliza@example.com",
role: "Pengepul",
status: "pending",
joinDate: "2024-06-20",
totalTransactions: 0,
avatar: ""
},
{
id: 3,
name: "Budi Santoso",
email: "budi.santoso@example.com",
role: "Masyarakat",
status: "active",
joinDate: "2024-03-10",
totalTransactions: 42,
avatar: ""
}
]
};
return json({ userData });
};
export default function UserManagement() {
const { userData } = useLoaderData<typeof loader>();
return (
<div className="space-y-6">
{/* Header */}
<div className="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<h1 className="text-3xl font-bold text-gray-900 dark:text-white">
Manajemen Pengguna
</h1>
<p className="text-gray-600 dark:text-gray-400 mt-1">
Kelola semua pengguna platform RIjig
</p>
</div>
</div>
{/* Summary Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium">Total Pengguna</CardTitle>
<Users className="h-4 w-4 text-muted-foreground" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{userData.summary.totalUsers.toLocaleString()}</div>
<p className="text-xs text-muted-foreground">terdaftar di platform</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium">Pengguna Aktif</CardTitle>
<UserCheck className="h-4 w-4 text-green-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-green-600">{userData.summary.activeUsers.toLocaleString()}</div>
<p className="text-xs text-muted-foreground">pengguna terverifikasi</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium">Menunggu Verifikasi</CardTitle>
<UserX className="h-4 w-4 text-orange-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-orange-600">{userData.summary.pendingVerification}</div>
<p className="text-xs text-muted-foreground">perlu ditinjau</p>
</CardContent>
</Card>
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium">Total Pengepul</CardTitle>
<Users className="h-4 w-4 text-blue-600" />
</CardHeader>
<CardContent>
<div className="text-2xl font-bold text-blue-600">{userData.summary.collectors}</div>
<p className="text-xs text-muted-foreground">pengepul aktif</p>
</CardContent>
</Card>
</div>
{/* Users Table */}
<Card>
<CardHeader>
<CardTitle>Daftar Pengguna</CardTitle>
<CardDescription>Semua pengguna yang terdaftar di platform</CardDescription>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>Pengguna</TableHead>
<TableHead>Email</TableHead>
<TableHead>Role</TableHead>
<TableHead>Status</TableHead>
<TableHead>Tanggal Bergabung</TableHead>
<TableHead>Total Transaksi</TableHead>
<TableHead className="text-right">Aksi</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{userData.users.map((user) => (
<TableRow key={user.id}>
<TableCell>
<div className="flex items-center gap-3">
<Avatar className="h-8 w-8">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback>
{user.name.split(' ').map(n => n[0]).join('')}
</AvatarFallback>
</Avatar>
<div>
<div className="font-medium">{user.name}</div>
</div>
</div>
</TableCell>
<TableCell className="text-gray-600">{user.email}</TableCell>
<TableCell>
<Badge variant="outline">{user.role}</Badge>
</TableCell>
<TableCell>
<Badge
variant={user.status === "active" ? "default" : "secondary"}
className={user.status === "active" ? "bg-green-100 text-green-800" : "bg-orange-100 text-orange-800"}
>
{user.status === "active" ? "Aktif" : "Pending"}
</Badge>
</TableCell>
<TableCell>{new Date(user.joinDate).toLocaleDateString('id-ID')}</TableCell>
<TableCell>{user.totalTransactions}</TableCell>
<TableCell className="text-right">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<MoreHorizontal className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem className="gap-2">
<Eye className="h-4 w-4" />
Lihat Detail
</DropdownMenuItem>
<DropdownMenuItem className="gap-2">
<Edit className="h-4 w-4" />
Edit
</DropdownMenuItem>
<DropdownMenuItem className="gap-2 text-red-600">
<Trash2 className="h-4 w-4" />
Hapus
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
</div>
);
}