Re-style TopUpCreditDialog to match design (#3597)

This commit is contained in:
Chenlei Hu
2025-04-23 22:28:35 -04:00
committed by GitHub
parent 3819db5ec4
commit 64ad6a9bb0
8 changed files with 111 additions and 108 deletions

View File

@@ -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'
})

View File

@@ -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": {

View File

@@ -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"
},

View File

@@ -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"
},

View File

@@ -110,12 +110,12 @@
"messageSupport": "サポートにメッセージ",
"purchaseCredits": "クレジットを購入",
"topUp": {
"addCredits": "残高にクレジットを追加",
"buyNow": "今すぐ購入",
"insufficientMessage": "このワークフローを実行するのに十分なクレジットがありません。",
"insufficientTitle": "クレジット不足",
"maxAmount": "(最大 $1,000 USD",
"title": "クレジット残高を追加"
"quickPurchase": "クイック購入",
"seeDetails": "詳細を見る"
},
"yourCreditBalance": "あなたのクレジット残高"
},

View File

@@ -110,12 +110,12 @@
"messageSupport": "지원 문의",
"purchaseCredits": "크레딧 구매",
"topUp": {
"addCredits": "잔액에 크레딧 추가",
"buyNow": "지금 구매",
"insufficientMessage": "이 워크플로우를 실행하기에 크레딧이 부족합니다.",
"insufficientTitle": "크레딧 부족",
"maxAmount": "(최대 $1,000 USD)",
"title": "크레딧 잔액 충전"
"quickPurchase": "빠른 구매",
"seeDetails": "자세히 보기"
},
"yourCreditBalance": "보유 크레딧 잔액"
},

View File

@@ -110,12 +110,12 @@
"messageSupport": "Связаться с поддержкой",
"purchaseCredits": "Купить кредиты",
"topUp": {
"addCredits": "Добавить кредиты на баланс",
"buyNow": "Купить сейчас",
"insufficientMessage": "У вас недостаточно кредитов для запуска этого рабочего процесса.",
"insufficientTitle": "Недостаточно кредитов",
"maxAmount": "(Макс. $1,000 USD)",
"title": "Пополнить баланс кредитов"
"quickPurchase": "Быстрая покупка",
"seeDetails": "Смотреть детали"
},
"yourCreditBalance": "Ваш баланс кредитов"
},

View File

@@ -110,12 +110,12 @@
"messageSupport": "联系客服",
"purchaseCredits": "购买积分",
"topUp": {
"addCredits": "为您的余额充值",
"buyNow": "立即购买",
"insufficientMessage": "您的积分不足,无法运行此工作流。",
"insufficientTitle": "积分不足",
"maxAmount": "(最高 $1,000 美元)",
"title": "充值余额"
"quickPurchase": "快速购买",
"seeDetails": "查看详情"
},
"yourCreditBalance": "您的积分余额"
},