Files
dumpsterChat/web/src/components/MemberContextMenu.tsx
T

139 lines
4.6 KiB
TypeScript

import { useState } from "react";
interface MemberContextMenuProps {
memberId: string;
username: string;
canKick: boolean;
canBan: boolean;
canMute: boolean;
onMessage?: () => void;
onKick?: (reason: string) => void;
onBan?: (reason: string) => void;
onMute?: (duration: string, reason: string) => void;
onClose: () => void;
}
export function MemberContextMenu({
username,
canKick,
canBan,
canMute,
onMessage,
onKick,
onBan,
onMute,
onClose,
}: MemberContextMenuProps) {
const [mode, setMode] = useState<"menu" | "kick" | "ban" | "mute">("menu");
const [reason, setReason] = useState("");
const [duration, setDuration] = useState("1h");
if (mode === "kick") {
return (
<div className="absolute z-50 bg-gb-bg border border-gb-bg-t p-3 font-mono text-xs shadow-lg min-w-[200px]">
<div className="text-gb-orange mb-2">KICK {username.toUpperCase()}</div>
<input
type="text"
value={reason}
onChange={(e) => setReason(e.target.value)}
placeholder="reason (optional)"
className="terminal-input w-full mb-2"
/>
<div className="flex gap-2">
<button onClick={() => onKick?.(reason)} className="flex-1 bg-gb-red text-gb-bg py-1 hover:bg-gb-orange">
[KICK]
</button>
<button onClick={() => setMode("menu")} className="flex-1 bg-gb-bg-t text-gb-fg py-1 hover:bg-gb-bg-s">
[BACK]
</button>
</div>
</div>
);
}
if (mode === "ban") {
return (
<div className="absolute z-50 bg-gb-bg border border-gb-bg-t p-3 font-mono text-xs shadow-lg min-w-[200px]">
<div className="text-gb-orange mb-2">BAN {username.toUpperCase()}</div>
<input
type="text"
value={reason}
onChange={(e) => setReason(e.target.value)}
placeholder="reason (optional)"
className="terminal-input w-full mb-2"
/>
<div className="flex gap-2">
<button onClick={() => onBan?.(reason)} className="flex-1 bg-gb-red text-gb-bg py-1 hover:bg-gb-orange">
[BAN]
</button>
<button onClick={() => setMode("menu")} className="flex-1 bg-gb-bg-t text-gb-fg py-1 hover:bg-gb-bg-s">
[BACK]
</button>
</div>
</div>
);
}
if (mode === "mute") {
return (
<div className="absolute z-50 bg-gb-bg border border-gb-bg-t p-3 font-mono text-xs shadow-lg min-w-[200px]">
<div className="text-gb-orange mb-2">MUTE {username.toUpperCase()}</div>
<select
value={duration}
onChange={(e) => setDuration(e.target.value)}
className="w-full mb-2 bg-gb-bg-s text-gb-fg text-xs border-none outline-none"
>
<option value="15m">15 minutes</option>
<option value="1h">1 hour</option>
<option value="6h">6 hours</option>
<option value="1d">1 day</option>
<option value="7d">7 days</option>
<option value="">permanent</option>
</select>
<input
type="text"
value={reason}
onChange={(e) => setReason(e.target.value)}
placeholder="reason (optional)"
className="terminal-input w-full mb-2"
/>
<div className="flex gap-2">
<button onClick={() => onMute?.(duration, reason)} className="flex-1 bg-gb-yellow text-gb-bg py-1 hover:bg-gb-orange">
[MUTE]
</button>
<button onClick={() => setMode("menu")} className="flex-1 bg-gb-bg-t text-gb-fg py-1 hover:bg-gb-bg-s">
[BACK]
</button>
</div>
</div>
);
}
return (
<div className="absolute z-50 bg-gb-bg border border-gb-bg-t py-1 font-mono text-xs shadow-lg min-w-[140px]">
<button onClick={onMessage} className="w-full text-left px-3 py-1 hover:bg-gb-bg-t text-gb-fg">
Message
</button>
{canKick && (
<button onClick={() => setMode("kick")} className="w-full text-left px-3 py-1 hover:bg-gb-bg-t text-gb-yellow">
Kick
</button>
)}
{canMute && (
<button onClick={() => setMode("mute")} className="w-full text-left px-3 py-1 hover:bg-gb-bg-t text-gb-orange">
Mute
</button>
)}
{canBan && (
<button onClick={() => setMode("ban")} className="w-full text-left px-3 py-1 hover:bg-gb-bg-t text-gb-red">
Ban
</button>
)}
<div className="border-t border-gb-bg-t my-1" />
<button onClick={onClose} className="w-full text-left px-3 py-1 hover:bg-gb-bg-t text-gb-fg-f">
Cancel
</button>
</div>
);
}