import { useEffect, useMemo, useState } from 'react'
import { IconPlus, IconTrash } from '@tabler/icons-react'
import { PageHeader } from '../components/PageHeader'
const defaultSettings = {
baseCurrency: 'RUB',
ratesUrl: 'https://www.cbr-xml-daily.ru/latest.js',
autoConvert: true,
syncEnabled: false,
syncIntervalMinutes: 60,
syncTariffsIntervalMinutes: 1440,
}
export function SettingsPage({ db, actions, ratesData, ratesError }) {
const current = db.settings?.[0] || defaultSettings
const [form, setForm] = useState({
baseCurrency: current.baseCurrency || 'RUB',
ratesUrl: current.ratesUrl || 'https://www.cbr-xml-daily.ru/latest.js',
autoConvert: current.autoConvert !== false,
syncEnabled: current.syncEnabled !== false && Boolean(current.syncEnabled),
syncIntervalMinutes: current.syncIntervalMinutes ?? 60,
syncTariffsIntervalMinutes: current.syncTariffsIntervalMinutes ?? 1440,
})
const [newFieldLabel, setNewFieldLabel] = useState('')
const customFields = Array.isArray(current.customFields) ? current.customFields : []
useEffect(() => {
/* eslint-disable-next-line react-hooks/set-state-in-effect -- sync form when settings change from parent */
setForm({
baseCurrency: current.baseCurrency || 'RUB',
ratesUrl: current.ratesUrl || 'https://www.cbr-xml-daily.ru/latest.js',
autoConvert: current.autoConvert !== false,
syncEnabled: Boolean(current.syncEnabled),
syncIntervalMinutes: current.syncIntervalMinutes ?? 60,
syncTariffsIntervalMinutes: current.syncTariffsIntervalMinutes ?? 1440,
})
}, [current.baseCurrency, current.ratesUrl, current.autoConvert, current.syncEnabled, current.syncIntervalMinutes, current.syncTariffsIntervalMinutes])
const availableCurrencies = useMemo(() => {
const list = new Set(['RUB', 'USD', 'EUR'])
if (ratesData?.rates) {
Object.keys(ratesData.rates).forEach((code) => list.add(code))
}
return [...list].sort()
}, [ratesData])
const onSubmit = (event) => {
event.preventDefault()
actions.upsertSettings({
baseCurrency: form.baseCurrency,
ratesUrl: form.ratesUrl,
autoConvert: form.autoConvert,
ratesUpdatedAt: ratesData?.date || '',
})
}
const onSyncSettingsSubmit = (event) => {
event.preventDefault()
actions.upsertSettings({
syncEnabled: form.syncEnabled,
syncIntervalMinutes: Math.max(15, Number(form.syncIntervalMinutes) || 60),
syncTariffsIntervalMinutes: Math.max(60, Number(form.syncTariffsIntervalMinutes) || 1440),
})
}
const addCustomField = () => {
const label = newFieldLabel.trim()
if (!label) return
const nextIndex = customFields.reduce((max, f) => {
const n = parseInt(f.key?.replace('cf_', '') || '0', 10)
return Math.max(max, n)
}, -1) + 1
const key = `cf_${nextIndex}`
actions.upsertSettings({ customFields: [...customFields, { key, label }] })
setNewFieldLabel('')
}
const removeCustomField = (key) => {
actions.upsertSettings({
customFields: customFields.filter((f) => f.key !== key),
})
}
return (
<>
Текстовые поля для расширенного режима просмотра списка VPS. Отображаются как колонки в таблице и в форме редактирования.
Периодическая синхронизация данных из BILLmanager для аккаунтов с настроенным API. Два независимых интервала: VPS и платежи обновляются чаще, тарифы — реже.