Files
ttrpg-tools/src/components/journal/JournalHeader.tsx
T
hypercross 421af125bb feat(journal): delete sessions from the ui
Add a confirmation dialog that spells out the removal is irreversible, and expose delete from the GM session dropdown and the lobby session list.
2026-09-13 13:36:42 +08:00

87 lines
2.8 KiB
TypeScript

/**
* JournalHeader — status dot, player name, session dropdown, leave & close
*/
import { Component, Show } from "solid-js";
import { useJournalStream, leaveSession } from "../stores/journalStream";
import { SessionDropdown } from "./SessionDropdown";
interface JournalHeaderProps {
onClose: () => void;
onCreateSession: () => void;
onDeleteSession: (id: string, name: string) => void;
}
export const JournalHeader: Component<JournalHeaderProps> = (props) => {
const stream = useJournalStream();
const handleLeave = () => leaveSession();
return (
<div class="flex items-center justify-between px-3 py-2 border-b border-gray-200 shrink-0">
<div class="flex items-center gap-2 min-w-0">
<span
class="w-2 h-2 rounded-full shrink-0"
classList={{
"bg-gray-400": stream.connectionStatus === "disconnected",
"bg-yellow-400 animate-pulse":
stream.connectionStatus === "connecting",
"bg-green-500": stream.connectionStatus === "connected",
"bg-red-500": stream.connectionStatus === "error",
}}
title={stream.connectionStatus}
/>
<Show
when={stream.connected && stream.sessionId}
fallback={
<h2 class="text-sm font-semibold text-gray-700 truncate">
{stream.connected ? "选择会话" : "未连接"}
</h2>
}
>
<div class="min-w-0">
<p class="text-sm font-semibold text-gray-700 truncate leading-tight flex items-center gap-1">
{stream.myName}
<Show when={stream.myRole !== "gm"}>
<span
class={`text-[10px] px-1 rounded ${
stream.myRole === "observer"
? "bg-gray-200 text-gray-500"
: "bg-blue-100 text-blue-600"
}`}
>
{stream.myRole}
</span>
</Show>
</p>
{/* Clickable subtitle — session dropdown (GM only) */}
<Show when={stream.myRole === "gm"}>
<SessionDropdown
onCreate={props.onCreateSession}
onDelete={props.onDeleteSession}
/>
</Show>
</div>
</Show>
</div>
<div class="flex items-center gap-1 shrink-0">
<Show when={stream.sessionId}>
<button
onClick={handleLeave}
class="text-xs text-gray-400 hover:text-blue-500 px-1"
title="返回会话列表"
>
←
</button>
</Show>
<button
onClick={props.onClose}
class="text-gray-400 hover:text-gray-600 text-sm px-1"
title="隐藏面板"
>
▸
</button>
</div>
</div>
);
};