Files
domnitor/app/Views/layout/messages.php
Hosteroid 24e732c10a Add test notification channel feature with AJAX support
Introduces the ability to test notification channels (email, Telegram, Discord, Slack) from the group edit page, both for new and existing channels. Adds a new testChannel method to NotificationGroupController with AJAX and form support, improves validation and error handling, and updates the UI to include test buttons and dynamic toast notifications. Also registers the new /channels/test route.
2025-10-13 16:35:28 +03:00

120 lines
5.0 KiB
PHP

<!-- Toast Notifications Container -->
<div id="toast-container" class="fixed bottom-4 right-4 z-[9999] space-y-3 max-w-sm">
<!-- Success Toast -->
<?php if (isset($_SESSION['success'])): ?>
<div class="toast bg-white border-l-4 border-green-500 rounded-lg shadow-lg p-4 flex items-start animate-slide-in">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-green-100 rounded-full flex items-center justify-center">
<i class="fas fa-check text-green-600 text-sm"></i>
</div>
</div>
<div class="ml-3 flex-1">
<p class="text-sm font-medium text-gray-900">Success</p>
<p class="text-sm text-gray-600 mt-0.5"><?= htmlspecialchars($_SESSION['success']) ?></p>
</div>
<button onclick="this.parentElement.remove()" class="ml-3 flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors">
<i class="fas fa-times text-sm"></i>
</button>
</div>
<?php unset($_SESSION['success']); ?>
<?php endif; ?>
<!-- Error Toast -->
<?php if (isset($_SESSION['error'])): ?>
<div class="toast bg-white border-l-4 border-red-500 rounded-lg shadow-lg p-4 flex items-start animate-slide-in">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-red-100 rounded-full flex items-center justify-center">
<i class="fas fa-times text-red-600 text-sm"></i>
</div>
</div>
<div class="ml-3 flex-1">
<p class="text-sm font-medium text-gray-900">Error</p>
<p class="text-sm text-gray-600 mt-0.5"><?= htmlspecialchars($_SESSION['error']) ?></p>
</div>
<button onclick="this.parentElement.remove()" class="ml-3 flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors">
<i class="fas fa-times text-sm"></i>
</button>
</div>
<?php unset($_SESSION['error']); ?>
<?php endif; ?>
<!-- Warning Toast -->
<?php if (isset($_SESSION['warning'])): ?>
<div class="toast bg-white border-l-4 border-orange-500 rounded-lg shadow-lg p-4 flex items-start animate-slide-in">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-orange-100 rounded-full flex items-center justify-center">
<i class="fas fa-exclamation-triangle text-orange-600 text-sm"></i>
</div>
</div>
<div class="ml-3 flex-1">
<p class="text-sm font-medium text-gray-900">Warning</p>
<p class="text-sm text-gray-600 mt-0.5"><?= htmlspecialchars($_SESSION['warning']) ?></p>
</div>
<button onclick="this.parentElement.remove()" class="ml-3 flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors">
<i class="fas fa-times text-sm"></i>
</button>
</div>
<?php unset($_SESSION['warning']); ?>
<?php endif; ?>
<!-- Info Toast -->
<?php if (isset($_SESSION['info'])): ?>
<div class="toast bg-white border-l-4 border-blue-500 rounded-lg shadow-lg p-4 flex items-start animate-slide-in">
<div class="flex-shrink-0">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center">
<i class="fas fa-info text-blue-600 text-sm"></i>
</div>
</div>
<div class="ml-3 flex-1">
<p class="text-sm font-medium text-gray-900">Info</p>
<p class="text-sm text-gray-600 mt-0.5"><?= htmlspecialchars($_SESSION['info']) ?></p>
</div>
<button onclick="this.parentElement.remove()" class="ml-3 flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors">
<i class="fas fa-times text-sm"></i>
</button>
</div>
<?php unset($_SESSION['info']); ?>
<?php endif; ?>
</div>
<!-- Toast Auto-Dismiss Script -->
<script>
// Auto-dismiss toasts after 5 seconds
document.addEventListener('DOMContentLoaded', function() {
const toasts = document.querySelectorAll('.toast');
toasts.forEach(toast => {
// Add fade-out animation after 5 seconds
setTimeout(() => {
toast.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out';
toast.style.opacity = '0';
toast.style.transform = 'translateX(100%)';
// Remove from DOM after animation
setTimeout(() => {
toast.remove();
}, 300);
}, 5000);
});
});
</script>
<style>
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.animate-slide-in {
animation: slideIn 0.3s ease-out;
}
</style>