forked from administration/panel
Compare commits
2 Commits
main
...
user-strea
Author | SHA1 | Date |
---|---|---|
|
b80ae05820 | |
|
7c22a25447 |
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
"use client"
|
||||
|
||||
import { UserReviewCard } from "@/components/pages/stream/UserReviewCard";
|
||||
import { Card, CardDescription } from "@/components/ui/card";
|
||||
import { Account, fetchAccountById, fetchUserById } from "@/lib/db";
|
||||
import { Circle } from "lucide-react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { User } from "revolt-api";
|
||||
|
||||
export default function UserStream() {
|
||||
const [connectionState, setConnectionState] = useState<"Connecting"|"Connected"|"Disconnected">("Connecting");
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [account, setAccount] = useState<Account | null>(null);
|
||||
|
||||
const connectionColour = useMemo(() => {
|
||||
switch(connectionState) {
|
||||
case "Connected": return "#55aa7f";
|
||||
case "Connecting": return "#fb923c";
|
||||
case "Disconnected": return "#ef4444";
|
||||
}
|
||||
}, [connectionState]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUserById("01H6BZB5F4B6GTKSJCV6TRGZ22").then(setUser);
|
||||
fetchAccountById("01H6BZB5F4B6GTKSJCV6TRGZ22").then(setAccount);
|
||||
|
||||
setTimeout(() => setConnectionState("Connected"), 1000);
|
||||
}, []);
|
||||
|
||||
return account ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<Card className="flex flex-row justify-end pr-2 h-[40px]">
|
||||
<CardDescription className="flex flex-row gap-2 items-center">
|
||||
<span className="flex flex-row items-center gap-1">
|
||||
{connectionState}
|
||||
<Circle color={connectionColour} fill={connectionColour} />
|
||||
</span>
|
||||
</CardDescription>
|
||||
</Card>
|
||||
<div className="flex flex-col gap-2">
|
||||
<UserReviewCard user={user ?? undefined} account={account} />
|
||||
<UserReviewCard user={undefined} account={account} />
|
||||
</div>
|
||||
</div>
|
||||
) : null;
|
||||
}
|
|
@ -11,6 +11,7 @@ import {
|
|||
Siren,
|
||||
Sparkles,
|
||||
TrendingUp,
|
||||
ClipboardList,
|
||||
} from "lucide-react";
|
||||
|
||||
export function NavigationLinks() {
|
||||
|
@ -40,6 +41,12 @@ export function NavigationLinks() {
|
|||
>
|
||||
<Search className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
className={buttonVariants({ variant: "outline", size: "icon" })}
|
||||
href="/panel/stream"
|
||||
>
|
||||
<ClipboardList className="h-4 w-4" />
|
||||
</Link>
|
||||
<Link
|
||||
className={buttonVariants({ variant: "outline", size: "icon" })}
|
||||
href="/panel/shield"
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
"use client"
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { DropdownMenuContent, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
|
||||
import { toast } from "@/components/ui/use-toast";
|
||||
import { Account } from "@/lib/db";
|
||||
import { DropdownMenu } from "@radix-ui/react-dropdown-menu";
|
||||
import dayjs from "dayjs";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { MoreHorizontal } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { User } from "revolt-api";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
export function UserReviewCard({ user, account }: { user?: User, account: Account }) {
|
||||
const router = useRouter();
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
|
||||
return <Card className="flex">
|
||||
<CardHeader className="flex-1">
|
||||
{
|
||||
user
|
||||
? <CardTitle>{user.username}#{user.discriminator}</CardTitle>
|
||||
: <CardTitle className="text-gray-500">Pending onboarding</CardTitle>
|
||||
}
|
||||
<CardDescription>{account.email} · {dayjs(decodeTime(account._id)).fromNow()}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex items-center py-0 gap-2">
|
||||
<Button className="bg-orange-400 hover:bg-orange-300">Suspend</Button>
|
||||
<Button variant="destructive">Ban</Button>
|
||||
<DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" className="px-2"><MoreHorizontal /></Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="flex flex-col">
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setDropdownOpen(false);
|
||||
navigator.clipboard.writeText(account._id);
|
||||
toast({
|
||||
title: "Copied ID",
|
||||
description: account._id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Copy ID
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setDropdownOpen(false);
|
||||
navigator.clipboard.writeText(account.email);
|
||||
toast({
|
||||
title: "Copied email",
|
||||
description: account.email,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Copy email
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setDropdownOpen(false);
|
||||
router.push(`/panel/inspect/account/${account._id}`);
|
||||
}}
|
||||
>
|
||||
Inspect account
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => {
|
||||
setDropdownOpen(false);
|
||||
router.push(`/panel/inspect/user/${user?._id}`);
|
||||
}}
|
||||
disabled={!user}
|
||||
>
|
||||
Inspect user
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => alert("todo")}
|
||||
disabled={true}
|
||||
>
|
||||
Block email provider
|
||||
</Button>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</CardContent>
|
||||
</Card>;
|
||||
}
|
Loading…
Reference in New Issue