feat(hk): expand search and add operational user overview
This commit is contained in:
1 parent
27447ce029
commit
89526af344
44 files changed
+3740
-416
No files matched your search
@@ -10,6 +10,7 @@ import {
|
||||
WifiOff,
|
||||
} from "lucide-react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { AdminBreadcrumb } from "@/components/admin/admin-breadcrumb";
|
||||
import { UserWatchToggle } from "@/components/admin/user-watch-toggle";
|
||||
import Link from "@/components/link";
|
||||
@@ -42,6 +43,7 @@ interface UserHeroProps {
|
||||
activeBan: boolean;
|
||||
mode: "show" | "edit";
|
||||
canEdit: boolean;
|
||||
canViewLogs?: boolean;
|
||||
/** When non-null, render the watch toggle with this initial state. */
|
||||
watching?: boolean | null;
|
||||
}
|
||||
@@ -58,7 +60,9 @@ export function UserHero({
|
||||
mode,
|
||||
canEdit,
|
||||
watching,
|
||||
canViewLogs = true,
|
||||
}: UserHeroProps) {
|
||||
const t = useTranslations("pages.admin.users.presentation");
|
||||
const params = useSearchParams();
|
||||
const list = params.get("list") ?? "";
|
||||
const listHref = userListHref(list);
|
||||
@@ -66,9 +70,9 @@ export function UserHero({
|
||||
<>
|
||||
<AdminBreadcrumb
|
||||
items={[
|
||||
{ label: "Users", href: listHref },
|
||||
{ label: t("users"), href: listHref },
|
||||
{ label: user.username },
|
||||
{ label: mode === "edit" ? "Edit" : "View" },
|
||||
{ label: mode === "edit" ? t("edit") : t("view") },
|
||||
]}
|
||||
/>
|
||||
|
||||
@@ -107,14 +111,14 @@ export function UserHero({
|
||||
{mode === "show" && canEdit && (
|
||||
<Button variant="outline" size="sm" asChild className="ml-2">
|
||||
<Link href={userDetailHref(user.id, "edit", list)}>
|
||||
<Pencil className="mr-1.5 h-3.5 w-3.5" /> Edit
|
||||
<Pencil className="mr-1.5 h-3.5 w-3.5" /> {t("edit")}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
{mode === "edit" && (
|
||||
<Button variant="outline" size="sm" asChild className="ml-2">
|
||||
<Link href={userDetailHref(user.id, "show", list)}>
|
||||
<Eye className="mr-1.5 h-3.5 w-3.5" /> View
|
||||
<Eye className="mr-1.5 h-3.5 w-3.5" /> {t("view")}
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
@@ -134,22 +138,24 @@ export function UserHero({
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Badge>{user.permission.rankName || `Rank ${user.rank}`}</Badge>
|
||||
<Badge>
|
||||
{user.permission.rankName || t("rank", { rank: user.rank })}
|
||||
</Badge>
|
||||
<Badge
|
||||
variant={isOnline ? "default" : "outline"}
|
||||
className={isOnline ? "bg-[var(--admin-success-subtle)]" : ""}
|
||||
>
|
||||
{isOnline ? (
|
||||
<>
|
||||
<Wifi className="mr-1 h-3 w-3" /> Online
|
||||
<Wifi className="mr-1 h-3 w-3" /> {t("online")}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<WifiOff className="mr-1 h-3 w-3" /> Offline
|
||||
<WifiOff className="mr-1 h-3 w-3" /> {t("offline")}
|
||||
</>
|
||||
)}
|
||||
</Badge>
|
||||
{activeBan && <Badge variant="destructive">Banned</Badge>}
|
||||
{activeBan && <Badge variant="destructive">{t("banned")}</Badge>}
|
||||
{user.twoFactorConfirmed ? (
|
||||
<Badge
|
||||
variant="outline"
|
||||
@@ -167,24 +173,32 @@ export function UserHero({
|
||||
<span className="font-semibold">
|
||||
{formatNumber(user.credits)}
|
||||
</span>
|
||||
<span className="text-muted-foreground text-xs">credits</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
{t("credits")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-sm">
|
||||
<CurrencyIcon kind="diamonds" size={18} />
|
||||
<span className="font-semibold">{formatNumber(diamonds)}</span>
|
||||
<span className="text-muted-foreground text-xs">diamonds</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
{t("diamonds")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-sm">
|
||||
<CurrencyIcon kind="duckets" size={18} />
|
||||
<span className="font-semibold">{formatNumber(duckets)}</span>
|
||||
<span className="text-muted-foreground text-xs">duckets</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
{t("duckets")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-sm">
|
||||
<CurrencyIcon kind="pixels" size={18} />
|
||||
<span className="font-semibold">
|
||||
{formatNumber(user.pixels)}
|
||||
</span>
|
||||
<span className="text-muted-foreground text-xs">pixels</span>
|
||||
<span className="text-muted-foreground text-xs">
|
||||
{t("pixels")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -197,18 +211,26 @@ export function UserHero({
|
||||
>
|
||||
<DoorOpen className="h-4 w-4 mx-auto text-muted-foreground" />
|
||||
<p className="text-lg font-bold">{roomCount}</p>
|
||||
<p className="text-[10px] text-muted-foreground">Rooms</p>
|
||||
<p className="text-[10px] text-muted-foreground">{t("rooms")}</p>
|
||||
</Link>
|
||||
<div className="rounded-lg border bg-card px-3 py-2 text-center">
|
||||
<MessageSquare className="h-4 w-4 mx-auto text-muted-foreground" />
|
||||
<p className="text-lg font-bold">{formatNumber(chatCount)}</p>
|
||||
<p className="text-[10px] text-muted-foreground">Messages</p>
|
||||
</div>
|
||||
<div className="rounded-lg border bg-card px-3 py-2 text-center">
|
||||
<ArrowLeftRight className="h-4 w-4 mx-auto text-muted-foreground" />
|
||||
<p className="text-lg font-bold">{tradeCount}</p>
|
||||
<p className="text-[10px] text-muted-foreground">Trades</p>
|
||||
</div>
|
||||
{canViewLogs && (
|
||||
<div className="rounded-lg border bg-card px-3 py-2 text-center">
|
||||
<MessageSquare className="h-4 w-4 mx-auto text-muted-foreground" />
|
||||
<p className="text-lg font-bold">{formatNumber(chatCount)}</p>
|
||||
<p className="text-[10px] text-muted-foreground">
|
||||
{t("messages")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{canViewLogs && (
|
||||
<div className="rounded-lg border bg-card px-3 py-2 text-center">
|
||||
<ArrowLeftRight className="h-4 w-4 mx-auto text-muted-foreground" />
|
||||
<p className="text-lg font-bold">{tradeCount}</p>
|
||||
<p className="text-[10px] text-muted-foreground">
|
||||
{t("trades")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user