refactor(ui): move category creation from ChannelSidebar to ServerSettingsMenu
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 3m24s
All checks were successful
Deploy Waveform to VPS / deploy (push) Successful in 3m24s
This commit is contained in:
parent
c6af4e1565
commit
4622dac9bf
2 changed files with 88 additions and 33 deletions
|
|
@ -1,57 +1,119 @@
|
||||||
/**
|
/**
|
||||||
* @file components/layout/ServerSettingsMenu.tsx
|
* @file components/layout/ServerSettingsMenu.tsx
|
||||||
* @description Header button triggering the server overview/settings modal.
|
* @description Single settings dropdown menu providing server management actions (Settings, Create Category, Create Channel).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
import { Settings } from "lucide-react";
|
import { Settings, FolderPlus, PlusCircle, Sliders } from "lucide-react";
|
||||||
import { EditServerModal } from "@/components/modals/EditServerModal";
|
import { EditServerModal } from "@/components/modals/EditServerModal";
|
||||||
|
import { CreateCategoryModal } from "@/components/modals/CreateCategoryModal";
|
||||||
|
import { CreateChannelModal } from "@/components/modals/CreateChannelModal";
|
||||||
|
|
||||||
/**
|
/** Props for the ServerSettingsMenu component. */
|
||||||
* Props for the ServerSettingsMenu component.
|
|
||||||
*
|
|
||||||
* @interface ServerSettingsMenuProps
|
|
||||||
* @property {string} serverId - The unique identifier of the server.
|
|
||||||
* @property {string} serverName - The display name of the server.
|
|
||||||
*/
|
|
||||||
interface ServerSettingsMenuProps {
|
interface ServerSettingsMenuProps {
|
||||||
serverId: string;
|
serverId: string;
|
||||||
serverName: string;
|
serverName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Renders a server management dropdown menu with modal triggers for channel, category, and server settings. */
|
||||||
* Renders a settings button that opens the edit server modal.
|
|
||||||
*
|
|
||||||
* @param {ServerSettingsMenuProps} props - The component props.
|
|
||||||
* @param {string} props.serverId - The unique identifier of the server.
|
|
||||||
* @param {string} props.serverName - The display name of the server.
|
|
||||||
* @returns {JSX.Element} The rendered server settings trigger and modal component.
|
|
||||||
*/
|
|
||||||
export function ServerSettingsMenu({
|
export function ServerSettingsMenu({
|
||||||
serverId,
|
serverId,
|
||||||
serverName,
|
serverName,
|
||||||
}: ServerSettingsMenuProps) {
|
}: ServerSettingsMenuProps) {
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||||
|
const [isEditServerOpen, setIsEditServerOpen] = useState(false);
|
||||||
|
const [isCreateCategoryOpen, setIsCreateCategoryOpen] = useState(false);
|
||||||
|
const [isCreateChannelOpen, setIsCreateChannelOpen] = useState(false);
|
||||||
|
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// Close the menu when clicked outside of it
|
||||||
|
useEffect(() => {
|
||||||
|
function handleClickOutside(event: MouseEvent) {
|
||||||
|
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isMenuOpen) {
|
||||||
|
document.addEventListener("mousedown", handleClickOutside);
|
||||||
|
}
|
||||||
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||||
|
}, [isMenuOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="relative" ref={menuRef}>
|
||||||
|
{/* Button */}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setIsModalOpen(true)}
|
onClick={() => setIsMenuOpen((prev) => !prev)}
|
||||||
title="Server Settings"
|
title="Server-Optionen"
|
||||||
className="p-1.5 rounded-md text-muted hover:text-white hover:bg-surface transition-colors cursor-pointer"
|
className="p-1.5 rounded-md text-muted hover:text-white hover:bg-surface transition-colors cursor-pointer"
|
||||||
>
|
>
|
||||||
<Settings className="w-5 h-5" />
|
<Settings className="w-5 h-5" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Dropdown Menü */}
|
||||||
|
{isMenuOpen && (
|
||||||
|
<div className="absolute right-0 mt-2 w-52 bg-surface border border-background rounded-lg shadow-lg py-1 z-50 animate-in fade-in zoom-in-95 duration-100">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
setIsCreateChannelOpen(true);
|
||||||
|
}}
|
||||||
|
className="w-full flex items-center gap-2 px-3 py-2 text-sm text-muted hover:text-white hover:bg-background transition-colors text-left cursor-pointer"
|
||||||
|
>
|
||||||
|
<PlusCircle className="w-4 h-4" />
|
||||||
|
<span>Kanal erstellen</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
setIsCreateCategoryOpen(true);
|
||||||
|
}}
|
||||||
|
className="w-full flex items-center gap-2 px-3 py-2 text-sm text-muted hover:text-white hover:bg-background transition-colors text-left cursor-pointer"
|
||||||
|
>
|
||||||
|
<FolderPlus className="w-4 h-4" />
|
||||||
|
<span>Kategorie erstellen</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="my-1 border-t border-background" />
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setIsMenuOpen(false);
|
||||||
|
setIsEditServerOpen(true);
|
||||||
|
}}
|
||||||
|
className="w-full flex items-center gap-2 px-3 py-2 text-sm text-muted hover:text-white hover:bg-background transition-colors text-left cursor-pointer"
|
||||||
|
>
|
||||||
|
<Sliders className="w-4 h-4" />
|
||||||
|
<span>Servereinstellungen</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Modals */}
|
||||||
<EditServerModal
|
<EditServerModal
|
||||||
isOpen={isModalOpen}
|
isOpen={isEditServerOpen}
|
||||||
serverId={serverId}
|
serverId={serverId}
|
||||||
initialName={serverName}
|
initialName={serverName}
|
||||||
onClose={() => setIsModalOpen(false)}
|
onClose={() => setIsEditServerOpen(false)}
|
||||||
/>
|
/>
|
||||||
</>
|
<CreateCategoryModal
|
||||||
|
isOpen={isCreateCategoryOpen}
|
||||||
|
onClose={() => setIsCreateCategoryOpen(false)}
|
||||||
|
serverId={serverId}
|
||||||
|
/>
|
||||||
|
<CreateChannelModal
|
||||||
|
isOpen={isCreateChannelOpen}
|
||||||
|
onClose={() => setIsCreateChannelOpen(false)}
|
||||||
|
serverId={serverId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import { CreateCategoryModal } from "@/components/modals/CreateCategoryModal";
|
||||||
import { EditChannelModal } from "@/components/modals/EditChannelModal";
|
import { EditChannelModal } from "@/components/modals/EditChannelModal";
|
||||||
import { EditCategoryModal } from "@/components/modals/EditCategoryModal";
|
import { EditCategoryModal } from "@/components/modals/EditCategoryModal";
|
||||||
import { CategorySection } from "./CategorySection";
|
import { CategorySection } from "./CategorySection";
|
||||||
import { FolderPlus, PanelLeftClose } from "lucide-react";
|
import { PanelLeftClose } from "lucide-react";
|
||||||
import type { Category, Channel } from "@/db/schema";
|
import type { Category, Channel } from "@/db/schema";
|
||||||
|
|
||||||
/** Renders the channel sidebar navigation for the active server. */
|
/** Renders the channel sidebar navigation for the active server. */
|
||||||
|
|
@ -55,13 +55,6 @@ export function ChannelSidebar() {
|
||||||
<div className="h-14 border-b border-background flex items-center justify-between px-4 font-bold text-white shadow-sm shrink-0">
|
<div className="h-14 border-b border-background flex items-center justify-between px-4 font-bold text-white shadow-sm shrink-0">
|
||||||
<span className="truncate">{activeServer.name}</span>
|
<span className="truncate">{activeServer.name}</span>
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setIsCreateCategoryOpen(true)}
|
|
||||||
className="p-1.5 rounded-md text-muted hover:text-white hover:bg-surface transition-colors cursor-pointer shrink-0"
|
|
||||||
>
|
|
||||||
<FolderPlus className="w-4 h-4" />
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={toggleNav}
|
onClick={toggleNav}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue