126 lines
5.2 KiB
TypeScript
126 lines
5.2 KiB
TypeScript
// 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'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'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>
|
||
);
|
||
}
|