mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-04 23:20:07 +00:00
Backport of #6350 to `rh-test` Automatically created by backport workflow. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6351-backport-rh-test-update-subscription-dialog-29a6d73d365081f284f1f5a9127e2cb3) by [Unito](https://www.unito.io) --------- Co-authored-by: Christian Byrne <cbyrne@comfy.org> Co-authored-by: GitHub Action <action@github.com>
284 lines
9.2 KiB
Vue
284 lines
9.2 KiB
Vue
<template>
|
|
<TabPanel value="PlanCredits" class="subscription-container h-full">
|
|
<div class="flex h-full flex-col">
|
|
<div class="flex items-center gap-2">
|
|
<h2 class="text-2xl">
|
|
{{ $t('subscription.title') }}
|
|
</h2>
|
|
<CloudBadge
|
|
reverse-order
|
|
background-color="var(--p-dialog-background)"
|
|
/>
|
|
</div>
|
|
|
|
<div class="grow overflow-auto">
|
|
<div class="rounded-lg border border-charcoal-400 p-4">
|
|
<div>
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<div class="flex items-baseline gap-1">
|
|
<span class="text-2xl font-bold">{{
|
|
formattedMonthlyPrice
|
|
}}</span>
|
|
<span>{{ $t('subscription.perMonth') }}</span>
|
|
</div>
|
|
<div v-if="isActiveSubscription" class="text-xs text-muted">
|
|
<template v-if="isCancelled">
|
|
{{
|
|
$t('subscription.expiresDate', {
|
|
date: formattedEndDate
|
|
})
|
|
}}
|
|
</template>
|
|
<template v-else>
|
|
{{
|
|
$t('subscription.renewsDate', {
|
|
date: formattedRenewalDate
|
|
})
|
|
}}
|
|
</template>
|
|
</div>
|
|
</div>
|
|
<Button
|
|
v-if="isActiveSubscription"
|
|
:label="$t('subscription.manageSubscription')"
|
|
severity="secondary"
|
|
class="text-xs"
|
|
@click="manageSubscription"
|
|
/>
|
|
<SubscribeButton
|
|
v-else
|
|
:label="$t('subscription.subscribeNow')"
|
|
size="small"
|
|
class="text-xs"
|
|
@subscribed="handleRefresh"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 gap-6 rounded-lg pt-10 lg:grid-cols-2">
|
|
<div class="flex flex-col">
|
|
<div class="flex flex-col gap-3">
|
|
<div class="flex flex-col">
|
|
<div class="text-sm">
|
|
{{ $t('subscription.apiNodesBalance') }}
|
|
</div>
|
|
<div class="flex items-center">
|
|
<div class="text-xs text-muted">
|
|
{{ $t('subscription.apiNodesDescription') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="flex flex-col gap-3 rounded-lg border p-4 dark-theme:border-0 dark-theme:bg-charcoal-600"
|
|
>
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<div class="text-xs text-muted">
|
|
{{ $t('subscription.totalCredits') }}
|
|
</div>
|
|
<div class="text-2xl font-bold">${{ totalCredits }}</div>
|
|
</div>
|
|
<Button
|
|
icon="pi pi-sync"
|
|
severity="secondary"
|
|
size="small"
|
|
:loading="isLoadingBalance"
|
|
@click="handleRefresh"
|
|
/>
|
|
</div>
|
|
|
|
<div
|
|
v-if="latestEvents.length > 0"
|
|
class="flex flex-col gap-2 pt-3 text-xs"
|
|
>
|
|
<div
|
|
v-for="event in latestEvents"
|
|
:key="event.event_id"
|
|
class="flex items-center justify-between py-1"
|
|
>
|
|
<div class="flex flex-col gap-0.5">
|
|
<span class="font-medium">
|
|
{{
|
|
event.event_type
|
|
? customerEventService.formatEventType(
|
|
event.event_type
|
|
)
|
|
: ''
|
|
}}
|
|
</span>
|
|
<span class="text-muted">
|
|
{{
|
|
event.createdAt
|
|
? customerEventService.formatDate(event.createdAt)
|
|
: ''
|
|
}}
|
|
</span>
|
|
</div>
|
|
<div
|
|
v-if="event.params?.amount !== undefined"
|
|
class="font-bold"
|
|
>
|
|
${{
|
|
customerEventService.formatAmount(
|
|
event.params.amount as number
|
|
)
|
|
}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex items-center justify-between pt-2">
|
|
<Button
|
|
:label="$t('subscription.viewUsageHistory')"
|
|
text
|
|
severity="secondary"
|
|
class="p-0 text-xs text-muted"
|
|
@click="handleViewUsageHistory"
|
|
/>
|
|
<Button
|
|
v-if="isActiveSubscription"
|
|
:label="$t('subscription.addApiCredits')"
|
|
severity="secondary"
|
|
class="text-xs"
|
|
@click="handleAddApiCredits"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col gap-3">
|
|
<div class="text-sm">
|
|
{{ $t('subscription.yourPlanIncludes') }}
|
|
</div>
|
|
|
|
<SubscriptionBenefits />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="flex items-center justify-between border-t border-charcoal-400 pt-3"
|
|
>
|
|
<div class="flex gap-2">
|
|
<Button
|
|
:label="$t('subscription.learnMore')"
|
|
text
|
|
severity="secondary"
|
|
icon="pi pi-question-circle"
|
|
class="text-xs"
|
|
@click="handleLearnMore"
|
|
/>
|
|
<Button
|
|
:label="$t('subscription.messageSupport')"
|
|
text
|
|
severity="secondary"
|
|
icon="pi pi-comment"
|
|
class="text-xs"
|
|
@click="handleMessageSupport"
|
|
/>
|
|
</div>
|
|
|
|
<Button
|
|
:label="$t('subscription.invoiceHistory')"
|
|
text
|
|
severity="secondary"
|
|
icon="pi pi-external-link"
|
|
icon-pos="right"
|
|
class="text-xs"
|
|
@click="handleInvoiceHistory"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</TabPanel>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import Button from 'primevue/button'
|
|
import TabPanel from 'primevue/tabpanel'
|
|
import { computed, onMounted, ref } from 'vue'
|
|
|
|
import CloudBadge from '@/components/topbar/CloudBadge.vue'
|
|
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
|
|
import SubscribeButton from '@/platform/cloud/subscription/components/SubscribeButton.vue'
|
|
import SubscriptionBenefits from '@/platform/cloud/subscription/components/SubscriptionBenefits.vue'
|
|
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
|
|
import type { AuditLog } from '@/services/customerEventsService'
|
|
import { useCustomerEventsService } from '@/services/customerEventsService'
|
|
import { useDialogService } from '@/services/dialogService'
|
|
import { useCommandStore } from '@/stores/commandStore'
|
|
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
|
|
import { formatMetronomeCurrency } from '@/utils/formatUtil'
|
|
|
|
const dialogService = useDialogService()
|
|
const authActions = useFirebaseAuthActions()
|
|
const commandStore = useCommandStore()
|
|
const authStore = useFirebaseAuthStore()
|
|
const customerEventService = useCustomerEventsService()
|
|
|
|
const {
|
|
isActiveSubscription,
|
|
isCancelled,
|
|
formattedRenewalDate,
|
|
formattedEndDate,
|
|
formattedMonthlyPrice,
|
|
manageSubscription,
|
|
handleViewUsageHistory,
|
|
handleLearnMore,
|
|
handleInvoiceHistory,
|
|
fetchStatus
|
|
} = useSubscription()
|
|
|
|
const latestEvents = ref<AuditLog[]>([])
|
|
|
|
const totalCredits = computed(() => {
|
|
if (!authStore.balance) return '0.00'
|
|
return formatMetronomeCurrency(authStore.balance.amount_micros, 'usd')
|
|
})
|
|
|
|
const isLoadingBalance = computed(() => authStore.isFetchingBalance)
|
|
|
|
const fetchLatestEvents = async () => {
|
|
try {
|
|
const response = await customerEventService.getMyEvents({
|
|
page: 1,
|
|
limit: 2
|
|
})
|
|
if (response?.events) {
|
|
latestEvents.value = response.events
|
|
}
|
|
} catch (error) {
|
|
console.error('[SubscriptionPanel] Error fetching latest events:', error)
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
void handleRefresh()
|
|
})
|
|
|
|
const handleAddApiCredits = () => {
|
|
dialogService.showTopUpCreditsDialog()
|
|
}
|
|
|
|
const handleMessageSupport = async () => {
|
|
await commandStore.execute('Comfy.ContactSupport')
|
|
}
|
|
|
|
const handleRefresh = async () => {
|
|
await Promise.all([
|
|
authActions.fetchBalance(),
|
|
fetchStatus(),
|
|
fetchLatestEvents()
|
|
])
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
:deep(.bg-comfy-menu-secondary) {
|
|
background-color: transparent;
|
|
}
|
|
</style>
|