Account-Liste: Status-Spalte sortiert nach Premium-Restlaufzeit (Klick)

User-Wunsch: in der Account-Liste auf "Status" klicken und nach Premium-Restlaufzeit
sortieren (laengste<->kuerzeste). Da die Accounts pro Anbieter gruppiert sind, wird
INNERHALB jeder Gruppe sortiert (dort sitzen die Premium-Tage).

- Neuer Zustand accountStatusSort (none -> desc -> asc -> none) per Klick auf den
  Status-Spaltenkopf (mit ▼/▲-Indikator).
- groupedAccountRows sortiert bei desc/asc jede Gruppe nach premiumUntilMs:
  Premium-Accounts nach Restlaufzeit (desc = laengste zuerst, asc = kuerzeste
  zuerst), Accounts ohne Premium/ohne Status bleiben am Ende.

Reine Renderer-Aenderung. tsc=6, build ok.
This commit is contained in:
Sucukdeluxe 2026-06-15 03:49:00 +02:00
parent f5fe52bbb3
commit 622ed1653b
2 changed files with 25 additions and 2 deletions

View File

@ -2617,6 +2617,9 @@ export function App(): ReactElement {
return rows;
}, [configuredAccounts, settingsDraft, snapshot.settings]);
const [accountStatusSort, setAccountStatusSort] = useState<"none" | "desc" | "asc">("none");
const cycleAccountStatusSort = (): void => setAccountStatusSort((s) => (s === "none" ? "desc" : s === "desc" ? "asc" : "none"));
const groupedAccountRows = useMemo(() => {
const groups: { service: string; serviceLabel: string; rows: typeof accountRows }[] = [];
const byService = new Map<string, { service: string; serviceLabel: string; rows: typeof accountRows }>();
@ -2630,8 +2633,26 @@ export function App(): ReactElement {
}
group.rows.push(row);
}
if (accountStatusSort !== "none") {
const statuses = snapshot.settings?.debridAccountStatuses || {};
const now = Date.now();
const remainingMs = (row: (typeof accountRows)[number]): number => {
const st = row.accountId ? statuses[row.accountId] : null;
return st && st.premiumUntilMs && st.premiumUntilMs > now ? st.premiumUntilMs - now : -1;
};
for (const group of groups) {
group.rows = [...group.rows].sort((a, b) => {
const ra = remainingMs(a);
const rb = remainingMs(b);
if (ra > 0 && rb > 0) return accountStatusSort === "desc" ? rb - ra : ra - rb;
if (ra > 0) return -1;
if (rb > 0) return 1;
return 0;
});
}
}
return groups;
}, [accountRows]);
}, [accountRows, accountStatusSort, snapshot.settings]);
const [collapsedAccountGroups, setCollapsedAccountGroups] = useState<Set<string>>(() => {
try {
@ -5403,7 +5424,7 @@ export function App(): ReactElement {
<span className="acct2-c-check" />
<span>Hoster</span>
<span>Download-Traffic</span>
<span>Status</span>
<span className="acct2-sortable" title="Nach Premium-Restlaufzeit sortieren (längste/kürzeste)" onClick={cycleAccountStatusSort}>Status{accountStatusSort === "desc" ? " ▼" : accountStatusSort === "asc" ? " ▲" : ""}</span>
<span>Benutzername</span>
<span>Verfallsdatum</span>
<span className="acct2-c-actions">Aktion</span>

View File

@ -3321,6 +3321,8 @@ td {
.acct2-expiry { font-variant-numeric: tabular-nums; color: var(--muted); }
.acct2-head > span:nth-child(3),
.acct2-traffic { text-align: center; }
.acct2-sortable { cursor: pointer; user-select: none; }
.acct2-sortable:hover { color: var(--text); }
.acct2-user { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acct2-status .account-validity-badge { margin-top: 0; }
.acct2-nostatus { color: var(--muted); opacity: 0.6; font-variant-numeric: tabular-nums; }