262 lines
12 KiB
Plaintext
262 lines
12 KiB
Plaintext
@using Microsoft.Extensions.Localization
|
|
@model QRRapidoApp.Models.ViewModels.SelecaoPlanoViewModel
|
|
@inject IStringLocalizer<QRRapidoApp.Resources.SharedResource> Localizer
|
|
@{
|
|
ViewData["Title"] = "Escolha seu Plano Premium";
|
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
|
var monthlyPlan = Model.Plans.FirstOrDefault(p => p.Interval == "month");
|
|
var yearlyPlan = Model.Plans.FirstOrDefault(p => p.Interval == "year");
|
|
var monthlyPrice = monthlyPlan?.PricesByCountry.GetValueOrDefault(Model.CountryCode)?.Amount ?? 0;
|
|
var yearlyPrice = yearlyPlan?.PricesByCountry.GetValueOrDefault(Model.CountryCode)?.Amount ?? 0;
|
|
var yearlySavings = (monthlyPrice * 12) - yearlyPrice;
|
|
var currency = monthlyPlan?.PricesByCountry.GetValueOrDefault(Model.CountryCode)?.Currency ?? "BRL";
|
|
var currencySymbol = currency == "PYG" ? "₲" : "R$";
|
|
}
|
|
|
|
<div class="container mt-5">
|
|
<div class="text-center mb-5">
|
|
<h1 class="display-4">@Localizer["UnlockFullPowerQRRapido"]</h1>
|
|
<p class="lead text-muted">@Localizer["UnlimitedAccessNoAdsExclusive"]</p>
|
|
</div>
|
|
|
|
<div class="row justify-content-center g-4">
|
|
<!-- Plano Mensal -->
|
|
@if (monthlyPlan != null)
|
|
{
|
|
<div class="col-lg-4 col-md-6">
|
|
<div class="card h-100 shadow-sm">
|
|
<div class="card-body d-flex flex-column">
|
|
<h3 class="card-title text-center">@Localizer["MonthlyPlan"]</h3>
|
|
<div class="text-center my-4">
|
|
<span class="display-4 fw-bold" id="monthly-price">@currencySymbol @(currency == "PYG" ? monthlyPrice.ToString("N0") : monthlyPrice.ToString("0.00"))</span>
|
|
<span class="text-muted">@Localizer["PerMonth"]</span>
|
|
</div>
|
|
<p class="text-center text-muted">@Localizer["IdealToStartExploring"]</p>
|
|
<button class="btn btn-outline-primary mt-auto checkout-btn" data-plan-id="@monthlyPlan.Id">@Localizer["SubscribeNow"]</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<!-- Plano Anual -->
|
|
@if (yearlyPlan != null)
|
|
{
|
|
<div class="col-lg-4 col-md-6">
|
|
<div class="card h-100 shadow border-primary">
|
|
<div class="card-header bg-primary text-white text-center">
|
|
<h3 class="card-title mb-0">@Localizer["AnnualPlan"]</h3>
|
|
<p class="mb-0">@Localizer["Recommended"]</p>
|
|
</div>
|
|
<div class="card-body d-flex flex-column">
|
|
<div class="text-center my-4">
|
|
<span class="display-4 fw-bold" id="yearly-price">@currencySymbol @(currency == "PYG" ? yearlyPrice.ToString("N0") : yearlyPrice.ToString("0.00"))</span>
|
|
<span class="text-muted">@Localizer["PerYear"]</span>
|
|
</div>
|
|
@if (yearlySavings > 0)
|
|
{
|
|
<div class="text-center mb-3">
|
|
<span class="badge bg-success" id="yearly-savings">@Localizer["SaveMoney"] @(currency == "PYG" ? yearlySavings.ToString("N0") : yearlySavings.ToString("0.00"))!</span>
|
|
</div>
|
|
}
|
|
<p class="text-center text-muted">@Localizer["BestValueFrequentUsers"]</p>
|
|
<button class="btn btn-primary mt-auto checkout-btn" data-plan-id="@yearlyPlan.Id">@Localizer["SubscribeAnnualPlan"]</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<!-- Lista de Recursos -->
|
|
<div class="row justify-content-center mt-5">
|
|
<div class="col-lg-8">
|
|
<h3 class="text-center mb-4">@Localizer["AllPlansInclude"]</h3>
|
|
<ul class="list-group list-group-flush">
|
|
<li class="list-group-item border-0"><i class="fas fa-check-circle text-success me-2"></i>@Localizer["UnlimitedQRCodes"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-check-circle text-success me-2"></i>@Localizer["NoAds"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-check-circle text-success me-2"></i>@Localizer["AdvancedCustomization"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-shapes text-success me-2"></i>@Localizer["ThreeQRStyles"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-check-circle text-success me-2"></i>@Localizer["LogoSupport"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-check-circle text-success me-2"></i>@Localizer["HistoryAndDownloads"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-chart-line text-success me-2"></i>@Localizer["QRReadCounter"]</li>
|
|
<li class="list-group-item border-0"><i class="fas fa-check-circle text-success me-2"></i>@Localizer["PrioritySupport"]</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@section Scripts {
|
|
<script>
|
|
// Plans data for dynamic pricing
|
|
const plansData = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.Plans.Select(p => new {
|
|
Id = p.Id,
|
|
Interval = p.Interval,
|
|
PricesByCountry = p.PricesByCountry.ToDictionary(kvp => kvp.Key, kvp => new {
|
|
Amount = kvp.Value.Amount,
|
|
Currency = kvp.Value.Currency,
|
|
StripePriceId = kvp.Value.StripePriceId
|
|
})
|
|
})));
|
|
|
|
// Current country code
|
|
let currentCountryCode = '@Model.CountryCode';
|
|
|
|
// Update prices based on country
|
|
function updatePrices(countryCode) {
|
|
const monthlyPlan = plansData.find(p => p.Interval === 'month');
|
|
const yearlyPlan = plansData.find(p => p.Interval === 'year');
|
|
|
|
if (!monthlyPlan || !yearlyPlan) return;
|
|
|
|
const monthlyPrice = monthlyPlan.PricesByCountry[countryCode];
|
|
const yearlyPrice = yearlyPlan.PricesByCountry[countryCode];
|
|
|
|
if (!monthlyPrice || !yearlyPrice) return;
|
|
|
|
const currencySymbol = monthlyPrice.Currency === 'PYG' ? '₲' : 'R$';
|
|
const isGuarani = monthlyPrice.Currency === 'PYG';
|
|
|
|
// Update monthly price
|
|
const monthlyPriceEl = document.getElementById('monthly-price');
|
|
if (monthlyPriceEl) {
|
|
monthlyPriceEl.textContent = currencySymbol + ' ' + (isGuarani ?
|
|
monthlyPrice.Amount.toLocaleString('es-PY') :
|
|
monthlyPrice.Amount.toFixed(2));
|
|
}
|
|
|
|
// Update yearly price
|
|
const yearlyPriceEl = document.getElementById('yearly-price');
|
|
if (yearlyPriceEl) {
|
|
yearlyPriceEl.textContent = currencySymbol + ' ' + (isGuarani ?
|
|
yearlyPrice.Amount.toLocaleString('es-PY') :
|
|
yearlyPrice.Amount.toFixed(2));
|
|
}
|
|
|
|
// Update yearly savings
|
|
const yearlySavings = (monthlyPrice.Amount * 12) - yearlyPrice.Amount;
|
|
const yearlySavingsEl = document.getElementById('yearly-savings');
|
|
if (yearlySavingsEl && yearlySavings > 0) {
|
|
yearlySavingsEl.innerHTML = '@Html.Raw(Localizer["SaveMoney"])' + ' ' + (isGuarani ?
|
|
yearlySavings.toLocaleString('es-PY') :
|
|
yearlySavings.toFixed(2)) + '!';
|
|
}
|
|
|
|
currentCountryCode = countryCode;
|
|
}
|
|
|
|
// Detect country based on current culture
|
|
function getCountryFromCulture() {
|
|
const path = window.location.pathname;
|
|
const segments = path.split('/').filter(s => s);
|
|
|
|
if (segments.length > 0) {
|
|
const culture = segments[0];
|
|
const countryMap = {
|
|
'pt-BR': 'BR',
|
|
'es-PY': 'PY',
|
|
'es': 'PY'
|
|
};
|
|
return countryMap[culture] || 'BR';
|
|
}
|
|
return 'BR';
|
|
}
|
|
|
|
// Listen for page visibility changes (when user switches language and page reloads)
|
|
document.addEventListener('visibilitychange', function() {
|
|
if (!document.hidden) {
|
|
const newCountryCode = getCountryFromCulture();
|
|
if (newCountryCode !== currentCountryCode) {
|
|
updatePrices(newCountryCode);
|
|
}
|
|
}
|
|
});
|
|
|
|
// Initial setup
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const detectedCountry = getCountryFromCulture();
|
|
if (detectedCountry !== currentCountryCode) {
|
|
updatePrices(detectedCountry);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
function obterIdiomaDaUrl() {
|
|
const path = window.location.pathname;
|
|
const segments = path.split('/').filter(segment => segment !== '');
|
|
|
|
// O primeiro segmento após o domínio é o idioma
|
|
return segments[0] || 'pt-BR'; // retorna 'pt-BR' como padrão se não encontrar
|
|
}
|
|
|
|
document.querySelectorAll('.checkout-btn').forEach(button => {
|
|
button.addEventListener('click', async function() {
|
|
const planId = this.dataset.planId;
|
|
const idioma = obterIdiomaDaUrl();
|
|
this.disabled = true;
|
|
this.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> @Localizer["Redirecting"]';
|
|
|
|
|
|
try {
|
|
const response = await fetch('/Pagamento/CreateCheckout', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
body: `planId=${planId}&lang=${idioma}`
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
window.location.href = result.url;
|
|
} else {
|
|
showToast('@Localizer["Error"] ' + result.error, 'danger');
|
|
this.disabled = false;
|
|
this.innerHTML = '@Localizer["SubscribeNow"]'; // Reset button text
|
|
}
|
|
} catch (error) {
|
|
console.error('Checkout error:', error);
|
|
showToast('@Localizer["PaymentInitializationError"]', 'danger');
|
|
this.disabled = false;
|
|
this.innerHTML = 'Assinar Agora'; // Reset button text
|
|
}
|
|
});
|
|
});
|
|
|
|
// Toast notification function
|
|
function showToast(message, type) {
|
|
// Create toast container if doesn't exist
|
|
let toastContainer = document.getElementById('toast-container');
|
|
if (!toastContainer) {
|
|
toastContainer = document.createElement('div');
|
|
toastContainer.id = 'toast-container';
|
|
toastContainer.className = 'toast-container position-fixed top-0 start-0 p-3';
|
|
toastContainer.style.zIndex = '1060';
|
|
toastContainer.style.marginTop = '80px';
|
|
document.body.appendChild(toastContainer);
|
|
}
|
|
|
|
// Create toast element
|
|
const toastId = 'toast-' + Date.now();
|
|
const toastElement = document.createElement('div');
|
|
toastElement.innerHTML = `
|
|
<div class="toast align-items-center text-white bg-${type} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
|
<div class="d-flex">
|
|
<div class="toast-body">${message}</div>
|
|
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
toastContainer.appendChild(toastElement);
|
|
const toast = new bootstrap.Toast(toastElement.querySelector('.toast'), { delay: 5000 });
|
|
toast.show();
|
|
|
|
// Remove toast element after it's hidden
|
|
toastElement.querySelector('.toast').addEventListener('hidden.bs.toast', function() {
|
|
toastElement.remove();
|
|
});
|
|
}
|
|
</script>
|
|
}
|