QrRapido/Views/Shared/_Layout.cshtml
Ricardo Carneiro a7af34659b
Some checks failed
Deploy QR Rapido / test (push) Successful in 29s
Deploy QR Rapido / build-and-push (push) Failing after 4s
Deploy QR Rapido / deploy-staging (push) Has been skipped
Deploy QR Rapido / deploy-production (push) Has been skipped
feat: delete e es-py
2025-08-04 20:34:29 -03:00

362 lines
16 KiB
Plaintext

@using QRRapidoApp.Services
@using Microsoft.AspNetCore.Http.Extensions
@using Microsoft.Extensions.Localization
@inject AdDisplayService AdService
@inject IStringLocalizer<QRRapidoApp.Resources.SharedResource> Localizer
<!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>
<!-- 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">
<!-- 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",
"30 dias sem anúncios",
"Download múltiplos formatos"
]
}
</script>
<!-- Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
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 -->
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXX"
crossorigin="anonymous"></script>
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
<!-- Custom CSS -->
<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"]'
};
</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">
<!-- 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</a></li>
<li><a class="dropdown-item" href="#" data-lang="es">🇪🇸 Español</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="/Premium/Upgrade">
<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>
</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="/Home/Privacy" class="text-light">@Localizer["Privacy"]</a></li>
<li><a href="/Home/Terms" class="text-light">@Localizer["TermsOfUse"]</a></li>
<li><a href="/Premium/Upgrade" 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="/Help" class="text-light">@Localizer["Help"]</a></li>
</ul>
</div>
</div>
<hr>
<div class="text-center">
<small>&copy; 2024 QR Rapido. @Localizer["AllRightsReserved"]</small>
</div>
</div>
</footer>
<!-- Bootstrap 5 JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Custom JS -->
<script src="~/js/test.js" asp-append-version="true"></script>
<script src="~/js/qr-speed-generator.js" asp-append-version="true"></script>
<script src="~/js/language-switcher.js" asp-append-version="true"></script>
<script src="~/js/theme-toggle.js" asp-append-version="true"></script>
<!-- Fallback inline script for debug -->
<script>
// Fallback inline para garantir funcionamento
document.addEventListener('DOMContentLoaded', function() {
// Fallback inline script starting
const btn = document.getElementById('theme-toggle');
if (btn) {
// Theme toggle button found
btn.onclick = function() {
// Theme toggle clicked
const html = document.documentElement;
const current = html.getAttribute('data-theme') || 'light';
const newTheme = current === 'light' ? 'dark' : 'light';
html.setAttribute('data-theme', newTheme);
console.log('Theme changed to:', newTheme);
const icon = document.getElementById('theme-icon');
const text = document.getElementById('theme-text');
if (icon) {
icon.className = newTheme === 'dark' ? 'fas fa-moon' : 'fas fa-sun';
}
if (text) {
text.textContent = newTheme === 'dark' ? 'Escuro' : 'Claro';
}
};
// Theme toggle configured inline
} else {
console.error('❌ Botão não encontrado pelo script inline!');
}
});
</script>
@await RenderSectionAsync("Scripts", required: false)
</body>
</html>