Files
joel/src/web/templates/components/dashboard/layout.tsx
2026-02-26 14:45:57 +01:00

126 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// oxlint-disable-next-line no-unused-vars
import { Html } from "@elysiajs/html";
import type { Guild, GuildDetailData, User } from "./shared";
import { GuildDetailView } from "./guild-detail";
export function DashboardEmptyState() {
return (
<div class="rounded-2xl border border-dashed border-slate-700 bg-slate-900/55 p-10 text-center">
<div class="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-xl border border-slate-700 bg-slate-800/70 text-xl">🛡</div>
<h2 class="text-2xl font-semibold text-white">Select a server</h2>
<p class="mx-auto mt-2 max-w-2xl text-sm text-slate-400">
Choose a server from the sidebar to configure Joel&apos;s system prompts and bot options.
</p>
</div>
);
}
export function DashboardSidebar({ user, guilds, initialGuild }: { user: User; guilds: Guild[]; initialGuild?: GuildDetailData }) {
return (
<aside class="h-fit rounded-2xl border border-slate-800 bg-slate-900/75 p-4 backdrop-blur-sm lg:sticky lg:top-6">
<div class="mb-4 flex items-center gap-3 rounded-xl border border-slate-800 bg-slate-950/90 px-3 py-3">
<div class="flex h-10 w-10 items-center justify-center rounded-xl bg-indigo-500/20 text-lg">🤖</div>
<div>
<div class="text-sm font-semibold text-white">Joel Dashboard</div>
<div class="text-xs text-slate-400">Server control panel</div>
</div>
</div>
<nav class="mb-4 space-y-1 rounded-xl border border-slate-800 bg-slate-950/60 p-2">
<button type="button" class="w-full rounded-lg bg-indigo-500/15 px-3 py-2 text-left text-sm font-medium text-indigo-200">
Servers
</button>
<button type="button" class="w-full rounded-lg px-3 py-2 text-left text-sm text-slate-500" disabled>
Settings
</button>
<button type="button" class="w-full rounded-lg px-3 py-2 text-left text-sm text-slate-500" disabled>
Analytics
</button>
<button type="button" class="w-full rounded-lg px-3 py-2 text-left text-sm text-slate-500" disabled>
Help
</button>
</nav>
<div class="rounded-xl border border-slate-800 bg-slate-950/60 p-3">
<div class="mb-2 flex items-center justify-between text-xs font-semibold uppercase tracking-wide text-slate-400">
<span>Your Servers</span>
<span>{guilds.length}</span>
</div>
<div id="guild-list" class="max-h-[52vh] space-y-2 overflow-y-auto pr-1">
{guilds.length === 0 ? (
<p class="text-sm text-slate-400">No shared servers found.</p>
) : (
guilds.map((g) => (
<button
type="button"
class={`guild-list-item flex w-full items-center gap-3 rounded-xl border px-3 py-2.5 text-left text-sm transition ${
initialGuild?.guildId === g.id
? "guild-item-active"
: "guild-item-inactive"
}`}
data-guild-id={g.id}
hx-get={`/dashboard/guild/${g.id}`}
hx-target="#guild-main-content"
hx-swap="innerHTML"
hx-push-url="true"
{...{ preload: "mouseover" }}
>
<span class="text-base">🛡</span>
<span class="truncate">{g.name}</span>
</button>
))
)}
</div>
</div>
<div class="mt-4 rounded-xl border border-slate-800 bg-slate-950/90 px-3 py-3">
<p class="text-[11px] font-medium uppercase tracking-wide text-slate-500">Logged in as</p>
<p class="mt-1 truncate text-sm text-slate-200">{user.global_name || user.username}</p>
</div>
</aside>
);
}
export function DashboardHeader() {
return (
<header class="flex flex-col gap-4 rounded-2xl border border-slate-800 bg-slate-900/75 px-4 py-4 backdrop-blur-sm sm:flex-row sm:items-center sm:justify-between sm:px-5">
<div>
<h1 class="text-lg font-semibold text-white sm:text-xl">Server Management</h1>
<p class="mt-1 text-sm text-slate-400">Configure Joel&apos;s prompts, behavior, and response settings.</p>
</div>
<div class="flex items-center gap-2">
<a
href="/ai-helper"
class="inline-flex items-center rounded-lg border border-indigo-500 bg-indigo-500/15 px-3 py-2 text-xs font-medium text-indigo-200 hover:bg-indigo-500/25"
>
🧠 AI Helper
</a>
<button
class="inline-flex items-center rounded-lg border border-slate-700 bg-slate-800 px-3 py-2 text-xs font-medium text-slate-200 hover:bg-slate-700"
hx-post="/auth/logout"
hx-redirect="/"
>
Logout
</button>
</div>
</header>
);
}
export function DashboardMainContent({ initialGuild }: { initialGuild?: GuildDetailData }) {
return (
<section id="guild-main-content" class="space-y-4">
{initialGuild ? (
<GuildDetailView
guildId={initialGuild.guildId}
guildName={initialGuild.guildName}
options={initialGuild.options}
personalities={initialGuild.personalities}
/>
) : (
<DashboardEmptyState />
)}
</section>
);
}