Update dashboard
This commit is contained in:
@@ -31,6 +31,13 @@ app.config['TEMPLATES_AUTO_RELOAD'] = os.environ.get('TEMPLATES_AUTO_RELOAD')
|
||||
# Initialize database
|
||||
db = SQLAlchemy(app)
|
||||
|
||||
@app.context_processor
|
||||
def inject_company_name():
|
||||
"""Make COMPANY_NAME available to all templates"""
|
||||
return {
|
||||
'COMPANY_NAME': os.environ.get('COMPANY_NAME', 'QR Code Management System')
|
||||
}
|
||||
|
||||
def create_performance_indexes():
|
||||
"""Create performance optimization indexes"""
|
||||
try:
|
||||
|
||||
+156
-19
@@ -4,31 +4,163 @@
|
||||
*/
|
||||
|
||||
/* Dashboard Header */
|
||||
.dashboard-header {
|
||||
.header-stats {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: var(--spacing-8);
|
||||
padding: var(--spacing-6);
|
||||
background: var(--white);
|
||||
border-radius: var(--radius-xl);
|
||||
box-shadow: var(--shadow);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1rem;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.header-stats-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
min-width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-stat-card {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid #e2e8f0;
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
transition: all 0.2s ease-in-out;
|
||||
backdrop-filter: blur(10px);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dashboard-header::before {
|
||||
.header-stat-card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
var(--primary-color),
|
||||
var(--primary-hover)
|
||||
);
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.header-stat-card.primary::before {
|
||||
background: linear-gradient(90deg, #2563eb, #1d4ed8);
|
||||
}
|
||||
|
||||
.header-stat-card.success::before {
|
||||
background: linear-gradient(90deg, #10b981, #047857);
|
||||
}
|
||||
|
||||
.header-stat-card.danger::before {
|
||||
background: linear-gradient(90deg, #ef4444, #dc2626);
|
||||
}
|
||||
|
||||
.header-stat-card.info::before {
|
||||
background: linear-gradient(90deg, #8b5cf6, #7c3aed);
|
||||
}
|
||||
|
||||
.header-stat-card:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.header-stat-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 0.375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1rem;
|
||||
color: #ffffff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header-stat-card.primary .header-stat-icon {
|
||||
background: linear-gradient(135deg, #2563eb, #1d4ed8);
|
||||
}
|
||||
|
||||
.header-stat-card.success .header-stat-icon {
|
||||
background: linear-gradient(135deg, #10b981, #047857);
|
||||
}
|
||||
|
||||
.header-stat-card.danger .header-stat-icon {
|
||||
background: linear-gradient(135deg, #ef4444, #dc2626);
|
||||
}
|
||||
|
||||
.header-stat-card.info .header-stat-icon {
|
||||
background: linear-gradient(135deg, #8b5cf6, #7c3aed);
|
||||
}
|
||||
|
||||
.header-stat-content h3 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: #0f172a;
|
||||
margin-bottom: 0.125rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.header-stat-content p {
|
||||
color: #64748b;
|
||||
font-size: 0.75rem;
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Update existing dashboard header to accommodate new layout */
|
||||
.dashboard-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
background: linear-gradient(135deg, #a0aff1 0%, #ebdef8 100%);
|
||||
border-radius: 0.75rem;
|
||||
color: white;
|
||||
margin-bottom: 2rem;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||
flex-wrap: wrap;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
/* Responsive Design for Header */
|
||||
@media (max-width: 1024px) {
|
||||
.dashboard-header {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.header-stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
min-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.dashboard-header {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.header-stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.header-stat-card {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.header-stat-content h3 {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.header-stat-content p {
|
||||
font-size: 0.6875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.welcome-section h1 {
|
||||
@@ -892,7 +1024,7 @@
|
||||
}
|
||||
|
||||
.qr-url {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
background: var(--gray-100);
|
||||
padding: var(--spacing-1) var(--spacing-2);
|
||||
border-radius: var(--radius-sm);
|
||||
@@ -927,7 +1059,8 @@
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.qr-status, .qr-project {
|
||||
.qr-status,
|
||||
.qr-project {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-1);
|
||||
@@ -1088,8 +1221,12 @@
|
||||
|
||||
/* Animations */
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
|
||||
+6
-2
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{% block title %}QR Code Management System{% endblock %}</title>
|
||||
<title>{% block title %}{{ COMPANY_NAME }}{% endblock %}</title>
|
||||
|
||||
<!-- Main CSS -->
|
||||
<link
|
||||
@@ -87,7 +87,11 @@
|
||||
</script>
|
||||
{% if turnstile_enabled %}
|
||||
<!-- Cloudflare Turnstile -->
|
||||
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
|
||||
<script
|
||||
src="https://challenges.cloudflare.com/turnstile/v0/api.js"
|
||||
async
|
||||
defer
|
||||
></script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{% block title %}QR Code Management System{% endblock %}</title>
|
||||
<title>{% block title %}{{ COMPANY_NAME }}{% endblock %}</title>
|
||||
|
||||
<!-- Main CSS -->
|
||||
<link
|
||||
@@ -55,8 +55,10 @@
|
||||
</a>
|
||||
|
||||
{% if session.role == 'admin' %}
|
||||
<a href="{{ url_for('projects') }}"
|
||||
class="menu-item {% if request.endpoint in ['projects', 'create_project', 'edit_project'] %}active{% endif %}">
|
||||
<a
|
||||
href="{{ url_for('projects') }}"
|
||||
class="menu-item {% if request.endpoint in ['projects', 'create_project', 'edit_project'] %}active{% endif %}"
|
||||
>
|
||||
<i class="fas fa-folder"></i>
|
||||
<span class="menu-text">Projects</span>
|
||||
</a>
|
||||
@@ -65,8 +67,8 @@
|
||||
<span class="menu-text">Users</span>
|
||||
</a>
|
||||
<a href="{{ url_for('employees') }}" class="menu-item">
|
||||
<i class="fas fa-user"></i>
|
||||
<span class="menu-text">Employees</span>
|
||||
<i class="fas fa-user"></i>
|
||||
<span class="menu-text">Employees</span>
|
||||
</a>
|
||||
<a href="{{ url_for('attendance_report') }}" class="menu-item">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
@@ -76,12 +78,17 @@
|
||||
<i class="fas fa-calculator"></i>
|
||||
<span class="menu-text">Payroll</span>
|
||||
</a>
|
||||
<a href="{{ url_for('qr_statistics') }}" class="menu-item {% if request.endpoint == 'qr_statistics' %}active{% endif %}">
|
||||
<a
|
||||
href="{{ url_for('qr_statistics') }}"
|
||||
class="menu-item {% if request.endpoint == 'qr_statistics' %}active{% endif %}"
|
||||
>
|
||||
<i class="fas fa-chart-pie"></i>
|
||||
<span class="menu-text">Statistics</span>
|
||||
</a>
|
||||
<a href="{{ url_for('admin_logs') }}"
|
||||
class="menu-item {% if request.endpoint == 'admin_logs' %}active{% endif %}">
|
||||
<a
|
||||
href="{{ url_for('admin_logs') }}"
|
||||
class="menu-item {% if request.endpoint == 'admin_logs' %}active{% endif %}"
|
||||
>
|
||||
<i class="fas fa-clipboard-list"></i>
|
||||
<span class="menu-text">System Logs</span>
|
||||
</a>
|
||||
@@ -137,7 +144,9 @@
|
||||
<span class="hamburger-line"></span>
|
||||
<span class="hamburger-line"></span>
|
||||
</button>
|
||||
<h1 class="page-title">{% block page_title %}QR Code Management System{% endblock %}</h1>
|
||||
<h1 class="page-title">
|
||||
{% block page_title %}{{ COMPANY_NAME }}{% endblock %}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="header-right">
|
||||
@@ -172,9 +181,7 @@
|
||||
{% endif %} {% endwith %}
|
||||
|
||||
<!-- Page Content -->
|
||||
<div class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
<div class="container">{% block content %}{% endblock %}</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
|
||||
+1422
-1300
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user