1682 lines
103 KiB
Plaintext
1682 lines
103 KiB
Plaintext
@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">
|
||
|
||
@if (User.Identity.IsAuthenticated)
|
||
{
|
||
var isPremium = await AdService.HasValidPremiumSubscription(userId);
|
||
@if (isPremium)
|
||
{
|
||
<div class="alert alert-success border-0">
|
||
<i class="fas fa-crown text-warning"></i>
|
||
<strong>@Localizer["PremiumUserActive"]</strong>
|
||
<span class="badge bg-success">@Localizer["NoAdsHistoryUnlimitedQR"]</span>
|
||
</div>
|
||
}
|
||
}
|
||
|
||
<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>
|
||
|
||
<!-- Premium Card for non-premium users -->
|
||
@if (User.Identity.IsAuthenticated && await AdService.ShouldShowAds(userId))
|
||
{
|
||
<div class="card border-warning mb-4">
|
||
<div class="card-header bg-warning text-dark">
|
||
<h6 class="mb-0">
|
||
<i class="fas fa-rocket"></i> QR Rapido Premium
|
||
</h6>
|
||
</div>
|
||
<div class="card-body">
|
||
<div class="text-center mb-3">
|
||
<div class="badge bg-success mb-2">@Localizer["ThreeTimesFaster"]</div>
|
||
</div>
|
||
<ul class="list-unstyled">
|
||
<li><i class="fas fa-check text-success"></i> @Localizer["NoAdsForever"]</li>
|
||
<li><i class="fas fa-check text-success"></i> @Localizer["UnlimitedQRCodes"]</li>
|
||
<li><i class="fas fa-check text-success"></i> @Localizer["AdvancedCustomization"]</li>
|
||
<li><i class="fas fa-shapes text-success"></i> @Localizer["ThreeQRStyles"]</li>
|
||
<li><i class="fas fa-check text-success"></i> @Localizer["LogoSupport"]</li>
|
||
<li><i class="fas fa-check text-success"></i> @Localizer["HistoryAndDownloads"]</li>
|
||
<li><i class="fas fa-chart-line text-success"></i> @Localizer["QRReadCounter"]</li>
|
||
<li><i class="fas fa-check text-success"></i> @Localizer["PrioritySupport"]</li>
|
||
</ul>
|
||
<div class="text-center">
|
||
<a href="/Pagamento/SelecaoPlano" class="btn btn-warning w-100">
|
||
<i class="fas fa-bolt"></i> @Localizer["AcceleratePrice"]
|
||
</a>
|
||
<small class="text-muted d-block mt-1">@Localizer["CancelAnytime"]</small>
|
||
</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>
|