diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index ec7d0636..2a24f332 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -1480,6 +1480,7 @@ export interface UserSubscription { user_id: number group_id: number status: 'active' | 'expired' | 'revoked' + starts_at: string daily_usage_usd: number weekly_usage_usd: number monthly_usage_usd: number diff --git a/frontend/src/utils/subscriptionQuota.ts b/frontend/src/utils/subscriptionQuota.ts new file mode 100644 index 00000000..719737be --- /dev/null +++ b/frontend/src/utils/subscriptionQuota.ts @@ -0,0 +1,42 @@ +import type { UserSubscription } from '@/types' + +const ONE_DAY_MS = 24 * 60 * 60 * 1000 + +export interface RemainingDurationParts { + days: number + hours: number + minutes: number +} + +export function isOneTimeDailyQuota( + subscription: Pick +): boolean { + if (!subscription.starts_at || !subscription.expires_at) return false + + const startsAt = new Date(subscription.starts_at).getTime() + const expiresAt = new Date(subscription.expires_at).getTime() + + if (!Number.isFinite(startsAt) || !Number.isFinite(expiresAt)) return false + + return expiresAt <= startsAt + ONE_DAY_MS +} + +export function getRemainingDurationParts( + targetAt: Date | string, + now: Date = new Date() +): RemainingDurationParts | null { + const targetTime = targetAt instanceof Date ? targetAt.getTime() : new Date(targetAt).getTime() + const nowTime = now.getTime() + + if (!Number.isFinite(targetTime) || !Number.isFinite(nowTime)) return null + + const diffMs = targetTime - nowTime + if (diffMs <= 0) return null + + const totalMinutes = Math.floor(diffMs / (1000 * 60)) + const days = Math.floor(totalMinutes / (24 * 60)) + const hours = Math.floor((totalMinutes % (24 * 60)) / 60) + const minutes = totalMinutes % 60 + + return { days, hours, minutes } +}