diff --git a/public/admin/app-data.js b/public/admin/app-data.js
index b1e9b87..b36410f 100644
--- a/public/admin/app-data.js
+++ b/public/admin/app-data.js
@@ -797,6 +797,34 @@ async function refreshAccount(id) {
}
}
+function resetResultToast(result) {
+ const windows =
+ typeof result?.windowsReset === "number" && result.windowsReset > 0
+ ? ` (${result.windowsReset} window${result.windowsReset === 1 ? "" : "s"} reset)`
+ : "";
+ switch (result?.code) {
+ case "reset":
+ return { message: `Limits restored${windows}`, type: "success" };
+ case "nothing_to_reset":
+ return {
+ message: "Nothing to reset - limits are already clear",
+ type: "info",
+ };
+ case "no_credit":
+ return {
+ message: "No reset credit available on this account",
+ type: "error",
+ };
+ case "already_redeemed":
+ return { message: `Credit was already redeemed${windows}`, type: "info" };
+ default:
+ return {
+ message: `Codex reset result: ${result?.code || "complete"}`,
+ type: "info",
+ };
+ }
+}
+
async function redeemResetCredit(accountId, creditId) {
const account = accountById(accountId);
const label = account?.label || account?.accountId || accountId;
@@ -820,7 +848,8 @@ async function redeemResetCredit(accountId, creditId) {
{ method: "POST", body: JSON.stringify(body) }
);
state.pendingResetRedemptions.delete(redemptionKey);
- toast(`Codex reset result: ${response.result?.code || "complete"}`);
+ const { message, type } = resetResultToast(response.result);
+ toast(message, type);
await loadAccounts();
} catch (e) {
const redeemRequestId = e.body?.redeemRequestId;
diff --git a/public/admin/app-render.js b/public/admin/app-render.js
index 9876000..2043877 100644
--- a/public/admin/app-render.js
+++ b/public/admin/app-render.js
@@ -102,18 +102,32 @@ function codexLimitsBody(account, data) {
const available =
data.resetCredits?.availableCount ?? status?.resetCreditsAvailable;
- const actions = (data.resetCredits?.credits || [])
+ const availableCredits = (data.resetCredits?.credits || [])
.filter((credit) => credit.status === "available")
- .map(
- (credit) =>
- ``
+ .sort(
+ (a, b) =>
+ (quotaTimestamp(a.expiresAt) ?? Number.POSITIVE_INFINITY) -
+ (quotaTimestamp(b.expiresAt) ?? Number.POSITIVE_INFINITY)
);
+ const actions = availableCredits.map((credit) => {
+ const expiry = quotaTimestamp(credit.expiresAt);
+ const expiryLabel = expiry
+ ? `credit expires ${relativeTime(expiry)}`
+ : "credit does not expire";
+ const title = `${credit.description || "Consume a reset credit to restore limits"} \u00b7 ${expiryLabel}`;
+ return ``;
+ });
if (!actions.length && typeof available === "number" && available > 0) {
actions.push(
``
);
}
+ const soonestExpiry = quotaTimestamp(availableCredits[0]?.expiresAt);
+ if (soonestExpiry) {
+ chips.push(`reset credit expires ${relativeTime(soonestExpiry)}`);
+ }
+
return { rows, chips, actions };
}