import type { PaddleRegionAutoMode, PaddleRegionPending } from '@trek/shared'; import { Ban, CloudDownload, Hand, Loader2, Power, Sparkles } from 'lucide-react'; import { useTranslation } from '../../../i18n'; import { ChoiceChips, SettingRows, SETTINGS_BUTTON, SettingsHint, StatusPill } from '../../Settings/settingsKit'; import { LABEL, Segmented } from '../../shared/dialogParts'; import { fs } from '../../shared/DialogShell'; import { Tooltip } from '../../shared/Tooltip'; import { AUTO_LOAD_MODES, autoLoadSizes, formatMegabytes } from './paddleRegionsModel'; import type { usePaddleRegionsAdmin } from './usePaddleRegionsAdmin'; type Admin = ReturnType; const MODE_ICONS = { auto: CloudDownload, ask: Hand, off: Power } as const; /** `formatMegabytes` in the reader's language. */ function useMegabytes() { const { language } = useTranslation(); return (mb: number) => formatMegabytes(mb, language); } const MB = 1024 * 1024; /** * PAD-11C: how TREK gets the water data of a place a paddler plans in. The * mode, and in the automatic one the largest region it loads without asking. */ export function AutoLoadSettings({ admin }: { admin: Admin }) { const { t } = useTranslation(); const megabytes = useMegabytes(); const { settings, saving, save } = admin.autoLoad; if (!settings) return null; const sizes = autoLoadSizes(settings.max_mb); return (
{t('admin.paddleRegions.auto.title')}
value={settings.mode} onChange={(mode) => void save({ mode })} label={t('admin.paddleRegions.auto.title')} fill options={AUTO_LOAD_MODES.map((mode) => { const Icon = MODE_ICONS[mode]; return { value: mode, label: t(`admin.paddleRegions.auto.mode.${mode}`), icon:
{t(`admin.paddleRegions.auto.modeHint.${settings.mode}`)}
{settings.mode === 'auto' && (
{t('admin.paddleRegions.auto.maxSize')} value={String(settings.max_mb)} label={t('admin.paddleRegions.auto.maxSize')} onChange={(value) => void save({ max_mb: Number(value) })} options={sizes.map((mb) => ({ value: String(mb), label: megabytes(mb) }))} /> {t('admin.paddleRegions.auto.maxSizeHint')}
)}
); } function RequestRow({ request, admin }: { request: PaddleRegionPending; admin: Admin }) { const { t, language } = useTranslation(); const megabytes = useMegabytes(); const busy = admin.busyId === request.id; const date = new Date(request.requested_at).toLocaleDateString(language, { dateStyle: 'medium' }); return (
{request.name} {request.declined ? ( }> {t('admin.paddleRegions.requests.declined')} ) : ( {t(`admin.paddleRegions.requests.reason.${request.reason}`)} )} {request.bytes !== null && {megabytes(Math.max(1, Math.round(request.bytes / MB)))}} {request.requested_by && ( {t('admin.paddleRegions.requests.by', { user: request.requested_by })} )} {date}
{!request.declined && ( )}
); } /** The regions paddlers asked for that wait for an admin, the open ones first. */ export function RequestList({ admin }: { admin: Admin }) { const { t } = useTranslation(); if (admin.requests.length === 0) return null; const ordered = [...admin.requests].sort((a, b) => Number(a.declined) - Number(b.declined)); const open = admin.requests.filter((request) => !request.declined).length; return (
{t('admin.paddleRegions.requests.title')} {open > 0 && {open}} {ordered.map((request) => ( ))}
); } /** A region TREK loaded by itself for a paddler, told apart from those an admin added. */ export function AutoOriginPill() { const { t } = useTranslation(); return ( }>{t('admin.paddleRegions.origin.auto')} ); }