QrRapido/Views/Home/Index.cshtml
Ricardo Carneiro 16a9720a12
All checks were successful
Deploy QR Rapido / test (push) Successful in 59s
Deploy QR Rapido / build-and-push (push) Successful in 9m57s
Deploy QR Rapido / deploy-staging (push) Has been skipped
Deploy QR Rapido / deploy-production (push) Successful in 2m11s
feat: qrcode por creditos.
2026-01-26 20:13:45 -03:00

1636 lines
100 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@using QRRapidoApp.Services
@using Microsoft.Extensions.Localization
@inject AdDisplayService AdService
@inject IStringLocalizer<QRRapidoApp.Resources.SharedResource> Localizer
@{
ViewData["Title"] = "Home";
var userId = User?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
Layout = "~/Views/Shared/_Layout.cshtml";
// Server-Side Rendering: Determine which accordion to open based on qrType
var selectedQRType = (ViewBag.SelectedQRType as string)?.ToLowerInvariant() ?? "";
// Map qrType to accordion ID suffix (e.g., "pix" -> "pixQR")
var accordionIdMap = new Dictionary<string, string>
{
{ "url", "url" },
{ "text", "text" },
{ "texto", "text" },
{ "whatsapp", "whatsapp" },
{ "email", "email" },
{ "pix", "pix" },
{ "sms", "sms" },
{ "wifi", "wifi" },
{ "vcard", "vcard" }
};
// Helper function to determine if this accordion should be open
string GetAccordionClass(string accordionType) =>
accordionIdMap.TryGetValue(selectedQRType, out var mapped) && mapped == accordionType
? "accordion-collapse collapse show"
: "accordion-collapse collapse";
string GetButtonClass(string accordionType) =>
accordionIdMap.TryGetValue(selectedQRType, out var mapped) && mapped == accordionType
? "accordion-button"
: "accordion-button collapsed";
}
<div class="container">
<!-- Hidden input for JavaScript premium status check -->
@{
var statusValue = "anonymous";
if (User.Identity.IsAuthenticated)
{
var isPremium = await AdService.HasValidPremiumSubscription(userId);
statusValue = isPremium ? "premium" : "logged-in";
}
}
<input type="hidden" id="user-premium-status" value="@statusValue" />
<!-- Hidden localized strings for rate limiting -->
<div style="display: none;">
<span data-localized="RateLimitExceeded">@Localizer["RateLimitExceeded"]</span>
<span data-localized="QRCodesRemainingToday">@Localizer["QRCodesRemainingToday"]</span>
<span data-localized="UnlimitedToday">@Localizer["UnlimitedToday"]</span>
</div>
<div class="row">
<!-- QR Generator Form -->
<div class="col-lg-8">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h3 class="h5 mb-0">
<i class="fas fa-qrcode"></i> @Localizer["CreateQRCodeQuickly"]
</h3>
</div>
<div class="card-body">
<form id="qr-speed-form" class="needs-validation" novalidate>
<!-- Generation timer -->
<div class="row mb-3">
<div class="col-md-8">
<div class="d-flex align-items-center gap-3">
<div class="generation-timer d-none">
<i class="fas fa-stopwatch text-primary"></i>
<span class="fw-bold text-primary">0.0s</span>
</div>
<div class="speed-badge d-none">
<span class="badge bg-success">
<i class="fas fa-bolt"></i> @Localizer["UltraFastGeneration"]
</span>
</div>
</div>
</div>
<div class="col-md-4 text-end">
<small class="text-muted">
<span class="qr-counter">Carregando...</span>
</small>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">
<i class="fas fa-list"></i> @Localizer["QRCodeType"]
</label>
<select id="qr-type" class="form-select qr-type-highlight" required>
<option value="">@Localizer["SelectType"]</option>
<option value="pix">💸 @Localizer["PIX"]</option>
<option value="url">🌐 @Localizer["URLLink"]</option>
<option value="text">📝 @Localizer["SimpleText"]</option>
<option value="wifi">📶 @Localizer["WiFi"]</option>
<option value="vcard">👤 @Localizer["VCard"]</option>
<option value="sms">💬 @Localizer["SMS"]</option>
<option value="email">📧 @Localizer["Email"]</option>
</select>
<div class="type-selection-hint" id="type-selection-hint">
<i class="fas fa-hand-point-up"></i>
<span>@Localizer["ChooseTypeFirst"]</span>
</div>
<!-- Hidden localized guidance messages for JavaScript -->
<div style="display: none;">
<span data-type-guide-url>@Localizer["TypeGuideURL"]</span>
<span data-type-guide-vcard>@Localizer["TypeGuideVCard"]</span>
<span data-type-guide-wifi>@Localizer["TypeGuideWiFi"]</span>
<span data-type-guide-sms>@Localizer["TypeGuideSMS"]</span>
<span data-type-guide-email>@Localizer["TypeGuideEmail"]</span>
<span data-type-guide-pix>@Localizer["TypeGuidePIX"]</span>
<span data-type-guide-text>@Localizer["TypeGuideText"]</span>
</div>
</div>
<div class="col-md-6 mb-3 opacity-controlled disabled-state" id="quick-style-group">
<label class="form-label fw-semibold">
<i class="fas fa-palette"></i> @Localizer["QuickStyle"]
</label>
<div class="btn-group w-100" role="group">
<input type="radio" class="btn-check" name="quick-style" id="style-classic" value="classic" checked>
<label class="btn btn-outline-secondary" for="style-classic">@Localizer["Classic"]</label>
<input type="radio" class="btn-check" name="quick-style" id="style-modern" value="modern">
<label class="btn btn-outline-secondary" for="style-modern">@Localizer["Modern"]</label>
<input type="radio" class="btn-check" name="quick-style" id="style-colorful" value="colorful">
<label class="btn btn-outline-secondary" for="style-colorful">@Localizer["Colorful"]</label>
</div>
</div>
</div>
<div class="mb-3 opacity-controlled disabled-state" id="content-group">
<label class="form-label fw-semibold">
<i class="fas fa-edit"></i> @Localizer["Content"]
</label>
<textarea id="qr-content"
class="form-control form-control-lg required-field"
rows="3"
placeholder="@Localizer["EnterQRCodeContent"]"
required></textarea>
<div class="invalid-feedback">Conteúdo deve ter pelo menos 3 caracteres</div>
<div class="form-text">
<span id="content-hints">@Localizer["ContentHints"]</span>
</div>
</div>
<!-- Dynamic QR Section (Premium) -->
<div id="dynamic-qr-section" style="display: none;" class="opacity-controlled disabled-state">
<div class="premium-feature-box">
<div class="d-flex align-items-center justify-content-between">
<div>
<h6 class="mb-1">
<i class="fas fa-chart-line text-warning"></i> QR Dinâmico - Premium
</h6>
<small class="text-muted">
QR Code com seu logotipo!
</small>
</div>
<div class="form-check form-switch">
@if (ViewBag.IsPremium == true)
{
<input class="form-check-input" type="checkbox" id="qr-dynamic-toggle" style="display: none;">
<label class="form-check-label" for="qr-dynamic-toggle">
Adicione o logotivo na Personalização avançada
</label>
}
else
{
<div class="premium-upgrade-prompt">
<input class="form-check-input" type="checkbox" disabled style="display: none;">
<label class="form-check-label" for="qr-dynamic-toggle">
Gerar QR Code com logotipo? Assine o plano premium!
</label>
<br>
<small>
<a href="/Pagamento/SelecaoPlano" class="text-warning">
Upgrade Premium
</a> QR Code com logotipo
</small>
</div>
}
</div>
</div>
</div>
</div>
<!-- URL Preview -->
<div id="url-preview" class="mt-3 opacity-controlled disabled-state" style="display: none;">
<h6><i class="fas fa-link"></i> Preview</h6>
<div id="url-preview-content" class="bg-light p-3 rounded">
<strong>URL Final:</strong> <span id="final-url-display"></span><br>
<strong>Tipo:</strong> <span id="qr-type-display">QR Code Estático</span>
</div>
</div>
<!-- VCard Interface (dynamic) -->
<div id="vcard-interface" class="mb-3 opacity-controlled disabled-state" style="display: none;">
<div class="alert alert-info">
<i class="fas fa-address-card"></i>
<strong>Cartão de Visita Digital</strong> - Este QR Code criará um cartão de visita digital.
Quando escaneado, oferecerá para salvar seus contatos automaticamente.
</div>
<!-- Campos Obrigatórios -->
<div class="required-fields mb-4">
<h6 class="fw-bold text-primary mb-3">
<i class="fas fa-user-check"></i> Informações Essenciais
</h6>
<div class="row">
<div class="col-md-12 mb-3">
<label class="form-label fw-semibold">Nome Completo *</label>
<input type="text" id="vcard-name" class="form-control required-field" placeholder="Seu Nome Completo" required>
<div class="invalid-feedback">Nome é obrigatório</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">Telefone Celular *</label>
<input type="tel" id="vcard-mobile" class="form-control required-field" placeholder="11999998888" required>
<small class="form-text text-muted">Apenas números (DDD + número)</small>
<div class="invalid-feedback">Telefone celular é obrigatório</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">Email *</label>
<input type="email" id="vcard-email" class="form-control required-field" placeholder="seu.email@exemplo.com" required>
<div class="invalid-feedback">Email válido é obrigatório</div>
</div>
</div>
</div>
<!-- Campos Opcionais -->
<div class="optional-fields mb-4">
<h6 class="fw-bold text-secondary mb-3">
<i class="fas fa-plus-circle"></i> Informações Adicionais (Opcionais)
</h6>
<!-- Empresa -->
<div class="mb-3">
<div class="form-check mb-2">
<input type="checkbox" id="enable-company" class="form-check-input">
<label for="enable-company" class="form-check-label fw-semibold">
<i class="fas fa-building"></i> Empresa
</label>
</div>
<div class="form-group" id="company-group" style="display: none;">
<input type="text" id="vcard-company" class="form-control" placeholder="Nome da Empresa">
</div>
</div>
<!-- Cargo -->
<div class="mb-3">
<div class="form-check mb-2">
<input type="checkbox" id="enable-title" class="form-check-input">
<label for="enable-title" class="form-check-label fw-semibold">
<i class="fas fa-id-badge"></i> Cargo/Título
</label>
</div>
<div class="form-group" id="title-group" style="display: none;">
<input type="text" id="vcard-title" class="form-control" placeholder="CEO, Gerente, Desenvolvedor, etc.">
</div>
</div>
<!-- Website -->
<div class="mb-3">
<div class="form-check mb-2">
<input type="checkbox" id="enable-website" class="form-check-input">
<label for="enable-website" class="form-check-label fw-semibold">
<i class="fas fa-globe"></i> Website
</label>
</div>
<div class="form-group" id="website-group" style="display: none;">
<input type="url" id="vcard-website" class="form-control" placeholder="https://seusite.com">
<div class="invalid-feedback" id="website-error"></div>
<small class="form-text text-muted">
<i class="fas fa-info-circle"></i> O protocolo https:// será adicionado automaticamente
</small>
</div>
</div>
<!-- Telefone Fixo -->
<div class="mb-3">
<div class="form-check mb-2">
<input type="checkbox" id="enable-phone" class="form-check-input">
<label for="enable-phone" class="form-check-label fw-semibold">
<i class="fas fa-phone"></i> Telefone Fixo
</label>
</div>
<div class="form-group" id="phone-group" style="display: none;">
<input type="tel" id="vcard-phone" class="form-control" placeholder="1133334444">
<small class="form-text text-muted">Apenas números (DDD + número)</small>
</div>
</div>
<!-- Endereço -->
<div class="mb-3">
<div class="form-check mb-2">
<input type="checkbox" id="enable-address" class="form-check-input">
<label for="enable-address" class="form-check-label fw-semibold">
<i class="fas fa-map-marker-alt"></i> Endereço
</label>
</div>
<div id="address-group" style="display: none;">
<div class="form-group mb-2">
<input type="text" id="vcard-address" class="form-control" placeholder="Rua, número - Ex: Rua das Flores, 123">
</div>
<div class="row">
<div class="col-md-4">
<input type="text" id="vcard-city" class="form-control" placeholder="Cidade">
</div>
<div class="col-md-4">
<input type="text" id="vcard-state" class="form-control" placeholder="Estado">
</div>
<div class="col-md-4">
<input type="text" id="vcard-zip" class="form-control" placeholder="CEP">
</div>
</div>
</div>
</div>
</div>
<!-- Preview do VCard -->
<div class="vcard-preview mb-3">
<h6 class="fw-bold text-success mb-2">
<i class="fas fa-eye"></i> Preview do Cartão
</h6>
<div class="card bg-light">
<div class="card-body">
<pre id="vcard-preview-text" class="mb-0 small text-muted">BEGIN:VCARD
VERSION:3.0
CHARSET=UTF-8
Preencha os campos acima para ver o preview...
END:VCARD
</pre>
</div>
</div>
</div>
</div>
<!-- WiFi Interface (dynamic) -->
<div id="wifi-interface" class="mb-3 opacity-controlled disabled-state" style="display: none;">
<div class="alert alert-info">
<i class="fas fa-wifi"></i>
<strong>@Localizer["WiFiQRTitle"]</strong> - @Localizer["WiFiQRDescription"]
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">@Localizer["NetworkName"] *</label>
<input type="text" id="wifi-ssid" name="wifi-ssid" class="form-control" placeholder="NomeDaSuaRede" required>
<div class="invalid-feedback">@Localizer["NetworkNameRequired"]</div>
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">@Localizer["SecurityType"]</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifi-security" id="wifi-security-wpa" value="WPA" checked>
<label class="form-check-label" for="wifi-security-wpa">@Localizer["WPARecommended"]</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifi-security" id="wifi-security-wep" value="WEP">
<label class="form-check-label" for="wifi-security-wep">@Localizer["WEPLegacy"]</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifi-security" id="wifi-security-nopass" value="nopass">
<label class="form-check-label" for="wifi-security-nopass">@Localizer["OpenNetwork"]</label>
</div>
</div>
<div class="form-group mb-3" id="wifi-password-group">
<label class="form-label fw-semibold">@Localizer["NetworkPassword"] *</label>
<div class="input-group">
<input type="password" id="wifi-password" name="wifi-password" class="form-control" placeholder="SenhaDaSuaRede" required>
<button class="btn btn-outline-secondary" type="button" id="toggle-password">
<i class="fas fa-eye"></i>
</button>
</div>
<div class="invalid-feedback">@Localizer["PasswordRequiredForSecure"]</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="wifi-hidden" name="wifi-hidden">
<label class="form-check-label" for="wifi-hidden">@Localizer["HiddenNetwork"]</label>
</div>
<div class="wifi-preview">
<h6 class="fw-bold text-success mb-2">
<i class="fas fa-eye"></i> @Localizer["WiFiPreviewTitle"]
</h6>
<div class="card bg-light">
<div class="card-body">
<pre id="wifi-preview-text" class="mb-0 small text-muted">WIFI:T:WPA;S:;P:;H:false;;</pre>
</div>
</div>
</div>
</div>
<!-- WiFi Interface (dynamic) -->
<div id="wifi-interface" class="mb-3" style="display: none;">
<div class="alert alert-info">
<i class="fas fa-wifi"></i>
<strong>@Localizer["WiFiQRTitle"]</strong> - @Localizer["WiFiQRDescription"]
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">@Localizer["NetworkName"] *</label>
<input type="text" id="wifi-ssid2" class="form-control" placeholder="NomeDaSuaRede" required>
<div class="invalid-feedback">@Localizer["NetworkNameRequired"]</div>
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">@Localizer["SecurityType"]</label>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifi-security" id="wifi-security-wpa2" value="WPA" checked>
<label class="form-check-label" for="wifi-security-wpa">@Localizer["WPARecommended"]</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifi-security" id="wifi-security-wep2" value="WEP">
<label class="form-check-label" for="wifi-security-wep">@Localizer["WEPLegacy"]</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="wifi-security" id="wifi-security-nopass2" value="nopass">
<label class="form-check-label" for="wifi-security-nopass">@Localizer["OpenNetwork"]</label>
</div>
</div>
<div class="form-group mb-3" id="wifi-password-group">
<label class="form-label fw-semibold">@Localizer["NetworkPassword"] *</label>
<div class="input-group">
<input type="password" id="wifi-password2" class="form-control" placeholder="SenhaDaSuaRede" required>
<button class="btn btn-outline-secondary" type="button" id="toggle-password2">
<i class="fas fa-eye"></i>
</button>
</div>
<div class="invalid-feedback">@Localizer["PasswordRequiredForSecure"]</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="wifi-hidden2">
<label class="form-check-label" for="wifi-hidden">@Localizer["HiddenNetwork"]</label>
</div>
<div class="wifi-preview">
<h6 class="fw-bold text-success mb-2">
<i class="fas fa-eye"></i> @Localizer["WiFiPreviewTitle"]
</h6>
<div class="card bg-light">
<div class="card-body">
<pre id="wifi-preview-text" class="mb-0 small text-muted">WIFI:T:WPA;S:;P:;H:false;;</pre>
</div>
</div>
</div>
</div>
<!-- SMS Interface (dynamic) -->
<div id="sms-interface" class="mb-3" style="display: none;">
<div class="alert alert-info">
<strong>QR Code SMS:</strong> Permite enviar SMS automático com número e mensagem pré-definidos.
Compatível com Android, iOS e dispositivos modernos.
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">Número do Celular *</label>
<input type="tel" id="sms-number" name="sms-number" class="form-control" placeholder="11999998888" required>
<small class="text-muted">Apenas números (DDD + número, sem espaços)</small>
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">Mensagem *</label>
<textarea id="sms-message" name="sms-message" class="form-control" rows="3" placeholder="Sua mensagem aqui..." required></textarea>
<small class="text-muted">Mensagem que será pré-preenchida no SMS</small>
</div>
<div class="sms-preview">
<h6> Preview do SMS</h6>
<pre id="sms-preview-text" class="bg-light p-3 rounded">SMSTO::</pre>
</div>
</div>
<!-- Email Interface (dynamic) -->
<div id="email-interface" class="mb-3 opacity-controlled disabled-state" style="display: none;">
<div class="alert alert-info">
<strong>QR Code Email:</strong> Permite enviar email automático com destinatário, assunto e mensagem pré-definidos.
Compatível com Android, iOS e dispositivos modernos.
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">Email Destinatário *</label>
<input type="email" id="email-to" name="email-to" class="form-control" placeholder="contato@empresa.com" required>
<small class="text-muted">Email que receberá a mensagem</small>
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">Assunto *</label>
<input type="text" id="email-subject" name="email-subject" class="form-control" placeholder="Assunto do email" required>
<small class="text-muted">Linha de assunto do email</small>
</div>
<div class="form-group mb-3">
<label class="form-label fw-semibold">Mensagem</label>
<textarea id="email-body" name="email-body" class="form-control" rows="4" placeholder="Corpo da mensagem..."></textarea>
<small class="text-muted">Corpo da mensagem (opcional)</small>
</div>
<div class="email-preview">
<h6> Preview do Email</h6>
<pre id="email-preview-text" class="bg-light p-3 rounded">mailto:?subject=&body=</pre>
</div>
</div>
<!-- PIX Interface (dynamic) -->
<div id="pix-interface" class="mb-3 opacity-controlled disabled-state" style="display: none;">
<div class="alert alert-success border-success">
<div class="d-flex">
<div class="me-3 display-4"><i class="fas fa-qrcode"></i></div>
<div>
<h5 class="alert-heading fw-bold">@Localizer["PixGeneratorTitle"]</h5>
<p class="mb-0">@Localizer["PixGeneratorDesc"]</p>
</div>
</div>
</div>
<div class="alert alert-warning border-warning d-flex align-items-center mb-3">
<i class="fas fa-store fa-2x me-3 text-warning"></i>
<div>
<strong>@Localizer["SellManyProductsTitle"]</strong>
<p class="mb-0 small">Assine nosso plano mensal e gerencie QR Codes exclusivos para cada produto do seu catálogo.</p>
</div>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label class="form-label fw-semibold">@Localizer["PixKeyType"]</label>
<select id="pix-key-type" class="form-select">
<option value="cpf">CPF/CNPJ</option>
<option value="phone">@Localizer["PixKeyPhone"]</option>
<option value="email">Email</option>
<option value="random">@Localizer["PixKeyRandom"]</option>
</select>
</div>
<div class="col-md-8 mb-3">
<label class="form-label fw-semibold">@Localizer["PixKey"] *</label>
<input type="text" id="pix-key" class="form-control" placeholder="@Localizer["PixKeyPlaceholder"]" required>
</div>
</div>
<div class="row">
<div class="col-md-8 mb-3">
<label class="form-label fw-semibold">@Localizer["BeneficiaryName"] *</label>
<input type="text" id="pix-name" class="form-control" placeholder="Seu Nome ou Nome da Empresa" maxlength="25" required>
<div class="form-text">Máximo 25 caracteres (sem acentos recomendado)</div>
</div>
<div class="col-md-4 mb-3">
<label class="form-label fw-semibold">@Localizer["BeneficiaryCity"] *</label>
<input type="text" id="pix-city" class="form-control" placeholder="Sua Cidade" maxlength="15" required>
<div class="form-text">Máximo 15 caracteres (Padrão BACEN)</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">@Localizer["AmountOptional"]</label>
<div class="input-group">
<span class="input-group-text">R$</span>
<input type="text" id="pix-amount" class="form-control" placeholder="0,00" inputmode="decimal">
</div>
<div class="form-text">Deixe em branco para valor livre</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label fw-semibold">@Localizer["TxIDOptional"]</label>
<input type="text" id="pix-txid" class="form-control" placeholder="***">
<div class="form-text">Identificador da transação (padrão: ***)</div>
</div>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">@Localizer["DescriptionOptional"]</label>
<input type="text" id="pix-description" class="form-control" placeholder="Pagamento referente a...">
<div class="form-text">Alguns bancos exibem esta mensagem na tela de confirmação</div>
</div>
<div class="pix-preview mt-3">
<h6 class="fw-bold text-success mb-2">
<i class="fas fa-eye"></i> @Localizer["PixPreviewTitle"]
</h6>
<div class="card bg-light">
<div class="card-body">
<pre id="pix-preview-text" class="mb-0 small text-muted text-break">Preencha os campos obrigatórios para gerar o payload...</pre>
</div>
</div>
</div>
</div>
<!-- Navigation Buttons REMOVED - Simplified Flow -->
<!-- Advanced customization (collapsible) -->
<div class="accordion mb-3 opacity-controlled disabled-state" id="customization-accordion">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#customization-panel" id="btn-customization-toggle">
<i class="fas fa-sliders-h me-2"></i> @Localizer["AdvancedCustomization"]
</button>
</h2>
<div id="customization-panel" class="accordion-collapse collapse">
<div class="accordion-body">
<div class="row">
<div class="col-md-3 mb-3">
<label class="form-label">@Localizer["PrimaryColor"]</label>
<input type="color" id="primary-color" class="form-control form-control-color" value="#007BFF">
</div>
<div class="col-md-3 mb-3">
<label class="form-label">@Localizer["BackgroundColor"]</label>
<input type="color" id="bg-color" class="form-control form-control-color" value="#FFFFFF">
</div>
<div class="col-md-3 mb-3">
<label class="form-label">@Localizer["Size"]</label>
<select id="qr-size" class="form-select">
<option value="200">@Localizer["SmallSize200px"]</option>
<option value="300" selected>@Localizer["MediumSize300px"]</option>
<option value="500">@Localizer["LargeSize500px"]</option>
<option value="800">@Localizer["XLSize800px"]</option>
</select>
</div>
<div class="col-md-3 mb-3">
<label class="form-label">@Localizer["Margin"]</label>
<select id="qr-margin" class="form-select">
<option value="1">@Localizer["Minimal"]</option>
<option value="2" selected>@Localizer["Normal"]</option>
<option value="4">@Localizer["Large"]</option>
</select>
</div>
</div>
@if (User.Identity.IsAuthenticated)
{
<div class="row">
@{
var userService = Context.RequestServices.GetService<QRRapidoApp.Services.IUserService>();
var currentUserId = User?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
var currentUser = currentUserId != null ? await userService.GetUserAsync(currentUserId) : null;
var isPremium = currentUser?.IsPremium == true;
}
@if (isPremium)
{
<!-- Seção de Logo Premium Aprimorada -->
<div class="col-md-12 mb-3">
<div class="premium-feature-box p-3 border rounded bg-light">
<h6 class="fw-bold mb-3">
<i class="fas fa-crown text-warning"></i>
Logo Personalizado - Premium
</h6>
<!-- Upload de Logo -->
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label fw-semibold">
<i class="fas fa-image"></i> Upload do Logo
</label>
<input type="file" id="logo-upload" class="form-control" accept="image/png,image/jpeg,image/jpg">
<div class="form-text">PNG ou JPG, máximo 2MB, recomendado: formato quadrado</div>
<div id="logo-preview" class="mt-2 d-none">
<small class="text-success">
<i class="fas fa-check-circle"></i>
<span id="logo-filename"></span>
</small>
</div>
</div>
<!-- Preview Visual do Logo -->
<div class="col-md-6">
<div id="logo-visual-preview" style="display: none;">
<label class="form-label fw-semibold">
<i class="fas fa-eye"></i> Preview
</label>
<div class="d-flex align-items-center gap-3">
<div class="logo-preview-container border rounded p-2 bg-white" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
<img id="logo-preview-image" src="" alt="Preview" style="max-width: 100%; max-height: 100%; object-fit: contain;">
</div>
<div class="text-muted small">
<div>Tamanho: <span id="preview-size-text">20%</span></div>
<div>Colorização: <span id="preview-colorize-text">Desativada</span></div>
</div>
</div>
</div>
</div>
</div>
<!-- Controles Avançados -->
<div class="row mb-3">
<div class="col-md-6">
<label class="form-label fw-semibold">
<i class="fas fa-expand-arrows-alt"></i> Tamanho do Logo
</label>
<div class="d-flex align-items-center gap-2">
<input type="range" id="logo-size-slider" class="form-range flex-grow-1"
min="10" max="25" value="20" step="1">
<span class="badge bg-primary" id="logo-size-display">20%</span>
</div>
<div class="form-text">
<small>
<span class="text-muted">10% (Discreto)</span>
<span class="float-end text-muted">25% (Máximo seguro)</span>
</small>
</div>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">
<i class="fas fa-palette"></i> Colorização
</label>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="logo-colorize-toggle">
<label class="form-check-label" for="logo-colorize-toggle">
Aplicar cor do QR Code no logo
</label>
</div>
<div class="form-text">
<small class="text-info">
<i class="fas fa-info-circle"></i>
Converte o logo para a cor selecionada
</small>
</div>
</div>
</div>
<!-- Dicas de Otimização -->
<div class="alert alert-info border-0 mb-0 small">
<div class="row">
<div class="col-md-6">
<strong><i class="fas fa-lightbulb"></i> Dicas para Melhor Resultado:</strong>
<ul class="mb-0 mt-1">
<li>Use logos com formato quadrado ou circular</li>
<li>Prefira fundos transparentes (PNG)</li>
<li>Evite logos com muito detalhe</li>
</ul>
</div>
<div class="col-md-6">
<strong><i class="fas fa-mobile-alt"></i> Garantia de Leitura:</strong>
<ul class="mb-0 mt-1">
<li>✅ Correção de erro de 30%</li>
<li>✅ Bordas de proteção automáticas</li>
<li>✅ Testado em todos os leitores</li>
</ul>
</div>
</div>
</div>
</div>
</div>
}
else
{
<div class="col-md-6 mb-3">
<div class="premium-upgrade-box p-3 border rounded bg-light">
<h6 class="fw-bold mb-2">
<i class="fas fa-crown text-warning"></i>
Logo Personalizado - Premium
</h6>
<p class="mb-2 small">Adicione sua marca aos QR Codes! Agora com tamanho configurável (10-25%) e colorização automática.</p>
<a href="/Pagamento/SelecaoPlano" class="btn btn-warning btn-sm">
<i class="fas fa-arrow-up"></i> Fazer Upgrade
</a>
</div>
</div>
}
@* Analytics/Tracking - Premium Feature *@
@if (isPremium)
{
<div class="col-12 mb-3">
<div class="form-check">
<input type="checkbox" id="enable-tracking" class="form-check-input" value="true">
<label class="form-check-label" for="enable-tracking">
<i class="fas fa-chart-line text-primary"></i> @Localizer["EnableTracking"]
<span class="badge bg-primary">Premium</span>
</label>
<div class="form-text">
<i class="fas fa-info-circle"></i> @Localizer["TrackingInfo"]
</div>
</div>
</div>
}
<div class="col-md-6 mb-3">
<label class="form-label">@Localizer["BorderStyle"]</label>
<select id="corner-style" class="form-select @(isPremium ? "" : "border-warning")">
<option value="square">@Localizer["Square"] (Grátis)</option>
@if (isPremium)
{
<option value="rounded">@Localizer["Rounded"] 👑</option>
<option value="circle">Círculos 👑</option>
}
else
{
<option value="rounded" disabled>@Localizer["Rounded"] - Premium 👑</option>
<option value="circle" disabled>Círculos - Premium 👑</option>
}
</select>
@if (!isPremium)
{
<div class="form-text text-warning">
<i class="fas fa-crown"></i>
<a href="/Pagamento/SelecaoPlano" class="text-warning">Upgrade Premium</a> para estilos personalizados
</div>
}
</div>
</div>
}
</div>
</div>
</div>
</div>
<div class="d-grid opacity-controlled disabled-state" id="button-gerar-div">
<button type="submit" class="btn btn-primary btn-lg" id="generate-btn">
<i class="fas fa-bolt"></i> @Localizer["GenerateQRCodeQuickly"]
<div class="spinner-border spinner-border-sm ms-2 d-none" role="status">
<span class="visually-hidden">@Localizer["Generating"]</span>
</div>
</button>
</div>
</form>
</div>
</div>
<!-- Speed statistics -->
<div class="row mt-4">
<div class="col-md-4">
<div class="card text-center border-success">
<div class="card-body">
<h5 class="text-success">
<i class="fas fa-stopwatch"></i> 1.2s
</h5>
<small class="text-muted">@Localizer["AverageTime"]</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center border-primary">
<div class="card-body">
<h5 class="text-primary">
<i class="fas fa-chart-line"></i> 99.9%
</h5>
<small class="text-muted">@Localizer["Availability"]</small>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card text-center border-warning">
<div class="card-body">
<h5 class="text-warning">
<i class="fas fa-users"></i> <span id="total-qrs">10.5K</span>
</h5>
<small class="text-muted">@Localizer["QRsGeneratedToday"]</small>
</div>
</div>
</div>
</div>
<!-- QR Code Types Information Accordions -->
<div class="row mt-5">
<div class="col-12">
<h3 class="text-center mb-4">
<i class="fas fa-info-circle text-primary"></i> @Localizer["LearnQRTypes"]
</h3>
<div class="accordion" id="qrTypesAccordion">
<!-- URL/Link QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("url")" type="button" data-bs-toggle="collapse" data-bs-target="#urlQR">
<i class="fas fa-link text-primary me-2"></i>
<strong>@Localizer["URLLink"]</strong>
</button>
</h2>
<div id="urlQR" class="@GetAccordionClass("url")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["URLQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["URLStep1"]</li>
<li>@Localizer["URLStep2"]</li>
<li>@Localizer["URLStep3"]</li>
<li>@Localizer["URLStep4"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["URLTip1"]</li>
<li>@Localizer["URLTip2"]</li>
<li>@Localizer["URLTip3"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["URLUseCase1"]</li>
<li>@Localizer["URLUseCase2"]</li>
<li>@Localizer["URLUseCase3"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Text QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("text")" type="button" data-bs-toggle="collapse" data-bs-target="#textQR">
<i class="fas fa-align-left text-primary me-2"></i>
<strong>@Localizer["SimpleText"]</strong>
</button>
</h2>
<div id="textQR" class="@GetAccordionClass("text")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["TextQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["TextStep1"]</li>
<li>@Localizer["TextStep2"]</li>
<li>@Localizer["TextStep3"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["TextTip1"]</li>
<li>@Localizer["TextTip2"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["TextUseCase1"]</li>
<li>@Localizer["TextUseCase2"]</li>
<li>@Localizer["TextUseCase3"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- WhatsApp QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("whatsapp")" type="button" data-bs-toggle="collapse" data-bs-target="#whatsappQR">
<i class="fab fa-whatsapp text-success me-2"></i>
<strong>WhatsApp</strong>
</button>
</h2>
<div id="whatsappQR" class="@GetAccordionClass("whatsapp")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["WhatsAppQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["WhatsAppStep1"]</li>
<li>@Localizer["WhatsAppStep2"]</li>
<li>@Localizer["WhatsAppStep3"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["WhatsAppTip1"]</li>
<li>@Localizer["WhatsAppTip2"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["WhatsAppUseCase1"]</li>
<li>@Localizer["WhatsAppUseCase2"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Email QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("email")" type="button" data-bs-toggle="collapse" data-bs-target="#emailQR">
<i class="fas fa-envelope text-primary me-2"></i>
<strong>@Localizer["Email"]</strong>
</button>
</h2>
<div id="emailQR" class="@GetAccordionClass("email")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["EmailQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["EmailStep1"]</li>
<li>@Localizer["EmailStep2"]</li>
<li>@Localizer["EmailStep3"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["EmailTip1"]</li>
<li>@Localizer["EmailTip2"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["EmailUseCase1"]</li>
<li>@Localizer["EmailUseCase2"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- PIX QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("pix")" type="button" data-bs-toggle="collapse" data-bs-target="#pixQR">
<i class="fas fa-qrcode text-success me-2"></i>
<strong>@Localizer["PIX"]</strong>
</button>
</h2>
<div id="pixQR" class="@GetAccordionClass("pix")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["PIXQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["PixStep1"]</li>
<li>@Localizer["PixStep2"]</li>
<li>@Localizer["PixStep3"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["PixTip1"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["PixUseCase1"]</li>
<li>@Localizer["PixUseCase2"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- SMS QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("sms")" type="button" data-bs-toggle="collapse" data-bs-target="#smsQR">
<i class="fas fa-sms text-primary me-2"></i>
<strong>@Localizer["SMS"]</strong>
</button>
</h2>
<div id="smsQR" class="@GetAccordionClass("sms")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["SMSQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["SMSStep1"]</li>
<li>@Localizer["SMSStep2"]</li>
<li>@Localizer["SMSStep3"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["SMSTip1"]</li>
<li>@Localizer["SMSTip2"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["SMSUseCase1"]</li>
<li>@Localizer["SMSUseCase2"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- WiFi QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("wifi")" type="button" data-bs-toggle="collapse" data-bs-target="#wifiQR">
<i class="fas fa-wifi text-primary me-2"></i>
<strong>@Localizer["WiFi"]</strong>
</button>
</h2>
<div id="wifiQR" class="@GetAccordionClass("wifi")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["WiFiQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["WiFiStep1"]</li>
<li>@Localizer["WiFiStep2"]</li>
<li>@Localizer["WiFiStep3"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["WiFiTip1"]</li>
<li>@Localizer["WiFiTip2"]</li>
<li>@Localizer["WiFiTip3"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["WiFiUseCase1"]</li>
<li>@Localizer["WiFiUseCase2"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- vCard QR Code -->
<div class="accordion-item">
<h2 class="accordion-header">
<button class="@GetButtonClass("vcard")" type="button" data-bs-toggle="collapse" data-bs-target="#vcardQR">
<i class="fas fa-address-card text-primary me-2"></i>
<strong>@Localizer["VCard"]</strong>
</button>
</h2>
<div id="vcardQR" class="@GetAccordionClass("vcard")" data-bs-parent="#qrTypesAccordion">
<div class="accordion-body">
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-question-circle text-info"></i> @Localizer["WhatIsIt"]</h6>
<p>@Localizer["VCardQRDescription"]</p>
<h6><i class="fas fa-play text-success"></i> @Localizer["HowToUse"]</h6>
<ol class="small">
<li>@Localizer["VCardStep1"]</li>
<li>@Localizer["VCardStep2"]</li>
<li>@Localizer["VCardStep3"]</li>
<li>@Localizer["VCardStep4"]</li>
</ol>
</div>
<div class="col-md-6">
<h6><i class="fas fa-lightbulb text-warning"></i> @Localizer["Tips"]</h6>
<ul class="small">
<li>@Localizer["VCardTip1"]</li>
<li>@Localizer["VCardTip2"]</li>
<li>@Localizer["VCardTip3"]</li>
</ul>
<h6><i class="fas fa-users text-secondary"></i> @Localizer["UseCases"]</h6>
<ul class="small">
<li>@Localizer["VCardUseCase1"]</li>
<li>@Localizer["VCardUseCase2"]</li>
<li>@Localizer["VCardUseCase3"]</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Ad Space Between Content (conditional) -->
@await Html.PartialAsync("_AdSpace", new { position = "content" })
</div>
<!-- Sidebar with preview and ads -->
<div class="col-lg-4">
<!-- Preview with timer -->
<div class="card shadow-sm mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-eye"></i> Preview
</h5>
<div class="generation-stats d-none">
<small class="text-success">
<i class="fas fa-check-circle"></i> Gerado em <span class="generation-time">0s</span>
</small>
</div>
</div>
<div class="card-body text-center">
<div id="qr-preview" class="mb-3">
<div class="placeholder-qr p-5">
<i class="fas fa-qrcode fa-4x text-muted mb-3"></i>
<p class="text-muted">@Localizer["YourQRCodeWillAppear"]</p>
<small class="text-muted">
<i class="fas fa-bolt"></i> @Localizer["UltraFastGenerationGuaranteed"]
</small>
</div>
</div>
<div id="download-section" style="display: none;">
<div class="btn-group-vertical w-100 mb-3">
<button id="download-png" class="btn btn-success">
<i class="fas fa-download"></i> @Localizer["DownloadPNG"]
</button>
<button id="download-svg" class="btn btn-outline-success">
<i class="fas fa-vector-square"></i> @Localizer["DownloadSVGVector"]
</button>
<button id="download-pdf" class="btn btn-outline-success">
<i class="fas fa-file-pdf"></i> @Localizer["DownloadPDF"]
</button>
</div>
<!-- Share Button with Dropdown (Temporarily Disabled) -->
<div class="dropdown w-100 mb-3">
<button class="btn btn-secondary dropdown-toggle w-100" type="button" id="share-qr-btn" disabled title="Em desenvolvimento">
<i class="fas fa-share-alt"></i> @Localizer["ShareQRCode"] (Em breve)
</button>
<ul class="dropdown-menu w-100" aria-labelledby="share-qr-btn" id="share-dropdown">
<!-- Native share option (mobile only) -->
<li class="d-none" id="native-share-option">
<a class="dropdown-item" href="#" id="native-share">
<i class="fas fa-mobile-alt text-primary"></i> @Localizer["ShareSystem"]
</a>
</li>
<!-- WhatsApp -->
<li>
<a class="dropdown-item" href="#" id="share-whatsapp">
<i class="fab fa-whatsapp text-success"></i> WhatsApp
</a>
</li>
<!-- Telegram -->
<li>
<a class="dropdown-item" href="#" id="share-telegram">
<i class="fab fa-telegram text-info"></i> Telegram
</a>
</li>
<!-- Email -->
<li>
<a class="dropdown-item" href="#" id="share-email">
<i class="fas fa-envelope text-warning"></i> Email
</a>
</li>
<!-- Copy to clipboard -->
<li>
<a class="dropdown-item" href="#" id="copy-qr-link">
<i class="fas fa-copy text-secondary"></i> Copiar Link
</a>
</li>
<!-- Save to gallery (mobile only) -->
<li class="d-none" id="save-gallery-option">
<a class="dropdown-item" href="#" id="save-to-gallery">
<i class="fas fa-images text-purple"></i> Salvar na Galeria
</a>
</li>
</ul>
</div>
@if (User.Identity.IsAuthenticated)
{
<button id="save-to-history" class="btn btn-outline-primary w-100">
<i class="fas fa-save"></i> @Localizer["SaveToHistory"]
</button>
}
else
{
<div class="text-center">
<small class="text-muted">
<a href="/Account/Login" class="text-primary">@Localizer["Login"]</a>
@Localizer["ToSaveToHistory"]
</small>
</div>
}
</div>
</div>
</div>
<!-- Tutorials Card -->
@{
var tutorialCulture = System.Globalization.CultureInfo.CurrentUICulture.Name;
}
<div class="card border-primary mb-4">
<div class="card-header bg-primary text-white">
<h6 class="mb-0">
<i class="fas fa-book-open"></i> @Localizer["LearnMore"]
</h6>
</div>
<div class="card-body">
<p class="small mb-2">@Localizer["CompleteGuidesAboutQRCodes"]</p>
<ul class="list-unstyled small mb-3">
<li class="mb-1"><i class="fas fa-check text-primary"></i> WhatsApp Business</li>
<li class="mb-1"><i class="fas fa-check text-primary"></i> @Localizer["WiFi"] Networks</li>
<li class="mb-1"><i class="fas fa-check text-primary"></i> @Localizer["VCard"]</li>
<li class="mb-1"><i class="fas fa-check text-primary"></i> @Localizer["RealEstateAndBrokers"]</li>
</ul>
<a href="/@tutorialCulture/tutoriais" class="btn btn-primary btn-sm w-100">
<i class="fas fa-graduation-cap"></i> @Localizer["ViewAllTutorials"]
</a>
</div>
</div>
<!-- Speed Tips Card -->
<div class="card bg-light mb-4">
<div class="card-header">
<h6 class="mb-0">
<i class="fas fa-lightbulb text-warning"></i> @Localizer["TipsFasterQR"]
</h6>
</div>
<div class="card-body">
<ul class="list-unstyled small">
<li><i class="fas fa-arrow-right text-primary"></i> @Localizer["ShortURLsFaster"]</li>
<li><i class="fas fa-arrow-right text-primary"></i> @Localizer["LessTextMoreSpeed"]</li>
<li><i class="fas fa-arrow-right text-primary"></i> @Localizer["SolidColorsOptimize"]</li>
<li><i class="fas fa-arrow-right text-primary"></i> @Localizer["SmallerSizesAccelerate"]</li>
</ul>
</div>
</div>
<!-- Ad Space Sidebar (conditional) -->
@await Html.PartialAsync("_AdSpace", new { position = "sidebar" })
</div>
</div>
</div>
<!-- Speed Comparison Section -->
<section class="mt-5 mb-4">
<div class="container">
<div class="text-center mb-4">
<h3><i class="fas fa-tachometer-alt text-primary"></i> @Localizer["WhyQRRapidoFaster"]</h3>
<p class="text-muted">@Localizer["ComparisonOtherGenerators"]</p>
</div>
<div class="row">
<div class="col-md-3">
<div class="card h-100 border-success">
<div class="card-body text-center">
<h5 class="text-success">QR Rapido</h5>
<div class="display-4 text-success fw-bold">1.2s</div>
<p class="text-muted">@Localizer["OptimizedForSpeed"]</p>
<i class="fas fa-crown text-warning"></i>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card h-100">
<div class="card-body text-center">
<h5 class="text-muted">@Localizer["CompetitorA"]</h5>
<div class="display-4 text-muted">3.5s</div>
<p class="text-muted">@Localizer["TraditionalGenerator"]</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card h-100">
<div class="card-body text-center">
<h5 class="text-muted">@Localizer["CompetitorB"]</h5>
<div class="display-4 text-muted">4.8s</div>
<p class="text-muted">@Localizer["HeavyInterface"]</p>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card h-100">
<div class="card-body text-center">
<h5 class="text-muted">@Localizer["CompetitorC"]</h5>
<div class="display-4 text-muted">6.2s</div>
<p class="text-muted">@Localizer["ManyAds"]</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Ad Space Footer (conditional) -->
@await Html.PartialAsync("_AdSpace", new { position = "footer" })
@section Scripts {
<!-- Script para controles de logo aprimorados -->
<script>
// JavaScript para controles de logo aprimorados
document.addEventListener('DOMContentLoaded', function() {
const logoUpload = document.getElementById('logo-upload');
const logoSizeSlider = document.getElementById('logo-size-slider');
const logoSizeDisplay = document.getElementById('logo-size-display');
const logoColorizeToggle = document.getElementById('logo-colorize-toggle');
const logoVisualPreview = document.getElementById('logo-visual-preview');
const logoPreviewImage = document.getElementById('logo-preview-image');
const previewSizeText = document.getElementById('preview-size-text');
const previewColorizeText = document.getElementById('preview-colorize-text');
new SimpleOpacityController('#qr-type', '#quick-style-group');
// new SimpleOpacityController('#qr-type', '#content-group'); // Reverted to avoid confusion
new SimpleOpacityController('#qr-type', '#dynamic-qr-section');
new SimpleOpacityController('#qr-type', '#url-preview');
new SimpleOpacityController('#qr-type', '#vcard-interface');
new SimpleOpacityController('#qr-type', '#wifi-interface');
new SimpleOpacityController('#qr-type', '#sms-interface');
new SimpleOpacityController('#qr-type', '#email-interface');
new SimpleOpacityController('#qr-type', '#pix-interface');
// new SimpleOpacityController('#qr-type', '#navigation-buttons'); // Element Removed
new SimpleOpacityController('#qr-type', '#customization-accordion');
new SimpleOpacityController('#qr-type', '#button-gerar-div');
// Controle do slider de tamanho
logoSizeSlider?.addEventListener('input', function() {
const size = this.value;
logoSizeDisplay.textContent = size + '%';
previewSizeText.textContent = size + '%';
// Feedback visual baseado no tamanho
if (size <= 15) {
logoSizeDisplay.className = 'badge bg-info';
} else if (size <= 20) {
logoSizeDisplay.className = 'badge bg-success';
} else {
logoSizeDisplay.className = 'badge bg-warning';
}
});
// Controle do toggle de colorização
logoColorizeToggle?.addEventListener('change', function() {
previewColorizeText.textContent = this.checked ? 'Ativada' : 'Desativada';
previewColorizeText.className = this.checked ? 'text-primary' : 'text-muted';
// Simular preview da colorização (opcional)
if (logoPreviewImage.src && this.checked) {
logoPreviewImage.style.filter = 'hue-rotate(200deg) saturate(0.8)';
} else {
logoPreviewImage.style.filter = 'none';
}
});
// Melhorar o upload e preview do logo existente
logoUpload?.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
// Validações já existem no handleLogoSelection
// Mostrar preview visual
const reader = new FileReader();
reader.onload = function(e) {
logoPreviewImage.src = e.target.result;
logoVisualPreview.style.display = 'block';
};
reader.readAsDataURL(file);
} else {
logoVisualPreview.style.display = 'none';
}
});
// Website field auto-complete functionality
const websiteField = document.getElementById('vcard-website');
if (websiteField) {
// Auto-add https:// on focus if field is empty
websiteField.addEventListener('focus', function() {
if (this.value.trim() === '') {
this.value = 'https://';
// Position cursor after https://
setTimeout(() => {
this.setSelectionRange(8, 8);
}, 10);
}
});
// Validate and auto-correct on blur
websiteField.addEventListener('blur', function() {
const value = this.value.trim();
// If empty, clear the field
if (value === '' || value === 'https://') {
this.value = '';
this.classList.remove('is-invalid');
return;
}
// Check if URL has protocol
if (value && !value.match(/^https?:\/\//i)) {
// Auto-add https:// if missing
this.value = 'https://' + value;
}
// Validate URL format
try {
const url = new URL(this.value);
// Valid URL
this.classList.remove('is-invalid');
this.classList.add('is-valid');
} catch (e) {
// Invalid URL
this.classList.remove('is-valid');
this.classList.add('is-invalid');
document.getElementById('website-error').textContent = 'Por favor, insira uma URL válida (ex: https://seusite.com)';
}
});
// Real-time validation as user types
websiteField.addEventListener('input', function() {
const value = this.value.trim();
// Reset validation if empty
if (value === '' || value === 'https://') {
this.classList.remove('is-invalid', 'is-valid');
return;
}
// Check if it looks like a valid URL structure
if (value.match(/^https?:\/\/.+\..+/i)) {
try {
new URL(value);
this.classList.remove('is-invalid');
this.classList.add('is-valid');
} catch (e) {
this.classList.remove('is-valid');
this.classList.add('is-invalid');
}
}
});
}
// Auto-select QR Type from Server Route (SEO)
const serverSelectedType = '@(ViewBag.SelectedQRType ?? "")';
if (serverSelectedType) {
const qrTypeSelect = document.getElementById('qr-type');
if (qrTypeSelect) {
// Find option with this value (case-insensitive)
const option = Array.from(qrTypeSelect.options).find(opt =>
opt.value.toLowerCase() === serverSelectedType.toLowerCase()
);
if (option) {
qrTypeSelect.value = option.value;
// Trigger change event to load correct interface
qrTypeSelect.dispatchEvent(new Event('change'));
}
}
}
});
</script>
}
<style>
/* Toast positioning improvements */
#toast-container {
max-width: 350px;
}
/* Responsive toast positioning */
@@media (max-width: 768px) {
#toast-container {
left: 50% !important;
transform: translateX(-50%);
top: 70px !important;
margin-top: 0 !important;
padding: 0.5rem !important;
max-width: calc(100vw - 1rem);
}
}
@@media (min-width: 769px) {
#toast-container {
margin-top: 85px !important;
}
}
/* Toast style improvements */
.toast {
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
border-radius: 8px;
min-width: 300px;
}
/* Website field validation improvements */
#vcard-website.is-valid {
border-color: #28a745;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='m2.3 6.73.13-.07.44-.44a.34.34 0 0 1 .48 0l.44.44.13.07a.33.33 0 0 1 0 .59.33.33 0 0 1-.59 0l-.44-.44-.44.44a.33.33 0 0 1-.59 0 .33.33 0 0 1 0-.59z'/%3e%3c/svg%3e");
background-repeat: no-repeat;
background-position: right calc(0.375em + 0.1875rem) center;
background-size: calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
}
#vcard-website.is-invalid {
border-color: #dc3545;
}
/* Smooth transitions for validation states */
#vcard-website {
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
</style>