diff --git a/Views/Account/History.cshtml b/Views/Account/History.cshtml
index 3a3d034..68d419e 100644
--- a/Views/Account/History.cshtml
+++ b/Views/Account/History.cshtml
@@ -172,7 +172,7 @@ function regenerateQR(qrId) {
})
.catch(error => {
console.error('Error regenerating QR:', error);
- alert('@Localizer["ErrorRegeneratingQR"]');
+ showToast('@Localizer["ErrorRegeneratingQR"]', 'danger');
});
}
@@ -236,23 +236,36 @@ function deleteQR(qrId) {
}
function showToast(message, type = 'info') {
+ // Create toast container if doesn't exist
+ let toastContainer = document.getElementById('toast-container');
+ if (!toastContainer) {
+ toastContainer = document.createElement('div');
+ toastContainer.id = 'toast-container';
+ toastContainer.className = 'toast-container position-fixed top-0 start-0 p-3';
+ toastContainer.style.zIndex = '1060';
+ toastContainer.style.marginTop = '80px';
+ document.body.appendChild(toastContainer);
+ }
+
// Create toast element
- const toast = document.createElement('div');
- toast.className = `alert alert-${type === 'success' ? 'success' : 'danger'} alert-dismissible fade show position-fixed`;
- toast.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
- toast.innerHTML = `
- ${message}
-
+ const toastElement = document.createElement('div');
+ toastElement.innerHTML = `
+
`;
-
- document.body.appendChild(toast);
-
- // Auto remove after 5 seconds
- setTimeout(() => {
- if (toast.parentNode) {
- toast.remove();
- }
- }, 5000);
+
+ toastContainer.appendChild(toastElement);
+ const toast = new bootstrap.Toast(toastElement.querySelector('.toast'), { delay: 5000 });
+ toast.show();
+
+ // Remove toast element after it's hidden
+ toastElement.querySelector('.toast').addEventListener('hidden.bs.toast', function() {
+ toastElement.remove();
+ });
}
// Event listeners
diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml
index 9c3c559..3639918 100644
--- a/Views/Home/Index.cshtml
+++ b/Views/Home/Index.cshtml
@@ -267,6 +267,10 @@
@@ -1337,5 +1341,124 @@ document.addEventListener('DOMContentLoaded', function() {
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');
+ }
+ }
+ });
+ }
});
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/Views/Pagamento/SelecaoPlano.cshtml b/Views/Pagamento/SelecaoPlano.cshtml
index 850f0f4..1df6c69 100644
--- a/Views/Pagamento/SelecaoPlano.cshtml
+++ b/Views/Pagamento/SelecaoPlano.cshtml
@@ -101,17 +101,52 @@
if (result.success) {
window.location.href = result.url;
} else {
- alert('@Localizer["Error"] ' + result.error);
+ showToast('@Localizer["Error"] ' + result.error, 'danger');
this.disabled = false;
this.innerHTML = '@Localizer["SubscribeNow"]'; // Reset button text
}
} catch (error) {
console.error('Checkout error:', error);
- alert('@Localizer["PaymentInitializationError"]');
+ showToast('@Localizer["PaymentInitializationError"]', 'danger');
this.disabled = false;
this.innerHTML = 'Assinar Agora'; // Reset button text
}
});
});
+
+ // Toast notification function
+ function showToast(message, type) {
+ // Create toast container if doesn't exist
+ let toastContainer = document.getElementById('toast-container');
+ if (!toastContainer) {
+ toastContainer = document.createElement('div');
+ toastContainer.id = 'toast-container';
+ toastContainer.className = 'toast-container position-fixed top-0 start-0 p-3';
+ toastContainer.style.zIndex = '1060';
+ toastContainer.style.marginTop = '80px';
+ document.body.appendChild(toastContainer);
+ }
+
+ // Create toast element
+ const toastId = 'toast-' + Date.now();
+ const toastElement = document.createElement('div');
+ toastElement.innerHTML = `
+
+ `;
+
+ toastContainer.appendChild(toastElement);
+ const toast = new bootstrap.Toast(toastElement.querySelector('.toast'), { delay: 5000 });
+ toast.show();
+
+ // Remove toast element after it's hidden
+ toastElement.querySelector('.toast').addEventListener('hidden.bs.toast', function() {
+ toastElement.remove();
+ });
+ }
}
diff --git a/Views/Premium/Upgrade.cshtml b/Views/Premium/Upgrade.cshtml
index 10998ff..9e73637 100644
--- a/Views/Premium/Upgrade.cshtml
+++ b/Views/Premium/Upgrade.cshtml
@@ -286,11 +286,11 @@
window.location.href = result.url;
} else {
- alert('@Localizer["PaymentProcessingError"]' + result.error);
+ showToast('@Localizer["PaymentProcessingError"]' + result.error, 'danger');
}
} catch (error) {
console.error('Erro:', error);
- alert('@Localizer["PaymentErrorTryAgain"]');
+ showToast('@Localizer["PaymentErrorTryAgain"]', 'danger');
} finally {
btn.disabled = false;
spinner.classList.add('d-none');
@@ -304,5 +304,40 @@
'page_location': window.location.href
});
}
+
+ // Toast notification function
+ function showToast(message, type) {
+ // Create toast container if doesn't exist
+ let toastContainer = document.getElementById('toast-container');
+ if (!toastContainer) {
+ toastContainer = document.createElement('div');
+ toastContainer.id = 'toast-container';
+ toastContainer.className = 'toast-container position-fixed top-0 start-0 p-3';
+ toastContainer.style.zIndex = '1060';
+ toastContainer.style.marginTop = '80px';
+ document.body.appendChild(toastContainer);
+ }
+
+ // Create toast element
+ const toastId = 'toast-' + Date.now();
+ const toastElement = document.createElement('div');
+ toastElement.innerHTML = `
+
+ `;
+
+ toastContainer.appendChild(toastElement);
+ const toast = new bootstrap.Toast(toastElement.querySelector('.toast'), { delay: 5000 });
+ toast.show();
+
+ // Remove toast element after it's hidden
+ toastElement.querySelector('.toast').addEventListener('hidden.bs.toast', function() {
+ toastElement.remove();
+ });
+ }
}
\ No newline at end of file
diff --git a/wwwroot/js/qr-speed-generator.js b/wwwroot/js/qr-speed-generator.js
index 06398da..3aee81b 100644
--- a/wwwroot/js/qr-speed-generator.js
+++ b/wwwroot/js/qr-speed-generator.js
@@ -1448,8 +1448,9 @@ class QRRapidoGenerator {
if (!toastContainer) {
toastContainer = document.createElement('div');
toastContainer.id = 'toast-container';
- toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3';
+ toastContainer.className = 'toast-container position-fixed top-0 start-0 p-3';
toastContainer.style.zIndex = '1060';
+ toastContainer.style.marginTop = '80px'; // Avoid covering logo/header
document.body.appendChild(toastContainer);
}
@@ -2452,7 +2453,7 @@ class QRRapidoGenerator {
// Initialize when DOM loads
document.addEventListener('DOMContentLoaded', () => {
- window.qrGenerator = new QRRapidoGenerator();
+ window.qrGenerator = new QRRapidoGenerator();
window.vcardGenerator = new VCardGenerator();
window.wifiGenerator = new WiFiQRGenerator();
window.smsGenerator = new SMSQRGenerator();