diff --git a/client/src/mobile/screens/admin/MAdminSettingsSection.tsx b/client/src/mobile/screens/admin/MAdminSettingsSection.tsx index 0c561a90d..c60306c0f 100644 --- a/client/src/mobile/screens/admin/MAdminSettingsSection.tsx +++ b/client/src/mobile/screens/admin/MAdminSettingsSection.tsx @@ -1,9 +1,12 @@ -import { AlertTriangle, RefreshCw, Sun } from 'lucide-react' +import { useState } from 'react' +import { AlertTriangle, ChevronDown, RefreshCw } 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 { MBlockDisclosure, MProviderBlock, MTrekApiBlock } from './MApiProviderBlocks' +import MSetPickerSheet from '../settings/MSetPickerSheet' import { MAdminButton, MAdminCard, @@ -23,6 +26,7 @@ interface MAdminSettingsSectionProps { // 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 [providerPickerOpen, setProviderPickerOpen] = useState(false) const { toast, setPlacesPhotosEnabled, setPlacesAutocompleteEnabled, setPlacesDetailsEnabled, setPlacesEnrichEnabled, setPlaceShadowEnabled, @@ -217,20 +221,22 @@ export default function MAdminSettingsSection({ admin, t }: MAdminSettingsSectio
+ {/* Comparable blocks in the order we would have somebody choose them, + matching the desktop tab: the free source first, the keys after it. + The recommendation used to sit on the Google field here, which told + a phone admin the opposite of what the same setting says on a + laptop. */} + + {/* The keys belong to the operator on a managed install, same as on the desktop tab; the provider choice below stays the admin's. */} {!managed && (<> - - {t('admin.mapsKey')} - - {t('admin.recommended')} - - - } - hint={t('admin.mapsKeyHintLong')} - > + + {/* Said before the field, not after it: somebody about to paste a key + should read this while deciding, not once they already have. */} +

+ {t('admin.mapsKeyHintShort')} +

{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')} - /> - - - - setUnsplashKey(e.target.value)} - placeholder={t('settings.keyPlaceholder')} - /> - - )} - - - - {/* From app-config, like the desktop card: the key fields are empty - on a managed install and on an operator key set by environment. */} - {((placesProvider === 'google' && !hasMapsKey) || (placesProvider === 'amap' && !hasAmapKey)) && ( -

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

- )} -
- -
- {/* The four Google switches trade away quota that is the operator's on - a managed install; the search log below is the instance's own. */} - {!managed && (<> + {/* What the key is allowed to be spent on. Under the key rather than + loose at the foot of the card: every one of them is a Google + request, and none of them mean anything without it. */} + } /> - )} + + + + {/* No Test button, same as the desktop tab: /auth/validate-keys only + knows how to probe Google Places and OpenWeatherMap. */} + +

{t('admin.amapKeyHintShort')}

+ setAmapKey(e.target.value)} + placeholder={t('settings.keyPlaceholder')} + /> +
+ + +

{t('admin.unsplashKeyHint')}

+ setUnsplashKey(e.target.value)} + placeholder={t('settings.keyPlaceholder')} + /> +
+ )} + + + {/* The app's own picker rather than a bare