feat(admin): Convert settings layout to use tabbed navigation, isolating SMTP configuration
This commit is contained in:
@@ -49,6 +49,15 @@ export default function AdminSettingsPage() {
|
|||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<string, Setting[]>);
|
}, {} as Record<string, Setting[]>);
|
||||||
|
|
||||||
|
const categories = Object.keys(groupedSettings);
|
||||||
|
const [activeTab, setActiveTab] = useState<string>('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (categories.length > 0 && !activeTab) {
|
||||||
|
setActiveTab(categories[0]);
|
||||||
|
}
|
||||||
|
}, [categories, activeTab]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-10 max-w-5xl mx-auto font-sans pb-32">
|
<div className="p-10 max-w-5xl mx-auto font-sans pb-32">
|
||||||
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-10 gap-4">
|
<div className="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-10 gap-4">
|
||||||
@@ -72,19 +81,40 @@ export default function AdminSettingsPage() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-8">
|
{categories.length > 0 && (
|
||||||
{Object.keys(groupedSettings).map(category => (
|
<div className="mb-8 border-b border-gray-200">
|
||||||
<div key={category} className="bg-white rounded-2xl shadow-xl shadow-gray-200/50 border border-gray-200 overflow-hidden relative">
|
<nav className="-mb-px flex space-x-8" aria-label="Tabs">
|
||||||
|
{categories.map((category) => (
|
||||||
|
<button
|
||||||
|
key={category}
|
||||||
|
onClick={() => setActiveTab(category)}
|
||||||
|
className={`
|
||||||
|
whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm capitalize transition-colors
|
||||||
|
${activeTab === category
|
||||||
|
? 'border-indigo-500 text-indigo-600'
|
||||||
|
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{category} Settings
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="space-y-8">
|
||||||
|
{activeTab && groupedSettings[activeTab] && (
|
||||||
|
<div className="bg-white rounded-2xl shadow-xl shadow-gray-200/50 border border-gray-200 overflow-hidden relative animate-in fade-in slide-in-from-bottom-4 duration-500">
|
||||||
{/* Category Header */}
|
{/* Category Header */}
|
||||||
<div className="bg-gradient-to-r from-gray-50 to-white px-8 py-5 border-b border-gray-100 flex items-center gap-3">
|
<div className="bg-gradient-to-r from-gray-50 to-white px-8 py-5 border-b border-gray-100 flex items-center gap-3">
|
||||||
<div className="w-2 h-6 bg-indigo-500 rounded-full"></div>
|
<div className="w-2 h-6 bg-indigo-500 rounded-full"></div>
|
||||||
<h2 className="text-xl font-bold text-gray-900 capitalize">{category} Configuration</h2>
|
<h2 className="text-xl font-bold text-gray-900 capitalize">{activeTab} Configuration</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-8 grid grid-cols-1 md:grid-cols-2 gap-8">
|
<div className="p-8 grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
{groupedSettings[category].map(setting => {
|
{groupedSettings[activeTab].map(setting => {
|
||||||
const isSecret = setting.key.includes('key') || setting.key.includes('secret') || setting.key.includes('password');
|
const isSecret = setting.key.includes('key') || setting.key.includes('secret') || setting.key.includes('password') || setting.key.includes('pass');
|
||||||
return (
|
return (
|
||||||
<div key={setting.key} className="space-y-2">
|
<div key={setting.key} className="space-y-2">
|
||||||
<label className="block text-sm font-bold text-gray-700 uppercase tracking-wider">
|
<label className="block text-sm font-bold text-gray-700 uppercase tracking-wider">
|
||||||
@@ -109,7 +139,7 @@ export default function AdminSettingsPage() {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user