449 lines
21 KiB
Plaintext
449 lines
21 KiB
Plaintext
@using QRRapidoApp.Services
|
|
@using Microsoft.AspNetCore.Http.Extensions
|
|
@using Microsoft.Extensions.Localization
|
|
@inject AdDisplayService AdService
|
|
@inject IStringLocalizer<QRRapidoApp.Resources.SharedResource> Localizer
|
|
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostEnvironment
|
|
|
|
@{
|
|
var isDevelopment = HostEnvironment?.IsDevelopment() ?? false;
|
|
var isPremiumUser = false;
|
|
|
|
if (User?.Identity?.IsAuthenticated == true)
|
|
{
|
|
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
|
if (!string.IsNullOrWhiteSpace(userId))
|
|
{
|
|
try
|
|
{
|
|
isPremiumUser = await AdService.HasValidPremiumSubscription(userId);
|
|
}
|
|
catch
|
|
{
|
|
isPremiumUser = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>@ViewData["Title"] - QR Rapido | Gerador QR Code Ultrarrápido</title>
|
|
|
|
<!-- Cache Control Headers -->
|
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
|
|
<meta http-equiv="Pragma" content="no-cache">
|
|
<meta http-equiv="Expires" content="0">
|
|
|
|
<!-- SEO Meta Tags -->
|
|
<meta name="description" content="@Localizer["QRGenerateDescription"]">
|
|
<meta name="keywords" content="qr rapido, gerador qr rapido, qr code rapido, codigo qr rapido, qr gratis rapido, generador qr rapido, qr ultrarapido">
|
|
<meta name="author" content="QR Rapido">
|
|
<meta name="robots" content="index, follow">
|
|
|
|
<!-- Canonical URL -->
|
|
<link rel="canonical" href="@Context.Request.GetDisplayUrl()">
|
|
|
|
<!-- Hreflang for multilingual -->
|
|
<link rel="alternate" hreflang="pt-BR" href="https://qrrapido.site/pt/">
|
|
<link rel="alternate" hreflang="es" href="https://qrrapido.site/es/">
|
|
<link rel="alternate" hreflang="en" href="https://qrrapido.site/en/">
|
|
<link rel="alternate" hreflang="x-default" href="https://qrrapido.site/">
|
|
|
|
<!-- Open Graph -->
|
|
<meta property="og:title" content="QR Rapido - @Localizer["FastestQRGeneratorWeb"]">
|
|
<meta property="og:description" content="@Localizer["QRGenerateDescription"]">
|
|
<meta property="og:image" content="https://qrrapido.site/images/qrrapido-og-image.png">
|
|
<meta property="og:url" content="@Context.Request.GetDisplayUrl()">
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:site_name" content="QR Rapido">
|
|
<meta property="og:locale" content="pt_BR">
|
|
|
|
<!-- Twitter Cards -->
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:title" content="QR Rapido - @Localizer["FastestQRGeneratorWeb"]">
|
|
<meta name="twitter:description" content="@Localizer["QRGenerateDescription"]">
|
|
<meta name="twitter:image" content="https://qrrapido.site/images/qrrapido-twitter-card.png">
|
|
|
|
<!-- Preload critical resources for performance -->
|
|
<link rel="preload" href="/webfonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
|
|
<link rel="preload" href="/webfonts/fa-brands-400.woff2" as="font" type="font/woff2" crossorigin>
|
|
<link rel="preload" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" as="style">
|
|
<link rel="preload" href="~/css/site.css" as="style">
|
|
<link rel="preload" href="~/css/qrrapido-theme.css" as="style">
|
|
|
|
|
|
<script type="text/javascript">
|
|
(function(c,l,a,r,i,t,y){
|
|
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
|
|
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
|
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
|
})(window, document, "clarity", "script", "tufamidcvb");
|
|
</script>
|
|
|
|
@*
|
|
<!-- Hotjar Tracking Code for https://qrrapido.site -->
|
|
<script data-cfasync="false">
|
|
(function(h,o,t,j,a,r){
|
|
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
|
h._hjSettings={hjid:6550944,hjsv:6};
|
|
a=o.getElementsByTagName('head')[0];
|
|
r=o.createElement('script');r.async=1;
|
|
r.crossOrigin='anonymous';
|
|
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
|
|
a.appendChild(r);
|
|
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
|
|
</script>
|
|
*@
|
|
<!-- Structured Data Schema.org -->
|
|
<script type="application/ld+json">
|
|
{
|
|
"@@context": "https://schema.org",
|
|
"@@type": "WebApplication",
|
|
"name": "QR Rapido",
|
|
"description": "Gerador de QR Code ultrarrápido em português e espanhol",
|
|
"url": "https://qrrapido.site",
|
|
"applicationCategory": "UtilityApplication",
|
|
"operatingSystem": "Web",
|
|
"author": {
|
|
"@@type": "Organization",
|
|
"name": "QR Rapido"
|
|
},
|
|
"offers": {
|
|
"@@type": "Offer",
|
|
"price": "0",
|
|
"priceCurrency": "BRL",
|
|
"description": "Geração gratuita de QR codes"
|
|
},
|
|
"aggregateRating": {
|
|
"@@type": "AggregateRating",
|
|
"ratingValue": "4.8",
|
|
"reviewCount": "2547"
|
|
},
|
|
"featureList": [
|
|
"Geração em segundos",
|
|
"Suporte multilíngue",
|
|
"Sem cadastro obrigatório",
|
|
"Sem limite diário",
|
|
"Download múltiplos formatos"
|
|
]
|
|
}
|
|
</script>
|
|
|
|
<!-- Google Analytics 4 - Optimized with defer -->
|
|
<script defer src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
|
|
<script defer>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
|
|
// Initialize with denied consent for GDPR compliance
|
|
gtag('consent', 'default', {
|
|
'analytics_storage': 'denied'
|
|
});
|
|
|
|
gtag('js', new Date());
|
|
gtag('config', 'GA_MEASUREMENT_ID', {
|
|
send_page_view: false
|
|
});
|
|
|
|
// Custom events for QR Rapido
|
|
window.trackQRGeneration = function(type, time, isPremium) {
|
|
gtag('event', 'qr_generated', {
|
|
'event_category': 'QR Generation',
|
|
'event_label': type,
|
|
'value': Math.round(parseFloat(time) * 1000),
|
|
'custom_parameters': {
|
|
'generation_time': parseFloat(time),
|
|
'user_type': isPremium ? 'premium' : 'free',
|
|
'speed_category': time < 1.0 ? 'ultra_fast' : time < 2.0 ? 'fast' : 'normal'
|
|
}
|
|
});
|
|
};
|
|
|
|
window.trackSpeedComparison = function(ourTime, competitorAvg) {
|
|
gtag('event', 'speed_comparison', {
|
|
'event_category': 'Performance',
|
|
'our_time': parseFloat(ourTime),
|
|
'competitor_avg': parseFloat(competitorAvg),
|
|
'speed_advantage': parseFloat(competitorAvg) - parseFloat(ourTime)
|
|
});
|
|
};
|
|
|
|
window.trackLanguageChange = function(from, to) {
|
|
gtag('event', 'language_change', {
|
|
'event_category': 'Localization',
|
|
'previous_language': from,
|
|
'new_language': to
|
|
});
|
|
};
|
|
</script>
|
|
|
|
@* AdSense removed - Preparing for Adsterra integration *@
|
|
|
|
<!-- Bootstrap 5 - Optimized loading -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" media="print" onload="this.media='all'">
|
|
<link rel="stylesheet" href="~/css/vendor/fontawesome.min.css" asp-append-version="true" media="print" onload="this.media='all'" />
|
|
<link rel="stylesheet" href="~/css/telegram-fab.css" asp-append-version="true" />
|
|
<link rel="stylesheet" href="~/css/rating.css" asp-append-version="true" />
|
|
|
|
<!-- Custom CSS - Critical above fold with cache busting -->
|
|
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
|
|
<link rel="stylesheet" href="~/css/qrrapido-theme.css" asp-append-version="true" />
|
|
|
|
<!-- Translation variables for JavaScript -->
|
|
<script>
|
|
window.QRRapidoTranslations = {
|
|
shareError: '@Localizer["ShareError"]',
|
|
linkCopied: '@Localizer["LinkCopied"]',
|
|
enterQRContent: '@Localizer["EnterQRContent"]',
|
|
contentTooLong: '@Localizer["ContentTooLong"]',
|
|
featureNotAvailable: '@Localizer["FeatureNotAvailable"]',
|
|
vCardValidationError: '@Localizer["VCardValidationError"]',
|
|
logoTooLarge: '@Localizer["LogoTooLarge"]',
|
|
invalidLogoFormat: '@Localizer["InvalidLogoFormat"]',
|
|
premiumCornerStyleRequired: '@Localizer["PremiumCornerStyleRequired"]',
|
|
fastestGeneratorBrazil: '@Localizer["FastestGeneratorBrazil"]',
|
|
validationContentMinLength: '@Localizer["ValidationContentMinLength"]',
|
|
errorSavingHistory: '@Localizer["ErrorSavingHistory"]',
|
|
rateLimitReached: '@Localizer["RateLimitReached"]',
|
|
premiumLogoRequired: '@Localizer["PremiumLogoRequired"]',
|
|
contentAddedToastTitle: '@Localizer["ContentAddedToastTitle"]',
|
|
contentAddedToastMessage: '@Localizer["ContentAddedToastMessage"]',
|
|
generateButtonReady: '@Localizer["GenerateButtonReady"]'
|
|
};
|
|
</script>
|
|
|
|
<!-- Favicon -->
|
|
<link rel="icon" type="image/svg+xml" href="/images/qrrapido-favicon.svg">
|
|
<link rel="icon" type="image/png" href="/images/qrrapido-favicon-32x32.png">
|
|
|
|
<!-- Web App Manifest -->
|
|
<link rel="manifest" href="/manifest.json">
|
|
<meta name="theme-color" content="#007BFF">
|
|
</head>
|
|
<body>
|
|
<!-- Header with QR Rapido branding -->
|
|
<header class="navbar navbar-expand-lg navbar-light bg-white border-bottom sticky-top">
|
|
<div class="container">
|
|
<a class="navbar-brand d-flex align-items-center" href="/">
|
|
<svg width="40" height="40" class="me-2" viewBox="0 0 100 100">
|
|
<!-- QR Rapido logo with speed effect -->
|
|
<rect x="10" y="10" width="80" height="80" fill="#007BFF" rx="8"/>
|
|
<rect x="20" y="20" width="15" height="15" fill="white"/>
|
|
<rect x="65" y="20" width="15" height="15" fill="white"/>
|
|
<rect x="20" y="65" width="15" height="15" fill="white"/>
|
|
<!-- Speed lines -->
|
|
<path d="M85 45 L95 45 M85 50 L92 50 M85 55 L89 55" stroke="#FF6B35" stroke-width="2"/>
|
|
</svg>
|
|
<div>
|
|
<h1 class="h4 mb-0 text-primary fw-bold">QR Rapido</h1>
|
|
<small class="text-muted" id="tagline">@Localizer["Tagline"]</small>
|
|
</div>
|
|
</a>
|
|
|
|
<div class="navbar-nav ms-auto d-flex flex-row align-items-center gap-3">
|
|
<!-- Main Menu Dropdown -->
|
|
<div class="dropdown">
|
|
<button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
|
<i class="fas fa-bars"></i> <span class="d-none d-md-inline ms-1">Menu</span>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="@Url.Action("Index", "Home")">
|
|
<i class="fas fa-home me-2"></i>@Localizer["Home"]
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="@Url.Action("HowToUse", "Home")">
|
|
<i class="fas fa-question-circle me-2"></i>@Localizer["HowToUse"]
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="@Url.Action("FAQ", "Home")">
|
|
<i class="fas fa-comments me-2"></i>FAQ
|
|
</a></li>
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li><a class="dropdown-item" href="@Url.Action("About", "Home")">
|
|
<i class="fas fa-info-circle me-2"></i>@Localizer["About"]
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="@Url.Action("Contact", "Home")">
|
|
<i class="fas fa-envelope me-2"></i>@Localizer["Contact"]
|
|
</a></li>
|
|
</ul>
|
|
</div>
|
|
<!-- Language selector -->
|
|
<div class="dropdown">
|
|
<button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
|
<i class="fas fa-globe"></i> <span id="current-lang">PT</span>
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="#" data-lang="pt-BR">🇧🇷 Português (Brasil)</a></li>
|
|
<li><a class="dropdown-item" href="#" data-lang="es-PY">🇵🇾 Español (Paraguay)</a></li>
|
|
@* <li><a class="dropdown-item" href="#" data-lang="en">🇺🇸 English</a></li> *@
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Theme Toggle -->
|
|
<div class="theme-toggle-container">
|
|
<button id="theme-toggle" class="btn btn-outline-secondary btn-sm" type="button" title="Alternar tema">
|
|
<i id="theme-icon" class="fas fa-sun"></i>
|
|
<span id="theme-text" class="d-none d-md-inline ms-1">Claro</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Global speed timer -->
|
|
<div class="d-none d-md-block">
|
|
<small class="text-success fw-bold">
|
|
<i class="fas fa-stopwatch"></i>
|
|
<span id="avg-generation-time">1.2s</span> @Localizer["Average"]
|
|
</small>
|
|
</div>
|
|
|
|
@if (User.Identity.IsAuthenticated)
|
|
{
|
|
<div class="dropdown">
|
|
<button class="btn btn-outline-primary btn-sm dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
|
<i class="fas fa-user"></i> @User.Identity.Name
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li><a class="dropdown-item" href="/">
|
|
<i class="fas fa-qrcode"></i> @Localizer["GenerateQRCode"]
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="/Account/Profile">
|
|
<i class="fas fa-user-cog"></i> @Localizer["Profile"]
|
|
</a></li>
|
|
<li><a class="dropdown-item" href="/Account/History">
|
|
<i class="fas fa-history"></i> @Localizer["History"]
|
|
</a></li>
|
|
@{
|
|
var userId = User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
|
|
var shouldShowAds = await AdService.ShouldShowAds(userId);
|
|
}
|
|
@if (!shouldShowAds)
|
|
{
|
|
<li><span class="dropdown-item text-success">
|
|
<i class="fas fa-crown"></i> @Localizer["PremiumActive"]
|
|
</span></li>
|
|
}
|
|
else
|
|
{
|
|
<li><a class="dropdown-item text-warning" href="/Pagamento/SelecaoPlano">
|
|
<i class="fas fa-rocket"></i> QR Rapido Premium
|
|
</a></li>
|
|
}
|
|
<li><hr class="dropdown-divider"></li>
|
|
<li>
|
|
<form method="post" action="/Account/Logout" class="d-inline">
|
|
<button type="submit" class="dropdown-item">
|
|
<i class="fas fa-sign-out-alt"></i> @Localizer["Logout"]
|
|
</button>
|
|
</form>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<a href="/Account/Login" class="btn btn-primary btn-sm">
|
|
<i class="fas fa-sign-in-alt"></i> @Localizer["Login"]
|
|
</a>
|
|
<div class="d-none d-md-block">
|
|
<small class="text-success">
|
|
<i class="fas fa-gift"></i> @Localizer["LoginThirtyDaysNoAds"]
|
|
</small>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- Hero Section for speed -->
|
|
<section class="bg-gradient-primary text-white py-4 mb-4">
|
|
<div class="container text-center">
|
|
<h2 class="h5 mb-2">
|
|
<i class="fas fa-bolt"></i> @Localizer["FastestQRGeneratorWeb"]
|
|
</h2>
|
|
<p class="mb-0 opacity-75">
|
|
@Localizer["AverageTimePrefix"] <strong>@Localizer["AverageTimeValue"]</strong> @Localizer["AverageTimeSuffix"]
|
|
</p>
|
|
@{
|
|
var currentCulture = System.Globalization.CultureInfo.CurrentUICulture.Name;
|
|
}
|
|
<div class="mt-3">
|
|
<a href="/@currentCulture/tutoriais" class="btn btn-sm btn-light">
|
|
<i class="fas fa-graduation-cap"></i> @Localizer["ViewTutorials"]
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Ad Space Header (conditional) -->
|
|
@await Html.PartialAsync("_AdSpace", new { position = "header" })
|
|
|
|
<main role="main">
|
|
@RenderBody()
|
|
</main>
|
|
|
|
<!-- Footer -->
|
|
<footer class="bg-dark text-light py-4 mt-5">
|
|
<div class="container">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h5>QR Rapido</h5>
|
|
<p class="small">@Localizer["FastestQRGeneratorDescription"]</p>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<h6>@Localizer["UsefulLinks"]</h6>
|
|
<ul class="list-unstyled">
|
|
<li><a href="@Url.Action("Privacy", "Home")" class="text-light">@Localizer["Privacy"]</a></li>
|
|
<li><a href="@Url.Action("Terms", "Home")" class="text-light">@Localizer["TermsOfUse"]</a></li>
|
|
<li><a href="@Url.Action("Upgrade", "Premium")" class="text-warning">Premium</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<h6>@Localizer["Support"]</h6>
|
|
<ul class="list-unstyled">
|
|
<li><a href="mailto:contato@qrrapido.site" class="text-light">Contato</a></li>
|
|
<li><a href="@Url.Action("FAQ", "Home")" class="text-light">@Localizer["Help"]</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<hr>
|
|
<div class="text-center mb-2">
|
|
<small class="text-muted">
|
|
@Html.Raw(Localizer["JobMakerCredit"].ToString().Replace("JobMaker", "<a href=\"https://jobmaker.com.br\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"text-warning\">JobMaker</a>"))
|
|
</small>
|
|
</div>
|
|
<div class="text-center">
|
|
<small>© 2024 QR Rapido. @Localizer["AllRightsReserved"]</small>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
<!-- Cookie Consent Banner -->
|
|
@await Html.PartialAsync("_CookieConsent")
|
|
|
|
<!-- Support FAB - Available for all users, with rating option -->
|
|
@await Html.PartialAsync("_TelegramPremiumFab", isPremiumUser)
|
|
|
|
<!-- Bootstrap 5 JS -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="~/js/telegram-fab.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/rating.js" asp-append-version="true" defer></script>
|
|
|
|
@if (isDevelopment)
|
|
{
|
|
<script src="~/js/simple-opcacity.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/test.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/qr-speed-generator.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/language-switcher.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/theme-toggle.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/cookie-consent.js" asp-append-version="true" defer></script>
|
|
<script src="~/js/performance-optimizations.js" asp-append-version="true" defer></script>
|
|
}
|
|
else
|
|
{
|
|
<script src="~/dist/app.min.js" asp-append-version="true"></script>
|
|
}
|
|
|
|
@await RenderSectionAsync("Scripts", required: false)
|
|
</body>
|
|
</html>
|