refactor: split subscription popover section

This commit is contained in:
bymyself
2025-12-08 19:17:09 -08:00
parent 8ce0c9ea58
commit b8f563d3f8
3 changed files with 133 additions and 59 deletions

View File

@@ -121,6 +121,11 @@ describe('CurrentUserPopover', () => {
vi.clearAllMocks()
})
const findButtonByLabel = (wrapper: VueWrapper, label: string) =>
wrapper
.findAllComponents(Button)
.find((button) => button.props('label') === label)!
const mountComponent = (): VueWrapper => {
const i18n = createI18n({
legacy: false,
@@ -161,8 +166,7 @@ describe('CurrentUserPopover', () => {
const wrapper = mountComponent()
// Find all buttons and get the settings button (third button)
const buttons = wrapper.findAllComponents(Button)
const settingsButton = buttons[2]
const settingsButton = findButtonByLabel(wrapper, 'User Settings')
// Click the settings button
await settingsButton.trigger('click')
@@ -179,8 +183,7 @@ describe('CurrentUserPopover', () => {
const wrapper = mountComponent()
// Find all buttons and get the logout button (last button)
const buttons = wrapper.findAllComponents(Button)
const logoutButton = buttons[4]
const logoutButton = findButtonByLabel(wrapper, 'Log Out')
// Click the logout button
await logoutButton.trigger('click')
@@ -197,8 +200,10 @@ describe('CurrentUserPopover', () => {
const wrapper = mountComponent()
// Find all buttons and get the Partner Nodes info button (first one)
const buttons = wrapper.findAllComponents(Button)
const partnerNodesButton = buttons[0]
const partnerNodesButton = findButtonByLabel(
wrapper,
'Partner Nodes pricing table'
)
// Click the Partner Nodes button
await partnerNodesButton.trigger('click')
@@ -218,8 +223,7 @@ describe('CurrentUserPopover', () => {
const wrapper = mountComponent()
// Find all buttons and get the top-up button (second one)
const buttons = wrapper.findAllComponents(Button)
const topUpButton = buttons[1]
const topUpButton = findButtonByLabel(wrapper, 'Top Up')
// Click the top-up button
await topUpButton.trigger('click')

View File

@@ -23,40 +23,49 @@
</div>
</div>
<div
v-if="isSubscriptionRequirementMet"
class="flex items-center justify-between"
>
<div class="flex flex-col gap-1">
<UserCredit text-class="text-2xl" />
<component
:is="SubscriptionSection"
v-if="SubscriptionSection"
@top-up="handleTopUp"
@open-partner-info="handleOpenPartnerNodesInfo"
@open-plan-settings="handleOpenPlanAndCreditsSettings"
/>
<template v-else>
<div class="flex items-center justify-between">
<div class="flex flex-col gap-1">
<UserCredit text-class="text-2xl" />
<Button
:label="$t('subscription.partnerNodesCredits')"
severity="secondary"
text
size="small"
class="pl-6 p-0 h-auto justify-start"
:pt="{
root: {
class: 'hover:bg-transparent active:bg-transparent'
}
}"
@click="handleOpenPartnerNodesInfo"
/>
</div>
<Button
:label="$t('subscription.partnerNodesCredits')"
:label="$t('credits.topUp.topUp')"
severity="secondary"
text
size="small"
class="pl-6 p-0 h-auto justify-start"
:pt="{
root: {
class: 'hover:bg-transparent active:bg-transparent'
}
}"
@click="handleOpenPartnerNodesInfo"
@click="handleTopUp"
/>
</div>
<Button
:label="$t('credits.topUp.topUp')"
class="justify-start"
:label="$t(planSettingsLabel)"
icon="pi pi-receipt"
text
fluid
severity="secondary"
size="small"
@click="handleTopUp"
@click="handleOpenPlanAndCreditsSettings"
/>
</div>
<SubscribeButton
v-else
:label="$t('subscription.subscribeToComfyCloud')"
size="small"
variant="gradient"
@subscribed="handleSubscribed"
/>
</template>
<Divider class="my-2" />
@@ -70,17 +79,6 @@
@click="handleOpenUserSettings"
/>
<Button
v-if="isSubscriptionRequirementMet"
class="justify-start"
:label="$t(planSettingsLabel)"
icon="pi pi-receipt"
text
fluid
severity="secondary"
@click="handleOpenPlanAndCreditsSettings"
/>
<Divider class="my-2" />
<Button
@@ -98,15 +96,13 @@
<script setup lang="ts">
import Button from 'primevue/button'
import Divider from 'primevue/divider'
import { computed, onMounted } from 'vue'
import { defineAsyncComponent, onMounted } from 'vue'
import UserAvatar from '@/components/common/UserAvatar.vue'
import UserCredit from '@/components/common/UserCredit.vue'
import { useCurrentUser } from '@/composables/auth/useCurrentUser'
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
import { useExternalLink } from '@/composables/useExternalLink'
import SubscribeButton from '@/platform/cloud/subscription/components/SubscribeButton.vue'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
import { isCloud } from '@/platform/distribution/types'
import { useTelemetry } from '@/platform/telemetry'
import { useDialogService } from '@/services/dialogService'
@@ -117,18 +113,18 @@ const emit = defineEmits<{
const { buildDocsUrl } = useExternalLink()
const planSettingsLabel = isCloud
? 'settingsCategories.PlanCredits'
: 'settingsCategories.Credits'
const planSettingsLabel = 'settingsCategories.Credits'
const SubscriptionSection = isCloud
? defineAsyncComponent(
() => import('./CurrentUserPopoverSubscriptionSection.vue')
)
: null
const { userDisplayName, userEmail, userPhotoUrl, handleSignOut } =
useCurrentUser()
const authActions = useFirebaseAuthActions()
const dialogService = useDialogService()
const subscription = isCloud ? useSubscription() : null
const isSubscriptionRequirementMet =
subscription?.isSubscriptionRequirementMet ?? computed(() => true)
const fetchStatus = subscription?.fetchStatus ?? (async () => {})
const handleOpenUserSettings = () => {
dialogService.showSettingsDialog('user')
@@ -167,10 +163,6 @@ const handleLogout = async () => {
emit('close')
}
const handleSubscribed = async () => {
await fetchStatus()
}
onMounted(() => {
void authActions.fetchBalance()
})

View File

@@ -0,0 +1,78 @@
<template>
<div v-if="isSubscriptionRequirementMet" class="flex flex-col gap-2">
<div class="flex items-center justify-between">
<div class="flex flex-col gap-1">
<UserCredit text-class="text-2xl" />
<Button
:label="$t('subscription.partnerNodesCredits')"
severity="secondary"
text
size="small"
class="pl-6 p-0 h-auto justify-start"
:pt="{
root: {
class: 'hover:bg-transparent active:bg-transparent'
}
}"
@click="handleOpenPartnerInfo"
/>
</div>
<Button
:label="$t('credits.topUp.topUp')"
severity="secondary"
size="small"
@click="handleTopUp"
/>
</div>
<Button
class="justify-start"
:label="$t('settingsCategories.PlanCredits')"
icon="pi pi-receipt"
text
fluid
severity="secondary"
@click="handleOpenPlanSettings"
/>
</div>
<SubscribeButton
v-else
:label="$t('subscription.subscribeToComfyCloud')"
size="small"
variant="gradient"
class="w-full"
@subscribed="handleSubscribed"
/>
</template>
<script setup lang="ts">
import Button from 'primevue/button'
import UserCredit from '@/components/common/UserCredit.vue'
import SubscribeButton from '@/platform/cloud/subscription/components/SubscribeButton.vue'
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
const emit = defineEmits<{
'top-up': []
'open-partner-info': []
'open-plan-settings': []
}>()
const { isSubscriptionRequirementMet, fetchStatus } = useSubscription()
const handleSubscribed = async () => {
await fetchStatus()
}
const handleTopUp = () => {
emit('top-up')
}
const handleOpenPartnerInfo = () => {
emit('open-partner-info')
}
const handleOpenPlanSettings = () => {
emit('open-plan-settings')
}
</script>