refactor: simplify RemnaWave sync tab - keep only panel sync

This commit is contained in:
c0mrade
2026-02-02 10:51:42 +03:00
parent 4034b4db39
commit 6c795539f2

View File

@@ -664,9 +664,6 @@ interface SyncTabProps {
onRunAutoSync: () => void; onRunAutoSync: () => void;
onSyncFromPanel: () => void; onSyncFromPanel: () => void;
onSyncToPanel: () => void; onSyncToPanel: () => void;
onValidate: () => void;
onCleanup: () => void;
onSyncStatuses: () => void;
syncResults: Record<string, { success: boolean; message?: string } | null>; syncResults: Record<string, { success: boolean; message?: string } | null>;
loadingStates: Record<string, boolean>; loadingStates: Record<string, boolean>;
} }
@@ -677,9 +674,6 @@ function SyncTab({
onRunAutoSync, onRunAutoSync,
onSyncFromPanel, onSyncFromPanel,
onSyncToPanel, onSyncToPanel,
onValidate,
onCleanup,
onSyncStatuses,
syncResults, syncResults,
loadingStates, loadingStates,
}: SyncTabProps) { }: SyncTabProps) {
@@ -703,6 +697,7 @@ function SyncTab({
<SyncIcon /> <SyncIcon />
{t('admin.remnawave.sync.autoSync', 'Auto Sync')} {t('admin.remnawave.sync.autoSync', 'Auto Sync')}
</h3> </h3>
<div className="flex items-center gap-2">
<span <span
className={`rounded-full px-2 py-0.5 text-xs ${ className={`rounded-full px-2 py-0.5 text-xs ${
autoSyncStatus.enabled autoSyncStatus.enabled
@@ -712,71 +707,73 @@ function SyncTab({
> >
{autoSyncStatus.enabled ? 'Enabled' : 'Disabled'} {autoSyncStatus.enabled ? 'Enabled' : 'Disabled'}
</span> </span>
</div>
<div className="grid grid-cols-2 gap-4 text-sm lg:grid-cols-4">
<div>
<p className="text-dark-500">Schedule</p>
<p className="text-dark-200">
{autoSyncStatus.times.length > 0 ? autoSyncStatus.times.join(', ') : '—'}
</p>
</div>
<div>
<p className="text-dark-500">Next Run</p>
<p className="text-dark-200">
{autoSyncStatus.next_run ? new Date(autoSyncStatus.next_run).toLocaleString() : '—'}
</p>
</div>
<div>
<p className="text-dark-500">Last Run</p>
<p className="text-dark-200">
{autoSyncStatus.last_run_finished_at
? new Date(autoSyncStatus.last_run_finished_at).toLocaleString()
: '—'}
</p>
</div>
<div>
<p className="text-dark-500">Status</p>
<p
className={
autoSyncStatus.is_running
? 'text-warning-400'
: autoSyncStatus.last_run_success
? 'text-success-400'
: 'text-dark-200'
}
>
{autoSyncStatus.is_running
? 'Running...'
: autoSyncStatus.last_run_success
? 'Success'
: autoSyncStatus.last_run_error || '—'}
</p>
</div>
</div>
<button <button
onClick={onRunAutoSync} onClick={onRunAutoSync}
disabled={loadingStates.autoSync || autoSyncStatus.is_running} disabled={loadingStates.autoSync || autoSyncStatus.is_running}
className="mt-4 flex items-center gap-2 rounded-lg bg-accent-500/20 px-4 py-2 text-accent-400 transition-colors hover:bg-accent-500/30 disabled:opacity-50" className="flex items-center gap-1.5 rounded-lg bg-accent-500/20 px-3 py-1.5 text-sm text-accent-400 transition-colors hover:bg-accent-500/30 disabled:opacity-50"
> >
<RefreshIcon spinning={loadingStates.autoSync || autoSyncStatus.is_running} /> <RefreshIcon spinning={loadingStates.autoSync || autoSyncStatus.is_running} />
{t('admin.remnawave.sync.runNow', 'Run Now')} {t('admin.remnawave.sync.runNow', 'Run Now')}
</button> </button>
</div> </div>
</div>
<div className="grid grid-cols-2 gap-3 text-sm lg:grid-cols-4">
<div className="rounded-lg bg-dark-700/50 p-3">
<p className="text-xs text-dark-500">
{t('admin.remnawave.sync.schedule', 'Schedule')}
</p>
<p className="mt-1 text-dark-200">
{autoSyncStatus.times.length > 0 ? autoSyncStatus.times.join(', ') : '—'}
</p>
</div>
<div className="rounded-lg bg-dark-700/50 p-3">
<p className="text-xs text-dark-500">
{t('admin.remnawave.sync.nextRun', 'Next Run')}
</p>
<p className="mt-1 text-dark-200">
{autoSyncStatus.next_run ? new Date(autoSyncStatus.next_run).toLocaleString() : '—'}
</p>
</div>
<div className="rounded-lg bg-dark-700/50 p-3">
<p className="text-xs text-dark-500">
{t('admin.remnawave.sync.lastRun', 'Last Run')}
</p>
<p className="mt-1 text-dark-200">
{autoSyncStatus.last_run_finished_at
? new Date(autoSyncStatus.last_run_finished_at).toLocaleString()
: '—'}
</p>
</div>
<div className="rounded-lg bg-dark-700/50 p-3">
<p className="text-xs text-dark-500">{t('admin.remnawave.sync.status', 'Status')}</p>
<p
className={`mt-1 ${
autoSyncStatus.is_running
? 'text-warning-400'
: autoSyncStatus.last_run_success
? 'text-success-400'
: 'text-dark-200'
}`}
>
{autoSyncStatus.is_running
? t('admin.remnawave.sync.running', 'Running...')
: autoSyncStatus.last_run_success
? t('admin.remnawave.sync.success', 'Success')
: autoSyncStatus.last_run_error || '—'}
</p>
</div>
</div>
</div>
)} )}
{/* Manual Sync Options */} {/* Manual Sync */}
<div> <div className="grid gap-3 sm:grid-cols-2">
<h3 className="mb-3 text-sm font-medium text-dark-300">
{t('admin.remnawave.sync.manual', 'Manual Sync')}
</h3>
<div className="space-y-3">
<SyncCard <SyncCard
title={t('admin.remnawave.sync.fromPanel', 'Sync from Panel')} title={t('admin.remnawave.sync.fromPanel', 'Sync from Panel')}
description={t( description={t(
'admin.remnawave.sync.fromPanelDesc', 'admin.remnawave.sync.fromPanelDesc',
'Import users from RemnaWave panel to bot database', 'Import users from RemnaWave panel to bot',
)} )}
onAction={onSyncFromPanel} onAction={onSyncFromPanel}
isLoading={loadingStates.fromPanel} isLoading={loadingStates.fromPanel}
@@ -786,7 +783,7 @@ function SyncTab({
title={t('admin.remnawave.sync.toPanel', 'Sync to Panel')} title={t('admin.remnawave.sync.toPanel', 'Sync to Panel')}
description={t( description={t(
'admin.remnawave.sync.toPanelDesc', 'admin.remnawave.sync.toPanelDesc',
'Export users from bot database to RemnaWave panel', 'Export users from bot to RemnaWave panel',
)} )}
onAction={onSyncToPanel} onAction={onSyncToPanel}
isLoading={loadingStates.toPanel} isLoading={loadingStates.toPanel}
@@ -794,46 +791,6 @@ function SyncTab({
/> />
</div> </div>
</div> </div>
{/* Subscriptions */}
<div>
<h3 className="mb-3 text-sm font-medium text-dark-300">
{t('admin.remnawave.sync.subscriptions', 'Subscriptions')}
</h3>
<div className="space-y-3">
<SyncCard
title={t('admin.remnawave.sync.validate', 'Validate')}
description={t(
'admin.remnawave.sync.validateDesc',
'Check and fix subscription inconsistencies',
)}
onAction={onValidate}
isLoading={loadingStates.validate}
lastResult={syncResults.validate}
/>
<SyncCard
title={t('admin.remnawave.sync.cleanup', 'Cleanup')}
description={t(
'admin.remnawave.sync.cleanupDesc',
'Remove orphaned subscriptions without users',
)}
onAction={onCleanup}
isLoading={loadingStates.cleanup}
lastResult={syncResults.cleanup}
/>
<SyncCard
title={t('admin.remnawave.sync.statuses', 'Sync Statuses')}
description={t(
'admin.remnawave.sync.statusesDesc',
'Synchronize subscription statuses with panel',
)}
onAction={onSyncStatuses}
isLoading={loadingStates.statuses}
lastResult={syncResults.statuses}
/>
</div>
</div>
</div>
); );
} }
@@ -1074,11 +1031,6 @@ export default function AdminRemnawave() {
handleSyncAction('fromPanel', () => adminRemnawaveApi.syncFromPanel('all')) handleSyncAction('fromPanel', () => adminRemnawaveApi.syncFromPanel('all'))
} }
onSyncToPanel={() => handleSyncAction('toPanel', adminRemnawaveApi.syncToPanel)} onSyncToPanel={() => handleSyncAction('toPanel', adminRemnawaveApi.syncToPanel)}
onValidate={() => handleSyncAction('validate', adminRemnawaveApi.validateSubscriptions)}
onCleanup={() => handleSyncAction('cleanup', adminRemnawaveApi.cleanupSubscriptions)}
onSyncStatuses={() =>
handleSyncAction('statuses', adminRemnawaveApi.syncSubscriptionStatuses)
}
syncResults={syncResults} syncResults={syncResults}
loadingStates={loadingStates} loadingStates={loadingStates}
/> />