chore: Update credit grants
This commit is contained in:
@@ -460,11 +460,14 @@
|
||||
"CREDIT_GRANTS": {
|
||||
"TITLE": "Credit History",
|
||||
"DESCRIPTION": "View all your credit grants including topups and monthly credits.",
|
||||
"CREDITS": "credits",
|
||||
"CREDITS": "{credits} credits",
|
||||
"EXPIRES": "Expires",
|
||||
"NO_EXPIRY": "Never expires",
|
||||
"ADDED": "Added",
|
||||
"NO_GRANTS": "No credit grants yet."
|
||||
"ADDED": "Added on {date}",
|
||||
"VOIDED": "Voided",
|
||||
"NO_GRANTS": "No credit grants yet.",
|
||||
"TOPUPS": "Topups",
|
||||
"MONTHLY": "Monthly"
|
||||
},
|
||||
"SUBSCRIBE_MODAL": {
|
||||
"TITLE": "Confirm Subscription",
|
||||
|
||||
+67
-55
@@ -1,7 +1,9 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import BillingCard from '../../billing/components/BillingCard.vue';
|
||||
import format from 'date-fns/format';
|
||||
import BillingCard from 'dashboard/routes/dashboard/settings/billing/components/BillingCard.vue';
|
||||
import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
|
||||
|
||||
const props = defineProps({
|
||||
grants: {
|
||||
@@ -18,34 +20,35 @@ const { t } = useI18n();
|
||||
|
||||
const formatDate = dateStr => {
|
||||
if (!dateStr) return null;
|
||||
const date = new Date(dateStr);
|
||||
return new Intl.DateTimeFormat('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
}).format(date);
|
||||
return format(new Date(dateStr), 'MMM dd, yyyy');
|
||||
};
|
||||
|
||||
const formatNumber = num => {
|
||||
return new Intl.NumberFormat('en-US').format(num);
|
||||
};
|
||||
const formatNumber = num => new Intl.NumberFormat('en-US').format(num);
|
||||
|
||||
const sortedGrants = computed(() => {
|
||||
return [...props.grants].sort((a, b) => {
|
||||
// Sort by: active first, then by creation date (newest first)
|
||||
if (a.voided_at && !b.voided_at) return 1;
|
||||
if (!a.voided_at && b.voided_at) return -1;
|
||||
return new Date(b.created_at) - new Date(a.created_at);
|
||||
});
|
||||
const sortedGrants = computed(
|
||||
() =>
|
||||
[...props.grants]?.sort((a, b) => {
|
||||
if (a.voided_at && !b.voided_at) return 1;
|
||||
if (!a.voided_at && b.voided_at) return -1;
|
||||
return new Date(b.created_at) - new Date(a.created_at);
|
||||
}) || []
|
||||
);
|
||||
|
||||
const CATEGORY_CONFIG = computed(() => {
|
||||
return {
|
||||
paid: {
|
||||
label: t('BILLING_SETTINGS_V2.CREDIT_GRANTS.TOPUPS'),
|
||||
class: 'bg-n-blue-3 text-n-blue-11 outline outline-1 outline-n-blue-4',
|
||||
},
|
||||
granted: {
|
||||
label: t('BILLING_SETTINGS_V2.CREDIT_GRANTS.MONTHLY'),
|
||||
class: 'bg-n-teal-3 text-n-teal-11 outline outline-1 outline-n-teal-4',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const getCategoryColor = category => {
|
||||
return category === 'paid' ? 'bg-b-50 text-b-700' : 'bg-g-50 text-g-700';
|
||||
};
|
||||
|
||||
const getCategoryLabel = category => {
|
||||
return category === 'paid' ? 'Topup' : 'Monthly';
|
||||
};
|
||||
const getCategoryConfig = category =>
|
||||
CATEGORY_CONFIG.value[category] || CATEGORY_CONFIG.value.granted;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -54,64 +57,73 @@ const getCategoryLabel = category => {
|
||||
:description="$t('BILLING_SETTINGS_V2.CREDIT_GRANTS.DESCRIPTION')"
|
||||
>
|
||||
<div class="px-5 pb-5">
|
||||
<!-- Grants List -->
|
||||
<div class="space-y-3">
|
||||
<div v-if="sortedGrants.length" class="space-y-3">
|
||||
<div
|
||||
v-for="grant in sortedGrants"
|
||||
:key="grant.id"
|
||||
class="p-4 border border-n-weak rounded-lg"
|
||||
class="p-4 rounded-xl outline outline-1 outline-n-weak transition-opacity"
|
||||
:class="{ 'opacity-50': grant.voided_at }"
|
||||
>
|
||||
<div class="flex items-start justify-between">
|
||||
<div class="flex-1">
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span
|
||||
class="px-2 py-0.5 text-xs font-semibold rounded"
|
||||
:class="getCategoryColor(grant.category)"
|
||||
class="px-2 py-0.5 text-xs font-semibold rounded-md"
|
||||
:class="getCategoryConfig(grant.category).class"
|
||||
>
|
||||
{{ getCategoryLabel(grant.category) }}
|
||||
{{ getCategoryConfig(grant.category).label }}
|
||||
</span>
|
||||
<span
|
||||
v-if="grant.voided_at"
|
||||
class="px-2 py-0.5 text-xs font-semibold rounded bg-r-50 text-r-700"
|
||||
class="px-2 py-0.5 text-xs font-semibold rounded-md bg-n-ruby-3 text-n-ruby-11 outline outline-1 outline-n-ruby-4"
|
||||
>
|
||||
Voided
|
||||
{{ t('BILLING_SETTINGS_V2.CREDIT_GRANTS.VOIDED') }}
|
||||
</span>
|
||||
</div>
|
||||
<h4 class="text-sm font-semibold text-n-800">
|
||||
|
||||
<h4 class="text-sm font-semibold text-n-slate-12 truncate">
|
||||
{{ grant.name }}
|
||||
</h4>
|
||||
<p class="mt-1 text-xs text-n-600">
|
||||
{{ formatNumber(grant.credits) }}
|
||||
{{ $t('BILLING_SETTINGS_V2.CREDIT_GRANTS.CREDITS') }}
|
||||
<p class="mt-1 text-xs text-n-slate-11">
|
||||
{{
|
||||
t('BILLING_SETTINGS_V2.CREDIT_GRANTS.CREDITS', {
|
||||
credits: formatNumber(grant.credits),
|
||||
})
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div v-if="grant.expires_at" class="text-xs text-n-600">
|
||||
<span class="font-medium">{{
|
||||
$t('BILLING_SETTINGS_V2.CREDIT_GRANTS.EXPIRES')
|
||||
}}</span>
|
||||
<br />
|
||||
{{ formatDate(grant.expires_at) }}
|
||||
|
||||
<div class="text-right flex-shrink-0">
|
||||
<div v-if="grant.expires_at" class="text-xs text-n-slate-11">
|
||||
<span class="font-medium">
|
||||
{{ t('BILLING_SETTINGS_V2.CREDIT_GRANTS.EXPIRES') }}
|
||||
</span>
|
||||
<div class="mt-0.5">{{ formatDate(grant.expires_at) }}</div>
|
||||
</div>
|
||||
<div v-else class="text-xs text-g-600 font-medium">
|
||||
{{ $t('BILLING_SETTINGS_V2.CREDIT_GRANTS.NO_EXPIRY') }}
|
||||
|
||||
<div v-else class="text-xs text-n-teal-10 font-medium">
|
||||
{{ t('BILLING_SETTINGS_V2.CREDIT_GRANTS.NO_EXPIRY') }}
|
||||
</div>
|
||||
<div class="mt-1 text-xs text-n-500">
|
||||
{{ $t('BILLING_SETTINGS_V2.CREDIT_GRANTS.ADDED') }}
|
||||
{{ formatDate(grant.created_at) }}
|
||||
|
||||
<div v-if="grant.created_at" class="mt-1 text-xs text-n-slate-10">
|
||||
{{
|
||||
t('BILLING_SETTINGS_V2.CREDIT_GRANTS.ADDED', {
|
||||
date: formatDate(grant.created_at),
|
||||
})
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Empty State -->
|
||||
<div v-if="grants.length === 0 && !isLoading" class="py-8 text-center">
|
||||
<p class="text-sm text-n-600">
|
||||
{{ $t('BILLING_SETTINGS_V2.CREDIT_GRANTS.NO_GRANTS') }}
|
||||
<div v-else-if="!isLoading" class="py-8 text-center">
|
||||
<p class="text-sm text-n-slate-11">
|
||||
{{ t('BILLING_SETTINGS_V2.CREDIT_GRANTS.NO_GRANTS') }}
|
||||
</p>
|
||||
</div>
|
||||
<div v-else class="py-8 flex justify-center items-center">
|
||||
<Spinner class="text-n-brand" />
|
||||
</div>
|
||||
</div>
|
||||
</BillingCard>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user