{#snippet renderField(field)} {@const revealed = isSecretRevealed(field.key)}
{fieldLabelText(field)} {#if field.secret} {at("settings_badge_secret", {}, "Secret")} {/if} {#if isOverridden(field)} {at("settings_badge_override", {}, "Override")} {/if} {field.key} {#if fieldDescriptionText(field)} {fieldDescriptionText(field)} {/if}
{#if field.type === "bool"}
settingsStore.markDirty(field.key, checked)} class="admin-switch-root" > {valueFor(field) ? at("enabled", {}, "Включено") : at("disabled", {}, "Выключено")}
{:else if field.type === "color"} settingsStore.markDirty(field.key, e.currentTarget.value)} /> settingsStore.markDirty(field.key, e.currentTarget.value)} /> {:else if field.type === "icon"} {@const selectedIconName = iconValue(field)} {@const SelectedIcon = iconComponent(selectedIconName)} openIconPicker(field)} > {#if SelectedIcon} {/if} {iconLabel(field)} {#if !iconIsDefault(field)} settingsStore.markDirty(field.key, "")} > {at("clear", {}, "Clear")} {/if} {:else if field.choices && field.choices.length > 0} settingsStore.markDirty(field.key, value)} /> {:else if field.type === "int" || field.type === "float"} settingsStore.markDirty(field.key, e.currentTarget.value)} /> {:else if field.type === "text"} {:else if field.secret} settingsStore.markDirty(field.key, e.currentTarget.value)} /> toggleSecretReveal(field.key)} > {#if revealed}{:else}{/if} {:else} settingsStore.markDirty(field.key, e.currentTarget.value)} /> {/if} {#if isOverridden(field) || settingsDirty[field.key]} settingsStore.resetField(field)}> {at("reset", {}, "Сбросить")} {/if}
{/snippet} {#if settingsLoading || !visibleSettingsSections.length} {settingsLoading ? at("loading", {}, "Загрузка…") : at("no_data", {}, "Нет данных")} {:else}

{at( "settings_hint", {}, "Изменения в админке имеют приоритет над .env. Кнопка «Сбросить» возвращает значение из переменных окружения." )}

{settingsAllOpen ? at("collapse_all", {}, "Свернуть всё") : at("expand_all", {}, "Развернуть всё")} {#if Object.keys(settingsDirty).length > 0} settingsStore.saveSettings(onSettingsSaved)} disabled={settingsSaving} > {settingsSaving ? at("saving", {}, "Сохранение...") : at("save", {}, "Сохранить")} {/if}
{#each visibleSettingsSections as section} {@const dirtyInSection = section.fields.filter((f) => Boolean(settingsDirty[f.key])).length} {@const overriddenInSection = section.fields.filter((f) => isOverridden(f)).length} {sectionTitle(section.id)} {at( "settings_params_count", { count: section.fields.length }, `${section.fields.length} параметров` )}{#if overriddenInSection} · {at( "settings_overridden_count", { count: overriddenInSection }, `${overriddenInSection} override` )}{/if}{#if dirtyInSection} · {at( "settings_dirty_count", { count: dirtyInSection }, `${dirtyInSection} изм.` )}{/if} {@const groups = groupSectionFields(section)} {@const rootGroup = groups.find((g) => !g.label)} {@const labelGroups = groups.filter((g) => g.label)}
{#if rootGroup} {#each rootGroup.fields as field} {@render renderField(field)} {/each} {/if} {#if labelGroups.length} (settingsOpenSubsections = { ...settingsOpenSubsections, [section.id]: v })} class="admin-subsection-accordion" > {#each labelGroups as group} {@const subDirty = group.fields.filter((f) => Boolean(settingsDirty[f.key]) ).length} {@const subOverridden = group.fields.filter((f) => isOverridden(f)).length} {subsectionTitle(group)} {at( "settings_fields_count", { count: group.fields.length }, `${group.fields.length} полей` )}{#if subOverridden} · {at( "settings_overridden_count", { count: subOverridden }, `${subOverridden} override` )}{/if}{#if subDirty} · {at( "settings_dirty_count", { count: subDirty }, `${subDirty} изм.` )}{/if}
{#each group.fields as field} {@render renderField(field)} {/each}
{/each}
{/if}
{/each}
{/if}
{#if iconPickerField} {@const currentIconName = iconValue(iconPickerField)} {@const CurrentIcon = iconComponent(currentIconName)}
{at("settings_icon_current", {}, "Current icon")} {iconLabel(iconPickerField)} {#if !iconIsDefault(iconPickerField)} settingsStore.markDirty(iconPickerField.key, "")} > {at("settings_icon_use_default", {}, "Use default")} {/if}
{/if}
{#each filteredIconOptions as iconName} {@const Icon = iconComponent(iconName)} {/each}