[deploy] improve dashboard usability and form visibility
This commit is contained in:
@@ -10,12 +10,64 @@ html, body, #root {
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||||
|
background: #111111;
|
||||||
|
color: #f5f5f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
textarea,
|
||||||
|
select {
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.14);
|
||||||
|
border-radius: 14px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
color: inherit;
|
||||||
|
font: inherit;
|
||||||
|
padding: 0.85rem 1rem;
|
||||||
|
transition: border-color 160ms ease, background-color 160ms ease, box-shadow 160ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
min-height: 120px;
|
||||||
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::placeholder,
|
||||||
|
textarea::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.42);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:hover,
|
||||||
|
textarea:hover,
|
||||||
|
select:hover {
|
||||||
|
border-color: rgba(255, 255, 255, 0.22);
|
||||||
|
background: rgba(255, 255, 255, 0.07);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus,
|
||||||
|
textarea:focus,
|
||||||
|
select:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: rgba(58, 150, 255, 0.9);
|
||||||
|
box-shadow: 0 0 0 3px rgba(58, 150, 255, 0.18);
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 0.45rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.scrollbar-thin {
|
.scrollbar-thin {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
|
scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
|
||||||
|
|||||||
@@ -45,20 +45,20 @@ export function Header() {
|
|||||||
|
|
||||||
<div className="flex items-center gap-2 shrink-0">
|
<div className="flex items-center gap-2 shrink-0">
|
||||||
{statusMessage && (
|
{statusMessage && (
|
||||||
<Chip color="warning" size="sm" variant="flat" className="max-w-[200px]">
|
<Chip color="warning" size="sm" variant="solid" className="max-w-[220px]">
|
||||||
<span className="truncate">{statusMessage}</span>
|
<span className="truncate">{statusMessage}</span>
|
||||||
</Chip>
|
</Chip>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Tooltip content={dark ? 'Helles Design' : 'Dunkles Design'} placement="bottom">
|
<Tooltip content={dark ? 'Helles Design' : 'Dunkles Design'} placement="bottom">
|
||||||
<Button isIconOnly radius="lg" size="sm" variant="light" onPress={toggle}>
|
<Button isIconOnly radius="lg" size="sm" variant="bordered" onPress={toggle}>
|
||||||
{dark ? <Sun size={16} /> : <Moon size={16} />}
|
{dark ? <Sun size={16} /> : <Moon size={16} />}
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<Dropdown placement="bottom-end">
|
<Dropdown placement="bottom-end">
|
||||||
<DropdownTrigger>
|
<DropdownTrigger>
|
||||||
<Button className="gap-2" radius="lg" size="sm" variant="light">
|
<Button className="gap-2" radius="lg" size="sm" variant="bordered">
|
||||||
<Avatar name={user?.username} size="sm" className="size-6" />
|
<Avatar name={user?.username} size="sm" className="size-6" />
|
||||||
<span className="hidden sm:inline text-sm">{user?.username}</span>
|
<span className="hidden sm:inline text-sm">{user?.username}</span>
|
||||||
<ChevronDown size={14} />
|
<ChevronDown size={14} />
|
||||||
|
|||||||
@@ -114,10 +114,10 @@ export function Sidebar() {
|
|||||||
return (
|
return (
|
||||||
<Tooltip key={item.key} content={collapsed ? item.label : ''} placement="right" offset={8}>
|
<Tooltip key={item.key} content={collapsed ? item.label : ''} placement="right" offset={8}>
|
||||||
<Button
|
<Button
|
||||||
className="h-9 justify-start gap-3 px-2"
|
className="h-10 justify-start gap-3 px-3 font-medium"
|
||||||
color={isActive ? 'primary' : 'default'}
|
color={isActive ? 'primary' : 'default'}
|
||||||
radius="lg"
|
radius="lg"
|
||||||
variant={isActive ? 'flat' : 'light'}
|
variant={isActive ? 'solid' : 'flat'}
|
||||||
size="sm"
|
size="sm"
|
||||||
startContent={item.icon}
|
startContent={item.icon}
|
||||||
onPress={() => setSection(item.key)}
|
onPress={() => setSection(item.key)}
|
||||||
@@ -139,10 +139,10 @@ export function Sidebar() {
|
|||||||
)}
|
)}
|
||||||
<Tooltip content={collapsed ? 'Admin' : ''} placement="right" offset={8}>
|
<Tooltip content={collapsed ? 'Admin' : ''} placement="right" offset={8}>
|
||||||
<Button
|
<Button
|
||||||
className="h-9 justify-start gap-3 px-2"
|
className="h-10 justify-start gap-3 px-3 font-medium"
|
||||||
color={section === 'admin' ? 'warning' : 'default'}
|
color={section === 'admin' ? 'warning' : 'default'}
|
||||||
radius="lg"
|
radius="lg"
|
||||||
variant={section === 'admin' ? 'flat' : 'light'}
|
variant={section === 'admin' ? 'solid' : 'flat'}
|
||||||
size="sm"
|
size="sm"
|
||||||
startContent={<Wrench size={18} />}
|
startContent={<Wrench size={18} />}
|
||||||
onPress={() => setSection('admin')}
|
onPress={() => setSection('admin')}
|
||||||
@@ -161,7 +161,7 @@ export function Sidebar() {
|
|||||||
className="w-full"
|
className="w-full"
|
||||||
radius="lg"
|
radius="lg"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="light"
|
variant="bordered"
|
||||||
onPress={() => setCollapsed((c) => !c)}
|
onPress={() => setCollapsed((c) => !c)}
|
||||||
>
|
>
|
||||||
{collapsed ? <PanelLeft size={16} /> : <PanelLeftClose size={16} />}
|
{collapsed ? <PanelLeft size={16} /> : <PanelLeftClose size={16} />}
|
||||||
@@ -177,7 +177,7 @@ export function Sidebar() {
|
|||||||
<div className="text-[10px] text-default-400">Angemeldet</div>
|
<div className="text-[10px] text-default-400">Angemeldet</div>
|
||||||
</div>
|
</div>
|
||||||
<Tooltip content="Abmelden" placement="top">
|
<Tooltip content="Abmelden" placement="top">
|
||||||
<Button isIconOnly color="danger" radius="lg" size="sm" variant="light" onPress={handleLogout}>
|
<Button isIconOnly color="danger" radius="lg" size="sm" variant="flat" onPress={handleLogout}>
|
||||||
<LogOut size={14} />
|
<LogOut size={14} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -140,10 +140,10 @@ export function Dashboard() {
|
|||||||
{quickActions.map((action) => (
|
{quickActions.map((action) => (
|
||||||
<Button
|
<Button
|
||||||
key={action.key}
|
key={action.key}
|
||||||
className="justify-start"
|
className="justify-start font-medium"
|
||||||
color={action.color}
|
color={action.color}
|
||||||
startContent={action.icon}
|
startContent={action.icon}
|
||||||
variant="flat"
|
variant={action.color === 'default' ? 'bordered' : 'solid'}
|
||||||
onPress={() => setSection(action.key as any)}
|
onPress={() => setSection(action.key as any)}
|
||||||
>
|
>
|
||||||
{action.label}
|
{action.label}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export function ModulesPage() {
|
|||||||
</h3>
|
</h3>
|
||||||
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
||||||
{activeModules.map((module) => (
|
{activeModules.map((module) => (
|
||||||
<Card key={module.key} className="border border-success-100/30 bg-success-50/5">
|
<Card key={module.key} className="border border-success-400/25 bg-success-500/5">
|
||||||
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
|
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<div className="font-semibold">{module.name}</div>
|
<div className="font-semibold">{module.name}</div>
|
||||||
@@ -28,7 +28,7 @@ export function ModulesPage() {
|
|||||||
<div className="text-small text-default-400 truncate">{module.description}</div>
|
<div className="text-small text-default-400 truncate">{module.description}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Switch isSelected={module.enabled} onChange={(v) => toggleModule(module.key, v)} />
|
<Switch isSelected={module.enabled} color="success" onChange={(v) => toggleModule(module.key, v)} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
@@ -44,7 +44,7 @@ export function ModulesPage() {
|
|||||||
</h3>
|
</h3>
|
||||||
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
<div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
|
||||||
{inactiveModules.map((module) => (
|
{inactiveModules.map((module) => (
|
||||||
<Card key={module.key} className="border border-default-100 bg-default-50/20 opacity-70">
|
<Card key={module.key} className="border border-default-200/20 bg-default-100/5">
|
||||||
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
|
<CardContent className="flex flex-row items-center justify-between gap-4 p-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<div className="font-semibold">{module.name}</div>
|
<div className="font-semibold">{module.name}</div>
|
||||||
@@ -52,7 +52,7 @@ export function ModulesPage() {
|
|||||||
<div className="text-small text-default-400 truncate">{module.description}</div>
|
<div className="text-small text-default-400 truncate">{module.description}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Switch isSelected={module.enabled} onChange={(v) => toggleModule(module.key, v)} />
|
<Switch isSelected={module.enabled} color="primary" onChange={(v) => toggleModule(module.key, v)} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ export function SupportLogin() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Panel Channel ID</Label>
|
<Label>Panel Channel ID</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
placeholder="Channel ID eingeben"
|
placeholder="Channel ID eingeben"
|
||||||
value={supportLogin?.config?.panelChannelId || ''}
|
value={supportLogin?.config?.panelChannelId || ''}
|
||||||
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, panelChannelId: e.target.value } } : s)}
|
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, panelChannelId: e.target.value } } : s)}
|
||||||
@@ -36,6 +38,8 @@ export function SupportLogin() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Titel</Label>
|
<Label>Titel</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
value={supportLogin?.config?.title || 'Support Login'}
|
value={supportLogin?.config?.title || 'Support Login'}
|
||||||
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, title: e.target.value } } : s)}
|
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, title: e.target.value } } : s)}
|
||||||
/>
|
/>
|
||||||
@@ -44,6 +48,7 @@ export function SupportLogin() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Beschreibung</Label>
|
<Label>Beschreibung</Label>
|
||||||
<TextArea
|
<TextArea
|
||||||
|
variant="bordered"
|
||||||
value={supportLogin?.config?.description || ''}
|
value={supportLogin?.config?.description || ''}
|
||||||
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, description: e.target.value } } : s)}
|
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, description: e.target.value } } : s)}
|
||||||
/>
|
/>
|
||||||
@@ -52,6 +57,8 @@ export function SupportLogin() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Login Button Label</Label>
|
<Label>Login Button Label</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
value={supportLogin?.config?.loginLabel || 'Ich bin jetzt im Support'}
|
value={supportLogin?.config?.loginLabel || 'Ich bin jetzt im Support'}
|
||||||
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, loginLabel: e.target.value } } : s)}
|
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, loginLabel: e.target.value } } : s)}
|
||||||
/>
|
/>
|
||||||
@@ -60,6 +67,8 @@ export function SupportLogin() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Logout Button Label</Label>
|
<Label>Logout Button Label</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
value={supportLogin?.config?.logoutLabel || 'Ich bin nicht mehr im Support'}
|
value={supportLogin?.config?.logoutLabel || 'Ich bin nicht mehr im Support'}
|
||||||
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, logoutLabel: e.target.value } } : s)}
|
onChange={(e) => setSupportLogin((s) => s ? { ...s, config: { ...s.config, logoutLabel: e.target.value } } : s)}
|
||||||
/>
|
/>
|
||||||
@@ -71,7 +80,7 @@ export function SupportLogin() {
|
|||||||
<Button color="primary" startContent={<Save size={16} />} onPress={saveSupportLogin}>
|
<Button color="primary" startContent={<Save size={16} />} onPress={saveSupportLogin}>
|
||||||
Speichern & Panel senden
|
Speichern & Panel senden
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="flat" startContent={<Send size={16} />}>
|
<Button variant="bordered" startContent={<Send size={16} />}>
|
||||||
Panel manuell senden
|
Panel manuell senden
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,8 +107,8 @@ export function SupportLogin() {
|
|||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="flex gap-2">
|
<CardContent className="flex gap-2">
|
||||||
<Button size="sm" color="primary" variant="flat">{supportLogin?.config?.loginLabel || 'Login'}</Button>
|
<Button size="sm" color="primary">{supportLogin?.config?.loginLabel || 'Login'}</Button>
|
||||||
<Button size="sm" variant="flat">{supportLogin?.config?.logoutLabel || 'Logout'}</Button>
|
<Button size="sm" variant="bordered">{supportLogin?.config?.logoutLabel || 'Logout'}</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ export function Welcome() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Channel ID</Label>
|
<Label>Channel ID</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
placeholder="Channel ID fuer Willkommensnachrichten"
|
placeholder="Channel ID fuer Willkommensnachrichten"
|
||||||
value={settings.welcomeConfig?.channelId || settings.welcomeChannelId || ''}
|
value={settings.welcomeConfig?.channelId || settings.welcomeChannelId || ''}
|
||||||
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), channelId: e.target.value } }))}
|
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), channelId: e.target.value } }))}
|
||||||
@@ -33,6 +35,8 @@ export function Welcome() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Titel</Label>
|
<Label>Titel</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
placeholder="Willkommen {user}!"
|
placeholder="Willkommen {user}!"
|
||||||
value={settings.welcomeConfig?.embedTitle || ''}
|
value={settings.welcomeConfig?.embedTitle || ''}
|
||||||
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), embedTitle: e.target.value } }))}
|
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), embedTitle: e.target.value } }))}
|
||||||
@@ -42,6 +46,7 @@ export function Welcome() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Beschreibung</Label>
|
<Label>Beschreibung</Label>
|
||||||
<TextArea
|
<TextArea
|
||||||
|
variant="bordered"
|
||||||
placeholder="Beschreibung des Embeds"
|
placeholder="Beschreibung des Embeds"
|
||||||
value={settings.welcomeConfig?.embedDescription || ''}
|
value={settings.welcomeConfig?.embedDescription || ''}
|
||||||
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), embedDescription: e.target.value } }))}
|
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), embedDescription: e.target.value } }))}
|
||||||
@@ -51,6 +56,8 @@ export function Welcome() {
|
|||||||
<TextField>
|
<TextField>
|
||||||
<Label>Footer</Label>
|
<Label>Footer</Label>
|
||||||
<Input
|
<Input
|
||||||
|
variant="bordered"
|
||||||
|
size="lg"
|
||||||
placeholder={new Date().getFullYear().toString()}
|
placeholder={new Date().getFullYear().toString()}
|
||||||
value={settings.welcomeConfig?.embedFooter || ''}
|
value={settings.welcomeConfig?.embedFooter || ''}
|
||||||
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), embedFooter: e.target.value } }))}
|
onChange={(e) => setSettings((s) => ({ ...s, welcomeConfig: { ...(s.welcomeConfig || {}), embedFooter: e.target.value } }))}
|
||||||
@@ -59,7 +66,7 @@ export function Welcome() {
|
|||||||
|
|
||||||
<Separator />
|
<Separator />
|
||||||
|
|
||||||
<Button color="primary" startContent={<Save size={16} />} onPress={() => saveSettingsPayload({ welcomeConfig: settings.welcomeConfig || {} }, 'Welcome gespeichert')}>
|
<Button color="primary" size="lg" startContent={<Save size={16} />} onPress={() => saveSettingsPayload({ welcomeConfig: settings.welcomeConfig || {} }, 'Welcome gespeichert')}>
|
||||||
Speichern
|
Speichern
|
||||||
</Button>
|
</Button>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@@ -81,7 +88,7 @@ export function Welcome() {
|
|||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<p>{settings.welcomeConfig?.embedDescription || 'Willkommen auf dem Server!'}</p>
|
<p className="text-default-700 dark:text-default-300">{settings.welcomeConfig?.embedDescription || 'Willkommen auf dem Server!'}</p>
|
||||||
{settings.welcomeConfig?.embedFooter && (
|
{settings.welcomeConfig?.embedFooter && (
|
||||||
<p className="text-small text-default-500">{settings.welcomeConfig.embedFooter}</p>
|
<p className="text-small text-default-500">{settings.welcomeConfig.embedFooter}</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user