feat: make all sidebar data loading async

This commit is contained in:
2026-03-11 00:37:43 +07:00 Unverified
parent 8689bcad9a
commit 5052b05ea2
2 changed files with 107 additions and 41 deletions
+81 -23
View File
@@ -1,4 +1,4 @@
import { eq, sql } from "drizzle-orm";
import { desc, eq, sql } from "drizzle-orm";
import {
ArrowLeftRight,
Badge,
@@ -72,11 +72,24 @@ export default async function AdminLayout({
}) {
if (!(await adminCheck())) redirect("/login");
const vers = await db
const vers = db
.select()
.from(versions)
.orderBy(desc(versions.id))
.catch(() => [{ id: "..", name: "Error Fetching List." }]);
const tlVersions = db
.select({
name: sql<string>`${tierlistTypes.name} || ' ' || ${tierlistVersions.name}`.as(
"name",
),
url: sql<string>`${tierlistVersions.type} || '/' || ${tierlistVersions.id}`,
})
.from(tierlistVersions)
.orderBy(tierlistTypes.order, tierlistVersions.order)
.innerJoin(tierlistTypes, eq(tierlistTypes.id, tierlistVersions.type))
.catch(() => []);
return (
<SidebarProvider>
<Sidebar variant="floating">
@@ -169,13 +182,9 @@ export default async function AdminLayout({
</Dialog>
<SidebarGroupContent>
<SidebarMenu>
{vers.map((v) => (
<SidebarMenuItem key={v.id}>
<SidebarLink href={`/admin/ver/${v.id}`} disabled>
{v.name}
</SidebarLink>
</SidebarMenuItem>
))}
<Suspense>
<VersionsList versions={vers} />
</Suspense>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
@@ -197,7 +206,7 @@ export default async function AdminLayout({
</SidebarMenu>
}
>
<AdminShortcuts />
<AdminShortcuts versions={tlVersions} />
</Suspense>
<SidebarMenuItem>
<SidebarLink href="/admin/char">
@@ -230,7 +239,12 @@ export default async function AdminLayout({
</SidebarFooter>
</Sidebar>
<SidebarInset className="bg-transparent">
<AdminNavbar />
<Suspense>
<AdminNavbarLoader
adminShortcuts={tlVersions}
tierlistVersions={vers}
/>
</Suspense>
{modal}
{children}
</SidebarInset>
@@ -291,18 +305,62 @@ async function HealthStatus() {
);
}
async function AdminShortcuts() {
const versions = await db
.select({
name: sql<string>`${tierlistTypes.name} || ' ' || ${tierlistVersions.name}`.as(
"name",
),
url: sql<string>`${tierlistVersions.type} || '/' || ${tierlistVersions.id}`,
})
.from(tierlistVersions)
.orderBy(tierlistTypes.order, tierlistVersions.order)
.innerJoin(tierlistTypes, eq(tierlistTypes.id, tierlistVersions.type))
.catch(() => []);
async function AdminNavbarLoader({
adminShortcuts,
tierlistVersions,
}: {
adminShortcuts: Promise<
{
name: string;
url: string;
}[]
>;
tierlistVersions: Promise<
{
id: string;
name: string;
}[]
>;
}) {
return (
<AdminNavbar
adminShortcuts={await adminShortcuts}
tierlistVersions={await tierlistVersions}
/>
);
}
async function VersionsList({
versions: prom,
}: {
versions: Promise<
{
id: string;
name: string;
}[]
>;
}) {
const vers = await prom;
return (
<>
{vers.map((v) => (
<SidebarMenuItem key={v.id}>
<SidebarLink href={`/admin/ver/${v.id}`} disabled>
{v.name}
</SidebarLink>
</SidebarMenuItem>
))}
</>
);
}
async function AdminShortcuts({
versions: prom,
}: {
versions: Promise<{ name: string; url: string }[]>;
}) {
const versions = await prom;
return (
<SidebarMenu>
<SidebarMenuItem>
+26 -18
View File
@@ -45,7 +45,7 @@ function VersionBadge({
}) {
return (
<span className={cn("text-[10px] font-bold leading-none", className)}>
{name}
{name?.match(/[0-9.]+$/)?.[1]}
</span>
);
}
@@ -154,7 +154,19 @@ function DropdownMenu({
);
}
export function AdminNavbar() {
export function AdminNavbar({
adminShortcuts,
tierlistVersions,
}: {
adminShortcuts: {
name: string;
url: string;
}[];
tierlistVersions: {
id: string;
name: string;
}[];
}) {
const pathname = usePathname();
const isMobile = useIsMobile();
const [showLabels, setShowLabels] = useState(false);
@@ -162,7 +174,7 @@ export function AdminNavbar() {
const navRef = useRef<HTMLDivElement>(null);
const items: NavbarEntry[] = [
{ name: "หน้าหลัก", href: "/admin/", icon: Home, divide: true },
{ name: "หน้าหลัก", href: "/admin", icon: Home, divide: true },
{
name: "Tierlist",
icon: Table,
@@ -178,8 +190,11 @@ export function AdminNavbar() {
sub: [
{ name: "Types", icon: Form, href: "/admin/ver/types" },
{ name: "Create", icon: Plus, href: "/admin/ver/create" },
{ name: "6.4", icon: VersionBadge, href: "/admin/ver/64" },
{ name: "6.3", icon: VersionBadge, href: "/admin/ver/63" },
...tierlistVersions.map((v) => ({
name: v.name,
icon: VersionBadge,
href: `/admin/ver/${v.id}`,
})),
],
},
{
@@ -195,18 +210,11 @@ export function AdminNavbar() {
{
name: "Tierlist",
icon: Grid3x3,
sub: [
{
name: "Abyss 6.4",
icon: VersionBadge,
href: "/tl/aby/64/admin",
},
{
name: "Abyss 6.3",
icon: VersionBadge,
href: "/tl/aby/63/admin",
},
],
sub: adminShortcuts.map((s) => ({
name: s.name,
icon: VersionBadge,
href: `/tl/${s.url}/admin`,
})),
},
],
},
@@ -245,7 +253,7 @@ export function AdminNavbar() {
return (
<div ref={navRef} className="sticky top-0 z-49">
<div className="flex items-center gap-1 px-2 py-1.5 border-b border-white/10 bg-card/50 backdrop-blur-sm">
<div className="flex items-center gap-1 px-2 py-1.5 border-b border-white/10 bg-card/75 backdrop-blur-sm">
<div className="flex items-center gap-1 shrink-0">
{prefixParent && (
<button