update pricing section
fix: footer & header
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uvpn.shop",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
<span class="text-lg font-bold">uVPN</span>
|
||||
</div>
|
||||
<div class="flex gap-6 text-gray-500 dark:text-gray-400 text-sm">
|
||||
<a href="#" class="hover:text-gray-900 dark:text-white transition">Политика конфиденциальности</a>
|
||||
<a href="#" class="hover:text-gray-900 dark:text-white transition">Условия использования</a>
|
||||
<a href="#" class="hover:text-gray-900 dark:text-white transition">Поддержка</a>
|
||||
<a href="#" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Политика конфиденциальности</a>
|
||||
<a href="#" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Условия использования</a>
|
||||
<a href="#" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Поддержка</a>
|
||||
</div>
|
||||
<p class="text-gray-500 dark:text-gray-400 text-sm">
|
||||
© 2026 uVPN. Все права защищены.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<a href="#pricing" @click.prevent="scrollTo('pricing')" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Тарифы</a>
|
||||
<a href="#steps" @click.prevent="scrollTo('steps')" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Как начать</a>
|
||||
<a href="#testimonials" @click.prevent="scrollTo('testimonials')" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Отзывы</a>
|
||||
<a href="#footer" @click.prevent="scrollTo('footer')" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">Контакты</a>
|
||||
<a href="#footer" @click.prevent="scrollTo('faq')" class="hover:text-gray-900 dark:hover:text-gray-400 dark:text-white transition">FAQ</a>
|
||||
</nav>
|
||||
|
||||
<button class="bg-blue-600 dark:bg-blue-500 hover:bg-blue-700 transition px-5 py-2 rounded-lg font-medium text-sm text-white">
|
||||
|
||||
@@ -3,45 +3,59 @@
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-center mb-14">
|
||||
Прозрачные тарифы
|
||||
</h2>
|
||||
|
||||
<!-- Переключатель периода -->
|
||||
<div class="flex justify-center gap-2 mb-10">
|
||||
<button
|
||||
v-for="period in availablePeriods"
|
||||
:key="period.value"
|
||||
@click="selectedPeriod = period.value"
|
||||
class="px-5 py-2 rounded-full text-sm font-medium transition"
|
||||
:class="selectedPeriod === period.value
|
||||
? 'bg-blue-600 text-white shadow-md'
|
||||
: 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-300 dark:hover:bg-gray-600'"
|
||||
>
|
||||
{{ period.label }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Сетка тарифов -->
|
||||
<div class="grid md:grid-cols-3 gap-8">
|
||||
<!-- Тариф Месяц -->
|
||||
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 flex flex-col border border-gray-200 dark:border-gray-800 hover:border-blue-600 transition">
|
||||
<h3 class="text-xl font-semibold mb-2">Месяц</h3>
|
||||
<p class="text-4xl font-extrabold mb-4">$11.99<span class="text-lg font-normal text-gray-500 dark:text-gray-400">/мес</span></p>
|
||||
<div
|
||||
v-for="tariff in tariffCards"
|
||||
:key="tariff.key"
|
||||
class="bg-white dark:bg-gray-900 rounded-2xl p-8 flex flex-col border transition"
|
||||
:class="[
|
||||
tariff.isPopular
|
||||
? 'border-2 border-blue-600 relative transform scale-105 shadow-2xl shadow-blue-600/20'
|
||||
: 'border border-gray-200 dark:border-gray-800 hover:border-blue-600'
|
||||
]"
|
||||
>
|
||||
<span
|
||||
v-if="tariff.isPopular"
|
||||
class="absolute top-0 right-0 bg-blue-600 dark:bg-blue-500 text-gray-900 dark:text-white text-xs font-bold px-4 py-1 rounded-bl-xl rounded-tr-xl"
|
||||
>
|
||||
ПОПУЛЯРНЫЙ
|
||||
</span>
|
||||
|
||||
<h3 class="text-xl font-semibold mb-2">{{ tariff.name }}</h3>
|
||||
<p class="text-4xl font-extrabold mb-4">
|
||||
{{ tariff.price }}<span class="text-lg font-normal text-gray-500 dark:text-gray-400">/мес</span>
|
||||
</p>
|
||||
|
||||
<ul class="text-gray-500 dark:text-gray-400 space-y-3 mb-8 flex-1">
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Все устройства</li>
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Безлимитный трафик</li>
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Поддержка 24/7</li>
|
||||
<li v-for="feature in tariff.features" :key="feature" class="flex items-center gap-2">
|
||||
<Check class="w-4 h-4 text-green-400" /> {{ feature }}
|
||||
</li>
|
||||
</ul>
|
||||
<button class="w-full bg-gray-800 hover:bg-gray-700 transition py-3 rounded-xl font-medium text-white">
|
||||
Выбрать
|
||||
</button>
|
||||
</div>
|
||||
<!-- Тариф Год (выделенный) -->
|
||||
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 flex flex-col border-2 border-blue-600 relative transform scale-105 shadow-2xl shadow-blue-600/20">
|
||||
<span class="absolute top-0 right-0 bg-blue-600 dark:bg-blue-500 text-gray-900 dark:text-white text-xs font-bold px-4 py-1 rounded-bl-xl rounded-tr-xl">ПОПУЛЯРНЫЙ</span>
|
||||
<h3 class="text-xl font-semibold mb-2">Год</h3>
|
||||
<p class="text-4xl font-extrabold mb-4">$4.99<span class="text-lg font-normal text-gray-500 dark:text-gray-400">/мес</span></p>
|
||||
<ul class="text-gray-500 dark:text-gray-400 space-y-3 mb-8 flex-1">
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Все устройства</li>
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Безлимитный трафик</li>
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Приоритетная поддержка</li>
|
||||
</ul>
|
||||
<button class="w-full bg-blue-600 dark:bg-blue-500 hover:bg-blue-700 transition py-3 rounded-xl font-bold text-white">
|
||||
Выбрать тариф
|
||||
</button>
|
||||
</div>
|
||||
<!-- Тариф 2 года -->
|
||||
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 flex flex-col border border-gray-200 dark:border-gray-800 hover:border-blue-600 transition">
|
||||
<h3 class="text-xl font-semibold mb-2">2 года</h3>
|
||||
<p class="text-4xl font-extrabold mb-4">$2.99<span class="text-lg font-normal text-gray-500 dark:text-gray-400">/мес</span></p>
|
||||
<ul class="text-gray-500 dark:text-gray-400 space-y-3 mb-8 flex-1">
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Все устройства</li>
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Безлимитный трафик</li>
|
||||
<li class="flex items-center gap-2"><Check class="w-4 h-4 text-green-400" /> Максимальная экономия</li>
|
||||
</ul>
|
||||
<button class="w-full bg-gray-800 hover:bg-gray-700 transition py-3 rounded-xl font-medium text-white">
|
||||
Выбрать
|
||||
|
||||
<button
|
||||
class="w-full transition py-3 rounded-xl font-medium text-white"
|
||||
:class="tariff.isPopular
|
||||
? 'bg-blue-600 dark:bg-blue-500 hover:bg-blue-700 font-bold'
|
||||
: 'bg-gray-800 hover:bg-gray-700'"
|
||||
>
|
||||
{{ tariff.isPopular ? 'Выбрать тариф' : 'Выбрать' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -49,5 +63,93 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { Check } from '@lucide/vue'
|
||||
|
||||
// Исходный конфиг
|
||||
const pricingConfig = {
|
||||
default_tariff: "premium",
|
||||
tariffs: [
|
||||
{
|
||||
key: "standard",
|
||||
names: { ru: "Standard", en: "Standard" },
|
||||
descriptions: { ru: "До 2 устройств", en: "up to 2 devices" },
|
||||
prices_rub: { "1": 179.0, "3": 387.0, "6": 594.0, "12": 996.0 },
|
||||
hwid_device_limit: 2,
|
||||
monthly_gb: 0.0
|
||||
},
|
||||
{
|
||||
key: "medium",
|
||||
names: { ru: "Medium", en: "Medium" },
|
||||
descriptions: { ru: "До 3 устройств, YouTube без рекламы", en: "Up to 3 devices, YouTube without ads" },
|
||||
prices_rub: { "1": 229.0, "3": 507.0, "6": 954.0, "12": 1488.0 },
|
||||
hwid_device_limit: 3,
|
||||
monthly_gb: 0.0
|
||||
},
|
||||
{
|
||||
key: "premium",
|
||||
names: { ru: "Premium", en: "Premium" },
|
||||
descriptions: { ru: "До 10 устройств, YouTube без рекламы, сервера РФ", en: "Up to 10 devices, YouTube without ads, RU servers" },
|
||||
prices_rub: { "1": 349.0, "3": 987.0, "6": 1734.0, "12": 1992.0 },
|
||||
hwid_device_limit: 10,
|
||||
monthly_gb: 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// Доступные периоды
|
||||
const availablePeriods = [
|
||||
{ value: 1, label: '1 мес' },
|
||||
{ value: 3, label: '3 мес' },
|
||||
{ value: 6, label: '6 мес' },
|
||||
{ value: 12, label: '12 мес' }
|
||||
]
|
||||
|
||||
// Выбранный период (по умолчанию 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
|
||||
|
||||
// Разделяем тарифы: популярный (премиум) и остальные
|
||||
const premiumTariff = tariffs.find(t => t.key === defaultKey)
|
||||
const otherTariffs = tariffs.filter(t => t.key !== defaultKey)
|
||||
|
||||
// Порядок: первый обычный, премиум, второй обычный
|
||||
const ordered = [
|
||||
{ ...otherTariffs[0], isPopular: false },
|
||||
{ ...premiumTariff, isPopular: true },
|
||||
{ ...otherTariffs[1], isPopular: false }
|
||||
]
|
||||
|
||||
return ordered.map(tariff => {
|
||||
const price = getMonthlyPrice(tariff, selectedPeriod.value)
|
||||
|
||||
// Фичи: разбиваем описание по запятой и добавляем общие пункты
|
||||
const descriptionFeatures = tariff.descriptions.ru
|
||||
.split(',')
|
||||
.map(s => s.trim())
|
||||
.filter(Boolean)
|
||||
const staticFeatures = ['Безлимитный трафик', 'Поддержка 24/7']
|
||||
const features = [...new Set([...descriptionFeatures, ...staticFeatures])]
|
||||
|
||||
return {
|
||||
key: tariff.key,
|
||||
name: tariff.names.ru,
|
||||
price: `${price} ₽`,
|
||||
features,
|
||||
isPopular: tariff.isPopular
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user