refactor(SettingsPage): streamline loading and success/error message display for improved clarity and user experience
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m56s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m56s
This commit is contained in:
@@ -246,82 +246,58 @@ export default function SettingsPage() {
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<div className="page-body">
|
||||
<div className="container-xl">
|
||||
<PageHeader
|
||||
title="Настройки интерфейса"
|
||||
icon={<IconSettings size={28} />}
|
||||
pretitle="Интерфейс"
|
||||
/>
|
||||
<div className="card">
|
||||
<div className="card-body text-center py-5">
|
||||
<div className="spinner-border text-primary" role="status" />
|
||||
<p className="mt-2 mb-0 text-muted">Загрузка настроек…</p>
|
||||
</div>
|
||||
</div>
|
||||
<>
|
||||
<PageHeader title="Настройки интерфейса" icon={<IconSettings size={24} />} pretitle="Интерфейс" />
|
||||
<div className="card">
|
||||
<div className="card-body text-center py-5">
|
||||
<div className="spinner-border text-primary" role="status" />
|
||||
<p className="mt-2 mb-0 text-muted">Загрузка настроек…</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<div className="page-body">
|
||||
<div className="container-xl">
|
||||
<PageHeader
|
||||
title="Настройки интерфейса"
|
||||
icon={<IconSettings size={28} />}
|
||||
pretitle="Интерфейс"
|
||||
meta="WebSocket, DoH, пинг, PTR зона"
|
||||
actions={
|
||||
<div className="btn-list">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={onSave}
|
||||
disabled={saving}
|
||||
>
|
||||
{saving && (
|
||||
<span className="spinner-border spinner-border-sm me-2" />
|
||||
)}
|
||||
<IconDeviceFloppy size={18} className="me-1" />
|
||||
Сохранить
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<>
|
||||
{error && (
|
||||
<ErrorAlert message={error} onClose={() => setError('')} />
|
||||
)}
|
||||
{success && (
|
||||
<div className="alert alert-success alert-dismissible mb-3" role="alert">
|
||||
<div className="d-flex">
|
||||
<div className="flex-grow-1">{success}</div>
|
||||
</div>
|
||||
<button type="button" className="btn-close" onClick={() => setSuccess('')} aria-label="Закрыть" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && (
|
||||
<div className="mb-3">
|
||||
<ErrorAlert message={error} onClose={() => setError('')} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{success && (
|
||||
<div
|
||||
className="alert alert-success alert-dismissible mb-3"
|
||||
role="alert"
|
||||
<PageHeader
|
||||
title="Настройки интерфейса"
|
||||
icon={<IconSettings size={24} />}
|
||||
pretitle="Интерфейс"
|
||||
meta="WebSocket, DoH, пинг, PTR зона"
|
||||
actions={
|
||||
<div className="btn-list">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary"
|
||||
onClick={onSave}
|
||||
disabled={saving}
|
||||
>
|
||||
<div className="d-flex">
|
||||
<div className="flex-grow-1">{success}</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setSuccess('')}
|
||||
aria-label="Закрыть"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{saving && <span className="spinner-border spinner-border-sm me-2" />}
|
||||
<IconDeviceFloppy size={18} className="me-1" />
|
||||
Сохранить
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
{/* Как в Tabler Settings: одна card, row g-0, col-md-3 border-end + col-md-9 */}
|
||||
<div className="card">
|
||||
<div className="row g-0">
|
||||
{/* Левая колонка — навигация (list-group list-group-transparent) */}
|
||||
<div className="col-12 col-md-3 border-end">
|
||||
<div className="card-body">
|
||||
<div className="row">
|
||||
{/* Сайдбар навигации — как блок в общем стиле страниц */}
|
||||
<div className="col-12 col-md-3 mb-4 mb-md-0">
|
||||
<div className="card card-flat">
|
||||
<div className="card-body">
|
||||
<div className="input-icon mb-3">
|
||||
<span className="input-icon-addon">
|
||||
<IconSearch size={18} className="text-muted" />
|
||||
@@ -360,14 +336,16 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
))}
|
||||
{sidebarGroupsFiltered.length === 0 && (
|
||||
<p className="text-muted small mb-0">Нет подходящих разделов</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-muted small mb-0">Нет подходящих разделов</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Правая колонка — контент раздела */}
|
||||
<div className="col-12 col-md-9 d-flex flex-column">
|
||||
<div className="card-body">
|
||||
{/* Контент раздела — карточка как на других страницах */}
|
||||
<div className="col-12 col-md-9">
|
||||
<div className="card card-flat">
|
||||
<div className="card-body">
|
||||
{activeSection === 'live-doh' && (
|
||||
<>
|
||||
<SectionHeading title="BGP Live и DNS (DoH)" icon={IconPlugConnected} />
|
||||
@@ -558,12 +536,10 @@ export default function SettingsPage() {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user