Files
portal/app/resources/js/components/billing/BalanceCard.vue
T

195 lines
6.1 KiB
Vue

<script setup lang="ts">
/**
* BalanceCard — 3 wallet-cards в одной строке: Кошелёк ₽ (dark) +
* Баланс лидов + Тариф. Данные — из GET /api/billing/wallet (E3).
* tariff* допускают null (тенант без назначенного тарифа — trial).
*/
import { computed } from 'vue';
const props = defineProps<{
walletRub: number;
leadsBalance: number;
tariffName: string | null;
tariffPrice: string | null;
tariffFeatures: string[];
}>();
defineEmits<{ topup: [] }>();
const walletText = computed(() => new Intl.NumberFormat('ru-RU').format(props.walletRub));
const tariffPriceText = computed(() => {
if (props.tariffPrice === null) return 'по запросу';
return new Intl.NumberFormat('ru-RU').format(Number(props.tariffPrice)) + ' ₽/мес';
});
</script>
<template>
<v-row dense class="wallet-row mt-4">
<v-col cols="12" md="4">
<v-card variant="flat" color="secondary" class="wallet-card primary pa-4">
<div class="wallet-h">
<span class="wallet-label">Кошелёк </span>
<v-chip size="x-small" color="primary" variant="elevated">LIVE</v-chip>
</div>
<div class="wallet-amount mt-2">
<span class="num">{{ walletText }}</span>
<span class="ru">&nbsp;</span>
</div>
<div class="wallet-foot mt-3">мин. пополнение <strong>100 </strong> · округление вниз лиды</div>
<div class="wallet-actions mt-3">
<v-btn
color="primary"
variant="flat"
prepend-icon="mdi-plus"
size="small"
@click="$emit('topup')"
>Пополнить</v-btn
>
<v-tooltip text="Автопополнение будет доступно после подключения платёжного шлюза.">
<template #activator="{ props: tipProps }">
<span v-bind="tipProps" class="d-inline-flex">
<v-btn variant="outlined" prepend-icon="mdi-autorenew" size="small" disabled>
Автопополнение
</v-btn>
</span>
</template>
</v-tooltip>
</div>
</v-card>
</v-col>
<v-col cols="12" md="4">
<v-card variant="outlined" class="wallet-card pa-4">
<div class="wallet-h">
<span class="wallet-label">Баланс лидов (ГЦК)</span>
</div>
<div class="wallet-amount mt-2">
<span class="num">{{ leadsBalance }}</span>
<span class="ru-text">&nbsp;лидов</span>
</div>
</v-card>
</v-col>
<v-col cols="12" md="4">
<v-card variant="outlined" class="wallet-card pa-4 d-flex flex-column">
<span class="wallet-label">Тариф</span>
<template v-if="tariffName">
<div class="tariff-name mt-1">
{{ tariffName }}
<span class="tariff-price">· {{ tariffPriceText }}</span>
</div>
<ul v-if="tariffFeatures.length" class="tariff-feats mt-3">
<li v-for="f in tariffFeatures" :key="f">
<v-icon size="14" color="success" class="mr-1">mdi-check</v-icon>{{ f }}
</li>
</ul>
</template>
<div v-else class="tariff-empty mt-2">Тариф не выбран</div>
<v-tooltip text="Самостоятельная смена тарифа появится после запуска биллинга.">
<template #activator="{ props: tipProps }">
<span v-bind="tipProps" class="mt-auto d-inline-flex">
<v-btn variant="outlined" size="small" disabled>Сменить тариф </v-btn>
</span>
</template>
</v-tooltip>
</v-card>
</v-col>
</v-row>
</template>
<style scoped>
.num {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-feature-settings: 'tnum';
font-weight: 500;
}
.wallet-card {
height: 100%;
background: #fff;
}
.wallet-card.primary {
color: #fff;
background: #012019 !important;
}
.wallet-h {
display: flex;
align-items: center;
justify-content: space-between;
}
.wallet-label {
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #7a8c87;
font-family: 'JetBrains Mono', ui-monospace, monospace;
}
.wallet-card:not(.primary) .wallet-label {
color: #66635c;
}
.wallet-amount {
font-size: 32px;
font-weight: 600;
line-height: 1.1;
}
.wallet-amount .num {
color: inherit;
letter-spacing: -0.01em;
}
.wallet-amount .ru,
.wallet-amount .ru-text {
color: #66635c;
font-weight: 500;
font-size: 18px;
}
.wallet-card.primary .wallet-amount .ru {
color: #7a8c87;
}
.wallet-foot {
color: inherit;
opacity: 0.7;
font-size: 12px;
}
.wallet-card.primary .wallet-foot {
color: #b1c2bd;
opacity: 1;
}
.wallet-actions {
display: flex;
gap: 8px;
}
.tariff-name {
font-weight: 600;
font-size: 17px;
color: #081319;
}
.tariff-price {
font-family: 'JetBrains Mono', ui-monospace, monospace;
color: #0f6e56;
font-size: 13px;
font-weight: 500;
margin-left: 4px;
}
.tariff-empty {
color: #66635c;
font-size: 14px;
}
.tariff-feats {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 6px;
flex: 1;
}
.tariff-feats li {
font-size: 13px;
color: #343c41;
display: flex;
align-items: center;
}
</style>