Move notifications to base template with bubble popup

- Added global notification system to base.html with bubble popups
- Notifications auto-disappear after 6 seconds with slide-out animation
- Manual close button for immediate dismissal
- Updated login.html and register.html to extend base template
- Removed duplicate notification code from individual templates
- Notifications now appear on all pages including login/register
parent 778da463
...@@ -21,6 +21,47 @@ ...@@ -21,6 +21,47 @@
.user-dropdown a { display: block; padding: 0.75rem 1rem; text-decoration: none; color: #374151; border-bottom: 1px solid #f1f5f9; } .user-dropdown a { display: block; padding: 0.75rem 1rem; text-decoration: none; color: #374151; border-bottom: 1px solid #f1f5f9; }
.user-dropdown a:last-child { border-bottom: none; color: #dc2626; } .user-dropdown a:last-child { border-bottom: none; color: #dc2626; }
.user-dropdown a:hover { background: #f8fafc; } .user-dropdown a:hover { background: #f8fafc; }
/* Notification styles */
.notification-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 10000;
max-width: 400px;
}
.notification {
background: white;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
padding: 1rem;
margin-bottom: 0.5rem;
border-left: 4px solid;
animation: slideIn 0.3s ease-out;
opacity: 1;
transform: translateX(0);
transition: all 0.3s ease;
}
.notification.success { border-left-color: #10b981; }
.notification.error { border-left-color: #ef4444; }
.notification.info { border-left-color: #3b82f6; }
.notification.warning { border-left-color: #f59e0b; }
.notification.fade-out {
opacity: 0;
transform: translateX(100%);
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.notification-close {
float: right;
cursor: pointer;
font-weight: bold;
color: #6b7280;
margin-left: 1rem;
}
.notification-close:hover { color: #374151; }
</style> </style>
{% block head %}{% endblock %} {% block head %}{% endblock %}
</head> </head>
...@@ -58,6 +99,20 @@ ...@@ -58,6 +99,20 @@
</div> </div>
</header> </header>
<!-- Notification container -->
<div class="notification-container" id="notificationContainer">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="notification {{ category or 'info' }}" data-id="{{ loop.index }}">
<span class="notification-close" onclick="closeNotification(this)">&times;</span>
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
</div>
{% block content %}{% endblock %} {% block content %}{% endblock %}
<script> <script>
...@@ -74,6 +129,32 @@ ...@@ -74,6 +129,32 @@
dropdown.style.display = 'none'; dropdown.style.display = 'none';
} }
} }
// Notification functions
function closeNotification(element) {
const notification = element.parentElement;
notification.classList.add('fade-out');
setTimeout(() => {
notification.remove();
}, 300);
}
function autoHideNotifications() {
const notifications = document.querySelectorAll('.notification');
notifications.forEach((notification, index) => {
setTimeout(() => {
notification.classList.add('fade-out');
setTimeout(() => {
notification.remove();
}, 300);
}, 6000 + (index * 500)); // Stagger hiding by 500ms
});
}
// Auto-hide notifications after page load
document.addEventListener('DOMContentLoaded', function() {
autoHideNotifications();
});
</script> </script>
</body> </body>
</html> </html>
\ No newline at end of file
<!DOCTYPE html> {% extends "base.html" %}
<html>
<head> {% block title %}Login - VidAI{% endblock %}
<title>Login - VidAI</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> {% block head %}
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; } body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
body { font-family: 'Inter', sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
.login-container { background: white; padding: 2rem; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); width: 100%; max-width: 400px; } .login-container { background: white; padding: 2rem; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); width: 100%; max-width: 400px; }
.logo { text-align: center; font-size: 2rem; font-weight: 700; color: #667eea; margin-bottom: 2rem; } .logo { text-align: center; font-size: 2rem; font-weight: 700; color: #667eea; margin-bottom: 2rem; }
.form-group { margin-bottom: 1.5rem; } .form-group { margin-bottom: 1.5rem; }
...@@ -16,23 +15,13 @@ ...@@ -16,23 +15,13 @@
.btn:hover { background: #5a67d8; } .btn:hover { background: #5a67d8; }
.links { text-align: center; margin-top: 1.5rem; } .links { text-align: center; margin-top: 1.5rem; }
.links a { color: #667eea; text-decoration: none; margin: 0 0.5rem; } .links a { color: #667eea; text-decoration: none; margin: 0 0.5rem; }
.alert { padding: 0.75rem; border-radius: 8px; margin-bottom: 1rem; } </style>
.alert-error { background: #fee2e2; color: #dc2626; border: 1px solid #fecaca; } {% endblock %}
.alert-success { background: #d1fae5; color: #065f46; border: 1px solid #a7f3d0; }
</style> {% block content %}
</head> <div class="login-container">
<body>
<div class="login-container">
<div class="logo">VidAI</div> <div class="logo">VidAI</div>
<form method="post"> <form method="post">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'error' if category == 'error' else 'success' }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="form-group"> <div class="form-group">
<label for="username">Username</label> <label for="username">Username</label>
<input type="text" id="username" name="username" required> <input type="text" id="username" name="username" required>
...@@ -55,6 +44,5 @@ ...@@ -55,6 +44,5 @@
<a href="/register">Create Account</a> | <a href="/register">Create Account</a> |
<a href="/">Home</a> <a href="/">Home</a>
</div> </div>
</div> </div>
</body> {% endblock %}
</html> \ No newline at end of file
\ No newline at end of file
<!DOCTYPE html> {% extends "base.html" %}
<html>
<head> {% block title %}Register - VidAI{% endblock %}
<title>Register - VidAI</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> {% block head %}
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; } body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
body { font-family: 'Inter', sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; }
.register-container { background: white; padding: 2rem; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); width: 100%; max-width: 400px; } .register-container { background: white; padding: 2rem; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); width: 100%; max-width: 400px; }
.logo { text-align: center; font-size: 2rem; font-weight: 700; color: #667eea; margin-bottom: 2rem; } .logo { text-align: center; font-size: 2rem; font-weight: 700; color: #667eea; margin-bottom: 2rem; }
.form-group { margin-bottom: 1.5rem; } .form-group { margin-bottom: 1.5rem; }
...@@ -16,23 +15,13 @@ ...@@ -16,23 +15,13 @@
.btn:hover { background: #5a67d8; } .btn:hover { background: #5a67d8; }
.links { text-align: center; margin-top: 1.5rem; } .links { text-align: center; margin-top: 1.5rem; }
.links a { color: #667eea; text-decoration: none; margin: 0 0.5rem; } .links a { color: #667eea; text-decoration: none; margin: 0 0.5rem; }
.alert { padding: 0.75rem; border-radius: 8px; margin-bottom: 1rem; } </style>
.alert-error { background: #fee2e2; color: #dc2626; border: 1px solid #fecaca; } {% endblock %}
.alert-success { background: #d1fae5; color: #065f46; border: 1px solid #a7f3d0; }
</style> {% block content %}
</head> <div class="register-container">
<body>
<div class="register-container">
<div class="logo">VidAI</div> <div class="logo">VidAI</div>
<form method="post"> <form method="post">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'error' if category == 'error' else 'success' }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="form-group"> <div class="form-group">
<label for="username">Username</label> <label for="username">Username</label>
<input type="text" id="username" name="username" required> <input type="text" id="username" name="username" required>
...@@ -55,6 +44,5 @@ ...@@ -55,6 +44,5 @@
<a href="/login">Already have an account?</a> | <a href="/login">Already have an account?</a> |
<a href="/">Home</a> <a href="/">Home</a>
</div> </div>
</div> </div>
</body> {% endblock %}
</html> \ No newline at end of file
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment