@@ -0,0 +1,254 @@
|
|||||||
|
/**
|
||||||
|
* Authentication page specific styles
|
||||||
|
* static/css/auth.css
|
||||||
|
*
|
||||||
|
* This file contains all authentication-related styles for login/register pages
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Authentication Container - Center the form */
|
||||||
|
.auth-container {
|
||||||
|
min-height: 100vh !important;
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)) !important;
|
||||||
|
padding: 2rem 1rem !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Authentication Card - Modern centered design */
|
||||||
|
.auth-card {
|
||||||
|
background: var(--white) !important;
|
||||||
|
border-radius: var(--radius-2xl) !important;
|
||||||
|
box-shadow: var(--shadow-xl) !important;
|
||||||
|
padding: 3rem !important;
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 420px !important;
|
||||||
|
position: relative !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-card::before {
|
||||||
|
content: "" !important;
|
||||||
|
position: absolute !important;
|
||||||
|
top: 0 !important;
|
||||||
|
left: 0 !important;
|
||||||
|
right: 0 !important;
|
||||||
|
height: 4px !important;
|
||||||
|
background: linear-gradient(90deg, var(--primary-color), var(--primary-hover)) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Authentication Header */
|
||||||
|
.auth-header {
|
||||||
|
text-align: center !important;
|
||||||
|
margin-bottom: 2.5rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-logo {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
width: 80px !important;
|
||||||
|
height: 80px !important;
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)) !important;
|
||||||
|
border-radius: 50% !important;
|
||||||
|
margin-bottom: 1.5rem !important;
|
||||||
|
box-shadow: var(--shadow-lg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-logo i {
|
||||||
|
font-size: 2.5rem !important;
|
||||||
|
color: var(--white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-header h1 {
|
||||||
|
font-size: 2.25rem !important;
|
||||||
|
font-weight: 700 !important;
|
||||||
|
color: var(--gray-900) !important;
|
||||||
|
margin-bottom: 0.5rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-header p {
|
||||||
|
color: var(--gray-500) !important;
|
||||||
|
font-size: 1.125rem !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Authentication Form */
|
||||||
|
.auth-form {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group {
|
||||||
|
margin-bottom: 2rem !important;
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group label {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
gap: 0.75rem !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
color: var(--gray-700) !important;
|
||||||
|
margin-bottom: 0.75rem !important;
|
||||||
|
font-size: 0.925rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group label i {
|
||||||
|
width: 20px !important;
|
||||||
|
text-align: center !important;
|
||||||
|
color: var(--primary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group input {
|
||||||
|
width: 100% !important;
|
||||||
|
padding: 1rem !important;
|
||||||
|
border: 2px solid var(--gray-200) !important;
|
||||||
|
border-radius: var(--radius-xl) !important;
|
||||||
|
font-size: 1rem !important;
|
||||||
|
transition: var(--transition) !important;
|
||||||
|
background-color: var(--white) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group input:focus {
|
||||||
|
outline: none !important;
|
||||||
|
border-color: var(--primary-color) !important;
|
||||||
|
box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.1) !important;
|
||||||
|
transform: translateY(-1px) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group.focused label {
|
||||||
|
color: var(--primary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button Styles */
|
||||||
|
.auth-form .btn {
|
||||||
|
display: inline-flex !important;
|
||||||
|
align-items: center !important;
|
||||||
|
justify-content: center !important;
|
||||||
|
gap: 0.75rem !important;
|
||||||
|
padding: 1rem 2rem !important;
|
||||||
|
font-size: 1rem !important;
|
||||||
|
font-weight: 600 !important;
|
||||||
|
border: none !important;
|
||||||
|
border-radius: var(--radius-xl) !important;
|
||||||
|
cursor: pointer !important;
|
||||||
|
transition: var(--transition) !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
min-height: 52px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .btn-primary {
|
||||||
|
background: linear-gradient(135deg, var(--primary-color), var(--primary-hover)) !important;
|
||||||
|
color: var(--white) !important;
|
||||||
|
box-shadow: var(--shadow) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .btn-primary:hover {
|
||||||
|
transform: translateY(-2px) !important;
|
||||||
|
box-shadow: var(--shadow-lg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .btn-primary:active {
|
||||||
|
transform: translateY(0) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .btn-full {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .btn:disabled {
|
||||||
|
opacity: 0.7 !important;
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove Auth Footer (Register Link) */
|
||||||
|
.auth-footer {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive Design */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.auth-container {
|
||||||
|
padding: 1rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-card {
|
||||||
|
padding: 2rem !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-header h1 {
|
||||||
|
font-size: 2rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-logo {
|
||||||
|
width: 70px !important;
|
||||||
|
height: 70px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-logo i {
|
||||||
|
font-size: 2rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 480px) {
|
||||||
|
.auth-card {
|
||||||
|
padding: 1.5rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-header h1 {
|
||||||
|
font-size: 1.75rem !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group {
|
||||||
|
margin-bottom: 1.5rem !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Animation */
|
||||||
|
.fa-spinner {
|
||||||
|
animation: spin 1s linear infinite !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus Accessibility */
|
||||||
|
.auth-form .btn:focus,
|
||||||
|
.auth-form .form-group input:focus {
|
||||||
|
outline: 2px solid var(--primary-color) !important;
|
||||||
|
outline-offset: 2px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* High Contrast Mode Support */
|
||||||
|
@media (prefers-contrast: high) {
|
||||||
|
.auth-card {
|
||||||
|
border: 2px solid var(--gray-900) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .form-group input {
|
||||||
|
border-width: 3px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduced Motion Support */
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
* {
|
||||||
|
animation-duration: 0.01ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
transition-duration: 0.01ms !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-form .btn-primary:hover,
|
||||||
|
.auth-form .form-group input:focus {
|
||||||
|
transform: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
+47
-14
@@ -1,5 +1,12 @@
|
|||||||
{% extends "base.html" %} {% block title %}Login - QR Code Management{% endblock
|
{% extends "base.html" %}
|
||||||
%} {% block content %}
|
{% block title %}Login - QR Code Management{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_styles %}
|
||||||
|
<!-- Include the new authentication styles -->
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/auth.css') }}">
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
<div class="auth-container">
|
<div class="auth-container">
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
<div class="auth-header">
|
<div class="auth-header">
|
||||||
@@ -33,22 +40,19 @@
|
|||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div class="auth-footer">
|
<!-- Register link removed as requested -->
|
||||||
<p>
|
|
||||||
Don't have an account?
|
|
||||||
<a href="{{ url_for('register') }}" class="auth-link">Register here</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% endblock %}
|
||||||
{% endblock %} {% block extra_scripts %}
|
|
||||||
|
{% block extra_scripts %}
|
||||||
<script>
|
<script>
|
||||||
// Add form validation and user experience improvements
|
// Enhanced form validation and user experience improvements
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
const form = document.querySelector(".auth-form");
|
const form = document.querySelector(".auth-form");
|
||||||
const inputs = form.querySelectorAll("input");
|
const inputs = form.querySelectorAll("input");
|
||||||
|
|
||||||
// Add focus effects
|
// Add focus effects with improved visual feedback
|
||||||
inputs.forEach((input) => {
|
inputs.forEach((input) => {
|
||||||
input.addEventListener("focus", function () {
|
input.addEventListener("focus", function () {
|
||||||
this.parentElement.classList.add("focused");
|
this.parentElement.classList.add("focused");
|
||||||
@@ -59,15 +63,44 @@
|
|||||||
this.parentElement.classList.remove("focused");
|
this.parentElement.classList.remove("focused");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Keep focus state if input has value
|
||||||
|
if (input.value) {
|
||||||
|
input.parentElement.classList.add("focused");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form submission with loading state
|
// Enhanced form submission with loading state
|
||||||
form.addEventListener("submit", function () {
|
form.addEventListener("submit", function () {
|
||||||
const submitBtn = form.querySelector('button[type="submit"]');
|
const submitBtn = form.querySelector('button[type="submit"]');
|
||||||
submitBtn.innerHTML =
|
const originalContent = submitBtn.innerHTML;
|
||||||
'<i class="fas fa-spinner fa-spin"></i> Signing In...';
|
|
||||||
|
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Signing In...';
|
||||||
submitBtn.disabled = true;
|
submitBtn.disabled = true;
|
||||||
|
|
||||||
|
// Re-enable button after 10 seconds as fallback
|
||||||
|
setTimeout(() => {
|
||||||
|
if (submitBtn.disabled) {
|
||||||
|
submitBtn.innerHTML = originalContent;
|
||||||
|
submitBtn.disabled = false;
|
||||||
|
}
|
||||||
|
}, 10000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add keyboard navigation enhancement
|
||||||
|
inputs.forEach((input, index) => {
|
||||||
|
input.addEventListener("keydown", function (e) {
|
||||||
|
if (e.key === "Enter" && index < inputs.length - 1) {
|
||||||
|
e.preventDefault();
|
||||||
|
inputs[index + 1].focus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Auto-focus first input
|
||||||
|
if (inputs.length > 0) {
|
||||||
|
inputs[0].focus();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user