mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-23 00:04:06 +00:00
Re-style TopUpCreditDialog to match design (#3597)
This commit is contained in:
@@ -1,35 +1,67 @@
|
||||
<template>
|
||||
<div class="flex flex-col p-6">
|
||||
<div
|
||||
class="flex items-center gap-2"
|
||||
:class="{ 'text-red-500': isInsufficientCredits }"
|
||||
>
|
||||
<i
|
||||
:class="[
|
||||
'text-2xl',
|
||||
isInsufficientCredits ? 'pi pi-exclamation-triangle' : ''
|
||||
]"
|
||||
/>
|
||||
<h2 class="text-2xl font-semibold">
|
||||
{{
|
||||
$t(
|
||||
isInsufficientCredits
|
||||
? 'credits.topUp.insufficientTitle'
|
||||
: 'credits.topUp.title'
|
||||
)
|
||||
}}
|
||||
</h2>
|
||||
<div class="flex flex-col w-96 p-2 gap-10">
|
||||
<div v-if="isInsufficientCredits" class="flex flex-col gap-4">
|
||||
<h1 class="text-2xl font-medium leading-normal my-0">
|
||||
{{ $t('credits.topUp.insufficientTitle') }}
|
||||
</h1>
|
||||
<p class="text-base my-0">
|
||||
{{ $t('credits.topUp.insufficientMessage') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Error Message -->
|
||||
<p v-if="isInsufficientCredits" class="text-lg text-muted mt-6">
|
||||
{{ $t('credits.topUp.insufficientMessage') }}
|
||||
</p>
|
||||
|
||||
<!-- Balance Section -->
|
||||
<div class="flex justify-between items-center mt-8">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="text-muted">{{ $t('credits.yourCreditBalance') }}</div>
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
<div class="text-muted text-base">
|
||||
{{ $t('credits.yourCreditBalance') }}
|
||||
</div>
|
||||
<div class="flex items-center justify-between w-full">
|
||||
<div class="flex items-center gap-2">
|
||||
<Tag
|
||||
severity="secondary"
|
||||
icon="pi pi-dollar"
|
||||
rounded
|
||||
class="text-amber-400 p-1"
|
||||
/>
|
||||
<span class="text-2xl">{{ formattedBalance }}</span>
|
||||
</div>
|
||||
<Button
|
||||
outlined
|
||||
severity="secondary"
|
||||
:label="$t('credits.topUp.seeDetails')"
|
||||
icon="pi pi-arrow-up-right"
|
||||
@click="handleSeeDetails"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Amount Input Section -->
|
||||
<div class="flex flex-col gap-2">
|
||||
<span class="text-muted text-sm"
|
||||
>{{ $t('credits.topUp.quickPurchase') }}:</span
|
||||
>
|
||||
<div class="grid grid-cols-[2fr_1fr] gap-2">
|
||||
<template v-for="amount in amountOptions" :key="amount">
|
||||
<div class="flex items-center gap-2">
|
||||
<Tag
|
||||
severity="secondary"
|
||||
icon="pi pi-dollar"
|
||||
rounded
|
||||
class="text-amber-400 p-1"
|
||||
/>
|
||||
<span class="text-xl">{{ amount }}</span>
|
||||
</div>
|
||||
<Button
|
||||
:severity="
|
||||
preselectedAmountOption === amount ? 'primary' : 'secondary'
|
||||
"
|
||||
:outlined="preselectedAmountOption !== amount"
|
||||
:label="$t('credits.topUp.buyNow')"
|
||||
@click="handleBuyNow(amount)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<Tag
|
||||
severity="secondary"
|
||||
@@ -37,65 +69,42 @@
|
||||
rounded
|
||||
class="text-amber-400 p-1"
|
||||
/>
|
||||
<span class="text-2xl">{{ formattedBalance }}</span>
|
||||
<InputNumber
|
||||
v-model="customAmount"
|
||||
:min="1"
|
||||
:max="1000"
|
||||
:step="1"
|
||||
show-buttons
|
||||
:allow-empty="false"
|
||||
:highlight-on-focus="true"
|
||||
pt:pc-input-text:root="w-24"
|
||||
@blur="
|
||||
(e: InputNumberBlurEvent) => (customAmount = Number(e.value))
|
||||
"
|
||||
@input="
|
||||
(e: InputNumberInputEvent) => (customAmount = Number(e.value))
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
text
|
||||
severity="secondary"
|
||||
:label="$t('credits.creditsHistory')"
|
||||
icon="pi pi-arrow-up-right"
|
||||
@click="handleSeeDetails"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Amount Input Section -->
|
||||
<div class="flex flex-col gap-2 mt-8">
|
||||
<div>
|
||||
<span class="text-muted">{{ $t('credits.topUp.addCredits') }}</span>
|
||||
<span class="text-muted text-sm ml-1">{{
|
||||
$t('credits.topUp.maxAmount')
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<Tag
|
||||
<ProgressSpinner v-if="loading" class="w-8 h-8" />
|
||||
<Button
|
||||
v-else
|
||||
:label="$t('credits.topUp.buyNow')"
|
||||
severity="secondary"
|
||||
icon="pi pi-dollar"
|
||||
rounded
|
||||
class="text-amber-400 p-1"
|
||||
/>
|
||||
<InputNumber
|
||||
v-model="amount"
|
||||
:min="1"
|
||||
:max="1000"
|
||||
:step="1"
|
||||
mode="currency"
|
||||
currency="USD"
|
||||
show-buttons
|
||||
@blur="handleBlur"
|
||||
@input="handleInput"
|
||||
outlined
|
||||
@click="handleBuyNow(customAmount)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end mt-8">
|
||||
<ProgressSpinner v-if="loading" class="w-8 h-8" />
|
||||
<Button
|
||||
v-else
|
||||
severity="primary"
|
||||
:label="$t('credits.topUp.buyNow')"
|
||||
:disabled="!amount || amount > 1000"
|
||||
:pt="{
|
||||
root: { class: 'px-8' }
|
||||
}"
|
||||
@click="handleBuyNow"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Button from 'primevue/button'
|
||||
import InputNumber from 'primevue/inputnumber'
|
||||
import InputNumber, {
|
||||
type InputNumberBlurEvent,
|
||||
type InputNumberInputEvent
|
||||
} from 'primevue/inputnumber'
|
||||
import ProgressSpinner from 'primevue/progressspinner'
|
||||
import Tag from 'primevue/tag'
|
||||
import { computed, onBeforeUnmount, ref } from 'vue'
|
||||
@@ -103,25 +112,21 @@ import { computed, onBeforeUnmount, ref } from 'vue'
|
||||
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
|
||||
import { formatMetronomeCurrency, usdToMicros } from '@/utils/formatUtil'
|
||||
|
||||
defineProps<{
|
||||
const {
|
||||
isInsufficientCredits = false,
|
||||
amountOptions = [5, 10, 20, 50],
|
||||
preselectedAmountOption = 10
|
||||
} = defineProps<{
|
||||
isInsufficientCredits?: boolean
|
||||
amountOptions?: number[]
|
||||
preselectedAmountOption?: number
|
||||
}>()
|
||||
|
||||
const authStore = useFirebaseAuthStore()
|
||||
const amount = ref<number>(9.99)
|
||||
const customAmount = ref<number>(100)
|
||||
const didClickBuyNow = ref(false)
|
||||
const loading = computed(() => authStore.loading)
|
||||
|
||||
const handleBlur = (e: any) => {
|
||||
if (e.target.value) {
|
||||
amount.value = parseFloat(e.target.value)
|
||||
}
|
||||
}
|
||||
|
||||
const handleInput = (e: any) => {
|
||||
amount.value = e.value
|
||||
}
|
||||
|
||||
const formattedBalance = computed(() => {
|
||||
if (!authStore.balance) return '0.000'
|
||||
return formatMetronomeCurrency(authStore.balance.amount_micros, 'usd')
|
||||
@@ -133,11 +138,9 @@ const handleSeeDetails = async () => {
|
||||
window.open(response.billing_portal_url, '_blank')
|
||||
}
|
||||
|
||||
const handleBuyNow = async () => {
|
||||
if (!amount.value) return
|
||||
|
||||
const handleBuyNow = async (amount: number) => {
|
||||
const response = await authStore.initiateCreditPurchase({
|
||||
amount_micros: usdToMicros(amount.value),
|
||||
amount_micros: usdToMicros(amount),
|
||||
currency: 'usd'
|
||||
})
|
||||
|
||||
|
||||
@@ -1148,12 +1148,12 @@
|
||||
"messageSupport": "Message Support",
|
||||
"lastUpdated": "Last updated",
|
||||
"topUp": {
|
||||
"title": "Add to Credit Balance",
|
||||
"insufficientTitle": "Insufficient Credits",
|
||||
"insufficientMessage": "You don't have enough credits to run this workflow.",
|
||||
"addCredits": "Add credits to your balance",
|
||||
"quickPurchase": "Quick Purchase",
|
||||
"maxAmount": "(Max. $1,000 USD)",
|
||||
"buyNow": "Buy now"
|
||||
"buyNow": "Buy now",
|
||||
"seeDetails": "See details"
|
||||
}
|
||||
},
|
||||
"userSettings": {
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
"messageSupport": "Contactar soporte",
|
||||
"purchaseCredits": "Comprar créditos",
|
||||
"topUp": {
|
||||
"addCredits": "Agregar créditos a tu saldo",
|
||||
"buyNow": "Comprar ahora",
|
||||
"insufficientMessage": "No tienes suficientes créditos para ejecutar este flujo de trabajo.",
|
||||
"insufficientTitle": "Créditos insuficientes",
|
||||
"maxAmount": "(Máx. $1,000 USD)",
|
||||
"title": "Agregar al saldo de créditos"
|
||||
"quickPurchase": "Compra rápida",
|
||||
"seeDetails": "Ver detalles"
|
||||
},
|
||||
"yourCreditBalance": "Tu saldo de créditos"
|
||||
},
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
"messageSupport": "Contacter le support",
|
||||
"purchaseCredits": "Acheter des crédits",
|
||||
"topUp": {
|
||||
"addCredits": "Ajouter des crédits à votre solde",
|
||||
"buyNow": "Acheter maintenant",
|
||||
"insufficientMessage": "Vous n'avez pas assez de crédits pour exécuter ce workflow.",
|
||||
"insufficientTitle": "Crédits insuffisants",
|
||||
"maxAmount": "(Max. 1 000 $ US)",
|
||||
"title": "Ajouter au solde de crédits"
|
||||
"quickPurchase": "Achat rapide",
|
||||
"seeDetails": "Voir les détails"
|
||||
},
|
||||
"yourCreditBalance": "Votre solde de crédits"
|
||||
},
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
"messageSupport": "サポートにメッセージ",
|
||||
"purchaseCredits": "クレジットを購入",
|
||||
"topUp": {
|
||||
"addCredits": "残高にクレジットを追加",
|
||||
"buyNow": "今すぐ購入",
|
||||
"insufficientMessage": "このワークフローを実行するのに十分なクレジットがありません。",
|
||||
"insufficientTitle": "クレジット不足",
|
||||
"maxAmount": "(最大 $1,000 USD)",
|
||||
"title": "クレジット残高を追加"
|
||||
"quickPurchase": "クイック購入",
|
||||
"seeDetails": "詳細を見る"
|
||||
},
|
||||
"yourCreditBalance": "あなたのクレジット残高"
|
||||
},
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
"messageSupport": "지원 문의",
|
||||
"purchaseCredits": "크레딧 구매",
|
||||
"topUp": {
|
||||
"addCredits": "잔액에 크레딧 추가",
|
||||
"buyNow": "지금 구매",
|
||||
"insufficientMessage": "이 워크플로우를 실행하기에 크레딧이 부족합니다.",
|
||||
"insufficientTitle": "크레딧 부족",
|
||||
"maxAmount": "(최대 $1,000 USD)",
|
||||
"title": "크레딧 잔액 충전"
|
||||
"quickPurchase": "빠른 구매",
|
||||
"seeDetails": "자세히 보기"
|
||||
},
|
||||
"yourCreditBalance": "보유 크레딧 잔액"
|
||||
},
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
"messageSupport": "Связаться с поддержкой",
|
||||
"purchaseCredits": "Купить кредиты",
|
||||
"topUp": {
|
||||
"addCredits": "Добавить кредиты на баланс",
|
||||
"buyNow": "Купить сейчас",
|
||||
"insufficientMessage": "У вас недостаточно кредитов для запуска этого рабочего процесса.",
|
||||
"insufficientTitle": "Недостаточно кредитов",
|
||||
"maxAmount": "(Макс. $1,000 USD)",
|
||||
"title": "Пополнить баланс кредитов"
|
||||
"quickPurchase": "Быстрая покупка",
|
||||
"seeDetails": "Смотреть детали"
|
||||
},
|
||||
"yourCreditBalance": "Ваш баланс кредитов"
|
||||
},
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
"messageSupport": "联系客服",
|
||||
"purchaseCredits": "购买积分",
|
||||
"topUp": {
|
||||
"addCredits": "为您的余额充值",
|
||||
"buyNow": "立即购买",
|
||||
"insufficientMessage": "您的积分不足,无法运行此工作流。",
|
||||
"insufficientTitle": "积分不足",
|
||||
"maxAmount": "(最高 $1,000 美元)",
|
||||
"title": "充值余额"
|
||||
"quickPurchase": "快速购买",
|
||||
"seeDetails": "查看详情"
|
||||
},
|
||||
"yourCreditBalance": "您的积分余额"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user