import { AlertTriangle, RefreshCw, Sun } from 'lucide-react' import { adminApi, authApi } from '../../../api/client' import { getApiErrorMessage } from '../../../types' import type { TranslationFn } from '../../../types' import type { useAdmin } from '../../../pages/admin/useAdmin' import MToggle from '../../components/MToggle' import { MAdminButton, MAdminCard, MAdminCardHead, MAdminField, MAdminInput, MAdminRow, MAdminSecretInput, } from './MAdminUi' interface MAdminSettingsSectionProps { admin: ReturnType t: TranslationFn } // Settings section: auth methods, passkey login, require-MFA, allowed file // types, API keys, OIDC and the danger zone — the full desktop settings tab // relaid as mobile cards. All state and mutations come from useAdmin. export default function MAdminSettingsSection({ admin, t }: MAdminSettingsSectionProps) { const { toast, setPlacesPhotosEnabled, setPlacesAutocompleteEnabled, setPlacesDetailsEnabled, setPlacesEnrichEnabled, setPlaceShadowEnabled, placesPhotosEnabled, setPlacesPhotosEnabledState, placesAutocompleteEnabled, setPlacesAutocompleteEnabledState, placesDetailsEnabled, setPlacesDetailsEnabledState, placesEnrichEnabled, setPlacesEnrichEnabledState, placeShadowEnabled, setPlaceShadowEnabledState, oidcConfig, setOidcConfig, savingOidc, setSavingOidc, passwordLogin, setPasswordLogin, passwordRegistration, setPasswordRegistration, oidcLogin, setOidcLogin, oidcRegistration, setOidcRegistration, envOverrideOidcOnly, oidcConfigured, requireMfa, passkeyLogin, setPasskeyLogin, passkeyConfigured, webauthnRpId, setWebauthnRpId, webauthnOrigins, setWebauthnOrigins, savingWebauthn, handleSaveWebauthn, allowedFileTypes, setAllowedFileTypes, savingFileTypes, setSavingFileTypes, mapsKey, setMapsKey, unsplashKey, setUnsplashKey, amapKey, setAmapKey, savingKeys, validating, validation, placesProvider, savingPlacesProvider, handleSavePlacesProvider, setShowRotateJwtModal, handleToggleAuthSetting, handleToggleRequireMfa, handleSaveApiKeys, handleValidateKey, } = admin const saveFileTypes = async () => { setSavingFileTypes(true) try { await authApi.updateAppSettings({ allowed_file_types: allowedFileTypes }) toast.success(t('admin.fileTypesSaved')) } catch { toast.error(t('common.error')) } finally { setSavingFileTypes(false) } } const saveOidc = async () => { setSavingOidc(true) try { const payload: Record = { issuer: oidcConfig.issuer, client_id: oidcConfig.client_id, display_name: oidcConfig.display_name, discovery_url: oidcConfig.discovery_url, } if (oidcConfig.client_secret) payload.client_secret = oidcConfig.client_secret await adminApi.updateOidc(payload) toast.success(t('admin.oidcSaved')) } catch (err: unknown) { toast.error(getApiErrorMessage(err, t('common.error'))) } finally { setSavingOidc(false) } } return (
{/* Authentication methods */} {envOverrideOidcOnly && (

{t('admin.envOverrideHint')}

)} handleToggleAuthSetting('password_login', v, setPasswordLogin)} /> } /> handleToggleAuthSetting('password_registration', v, setPasswordRegistration)} /> } /> {oidcConfigured && ( handleToggleAuthSetting('oidc_login', v, setOidcLogin)} /> } /> )} {oidcConfigured && ( handleToggleAuthSetting('oidc_registration', v, setOidcRegistration)} /> } /> )}
{/* Passkey login */} handleToggleAuthSetting('passkey_login', v, setPasskeyLogin)} /> } /> {passkeyLogin && !passkeyConfigured && (

{t('admin.passkey.notConfigured')}

)}
setWebauthnRpId(e.target.value)} placeholder="trek.example.org" /> setWebauthnOrigins(e.target.value)} placeholder="https://trek.example.org" /> {t('common.save')}
{/* Require 2FA */} } /> {/* Allowed file types */}
setAllowedFileTypes(e.target.value)} placeholder="jpg,png,pdf,doc,docx,xls,xlsx,txt,csv" /> {t('common.save')}
{/* API keys */}
{t('admin.mapsKey')} {t('admin.recommended')} } hint={t('admin.mapsKeyHintLong')} >
setMapsKey(e.target.value)} placeholder={t('settings.keyPlaceholder')} />
handleValidateKey('maps')} className="h-[42px]" > {t('admin.validateKey')}
{validation.maps === true && (

{t('admin.keyValid')}

)} {validation.maps === false && (

{t('admin.keyInvalid')}

)}
{/* No Test button, same as the desktop tab: /auth/validate-keys only knows how to probe Google Places and OpenWeatherMap. */} setAmapKey(e.target.value)} placeholder={t('settings.keyPlaceholder')} /> {((placesProvider === 'google' && !mapsKey) || (placesProvider === 'amap' && !amapKey)) && (

{t('admin.placesProvider.missingKey')}

)}
setUnsplashKey(e.target.value)} placeholder={t('settings.keyPlaceholder')} />
{ setPlacesPhotosEnabledState(next) setPlacesPhotosEnabled(next) try { await adminApi.updatePlacesPhotos(next) } catch { setPlacesPhotosEnabledState(!next) setPlacesPhotosEnabled(!next) } }} /> } /> { setPlacesAutocompleteEnabledState(next) setPlacesAutocompleteEnabled(next) try { await adminApi.updatePlacesAutocomplete(next) } catch { setPlacesAutocompleteEnabledState(!next) setPlacesAutocompleteEnabled(!next) } }} /> } /> { setPlacesDetailsEnabledState(next) setPlacesDetailsEnabled(next) try { await adminApi.updatePlacesDetails(next) } catch { setPlacesDetailsEnabledState(!next) setPlacesDetailsEnabled(!next) } }} /> } /> { setPlacesEnrichEnabledState(next) setPlacesEnrichEnabled(next) try { await adminApi.updatePlacesEnrich(next) } catch { setPlacesEnrichEnabledState(!next) setPlacesEnrichEnabled(!next) } }} /> } /> { setPlaceShadowEnabledState(next) setPlaceShadowEnabled(next) try { await adminApi.updatePlaceShadow(next) } catch { setPlaceShadowEnabledState(!next) setPlaceShadowEnabled(!next) } }} /> } />
{/* Open-Meteo weather info */}
{t('admin.weather.title')} {t('admin.weather.badge')}

{t('admin.weather.description')}

{t('admin.weather.locationHint')}

{[ { title: t('admin.weather.forecast'), desc: t('admin.weather.forecastDesc') }, { title: t('admin.weather.climate'), desc: t('admin.weather.climateDesc') }, { title: t('admin.weather.requests'), desc: t('admin.weather.requestsDesc') }, ].map((row) => (

{row.title}

{row.desc}

))}
{t('common.save')}
{/* OIDC / SSO */}
setOidcConfig((c) => ({ ...c, display_name: e.target.value }))} placeholder="z.B. Google, Authentik, Keycloak" /> setOidcConfig((c) => ({ ...c, issuer: e.target.value }))} placeholder="https://accounts.google.com" /> setOidcConfig((c) => ({ ...c, discovery_url: e.target.value }))} placeholder="https://auth.example.com/application/o/trek/.well-known/openid-configuration" /> setOidcConfig((c) => ({ ...c, client_id: e.target.value }))} /> setOidcConfig((c) => ({ ...c, client_secret: e.target.value }))} placeholder={oidcConfig.client_secret_set ? '••••••••' : ''} /> {t('common.save')}
{/* Danger zone */}
Danger Zone
setShowRotateJwtModal(true)}> Rotate } />
) }