feat: refactor InstancePanel from tabs to sectioned single page

This commit is contained in:
Jannis Braun
2026-03-22 03:19:36 +01:00
parent f94958354a
commit 61a0bff4a3
@@ -1,54 +1,59 @@
import { useState, useEffect } from 'react'; import { useEffect } from 'react';
import { useSettingsStore } from '../../../stores/settingsStore'; import { useSettingsStore } from '../../../stores/settingsStore';
import { useSettingsSections } from '../../../hooks/useSettingsSections';
import { GeneralPanel } from '../instanceSettingsPanels/GeneralPanel'; import { GeneralPanel } from '../instanceSettingsPanels/GeneralPanel';
import { StreamingPanel } from '../instanceSettingsPanels/StreamingPanel'; import { StreamingPanel } from '../instanceSettingsPanels/StreamingPanel';
import { StoragePanel } from '../instanceSettingsPanels/StoragePanel'; import { StoragePanel } from '../instanceSettingsPanels/StoragePanel';
import { UsersPanel } from '../instanceSettingsPanels/UsersPanel'; import { UsersPanel } from '../instanceSettingsPanels/UsersPanel';
type SubTab = 'general' | 'streaming' | 'storage' | 'users'; const SECTIONS = [
{ id: 'general', label: 'General' },
{ id: 'streaming', label: 'Streaming' },
{ id: 'storage', label: 'Storage' },
{ id: 'users', label: 'Users' },
] as const;
export function InstancePanel() { export function InstancePanel() {
const fetchInstanceSettings = useSettingsStore((s) => s.fetchInstanceSettings); const fetchInstanceSettings = useSettingsStore((s) => s.fetchInstanceSettings);
const fetchStreamingLimits = useSettingsStore((s) => s.fetchStreamingLimits); const fetchStreamingLimits = useSettingsStore((s) => s.fetchStreamingLimits);
const { sectionRef } = useSettingsSections([...SECTIONS]);
const [subTab, setSubTab] = useState<SubTab>('general');
useEffect(() => { useEffect(() => {
fetchInstanceSettings(); fetchInstanceSettings();
fetchStreamingLimits(); fetchStreamingLimits();
}, [fetchInstanceSettings, fetchStreamingLimits]); }, [fetchInstanceSettings, fetchStreamingLimits]);
const pillClass = (t: SubTab) =>
`px-3 py-1 text-sm rounded-full transition-colors ${
subTab === t
? 'bg-interactive-selected text-txt-primary'
: 'text-txt-tertiary hover:text-txt-secondary hover:bg-interactive-hover'
}`;
return ( return (
<div className="space-y-4"> <div className="space-y-0">
<h2 className="text-lg font-semibold text-txt-primary mb-6">Instance</h2> {/* General */}
{/* Sub-tab switcher */} <h3 ref={sectionRef('general')} className="text-base font-semibold text-txt-primary mb-4">
<div className="flex gap-1 p-1 bg-white/[0.02] rounded-full w-fit"> General
<button onClick={() => setSubTab('general')} className={pillClass('general')}> </h3>
General <GeneralPanel />
</button>
<button onClick={() => setSubTab('streaming')} className={pillClass('streaming')}>
Streaming
</button>
<button onClick={() => setSubTab('storage')} className={pillClass('storage')}>
Storage
</button>
<button onClick={() => setSubTab('users')} className={pillClass('users')}>
Users
</button>
</div>
{/* Content */} <div className="border-t border-white/[0.04] my-6" />
{subTab === 'general' && <GeneralPanel />}
{subTab === 'streaming' && <StreamingPanel />} {/* Streaming */}
{subTab === 'storage' && <StoragePanel />} <h3 ref={sectionRef('streaming')} className="text-base font-semibold text-txt-primary mb-4">
{subTab === 'users' && <UsersPanel />} Streaming
</h3>
<StreamingPanel />
<div className="border-t border-white/[0.04] my-6" />
{/* Storage */}
<h3 ref={sectionRef('storage')} className="text-base font-semibold text-txt-primary mb-4">
Storage
</h3>
<StoragePanel />
<div className="border-t border-white/[0.04] my-6" />
{/* Users */}
<h3 ref={sectionRef('users')} className="text-base font-semibold text-txt-primary mb-4">
Users
</h3>
<UsersPanel />
</div> </div>
); );
} }