Close-Knopf je Slot, direkt vor der jeweiligen G/V-Anzeige
User-Wunsch. Zwei Slots heissen zwei Close-Moeglichkeiten - bisher gab es nur
den grossen CLOSE-Knopf, und der schliesst seit heute BEIDE. Neu je ein kleines
✕ vor "G/V" (Slot 1) und vor "G/V · BRK", rechtsbuendig gespiegelt.
BACKEND: `engine.close(slot=None)` - None/"" = beide (Verhalten des grossen
Knopfs, unveraendert), "main" = nur Slot 1, "brk" = nur der Breakout-Autotrader.
`POST /api/order {"side":"close","slot":"brk"}` reicht ihn durch; ohne `slot`
ist das Verhalten bitgleich zu vorher.
⚠ Sicherheitsabfrage NUR im Minus - dieselbe Regel wie beim grossen Knopf: im
Plus direkt schliessen, im Minus nachfragen. Hartes Blockieren ist im Projekt
verworfen, aber ein versehentlicher Klick soll kein Geld kosten.
⚠⚠ EIGENER FEHLER auf dem Weg, gefunden bevor er live ging: mein erster Entwurf
las den P&L aus `_letzterSnap` - eine Variable, die es NICHT gab. Das ist exakt
der ReferenceError, der am 19.08. den halben Render abgeschossen hat, nur
diesmal im Klick-Pfad (er waere erst beim Druecken geknallt, also genau dann,
wenn man schliessen will). Behoben durch `letzterSnap`, das `_applySnapshot`
jetzt fuehrt - die Variable fehlte im Projekt tatsaechlich, Klick-Handler hatten
bisher keinen Zugriff auf den aktuellen Zustand.
Verifiziert: 2 Knoepfe im ausgelieferten HTML, span/div/button ausgeglichen,
keine doppelten IDs, node --check, Render-Probe, 91 Tests und die volle Pipeline
gruen. Deploy verifiziert (v=199).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
14b3fd4f64
commit
d881636e1b
+39
@@ -1577,8 +1577,16 @@ let lastRecvMs = 0;
|
||||
// Getrennt davon: wann kam zuletzt eine WS-NACHRICHT? Nur diese Uhr entscheidet,
|
||||
// ob der Poll uebersprungen wird (s. Kommentar in `sock.onmessage`).
|
||||
let lastWsMs = 0;
|
||||
// ⚠ Letzter gerenderter Snapshot — gebraucht von Klick-Handlern, die den
|
||||
// AKTUELLEN Zustand kennen muessen (z. B. der P&L fuer die Sicherheitsabfrage
|
||||
// der Slot-Close-Knoepfe). Vorher gab es das nicht; mein erster Entwurf hat
|
||||
// eine Variable `_letzterSnap` ERFUNDEN — genau der ReferenceError, der am
|
||||
// 19.08. den halben Render abgeschossen hat, nur diesmal im Klick-Pfad.
|
||||
let letzterSnap = null;
|
||||
|
||||
function _applySnapshot(d) {
|
||||
if (typeof d.ts === "number" && d.ts <= lastTs) return; // schon Neueres gezeigt
|
||||
letzterSnap = d;
|
||||
if (typeof d.ts === "number") lastTs = d.ts;
|
||||
lastRecvMs = Date.now();
|
||||
render(d);
|
||||
@@ -2308,3 +2316,34 @@ async function setMgGlobal() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// --- Close je Slot (User-Wunsch 2026-08-20) --------------------------------
|
||||
// ⚠ Der grosse CLOSE-Knopf unten bleibt der Hauptweg und schliesst BEIDE Slots.
|
||||
// Diese zwei sind fuer den Fall, dass genau EINE Position weg soll.
|
||||
// ⚠ Sicherheitsabfrage NUR im Minus — dieselbe Regel wie beim grossen Knopf:
|
||||
// im Plus direkt schliessen, im Minus nachfragen (hartes Blockieren ist im
|
||||
// Projekt verworfen, aber ein versehentlicher Klick soll kein Geld kosten).
|
||||
async function closeSlot(slot, label, pnl) {
|
||||
if (pnl != null && pnl < 0 &&
|
||||
!confirm(`${label} steht bei ${pnl.toFixed(2)} € im MINUS — wirklich schliessen?`)) {
|
||||
return;
|
||||
}
|
||||
const tok = await ensureToken();
|
||||
if (tok === null) return;
|
||||
try {
|
||||
const r = await fetch("api/order", { method: "POST",
|
||||
headers: { "X-Auth-Token": tok, "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ side: "close", slot: slot }) });
|
||||
if (r.status === 401) { clearToken(); throw new Error("401"); }
|
||||
const j = await r.json();
|
||||
toast(j.ok ? `${label} geschlossen` : (j.error || "Close fehlgeschlagen"), !!j.ok);
|
||||
} catch (e) {
|
||||
toast(e.message === "401" ? "Token abgelaufen — neu eingeben" : "Netzwerkfehler", false);
|
||||
}
|
||||
}
|
||||
{
|
||||
const a = $streng("close-main"), b = $streng("close-brk");
|
||||
if (a) a.onclick = () => closeSlot("main", "Slot 1", letzterSnap && letzterSnap.position ? letzterSnap.position.pnl : null);
|
||||
if (b) b.onclick = () => closeSlot("brk", "BRK", letzterSnap && letzterSnap.position_brk ? letzterSnap.position_brk.pnl : null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user