fix(costs): guard routes, fix DST ranges, sync provider state, wire live updates
- add companyAccess guard to costs route - fix effectiveProvider/activeProvider desync via sync-back useEffect - move ROLLING_WINDOWS to module level; replace IIFE with useMemo in ProviderQuotaCard - add NO_COMPANY sentinel to eliminate non-null assertions before enabled guard - fix DST-unsafe 7d/30d ranges in useDateRange (use Date constructor) - remove providerData from providerTabItems memo deps (use byProvider) - normalize used_percent 0-1 vs 0-100 ambiguity in quota-windows service - rename secondsToWindowLabel index param to fallback; pass explicit labels - add 4.33 magic number comment; fix quota window key collision - remove rounded-md from date inputs (violates --radius: 0 theme) - wire cost_event invalidation in LiveUpdatesProvider
This commit is contained in:
@@ -79,6 +79,8 @@ export function costRoutes(db: Db) {
|
||||
});
|
||||
|
||||
router.get("/companies/:companyId/costs/quota-windows", async (req, res) => {
|
||||
const companyId = req.params.companyId as string;
|
||||
assertCompanyAccess(req, companyId);
|
||||
assertBoard(req);
|
||||
const results = await fetchAllQuotaWindows();
|
||||
res.json(results);
|
||||
|
||||
@@ -164,12 +164,12 @@ interface WhamUsageResponse {
|
||||
credits?: WhamCredits | null;
|
||||
}
|
||||
|
||||
function secondsToWindowLabel(seconds: number | null | undefined): string {
|
||||
if (seconds == null) return "Window";
|
||||
function secondsToWindowLabel(seconds: number | null | undefined, fallback: string): string {
|
||||
if (seconds == null) return fallback;
|
||||
const hours = seconds / 3600;
|
||||
if (hours <= 6) return "5h";
|
||||
if (hours <= 30) return "24h";
|
||||
return "Weekly";
|
||||
if (hours < 6) return "5h";
|
||||
if (hours <= 24) return "24h";
|
||||
return "7d";
|
||||
}
|
||||
|
||||
async function fetchCodexQuota(token: string, accountId: string | null): Promise<QuotaWindow[]> {
|
||||
@@ -186,18 +186,28 @@ async function fetchCodexQuota(token: string, accountId: string | null): Promise
|
||||
const rateLimit = body.rate_limit;
|
||||
if (rateLimit?.primary_window != null) {
|
||||
const w = rateLimit.primary_window;
|
||||
// wham used_percent is 0-100 (confirmed empirically); guard against 0-1 format just in case
|
||||
const rawPct = w.used_percent ?? null;
|
||||
const usedPercent = rawPct != null
|
||||
? Math.min(100, Math.round(rawPct <= 1 ? rawPct * 100 : rawPct))
|
||||
: null;
|
||||
windows.push({
|
||||
label: secondsToWindowLabel(w.limit_window_seconds),
|
||||
usedPercent: w.used_percent ?? null,
|
||||
label: secondsToWindowLabel(w.limit_window_seconds, "Primary"),
|
||||
usedPercent,
|
||||
resetsAt: w.reset_at ?? null,
|
||||
valueLabel: null,
|
||||
});
|
||||
}
|
||||
if (rateLimit?.secondary_window != null) {
|
||||
const w = rateLimit.secondary_window;
|
||||
// wham used_percent is 0-100 (confirmed empirically); guard against 0-1 format just in case
|
||||
const rawPct = w.used_percent ?? null;
|
||||
const usedPercent = rawPct != null
|
||||
? Math.min(100, Math.round(rawPct <= 1 ? rawPct * 100 : rawPct))
|
||||
: null;
|
||||
windows.push({
|
||||
label: secondsToWindowLabel(w.limit_window_seconds),
|
||||
usedPercent: w.used_percent ?? null,
|
||||
label: secondsToWindowLabel(w.limit_window_seconds, "Secondary"),
|
||||
usedPercent,
|
||||
resetsAt: w.reset_at ?? null,
|
||||
valueLabel: null,
|
||||
});
|
||||
@@ -206,7 +216,7 @@ async function fetchCodexQuota(token: string, accountId: string | null): Promise
|
||||
const balance = body.credits.balance;
|
||||
const valueLabel = balance != null
|
||||
? `$${(balance / 100).toFixed(2)} remaining`
|
||||
: null;
|
||||
: "N/A";
|
||||
windows.push({
|
||||
label: "Credits",
|
||||
usedPercent: null,
|
||||
|
||||
Reference in New Issue
Block a user