bmc_hub/app/dashboard/frontend/index.html

226 lines
10 KiB
HTML

{% extends "shared/frontend/base.html" %}
{% block title %}Dashboard - BMC Hub{% endblock %}
{% block content %}
<div class="d-flex justify-content-between align-items-center mb-5">
<div>
<h2 class="fw-bold mb-1">Dashboard</h2>
<p class="text-muted mb-0">Velkommen tilbage, Christian</p>
</div>
<div class="d-flex gap-3">
<div class="input-group">
<span class="input-group-text bg-white border-end-0"><i class="bi bi-search"></i></span>
<input type="text" id="dashboardSearchInput" class="form-control border-start-0 ps-0" placeholder="Søg i alt... (⌘K)" style="max-width: 250px;" role="button">
</div>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown">
<i class="bi bi-plus-lg me-2"></i>Ny Oprettelse
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="/customers"><i class="bi bi-building me-2"></i>Ny Kunde</a></li>
<li><a class="dropdown-item" href="/contacts"><i class="bi bi-person me-2"></i>Ny Kontakt</a></li>
<li><a class="dropdown-item" href="/vendors"><i class="bi bi-shop me-2"></i>Ny Leverandør</a></li>
</ul>
</div>
</div>
</div>
<!-- 1. Live Metrics Cards -->
<div class="row g-4 mb-5">
<div class="col-md-3">
<div class="card stat-card p-4 h-100">
<div class="d-flex justify-content-between mb-2">
<p>Kunder</p>
<i class="bi bi-building text-primary" style="color: var(--accent) !important;"></i>
</div>
<h3 id="customerCount">-</h3>
<small class="text-success"><i class="bi bi-check-circle"></i> Aktive i systemet</small>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card p-4 h-100">
<div class="d-flex justify-content-between mb-2">
<p>Kontakter</p>
<i class="bi bi-people text-primary" style="color: var(--accent) !important;"></i>
</div>
<h3 id="contactCount">-</h3>
<small class="text-muted">Tilknyttede personer</small>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card p-4 h-100">
<div class="d-flex justify-content-between mb-2">
<p>Leverandører</p>
<i class="bi bi-shop text-primary" style="color: var(--accent) !important;"></i>
</div>
<h3 id="vendorCount">-</h3>
<small class="text-muted">Aktive leverandøraftaler</small>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card p-4 h-100">
<div class="d-flex justify-content-between mb-2">
<p>System Status</p>
<i class="bi bi-cpu text-primary" style="color: var(--accent) !important;"></i>
</div>
<h3 id="systemStatus" class="text-success">Online</h3>
<small class="text-muted" id="systemVersion">v1.0.0</small>
</div>
</div>
</div>
<div class="row g-4">
<!-- 2. Recent Activity (New Customers) -->
<div class="col-lg-8">
<div class="card p-4 h-100">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="fw-bold mb-0">Seneste Tilføjelser</h5>
<a href="/customers" class="btn btn-sm btn-light">Se alle</a>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead>
<tr>
<th>Navn</th>
<th>Type</th>
<th>Oprettet</th>
<th class="text-end">Handling</th>
</tr>
</thead>
<tbody id="recentActivityTable">
<tr>
<td colspan="4" class="text-center py-4">
<div class="spinner-border text-primary" role="status"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- 3. Vendor Distribution & Quick Links -->
<div class="col-lg-4">
<div class="card p-4 mb-4">
<h5 class="fw-bold mb-4">Leverandør Fordeling</h5>
<div id="vendorDistribution">
<div class="text-center py-3">
<div class="spinner-border text-primary" role="status"></div>
</div>
</div>
</div>
<!-- 4. Quick Actions / Shortcuts -->
<div class="card p-4">
<h5 class="fw-bold mb-3">Genveje</h5>
<div class="d-grid gap-2">
<a href="/settings" class="btn btn-light text-start p-3 d-flex align-items-center">
<div class="bg-white p-2 rounded me-3 shadow-sm">
<i class="bi bi-gear text-primary"></i>
</div>
<div>
<div class="fw-bold">Indstillinger</div>
<small class="text-muted">Konfigurer systemet</small>
</div>
</a>
<a href="/vendors" class="btn btn-light text-start p-3 d-flex align-items-center">
<div class="bg-white p-2 rounded me-3 shadow-sm">
<i class="bi bi-truck text-success"></i>
</div>
<div>
<div class="fw-bold">Leverandører</div>
<small class="text-muted">Administrer aftaler</small>
</div>
</a>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
async function loadDashboardStats() {
try {
const response = await fetch('/api/v1/dashboard/stats');
const data = await response.json();
// Update Counts
document.getElementById('customerCount').textContent = data.counts.customers;
document.getElementById('contactCount').textContent = data.counts.contacts;
document.getElementById('vendorCount').textContent = data.counts.vendors;
// Update Recent Activity
const activityTable = document.getElementById('recentActivityTable');
if (data.recent_activity && data.recent_activity.length > 0) {
activityTable.innerHTML = data.recent_activity.map(item => `
<tr>
<td class="fw-bold">
<div class="d-flex align-items-center">
<div class="rounded-circle bg-light d-flex align-items-center justify-content-center me-3" style="width: 32px; height: 32px;">
<i class="bi bi-building text-primary"></i>
</div>
${item.name}
</div>
</td>
<td><span class="badge bg-primary bg-opacity-10 text-primary">Kunde</span></td>
<td class="text-muted">${new Date(item.created_at).toLocaleDateString('da-DK')}</td>
<td class="text-end">
<a href="/customers/${item.id}" class="btn btn-sm btn-light"><i class="bi bi-arrow-right"></i></a>
</td>
</tr>
`).join('');
} else {
activityTable.innerHTML = '<tr><td colspan="4" class="text-center text-muted py-4">Ingen nylig aktivitet</td></tr>';
}
// Update Vendor Distribution
const vendorDist = document.getElementById('vendorDistribution');
if (data.vendor_distribution && data.vendor_distribution.length > 0) {
const total = data.counts.vendors;
vendorDist.innerHTML = data.vendor_distribution.map(cat => {
const percentage = Math.round((cat.count / total) * 100);
return `
<div class="mb-3">
<div class="d-flex justify-content-between mb-1">
<span class="small fw-bold">${cat.category || 'Ukendt'}</span>
<span class="small text-muted">${cat.count}</span>
</div>
<div class="progress" style="height: 6px;">
<div class="progress-bar" role="progressbar" style="width: ${percentage}%" aria-valuenow="${percentage}" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
`;
}).join('');
} else {
vendorDist.innerHTML = '<p class="text-muted text-center">Ingen leverandørdata</p>';
}
} catch (error) {
console.error('Error loading dashboard stats:', error);
}
}
document.addEventListener('DOMContentLoaded', loadDashboardStats);
// Connect dashboard search input to global search modal
document.getElementById('dashboardSearchInput').addEventListener('click', () => {
const modalEl = document.getElementById('globalSearchModal');
const modal = bootstrap.Modal.getOrCreateInstance(modalEl);
modal.show();
// Focus input when modal opens
modalEl.addEventListener('shown.bs.modal', () => {
document.getElementById('globalSearchInput').focus();
}, { once: true });
});
// Also handle focus (e.g. via tab navigation)
document.getElementById('dashboardSearchInput').addEventListener('focus', (e) => {
e.target.click();
e.target.blur(); // Remove focus from this input so we don't get stuck in a loop or keep cursor here
});
</script>
{% endblock %}