import { useId, useMemo, useState } from 'react' import { FolderPlus, KeyRound, Loader2, Search } from 'lucide-react' import { DialogHeader, DialogShell, DialogTile, NEUTRAL_TINT } from '../../shared/DialogShell' import { useTranslation } from '../../../i18n/TranslationContext' import type { DocSyncConnection, useDocSync } from './useDocSync' import { NEW_SCOPE, useScopePicker } from './useScopePicker' /** * Picking the container a trip lives in. * * The list is filtered client-side: these are a person's own folders or tags, * so there are tens of them, not thousands, and a round trip per keystroke * would be slower than the filter it replaces. * * "Create" is a first-class action rather than a fallback at the bottom, * because for a new trip it is the common case: there is no folder yet. */ export default function DocSyncScopeModal({ connection, providerName, suggestedName, sync, onClose, onBound, onEditConnection, }: { connection: DocSyncConnection providerName: string /** Pre-filled name for a new container, from the trip's title. */ suggestedName: string sync: ReturnType onClose: () => void onBound: () => void /** Back to the stored connection, to change the login or remove it before choosing a folder. */ onEditConnection?: () => void }) { const { t } = useTranslation() const labelId = useId() const [query, setQuery] = useState('') const { scopes, error, name: newName, setName: setNewName, working, bind, createAndBind } = useScopePicker({ connectionId: connection.id, suggestedName, sync, onBound, }) const shown = useMemo(() => { const needle = query.trim().toLowerCase() if (!needle || !scopes) return scopes ?? [] return scopes.filter(s => s.label.toLowerCase().includes(needle)) }, [scopes, query]) return ( } tint={NEUTRAL_TINT} labelId={labelId} onClose={onClose} title={t('docsync.scope.title', { provider: providerName })} /> )} >

{t('docsync.scope.intro')}

{onEditConnection && ( )}
{t('docsync.scope.createTitle')}
setNewName(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') void createAndBind() }} placeholder={t('docsync.newFolderPlaceholder')} className="min-w-0 flex-1 rounded-lg border border-edge bg-surface-input px-3 py-2 text-body text-content ring-accent focus:outline-none focus:ring-2" />
{t('docsync.scope.pickTitle')} {scopes && scopes.length > 6 && ( setQuery(e.target.value)} placeholder={t('docsync.scope.search')} className="w-44 rounded-lg border border-edge bg-surface-input py-1.5 ps-8 pe-2.5 text-caption text-content ring-accent focus:outline-none focus:ring-2" /> )}
{sync.error && (

{t(`docsync.error.${sync.error}`)}

)} {scopes === null ? (
) : error ? (

{t(`docsync.error.${error}`)}

) : shown.length === 0 ? (

{query ? t('docsync.scope.noMatch') : t('docsync.noFolders')}

) : (
    {shown.map(s => (
  • ))}
)}
) }