feat: option lab
This commit is contained in:
@@ -338,18 +338,18 @@ function RiskProfilesCard() {
|
|||||||
function SaxoLinkPicker({ ticker, saxoSymbol }: { ticker: string; saxoSymbol: string | null }) {
|
function SaxoLinkPicker({ ticker, saxoSymbol }: { ticker: string; saxoSymbol: string | null }) {
|
||||||
const [editing, setEditing] = useState(false)
|
const [editing, setEditing] = useState(false)
|
||||||
const [value, setValue] = useState(saxoSymbol ?? '')
|
const [value, setValue] = useState(saxoSymbol ?? '')
|
||||||
|
const [showDropdown, setShowDropdown] = useState(false)
|
||||||
const { mutate: setLink, isPending } = useSetWatchlistSaxoLink()
|
const { mutate: setLink, isPending } = useSetWatchlistSaxoLink()
|
||||||
const { data: catalogMatches } = useSaxoCatalog(undefined, value.length >= 2 ? value : undefined)
|
const { data: catalogMatches } = useSaxoCatalog(undefined, value.length >= 2 ? value : undefined)
|
||||||
const datalistId = `saxo-symbols-${ticker}`
|
|
||||||
|
|
||||||
const save = () => {
|
const save = (sym?: string) => {
|
||||||
const sym = value.trim().toUpperCase() || null
|
const resolved = (sym ?? value).trim().toUpperCase() || null
|
||||||
setLink({ ticker, saxoSymbol: sym }, { onSuccess: () => setEditing(false) })
|
setLink({ ticker, saxoSymbol: resolved }, { onSuccess: () => setEditing(false) })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!editing) {
|
if (!editing) {
|
||||||
return saxoSymbol ? (
|
return saxoSymbol ? (
|
||||||
<button onClick={() => setEditing(true)} className="flex items-center gap-1 text-[9px] text-emerald-400 hover:text-emerald-300 bg-emerald-900/20 border border-emerald-700/30 px-1.5 py-0.5 rounded">
|
<button onClick={() => { setEditing(true); setValue(saxoSymbol) }} className="flex items-center gap-1 text-[9px] text-emerald-400 hover:text-emerald-300 bg-emerald-900/20 border border-emerald-700/30 px-1.5 py-0.5 rounded">
|
||||||
<Link2 className="w-2.5 h-2.5" /> {saxoSymbol}
|
<Link2 className="w-2.5 h-2.5" /> {saxoSymbol}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
@@ -360,21 +360,34 @@ function SaxoLinkPicker({ ticker, saxoSymbol }: { ticker: string; saxoSymbol: st
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1">
|
<div className="relative">
|
||||||
<input
|
<input
|
||||||
autoFocus
|
autoFocus
|
||||||
list={datalistId}
|
|
||||||
value={value}
|
value={value}
|
||||||
onChange={e => setValue(e.target.value)}
|
onChange={e => { setValue(e.target.value); setShowDropdown(true) }}
|
||||||
|
onFocus={() => setShowDropdown(true)}
|
||||||
onKeyDown={e => { if (e.key === 'Enter') save(); if (e.key === 'Escape') setEditing(false) }}
|
onKeyDown={e => { if (e.key === 'Enter') save(); if (e.key === 'Escape') setEditing(false) }}
|
||||||
onBlur={save}
|
onBlur={() => save()}
|
||||||
placeholder="Saxo symbol"
|
placeholder="Search Saxo symbol…"
|
||||||
className="bg-dark-800 border border-slate-700/40 rounded px-1.5 py-0.5 text-[9px] text-white w-24 focus:outline-none focus:border-blue-500/50"
|
className="bg-dark-800 border border-slate-700/40 rounded px-1.5 py-0.5 text-[9px] text-white w-28 focus:outline-none focus:border-blue-500/50"
|
||||||
/>
|
/>
|
||||||
<datalist id={datalistId}>
|
{isPending && <span className="text-[9px] text-slate-600 ml-1">…</span>}
|
||||||
{(catalogMatches ?? []).map((c: any) => <option key={c.symbol} value={c.symbol}>{c.description}</option>)}
|
{showDropdown && (catalogMatches ?? []).length > 0 && (
|
||||||
</datalist>
|
<div className="absolute z-20 top-full left-0 mt-1 w-72 max-h-60 overflow-y-auto bg-dark-800 border border-slate-700 rounded shadow-xl">
|
||||||
{isPending && <span className="text-[9px] text-slate-600">…</span>}
|
{(catalogMatches ?? []).map((c: any) => (
|
||||||
|
<button
|
||||||
|
key={c.symbol}
|
||||||
|
type="button"
|
||||||
|
onMouseDown={e => e.preventDefault()}
|
||||||
|
onClick={() => { setValue(c.symbol); setShowDropdown(false); save(c.symbol) }}
|
||||||
|
className="flex items-center justify-between gap-3 w-full text-left px-2.5 py-1.5 text-[10px] hover:bg-dark-700 transition-colors"
|
||||||
|
>
|
||||||
|
<span className="font-mono font-bold text-white shrink-0">{c.symbol}</span>
|
||||||
|
<span className="text-slate-500 truncate">{c.description}</span>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user