From b48019b08f21e42db2232c66bed092c8bb9da6be Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Tue, 1 Sep 2026 21:04:55 +0200 Subject: [PATCH] Four cards is three too many to scroll past MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The charging column grew a card at a time and now runs well past a screen, so each of the four folds away: connection, control, readings, information. The mechanism is the provider panel's, down to the chevron and the localStorage key — folding is a reading habit of this browser, not an account setting, and one learned gesture should work in both places. The connected badge stays in the connection header while it is folded, since whether the charger is reachable is the thing worth seeing without opening anything. Charger information keeps its Refresh button beside the toggle rather than inside it, a button being no place for another button. Co-Authored-By: Claude Opus 5 --- Web App/web/src/views/Charging.vue | 106 +++++++++++++++++++++++++++-- 1 file changed, 99 insertions(+), 7 deletions(-) diff --git a/Web App/web/src/views/Charging.vue b/Web App/web/src/views/Charging.vue index 2dd9811..6a65141 100644 --- a/Web App/web/src/views/Charging.vue +++ b/Web App/web/src/views/Charging.vue @@ -57,6 +57,41 @@ const sessionMetrics = computed(() => // --- Real OCPP control (Anker Solix), gated by the per-user control mode --- // The demo session card above is presentational; this card drives a real charger // via the control endpoints when the user has picked Own/Proxy CSMS in Settings. +// --- Folding the cards --- +// +// The column runs long once the readings are in it, so every card folds away. +// Which ones are folded is kept in localStorage rather than on the profile, the +// same way the provider panel keeps its own: it is a per-device reading habit, +// not an account setting, and it should survive leaving the tab. Keyed by card, +// so a fold outlives switching charger. +const COLLAPSED_KEY = "dv_charging_collapsed"; + +const collapsed = ref(readCollapsed()); + +function readCollapsed() { + try { + const raw = JSON.parse(localStorage.getItem(COLLAPSED_KEY) || "[]"); + return Array.isArray(raw) ? raw.filter((id) => typeof id === "string") : []; + } catch { + return []; // unreadable (hand-edited, or written by an older version) + } +} + +function isOpen(id) { + return !collapsed.value.includes(id); +} + +function toggleCard(id) { + collapsed.value = isOpen(id) + ? [...collapsed.value, id] + : collapsed.value.filter((k) => k !== id); + try { + localStorage.setItem(COLLAPSED_KEY, JSON.stringify(collapsed.value)); + } catch { + // A full or blocked store just means the choice lasts this visit only. + } +} + const ctlMode = ref("off"); const ctlSerial = ref(localStorage.getItem("dv_ctl_serial") || ""); const ctl = ref(null); // { connected, status, controlMode, ... } @@ -728,12 +763,27 @@ onMounted(async () => {
-
+
+ + +