import { useEffect, useMemo, useState } from 'react'; import { X, Plus } from 'lucide-react'; import { ADIFFields } from '../../wailsjs/go/main/App'; import { Input } from '@/components/ui/input'; import { Combobox } from '@/components/ui/combobox'; import { Button } from '@/components/ui/button'; import { useI18n } from '@/lib/i18n'; type FieldDef = { name: string; kind: string; category: string; promoted: boolean; deprecated: boolean; intl: boolean; }; interface Props { // The QSO's extras map (uppercase ADIF tag → raw value). value: Record | undefined; onChange: (next: Record | undefined) => void; } // AdifExtrasEditor — a dictionary-driven editor for every ADIF field that is // NOT promoted to a first-class column. Backed by the QSO's extras map, so any // ADIF 3.1.7 field (plus custom/vendor tags) can be viewed and edited. This is // what makes "100% of ADIF fields available" true without 160 DB columns. export function AdifExtrasEditor({ value, onChange }: Props) { const { t } = useI18n(); const [dict, setDict] = useState([]); const [showDeprecated, setShowDeprecated] = useState(false); useEffect(() => { ADIFFields().then((f) => setDict((f ?? []) as any)).catch(() => {}); }, []); // Entries currently set, sorted for stable display. const entries = useMemo( () => Object.entries(value ?? {}).sort((a, b) => a[0].localeCompare(b[0])), [value], ); // Addable fields: standard non-promoted ADIF fields not already present. // Deprecated (import-only) fields are hidden unless the toggle is on. const addable = useMemo(() => { const have = new Set(Object.keys(value ?? {})); return dict .filter((f) => !f.promoted && !have.has(f.name) && (showDeprecated || !f.deprecated)) .map((f) => f.name); }, [dict, value, showDeprecated]); const meta = useMemo(() => { const m: Record = {}; for (const f of dict) m[f.name] = f; return m; }, [dict]); function setKV(key: string, val: string) { const next = { ...(value ?? {}) }; next[key] = val; onChange(next); } function remove(key: string) { const next = { ...(value ?? {}) }; delete next[key]; onChange(Object.keys(next).length ? next : undefined); } function addField(name: string) { const key = name.trim().toUpperCase(); if (!key || (value && key in value)) return; setKV(key, ''); } return (

{t('adx.introPart1')}APP_*{t('adx.introPart2')}{t('adx.fullMode')}{t('adx.introPart3')}

{/* Add a field */}
{/* Current entries */} {entries.length === 0 ? (
{t('adx.noExtra')}
) : (
{entries.map(([k, v]) => { const def = meta[k]; return (
{k} {def && ( {def.category}{def.deprecated ? ' · ' + t('adx.deprecated') : ''}{def.intl ? ' · ' + t('adx.intl') : ''} {!def && ''} )} {!def && {t('adx.nonStandard')}}
setKV(k, e.target.value)} />
); })}
)}
); }