diff --git a/ui/src/components/account/flow-viz/account-card.tsx b/ui/src/components/account/flow-viz/account-card.tsx
index 569d640c..ac86917b 100644
--- a/ui/src/components/account/flow-viz/account-card.tsx
+++ b/ui/src/components/account/flow-viz/account-card.tsx
@@ -6,7 +6,7 @@ import {
cn,
sortModelsByPriority,
formatResetTime,
- getEarliestResetTime,
+ getClaudeResetTime,
getMinClaudeQuota,
} from '@/lib/utils';
import { PRIVACY_BLUR_CLASS } from '@/contexts/privacy-context';
@@ -226,7 +226,7 @@ export function AccountCard({
))}
{(() => {
- const resetTime = getEarliestResetTime(quota?.models || []);
+ const resetTime = getClaudeResetTime(quota?.models || []);
return resetTime ? (
diff --git a/ui/src/components/cliproxy/provider-editor/account-item.tsx b/ui/src/components/cliproxy/provider-editor/account-item.tsx
index f0f4aed6..8126989a 100644
--- a/ui/src/components/cliproxy/provider-editor/account-item.tsx
+++ b/ui/src/components/cliproxy/provider-editor/account-item.tsx
@@ -33,7 +33,7 @@ import {
cn,
sortModelsByPriority,
formatResetTime,
- getEarliestResetTime,
+ getClaudeResetTime,
getMinClaudeQuota,
} from '@/lib/utils';
import { PRIVACY_BLUR_CLASS } from '@/contexts/privacy-context';
@@ -121,7 +121,7 @@ export function AccountItem({
// Get earliest reset time
const nextReset =
- quota?.success && quota.models.length > 0 ? getEarliestResetTime(quota.models) : null;
+ quota?.success && quota.models.length > 0 ? getClaudeResetTime(quota.models) : null;
return (
=24h (weekly limits)
*/
export function formatResetTime(resetTime: string | null): string | null {
if (!resetTime) return null;
@@ -92,8 +92,19 @@ export function formatResetTime(resetTime: string | null): string | null {
if (diff <= 0) return 'soon';
const hours = Math.floor(diff / (1000 * 60 * 60));
- const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
+ // Weekly/long resets: show absolute date (e.g., "01/27, 12:07")
+ if (hours >= 24) {
+ return reset.toLocaleDateString(undefined, {
+ month: '2-digit',
+ day: '2-digit',
+ hour: '2-digit',
+ minute: '2-digit',
+ });
+ }
+
+ // Daily resets: show relative time
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
if (hours > 0) return `in ${hours}h ${minutes}m`;
return `in ${minutes}m`;
} catch {
@@ -117,6 +128,16 @@ export function getEarliestResetTime(
);
}
+/**
+ * Filter to get Claude models from a model array
+ */
+function filterClaudeModels(models: T[]): T[] {
+ return models.filter((m) => {
+ const name = (m.displayName || m.name || '').toLowerCase();
+ return name.includes('claude');
+ });
+}
+
/**
* Calculate the minimum quota percentage from Claude models (primary usage).
* Falls back to minimum of all models if no Claude models exist.
@@ -127,11 +148,7 @@ export function getMinClaudeQuota<
>(models: T[]): number | null {
if (models.length === 0) return null;
- const claudeModels = models.filter((m) => {
- const name = (m.displayName || m.name || '').toLowerCase();
- return name.includes('claude');
- });
-
+ const claudeModels = filterClaudeModels(models);
const targetModels = claudeModels.length > 0 ? claudeModels : models;
const percentages = targetModels
.map((m) => m.percentage)
@@ -140,3 +157,25 @@ export function getMinClaudeQuota<
if (percentages.length === 0) return null;
return Math.min(...percentages);
}
+
+/**
+ * Get reset time for Claude models (matches getMinClaudeQuota logic).
+ * Shows when the Claude quota will reset, not just earliest across all models.
+ */
+export function getClaudeResetTime<
+ T extends { name: string; displayName?: string; resetTime: string | null },
+>(models: T[]): string | null {
+ if (models.length === 0) return null;
+
+ const claudeModels = filterClaudeModels(models);
+ const targetModels = claudeModels.length > 0 ? claudeModels : models;
+
+ return targetModels.reduce(
+ (earliest, m) => {
+ if (!m.resetTime) return earliest;
+ if (!earliest) return m.resetTime;
+ return new Date(m.resetTime) < new Date(earliest) ? m.resetTime : earliest;
+ },
+ null as string | null
+ );
+}