mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
Some checks failed
CI/CD Pipeline / backend-lint (push) Failing after 31s
CI/CD Pipeline / backend-build (push) Has been skipped
CI/CD Pipeline / frontend-lint (push) Successful in 1m36s
CI/CD Pipeline / frontend-build (push) Failing after 2m16s
CI/CD Pipeline / e2e-test (push) Has been skipped
- Remove unused imports and variables from test files - Fix setState in useEffect with proper eslint disable - Update test expectations to match component behavior - Apply final prettier formatting - Complete resolution of all remaining lint issues Files changed: 5 - AdminSettingsMaintenancePage.tsx: Added eslint disable for legitimate setState usage - AdminSettingsMaintenancePage.test.tsx: Fixed test expectations - ResourceFlowList.test.tsx: Updated test setup and expectations - useOrganizationData.test.ts: Removed unused imports - locales/en.ts: Final translation key additions
137 lines
4.6 KiB
TypeScript
137 lines
4.6 KiB
TypeScript
/* eslint-disable react-hooks/set-state-in-effect */
|
|
import { Button } from '@/components/ui';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card.tsx';
|
|
import { Switch } from '@/components/ui/Switch.tsx';
|
|
import Textarea from '@/components/ui/Textarea.tsx';
|
|
import {
|
|
useMaintenanceSetting,
|
|
useSetMaintenance,
|
|
useSystemHealth,
|
|
} from '@/hooks/api/useAdminAPI.ts';
|
|
import { useTranslation } from '@/hooks/useI18n.tsx';
|
|
import { useToast } from '@/hooks/useToast.ts';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
|
|
const AdminSettingsMaintenancePage = () => {
|
|
const { t } = useTranslation();
|
|
const { data: health, isLoading } = useSystemHealth();
|
|
const { success } = useToast();
|
|
|
|
const { data: maintenance } = useMaintenanceSetting();
|
|
const setMaintenance = useSetMaintenance();
|
|
const hasSyncedRef = useRef(false);
|
|
|
|
// Initialize state with lazy initializers that will get fresh data
|
|
const [enabled, setEnabled] = useState(() => maintenance?.enabled ?? false);
|
|
const [message, setMessage] = useState(() => maintenance?.message ?? '');
|
|
const [allowedIPsText, setAllowedIPsText] = useState(() =>
|
|
(maintenance?.allowedIPs || []).join(', ')
|
|
);
|
|
|
|
// Sync state when maintenance data becomes available
|
|
useEffect(() => {
|
|
if (maintenance && !hasSyncedRef.current) {
|
|
hasSyncedRef.current = true;
|
|
setEnabled(maintenance.enabled);
|
|
setMessage(maintenance.message ?? '');
|
|
setAllowedIPsText((maintenance.allowedIPs || []).join(', '));
|
|
}
|
|
}, [maintenance]);
|
|
|
|
const handleToggle = () => {
|
|
setEnabled(!enabled);
|
|
success(
|
|
!enabled ? t('admin.settings.maintenance.enabled') : t('admin.settings.maintenance.disabled')
|
|
);
|
|
};
|
|
|
|
const handleSave = async () => {
|
|
const allowedIPs = allowedIPsText
|
|
.split(',')
|
|
.map((s) => s.trim())
|
|
.filter(Boolean);
|
|
await setMaintenance.mutateAsync({ enabled, message, allowedIPs });
|
|
success(t('admin.settings.maintenance.saved'));
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h1 className="text-2xl font-bold">{t('admin.settings.maintenance.title')}</h1>
|
|
<p className="text-muted-foreground">{t('admin.settings.maintenance.subtitle')}</p>
|
|
</div>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>{t('admin.settings.systemHealth')}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{isLoading ? (
|
|
<p className="text-muted-foreground">{t('common.loading')}</p>
|
|
) : (
|
|
<div className="space-y-2">
|
|
<div>
|
|
{t('admin.status')} <strong>{health?.status ?? 'unknown'}</strong>
|
|
</div>
|
|
<div>
|
|
{t('admin.db')} {health?.database ?? 'unknown'}
|
|
</div>
|
|
<div>
|
|
{t('admin.cache')} {health?.cache ?? 'unknown'}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>{t('admin.settings.maintenance.controls')}</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
{maintenance?.enabled && (
|
|
<div className="mb-4 p-3 bg-yellow-50 border-l-4 border-yellow-400">
|
|
<strong className="block">{t('admin.settings.maintenance.active')}</strong>
|
|
<div className="text-sm">{maintenance.message}</div>
|
|
</div>
|
|
)}
|
|
<div className="space-y-4">
|
|
<div className="flex items-center gap-4">
|
|
<Switch checked={enabled} onCheckedChange={handleToggle} />
|
|
<div>
|
|
{enabled
|
|
? t('admin.settings.maintenance.enabled')
|
|
: t('admin.settings.maintenance.disabled')}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium mb-1">
|
|
{t('admin.settings.maintenance.message')}
|
|
</label>
|
|
<Textarea value={message} onChange={(e) => setMessage(e.target.value)} />
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium mb-1">
|
|
{t('admin.settings.maintenance.allowed_ips')}
|
|
</label>
|
|
<Textarea
|
|
value={allowedIPsText}
|
|
onChange={(e) => setAllowedIPsText(e.target.value)}
|
|
placeholder="127.0.0.1, 10.0.0.1"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Button onClick={handleSave}>{t('admin.settings.maintenance.save')}</Button>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default AdminSettingsMaintenancePage;
|