fix: ajustes de toast e msg de erro
This commit is contained in:
parent
83e46a5782
commit
3e84e8d7a6
@ -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}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
const toastElement = document.createElement('div');
|
||||
toastElement.innerHTML = `
|
||||
<div class="toast align-items-center text-white bg-${type === 'success' ? 'success' : 'danger'} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">${message}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(toast);
|
||||
toastContainer.appendChild(toastElement);
|
||||
const toast = new bootstrap.Toast(toastElement.querySelector('.toast'), { delay: 5000 });
|
||||
toast.show();
|
||||
|
||||
// Auto remove after 5 seconds
|
||||
setTimeout(() => {
|
||||
if (toast.parentNode) {
|
||||
toast.remove();
|
||||
}
|
||||
}, 5000);
|
||||
// Remove toast element after it's hidden
|
||||
toastElement.querySelector('.toast').addEventListener('hidden.bs.toast', function() {
|
||||
toastElement.remove();
|
||||
});
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
|
||||
@ -267,6 +267,10 @@
|
||||
</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>
|
||||
|
||||
@ -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');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</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>
|
||||
@ -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 = `
|
||||
<div class="toast align-items-center text-white bg-${type} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">${message}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
}
|
||||
|
||||
@ -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 = `
|
||||
<div class="toast align-items-center text-white bg-${type} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="d-flex">
|
||||
<div class="toast-body">${message}</div>
|
||||
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user