diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml
index 0406913..f06d1ca 100644
--- a/Views/Home/Index.cshtml
+++ b/Views/Home/Index.cshtml
@@ -103,7 +103,7 @@
-
diff --git a/wwwroot/js/qr-speed-generator.js b/wwwroot/js/qr-speed-generator.js
index 71fc512..a47de8c 100644
--- a/wwwroot/js/qr-speed-generator.js
+++ b/wwwroot/js/qr-speed-generator.js
@@ -106,16 +106,21 @@ class QRRapidoGenerator {
});
});
- // VCard fields validation
- const vcardFields = ['vcard-name', 'vcard-mobile', 'vcard-email'];
- vcardFields.forEach(fieldId => {
- const field = document.getElementById(fieldId);
- if (field) {
- field.addEventListener('input', () => {
- this.updateGenerateButton();
- });
+ // Add listeners to all relevant fields to update button state
+ const fieldsToWatch = [
+ 'qr-content', 'vcard-name', 'vcard-mobile', 'vcard-email',
+ 'wifi-ssid', 'wifi-password', 'sms-number', 'sms-message',
+ 'email-to', 'email-subject', 'email-body'
+ ];
+ fieldsToWatch.forEach(id => {
+ const el = document.getElementById(id);
+ if (el) {
+ el.addEventListener('input', () => this.updateGenerateButton());
}
});
+ document.querySelectorAll('input[name="wifi-security"]').forEach(radio => {
+ radio.addEventListener('change', () => this.updateGenerateButton());
+ });
// Language selector
document.querySelectorAll('[data-lang]').forEach(link => {
@@ -431,6 +436,27 @@ class QRRapidoGenerator {
this.showError('Erro na validação do VCard: ' + error.message);
return false;
}
+ } else if (qrType === 'wifi') {
+ const errors = window.wifiGenerator.validateWiFiData();
+ if (errors.length > 0) {
+ this.showError(errors.join('
'));
+ return false;
+ }
+ return true;
+ } else if (qrType === 'sms') {
+ const errors = window.smsGenerator.validateSMSData();
+ if (errors.length > 0) {
+ this.showError(errors.join('
'));
+ return false;
+ }
+ return true;
+ } else if (qrType === 'email') {
+ const errors = window.emailGenerator.validateEmailData();
+ if (errors.length > 0) {
+ this.showError(errors.join('
'));
+ return false;
+ }
+ return true;
}
// Normal validation for other types
@@ -454,6 +480,62 @@ class QRRapidoGenerator {
const quickStyle = document.querySelector('input[name="quick-style"]:checked')?.value || 'classic';
const styleSettings = this.getStyleSettings(quickStyle);
+ if (type === 'wifi') {
+ const wifiContent = window.wifiGenerator.generateWiFiString();
+ return {
+ data: {
+ type: 'text', // WiFi is treated as text in the backend
+ content: wifiContent,
+ quickStyle: quickStyle,
+ primaryColor: document.getElementById('primary-color').value || (styleSettings.primaryColor || '#000000'),
+ backgroundColor: document.getElementById('bg-color').value || (styleSettings.backgroundColor || '#FFFFFF'),
+ size: parseInt(document.getElementById('qr-size').value),
+ margin: parseInt(document.getElementById('qr-margin').value),
+ cornerStyle: document.getElementById('corner-style')?.value || 'square',
+ optimizeForSpeed: true,
+ language: this.currentLang
+ },
+ isMultipart: false,
+ endpoint: '/api/QR/GenerateRapid'
+ };
+ } else if (type === 'sms') {
+ const smsContent = window.smsGenerator.generateSMSString();
+ return {
+ data: {
+ type: 'text',
+ content: smsContent,
+ quickStyle: quickStyle,
+ primaryColor: document.getElementById('primary-color').value || (styleSettings.primaryColor || '#000000'),
+ backgroundColor: document.getElementById('bg-color').value || (styleSettings.backgroundColor || '#FFFFFF'),
+ size: parseInt(document.getElementById('qr-size').value),
+ margin: parseInt(document.getElementById('qr-margin').value),
+ cornerStyle: document.getElementById('corner-style')?.value || 'square',
+ optimizeForSpeed: true,
+ language: this.currentLang
+ },
+ isMultipart: false,
+ endpoint: '/api/QR/GenerateRapid'
+ };
+ } else if (type === 'email') {
+ const emailContent = window.emailGenerator.generateEmailString();
+ return {
+ data: {
+ type: 'text',
+ content: emailContent,
+ quickStyle: quickStyle,
+ primaryColor: document.getElementById('primary-color').value || (styleSettings.primaryColor || '#000000'),
+ backgroundColor: document.getElementById('bg-color').value || (styleSettings.backgroundColor || '#FFFFFF'),
+ size: parseInt(document.getElementById('qr-size').value),
+ margin: parseInt(document.getElementById('qr-margin').value),
+ cornerStyle: document.getElementById('corner-style')?.value || 'square',
+ optimizeForSpeed: true,
+ language: this.currentLang
+ },
+ isMultipart: false,
+ endpoint: '/api/QR/GenerateRapid'
+ };
+ }
+
// Handle VCard type
if (type === 'vcard') {
if (window.vcardGenerator) {
@@ -729,7 +811,7 @@ class QRRapidoGenerator {
'wifi': 'Nombre de red;Contraseña;Tipo de seguridad (WPA/WEP)',
'vcard': 'Nombre;Teléfono;Email;Empresa',
'sms': 'Número;Mensaje',
- 'email': 'email@ejemplo.com;Asunto;Mensaje'
+ 'email': 'email@ejemplo.com;Asunto;Mensagem'
}
};
@@ -1207,29 +1289,51 @@ class QRRapidoGenerator {
}
enableContentFields(type) {
- const qrContent = document.getElementById('qr-content');
+ const contentGroup = document.getElementById('content-group');
const vcardInterface = document.getElementById('vcard-interface');
-
+ const wifiInterface = document.getElementById('wifi-interface');
+ const smsInterface = document.getElementById('sms-interface');
+ const emailInterface = document.getElementById('email-interface');
+
+ // Hide all interfaces by default
+ if (vcardInterface) vcardInterface.style.display = 'none';
+ if (wifiInterface) wifiInterface.style.display = 'none';
+ if (smsInterface) smsInterface.style.display = 'none';
+ if (emailInterface) emailInterface.style.display = 'none';
+ if (contentGroup) contentGroup.style.display = 'block';
+
if (type === 'vcard') {
// Para vCard, ocultar textarea e mostrar interface específica
- if (qrContent) {
- qrContent.style.display = 'none';
- qrContent.removeAttribute('required');
- }
+ if (contentGroup) contentGroup.style.display = 'none';
if (vcardInterface) {
vcardInterface.style.display = 'block';
this.enableVCardFields();
}
+ } else if (type === 'wifi') {
+ // Para WiFi, ocultar textarea e mostrar interface específica
+ if (contentGroup) contentGroup.style.display = 'none';
+ if (wifiInterface) {
+ wifiInterface.style.display = 'block';
+ }
+ } else if (type === 'sms') {
+ // Para SMS, ocultar textarea e mostrar interface específica
+ if (contentGroup) contentGroup.style.display = 'none';
+ if (smsInterface) {
+ smsInterface.style.display = 'block';
+ }
+ } else if (type === 'email') {
+ // Para Email, ocultar textarea e mostrar interface específica
+ if (contentGroup) contentGroup.style.display = 'none';
+ if (emailInterface) {
+ emailInterface.style.display = 'block';
+ }
} else {
// Para outros tipos, mostrar textarea
- if (qrContent) {
- qrContent.style.display = 'block';
- qrContent.setAttribute('required', 'required');
+ if (contentGroup) contentGroup.style.display = 'block';
+ const qrContent = document.getElementById('qr-content');
+ if(qrContent) {
qrContent.disabled = false;
}
- if (vcardInterface) {
- vcardInterface.style.display = 'none';
- }
}
}
@@ -1323,30 +1427,37 @@ class QRRapidoGenerator {
updateGenerateButton() {
const generateBtn = document.getElementById('generate-btn');
if (!generateBtn) return;
-
- let shouldEnable = false;
-
- // Verificar se tem tipo selecionado
- if (this.selectedType) {
- if (this.selectedType === 'vcard') {
- // Para vCard, validar campos obrigatórios
- shouldEnable = this.validateVCardFields();
- } else {
- // Para outros tipos, validar conteúdo
- const content = document.getElementById('qr-content')?.value || '';
- shouldEnable = this.validateContent(content);
+
+ let isValid = false;
+ const type = this.selectedType;
+
+ if (type === 'url' || type === 'text') {
+ const content = document.getElementById('qr-content')?.value || '';
+ isValid = content.trim().length >= 3;
+ } else if (type === 'vcard') {
+ isValid = this.validateVCardFields();
+ } else if (type === 'wifi') {
+ const data = window.wifiGenerator.collectWiFiData();
+ isValid = data.ssid.trim() !== '';
+ if (data.security !== 'nopass' && !data.password.trim()) {
+ isValid = false;
}
+ } else if (type === 'sms') {
+ const data = window.smsGenerator.collectSMSData();
+ isValid = data.number.trim() !== '' && data.message.trim() !== '';
+ } else if (type === 'email') {
+ const data = window.emailGenerator.collectEmailData();
+ isValid = data.to.trim() !== '' && data.subject.trim() !== '';
}
-
- generateBtn.disabled = !shouldEnable;
-
- // Feedback visual
- if (shouldEnable) {
- generateBtn.classList.remove('btn-secondary');
+
+ generateBtn.disabled = !isValid;
+
+ if (isValid) {
+ generateBtn.classList.remove('btn-secondary', 'disabled');
generateBtn.classList.add('btn-primary');
} else {
generateBtn.classList.remove('btn-primary');
- generateBtn.classList.add('btn-secondary');
+ generateBtn.classList.add('btn-secondary', 'disabled');
}
}
@@ -1369,7 +1480,7 @@ class QRRapidoGenerator {
// Garantir que o conteúdo seja tratado como UTF-8
try {
// Verificar se há caracteres especiais
- const hasSpecialChars = /[^\x00-\x7F]/.test(content);
+ const hasSpecialChars = /[^ -]/.test(content);
if (hasSpecialChars) {
console.log('Caracteres especiais detectados, aplicando codificação UTF-8');
@@ -1441,6 +1552,9 @@ class QRRapidoGenerator {
document.addEventListener('DOMContentLoaded', () => {
window.qrGenerator = new QRRapidoGenerator();
window.vcardGenerator = new VCardGenerator();
+ window.wifiGenerator = new WiFiQRGenerator();
+ window.smsGenerator = new SMSQRGenerator();
+ window.emailGenerator = new EmailQRGenerator();
// Initialize AdSense if necessary
if (window.adsbygoogle && document.querySelector('.adsbygoogle')) {
@@ -1448,7 +1562,312 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
+class SMSQRGenerator {
+ constructor() {
+ this.initializeSMSInterface();
+ }
+
+ initializeSMSInterface() {
+ // Atualizar preview em tempo real
+ const fieldsToWatch = ['sms-number', 'sms-message'];
+ fieldsToWatch.forEach(fieldId => {
+ const element = document.getElementById(fieldId);
+ if (element) {
+ element.addEventListener('input', () => this.updatePreview());
+ element.addEventListener('change', () => this.updatePreview());
+ }
+ });
+
+ // Inicializar preview
+ this.updatePreview();
+ }
+
+ updatePreview() {
+ const smsString = this.generateSMSString();
+ const previewElement = document.getElementById('sms-preview-text');
+ if (previewElement) {
+ previewElement.textContent = smsString;
+ }
+ }
+
+ generateSMSString() {
+ const data = this.collectSMSData();
+
+ if (!data.number || !data.message) {
+ return 'SMSTO::';
+ }
+
+ return `SMSTO:${data.number}:${data.message}`;
+ }
+
+ collectSMSData() {
+ return {
+ number: document.getElementById('sms-number')?.value || '',
+ message: document.getElementById('sms-message')?.value || ''
+ };
+ }
+
+ validateSMSData() {
+ const data = this.collectSMSData();
+ const errors = [];
+
+ if (!data.number.trim()) {
+ errors.push('Número do celular é obrigatório');
+ }
+
+ if (!data.message.trim()) {
+ errors.push('Mensagem é obrigatória');
+ }
+
+ // Validação de telefone brasileiro básica
+ const phoneRegex = /^\d{10,11}$/;
+ if (data.number && !phoneRegex.test(data.number.replace(/\D/g, ''))) {
+ errors.push('Número deve ter 10 ou 11 dígitos (DDD + número)');
+ }
+
+ return errors;
+ }
+}
+
+class EmailQRGenerator {
+ constructor() {
+ this.initializeEmailInterface();
+ }
+
+ initializeEmailInterface() {
+ // Atualizar preview em tempo real
+ const fieldsToWatch = ['email-to', 'email-subject', 'email-body'];
+ fieldsToWatch.forEach(fieldId => {
+ const element = document.getElementById(fieldId);
+ if (element) {
+ element.addEventListener('input', () => this.updatePreview());
+ element.addEventListener('change', () => this.updatePreview());
+ }
+ });
+
+ // Inicializar preview
+ this.updatePreview();
+ }
+
+ updatePreview() {
+ const emailString = this.generateEmailString();
+ const previewElement = document.getElementById('email-preview-text');
+ if (previewElement) {
+ previewElement.textContent = emailString;
+ }
+ }
+
+ generateEmailString() {
+ const data = this.collectEmailData();
+
+ if (!data.to) {
+ return 'mailto:?subject=&body=';
+ }
+
+ let emailString = `mailto:${data.to}`;
+ const params = [];
+
+ if (data.subject) {
+ params.push(`subject=${encodeURIComponent(data.subject)}`);
+ }
+
+ if (data.body) {
+ params.push(`body=${encodeURIComponent(data.body)}`);
+ }
+
+ if (params.length > 0) {
+ emailString += '?' + params.join('&');
+ }
+
+ return emailString;
+ }
+
+ collectEmailData() {
+ return {
+ to: document.getElementById('email-to')?.value || '',
+ subject: document.getElementById('email-subject')?.value || '',
+ body: document.getElementById('email-body')?.value || ''
+ };
+ }
+
+ validateEmailData() {
+ const data = this.collectEmailData();
+ const errors = [];
+
+ if (!data.to.trim()) {
+ errors.push('Email destinatário é obrigatório');
+ }
+
+ if (!data.subject.trim()) {
+ errors.push('Assunto é obrigatório');
+ }
+
+ // Validação básica de email
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (data.to && !emailRegex.test(data.to)) {
+ errors.push('Email destinatário inválido');
+ }
+
+ return errors;
+ }
+}
+
+class WiFiQRGenerator {
+ constructor() {
+ this.initializeWiFiInterface();
+ }
+
+ initializeWiFiInterface() {
+ // Radio buttons: usar name para group
+ document.querySelectorAll('input[name="wifi-security"]').forEach(radio => {
+ radio.addEventListener('change', () => {
+ this.togglePasswordField();
+ this.updatePreview();
+ });
+ });
+
+ // Campos individuais: usar IDs únicos
+ const fieldsToWatch = ['wifi-ssid', 'wifi-password', 'wifi-hidden'];
+ fieldsToWatch.forEach(fieldId => {
+ const element = document.getElementById(fieldId);
+ if (element) {
+ element.addEventListener('input', () => this.updatePreview());
+ element.addEventListener('change', () => this.updatePreview());
+ }
+ });
+
+ const togglePassword = document.getElementById('toggle-password');
+ if (togglePassword) {
+ togglePassword.addEventListener('click', () => {
+ this.togglePasswordVisibility();
+ });
+ }
+
+ // Inicializar estado
+ this.togglePasswordField();
+ this.updatePreview();
+ }
+
+ togglePasswordField() {
+ const selectedRadio = document.querySelector('input[name="wifi-security"]:checked');
+ const securityType = selectedRadio ? selectedRadio.value : 'WPA';
+
+ const passwordGroup = document.getElementById('wifi-password-group');
+ const passwordInput = document.getElementById('wifi-password');
+
+ if (securityType === 'nopass') {
+ passwordGroup.style.display = 'none';
+ passwordInput.removeAttribute('required');
+ passwordInput.value = '';
+ } else {
+ passwordGroup.style.display = 'block';
+ passwordInput.setAttribute('required', 'required');
+ }
+ }
+
+ togglePasswordVisibility() {
+ const passwordInput = document.getElementById('wifi-password');
+ const toggleIcon = document.getElementById('toggle-password');
+
+ if (passwordInput.type === 'password') {
+ passwordInput.type = 'text';
+ toggleIcon.className = 'fas fa-eye-slash';
+ } else {
+ passwordInput.type = 'password';
+ toggleIcon.className = 'fas fa-eye';
+ }
+ }
+
+ updatePreview() {
+ const wifiString = this.generateWiFiString();
+ const previewText = document.getElementById('wifi-preview-text');
+ if(previewText) {
+ previewText.textContent = wifiString;
+ }
+ }
+
+ generateWiFiString() {
+ const data = this.collectWiFiData();
+
+ // Validar dados mínimos
+ if (!data.ssid) {
+ return 'WIFI:T:WPA;S:;P:;H:false;;';
+ }
+
+ // Escapar caracteres especiais
+ const ssid = this.escapeWiFiString(data.ssid);
+ const password = this.escapeWiFiString(data.password);
+
+ // Construir string WiFi
+ return `WIFI:T:${data.security};S:${ssid};P:${password};H:${data.hidden};;`;
+ }
+
+ collectWiFiData() {
+ return {
+ ssid: document.getElementById('wifi-ssid').value,
+ security: document.querySelector('input[name="wifi-security"]:checked')?.value || 'WPA',
+ password: document.getElementById('wifi-password').value,
+ hidden: document.getElementById('wifi-hidden').checked.toString()
+ };
+ }
+
+ escapeWiFiString(str) {
+ if (!str) return '';
+ // Escapar caracteres especiais do formato WiFi
+ return str.replace(/[\\;,:"]/g, '\\escapeWiFiString(str) { if (!str) return; }');
+
+ // Escapar caracteres especiais do formato WiFi
+ //return str.replace(/[\\;,:""]/g, '\\document.addEventListener('DOMContentLoaded', () => {
+ // window.qrGenerator = new QRRapidoGenerator();
+ // window.vcardGenerator = new VCardGenerator();
+
+ // // Initialize AdSense if necessary
+ // if (window.adsbygoogle && document.querySelector('.adsbygoogle')) {
+ // (adsbygoogle = window.adsbygoogle || []).push({});
+ // }
+ //});
+ return str.replace(/[\\;,:"']/g, '\\$&');
+
+ // VCard Generator Class');
+ }
+
+ validateWiFiData() {
+ const data = this.collectWiFiData();
+ const errors = [];
+
+ // Validações obrigatórias
+ if (!data.ssid.trim()) {
+ errors.push('Nome da rede (SSID) é obrigatório');
+ }
+
+ // Validação de senha conforme tipo de segurança
+ if ((data.security === 'WPA' || data.security === 'WEP') && !data.password.trim()) {
+ errors.push('Senha é obrigatória para redes protegidas');
+ }
+
+ // Validação de comprimento
+ if (data.ssid.length > 32) {
+ errors.push('Nome da rede deve ter no máximo 32 caracteres');
+ }
+
+ if (data.password.length > 63) {
+ errors.push('Senha deve ter no máximo 63 caracteres');
+ }
+
+ // Validação WEP específica
+ if (data.security === 'WEP' && data.password) {
+ const validWEPLengths = [5, 10, 13, 26]; // WEP 64/128 bit
+ if (!validWEPLengths.includes(data.password.length)) {
+ errors.push('Senha WEP deve ter 5, 10, 13 ou 26 caracteres');
+ }
+ }
+
+ return errors;
+ }
+}
+
// VCard Generator Class
+
class VCardGenerator {
constructor() {
this.initializeVCardInterface();
@@ -1458,7 +1877,7 @@ class VCardGenerator {
encodeQuotedPrintable(text) {
if (!text) return '';
- return text.replace(/[^\x20-\x7E]/g, (char) => {
+ return text.replace(/[^\u0020-\u007E]/g, (char) => {
// Para caracteres especiais comuns do português, usar codificação UTF-8
const utf8Bytes = new TextEncoder().encode(char);
return Array.from(utf8Bytes)
@@ -1475,7 +1894,7 @@ class VCardGenerator {
if (!needsEncoding) return trimmedText;
// Verifica se há caracteres especiais que precisam de codificação
- const hasSpecialChars = /[^\x20-\x7E]/.test(trimmedText);
+ const hasSpecialChars = /[^\u0020-\u007E]/.test(trimmedText);
if (hasSpecialChars) {
return `CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:${this.encodeQuotedPrintable(trimmedText)}`;
@@ -1674,7 +2093,7 @@ class VCardGenerator {
}
isValidEmail(email) {
- return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
+ return /^[^ @]+@[^ @]+\.[^ @]+$/.test(email);
}
isValidURL(url) {
@@ -1717,4 +2136,22 @@ window.QRApp = {
ad.style.display = 'none';
});
}
+};
+
+// Google Analytics 4 Event Tracking
+window.trackLanguageChange = function(from, to) {
+ if (typeof gtag !== 'undefined') {
+ gtag('event', 'language_change', {
+ 'from_language': from,
+ 'to_language': to
+ });
+ }
+};
+
+window.trackUpgradeClick = function(location) {
+ if (typeof gtag !== 'undefined') {
+ gtag('event', 'upgrade_click', {
+ 'click_location': location
+ });
+ }
};
\ No newline at end of file