update pricing to new api
This commit is contained in:
@@ -4,8 +4,20 @@
|
||||
Прозрачные тарифы
|
||||
</h2>
|
||||
|
||||
<!-- Состояние загрузки -->
|
||||
<div v-if="loading" class="flex justify-center py-12">
|
||||
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
|
||||
</div>
|
||||
|
||||
<!-- Состояние ошибки -->
|
||||
<div v-else-if="error" class="text-center text-red-500 py-12">
|
||||
{{ error }}
|
||||
</div>
|
||||
|
||||
<!-- Основной контент -->
|
||||
<template v-else>
|
||||
<!-- Переключатель периода -->
|
||||
<div class="flex justify-center gap-2 mb-10">
|
||||
<div class="flex justify-center gap-2 mb-10 flex-wrap">
|
||||
<button
|
||||
v-for="period in availablePeriods"
|
||||
:key="period.value"
|
||||
@@ -20,7 +32,10 @@
|
||||
</div>
|
||||
|
||||
<!-- Сетка тарифов -->
|
||||
<div class="grid md:grid-cols-2 gap-12">
|
||||
<div
|
||||
v-if="tariffCards.length"
|
||||
class="grid md:grid-cols-2 gap-12"
|
||||
>
|
||||
<div
|
||||
v-for="tariff in tariffCards"
|
||||
:key="tariff.key"
|
||||
@@ -59,88 +74,115 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-center py-12 text-gray-500">
|
||||
Нет доступных тарифов для выбранного периода
|
||||
</div>
|
||||
</template>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { Check } from '@lucide/vue'
|
||||
|
||||
// Исходный конфиг
|
||||
const pricingConfig = {
|
||||
default_tariff: "premium",
|
||||
tariffs: [
|
||||
{
|
||||
key: "standard",
|
||||
names: { ru: "Standard", en: "Standard" },
|
||||
descriptions: { ru: "До 3 устройств", en: "up to 3 devices" },
|
||||
prices_rub: { "1": 179.0, "3": 387.0, "6": 594.0, "12": 996.0 },
|
||||
hwid_device_limit: 2,
|
||||
monthly_gb: 0.0
|
||||
},
|
||||
{
|
||||
key: "premium",
|
||||
names: { ru: "Premium", en: "Premium"},
|
||||
descriptions: { ru: "До 10 устройств, сервера РФ и США", en: "Up to 10 devices, RU, USA servers" },
|
||||
prices_rub: { "1": 349.0, "3": 987.0, "6": 1734.0, "12": 1992.0 },
|
||||
hwid_device_limit: 10,
|
||||
monthly_gb: 0.0
|
||||
// Состояния
|
||||
const loading = ref(true)
|
||||
const error = ref(null)
|
||||
const tariffsData = ref([]) // исходные тарифы (из API)
|
||||
const defaultTariffKey = ref('') // ключ популярного тарифа
|
||||
const selectedPeriod = ref(1) // выбранный период (месяцев)
|
||||
|
||||
// Доступные периоды (вычисляются динамически)
|
||||
const availablePeriods = computed(() => {
|
||||
const periodsSet = new Set()
|
||||
for (const tariff of tariffsData.value) {
|
||||
if (tariff.enabled && tariff.enabled_periods) {
|
||||
tariff.enabled_periods.forEach(p => periodsSet.add(p))
|
||||
}
|
||||
]
|
||||
}
|
||||
const sorted = Array.from(periodsSet).sort((a, b) => a - b)
|
||||
return sorted.map(value => ({
|
||||
value,
|
||||
label: value === 1 ? '1 мес' : `${value} мес`
|
||||
}))
|
||||
})
|
||||
|
||||
// Доступные периоды
|
||||
const availablePeriods = [
|
||||
{ value: 1, label: '1 мес' },
|
||||
{ value: 3, label: '3 мес' },
|
||||
{ value: 6, label: '6 мес' },
|
||||
{ value: 12, label: '12 мес' }
|
||||
]
|
||||
// Активные (включённые) тарифы, отфильтрованные по выбранному периоду
|
||||
const activeTariffs = computed(() => {
|
||||
return tariffsData.value.filter(tariff =>
|
||||
tariff.enabled && tariff.enabled_periods?.includes(selectedPeriod.value)
|
||||
)
|
||||
})
|
||||
|
||||
// Выбранный период (по умолчанию 1 месяц)
|
||||
const selectedPeriod = ref(1)
|
||||
|
||||
// Функция для получения цены за месяц
|
||||
const getMonthlyPrice = (tariff, period) => {
|
||||
const total = tariff.prices_rub[String(period)]
|
||||
if (!total) return '—'
|
||||
const monthly = total / period
|
||||
return Number.isInteger(monthly) ? monthly : monthly.toFixed(2)
|
||||
}
|
||||
|
||||
// Подготовка данных для карточек
|
||||
// Карточки для отображения (с ценами, фичами и флагом популярности)
|
||||
const tariffCards = computed(() => {
|
||||
const tariffs = pricingConfig.tariffs
|
||||
const defaultKey = pricingConfig.default_tariff
|
||||
return activeTariffs.value.map(tariff => {
|
||||
const totalPrice = tariff.prices_rub?.[String(selectedPeriod.value)]
|
||||
let monthlyPrice = '—'
|
||||
if (totalPrice && totalPrice > 0) {
|
||||
const monthly = totalPrice / selectedPeriod.value
|
||||
monthlyPrice = Number.isInteger(monthly) ? monthly : monthly.toFixed(2)
|
||||
}
|
||||
|
||||
// Разделяем тарифы: популярный (премиум) и остальные
|
||||
const premiumTariff = tariffs.find(t => t.key === defaultKey)
|
||||
const otherTariffs = tariffs.filter(t => t.key !== defaultKey)
|
||||
// Формируем список особенностей (features)
|
||||
const features = []
|
||||
|
||||
// Порядок: первый обычный, премиум, второй обычный
|
||||
const ordered = [
|
||||
{ ...otherTariffs[0], isPopular: false },
|
||||
{ ...premiumTariff, isPopular: true },
|
||||
]
|
||||
// 1. Описание из JSON (если есть)
|
||||
const description = tariff.descriptions?.ru?.trim()
|
||||
if (description) {
|
||||
features.push(description)
|
||||
}
|
||||
|
||||
return ordered.map(tariff => {
|
||||
const price = getMonthlyPrice(tariff, selectedPeriod.value)
|
||||
// 2. Лимит устройств
|
||||
if (tariff.hwid_device_limit) {
|
||||
features.push(`До ${tariff.hwid_device_limit} устройств`)
|
||||
}
|
||||
|
||||
// Фичи: разбиваем описание по запятой и добавляем общие пункты
|
||||
const descriptionFeatures = tariff.descriptions.ru
|
||||
.split(',')
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean)
|
||||
const staticFeatures = ['Безлимитный трафик', 'Поддержка 24/7']
|
||||
const features = [...new Set([...descriptionFeatures, ...staticFeatures])]
|
||||
// 3. Безлимитный трафик (всегда)
|
||||
features.push('Безлимитный трафик')
|
||||
|
||||
// 4. Поддержка 24/7
|
||||
features.push('Поддержка 24/7')
|
||||
|
||||
return {
|
||||
key: tariff.key,
|
||||
name: tariff.names.ru,
|
||||
price: `${price} ₽`,
|
||||
name: tariff.names?.ru || tariff.key,
|
||||
price: `${monthlyPrice} ₽`,
|
||||
features,
|
||||
isPopular: tariff.isPopular
|
||||
isPopular: tariff.key === defaultTariffKey.value
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Загрузка данных с API
|
||||
const fetchTariffs = async () => {
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const response = await fetch('/api/v1/tariffs')
|
||||
if (!response.ok) {
|
||||
throw new Error(`Ошибка загрузки: ${response.status}`)
|
||||
}
|
||||
const data = await response.json()
|
||||
tariffsData.value = data.tariffs || []
|
||||
defaultTariffKey.value = data.default_tariff || ''
|
||||
|
||||
// Установка начального периода (первый доступный)
|
||||
if (availablePeriods.value.length > 0) {
|
||||
const exists = availablePeriods.value.some(p => p.value === selectedPeriod.value)
|
||||
if (!exists) {
|
||||
selectedPeriod.value = availablePeriods.value[0].value
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to load tariffs:', err)
|
||||
error.value = 'Не удалось загрузить тарифы. Попробуйте позже.'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchTariffs()
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user