refactor: migrate to eslint flat config and format codebase with prettier

- Remove legacy .eslintrc.cjs and .eslintignore
- Add eslint.config.js with flat config, security rules (no-eval, no-implied-eval, no-new-func, no-script-url)
- Add .prettierrc and .prettierignore
- Format entire codebase with prettier
This commit is contained in:
c0mrade
2026-01-27 17:37:31 +03:00
parent 111ccc4e7a
commit bc90ba3779
133 changed files with 19972 additions and 15523 deletions

View File

@@ -1,22 +1,22 @@
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { SettingDefinition, adminSettingsApi } from '../../api/adminSettings'
import { ChevronDownIcon } from './icons'
import { SettingRow } from './SettingRow'
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { SettingDefinition, adminSettingsApi } from '../../api/adminSettings';
import { ChevronDownIcon } from './icons';
import { SettingRow } from './SettingRow';
interface CategoryGroup {
key: string
label: string
settings: SettingDefinition[]
key: string;
label: string;
settings: SettingDefinition[];
}
interface SettingsTabProps {
categories: CategoryGroup[]
searchQuery: string
filteredSettings: SettingDefinition[]
isFavorite: (key: string) => boolean
toggleFavorite: (key: string) => void
categories: CategoryGroup[];
searchQuery: string;
filteredSettings: SettingDefinition[];
isFavorite: (key: string) => boolean;
toggleFavorite: (key: string) => void;
}
export function SettingsTab({
@@ -24,49 +24,50 @@ export function SettingsTab({
searchQuery,
filteredSettings,
isFavorite,
toggleFavorite
toggleFavorite,
}: SettingsTabProps) {
const { t } = useTranslation()
const queryClient = useQueryClient()
const { t } = useTranslation();
const queryClient = useQueryClient();
const [expandedSections, setExpandedSections] = useState<Set<string>>(new Set())
const [expandedSections, setExpandedSections] = useState<Set<string>>(new Set());
const toggleSection = (key: string) => {
setExpandedSections(prev => {
const next = new Set(prev)
setExpandedSections((prev) => {
const next = new Set(prev);
if (next.has(key)) {
next.delete(key)
next.delete(key);
} else {
next.add(key)
next.add(key);
}
return next
})
}
return next;
});
};
const updateSettingMutation = useMutation({
mutationFn: ({ key, value }: { key: string; value: string }) => adminSettingsApi.updateSetting(key, value),
mutationFn: ({ key, value }: { key: string; value: string }) =>
adminSettingsApi.updateSetting(key, value),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['admin-settings'] })
queryClient.invalidateQueries({ queryKey: ['admin-settings'] });
},
})
});
const resetSettingMutation = useMutation({
mutationFn: (key: string) => adminSettingsApi.resetSetting(key),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['admin-settings'] })
queryClient.invalidateQueries({ queryKey: ['admin-settings'] });
},
})
});
// If searching, show flat list
if (searchQuery) {
return (
<div className="space-y-4">
{filteredSettings.length === 0 ? (
<div className="p-12 rounded-2xl bg-dark-800/30 border border-dark-700/30 text-center">
<div className="rounded-2xl border border-dark-700/30 bg-dark-800/30 p-12 text-center">
<p className="text-dark-400">{t('admin.settings.noSettings')}</p>
</div>
) : (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
{filteredSettings.map((setting) => (
<SettingRow
key={setting.key}
@@ -82,46 +83,50 @@ export function SettingsTab({
</div>
)}
</div>
)
);
}
// Show accordion for subcategories
return (
<div className="space-y-3">
{categories.map((cat) => {
const isExpanded = expandedSections.has(cat.key)
const isExpanded = expandedSections.has(cat.key);
return (
<div
key={cat.key}
className="rounded-2xl bg-dark-800/30 border border-dark-700/30 overflow-hidden"
className="overflow-hidden rounded-2xl border border-dark-700/30 bg-dark-800/30"
>
{/* Accordion header */}
<button
onClick={() => toggleSection(cat.key)}
className="w-full flex items-center justify-between p-4 hover:bg-dark-800/50 transition-colors"
className="flex w-full items-center justify-between p-4 transition-colors hover:bg-dark-800/50"
>
<div className="flex items-center gap-3">
<span className="font-medium text-dark-100">{cat.label}</span>
<span className="px-2 py-0.5 text-xs rounded-full bg-dark-700 text-dark-400">
<span className="rounded-full bg-dark-700 px-2 py-0.5 text-xs text-dark-400">
{cat.settings.length}
</span>
</div>
<div className={`transition-transform duration-200 text-dark-400 ${isExpanded ? 'rotate-180' : ''}`}>
<div
className={`text-dark-400 transition-transform duration-200 ${isExpanded ? 'rotate-180' : ''}`}
>
<ChevronDownIcon />
</div>
</button>
{/* Accordion content */}
{isExpanded && (
<div className="p-4 pt-0 border-t border-dark-700/30">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 pt-4">
<div className="border-t border-dark-700/30 p-4 pt-0">
<div className="grid grid-cols-1 gap-4 pt-4 lg:grid-cols-2">
{cat.settings.map((setting) => (
<SettingRow
key={setting.key}
setting={setting}
isFavorite={isFavorite(setting.key)}
onToggleFavorite={() => toggleFavorite(setting.key)}
onUpdate={(value) => updateSettingMutation.mutate({ key: setting.key, value })}
onUpdate={(value) =>
updateSettingMutation.mutate({ key: setting.key, value })
}
onReset={() => resetSettingMutation.mutate(setting.key)}
isUpdating={updateSettingMutation.isPending}
isResetting={resetSettingMutation.isPending}
@@ -131,14 +136,14 @@ export function SettingsTab({
</div>
)}
</div>
)
);
})}
{categories.length === 0 && (
<div className="p-12 rounded-2xl bg-dark-800/30 border border-dark-700/30 text-center">
<div className="rounded-2xl border border-dark-700/30 bg-dark-800/30 p-12 text-center">
<p className="text-dark-400">{t('admin.settings.noSettings')}</p>
</div>
)}
</div>
)
);
}