This commit is contained in:
Felix Baumann
2026-06-28 12:14:59 +00:00
parent 148efd919d
commit 09e198b3ef
6 changed files with 57 additions and 50 deletions
+36 -36
View File
@@ -12,20 +12,20 @@ Willkommen {{ user.username }}
{# Navigation #}
<div class="grid grid-cols-2 md:grid-cols-4 gap-2 mb-6">
<a href="{% url 'invoices:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200">
<p class="text-[11px] text-slate-400 mb-0.5">Modul</p>
<a href="{% url 'invoices:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 company-border hover:shadow-sm transition-all duration-200">
<p class="text-sm text-slate-400 mb-0.5">Modul</p>
<p class="text-sm font-semibold text-slate-800 dark:text-white">Rechnungswesen</p>
</a>
<a href="{% url 'inventory_global:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200">
<p class="text-[11px] text-slate-400 mb-0.5">Modul</p>
<a href="{% url 'inventory_global:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 company-border hover:shadow-sm transition-all duration-200">
<p class="text-sm text-slate-400 mb-0.5">Modul</p>
<p class="text-sm font-semibold text-slate-800 dark:text-white">Inventar</p>
</a>
<a href="{% url 'accounts:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200">
<p class="text-[11px] text-slate-400 mb-0.5">Modul</p>
<a href="{% url 'accounts:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 company-border hover:shadow-sm transition-all duration-200">
<p class="text-sm text-slate-400 mb-0.5">Modul</p>
<p class="text-sm font-semibold text-slate-800 dark:text-white">Mitarbeiter</p>
</a>
<a href="{% url 'masterdata:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200">
<p class="text-[11px] text-slate-400 mb-0.5">Modul</p>
<a href="{% url 'masterdata:overview' %}" class="group p-4 rounded-xl bg-white dark:bg-slate-800 company-border hover:shadow-sm transition-all duration-200">
<p class="text-sm text-slate-400 mb-0.5">Modul</p>
<p class="text-sm font-semibold text-slate-800 dark:text-white">Einstellungen</p>
</a>
</div>
@@ -34,8 +34,8 @@ Willkommen {{ user.username }}
<div class="bg-white dark:bg-slate-800 rounded-2xl border border-slate-100 dark:border-slate-700 overflow-hidden mb-6">
{# KPIs #}
<div class="px-5 pt-5 pb-4 border-b border-slate-100 dark:border-slate-700">
<p class="text-[11px] font-semibold uppercase tracking-widest text-slate-400 mb-3">Handlungsbedarf</p>
<div class="p-4 border-b border-slate-100 dark:border-slate-700">
<p class="text-sm font-semibold uppercase tracking-widest text-slate-400 mb-3">Handlungsbedarf</p>
<div class="grid grid-cols-2 md:grid-cols-4 gap-2" id="kpiMetrics">
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 animate-pulse h-16"></div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 animate-pulse h-16"></div>
@@ -45,49 +45,49 @@ Willkommen {{ user.username }}
</div>
{# Charts #}
<div class="px-5 py-4 border-b border-slate-100 dark:border-slate-700">
<p class="text-[11px] font-semibold uppercase tracking-widest text-slate-400 mb-3">Aktueller Monat</p>
<div class="p-4 border-b border-slate-100 dark:border-slate-700">
<p class="text-sm font-semibold uppercase tracking-widest text-slate-400 mb-3">Aktueller Monat</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-2">
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold text-slate-600 dark:text-slate-300">Rechnungen</p>
<a href="{% url 'invoices:invoices_invoices_overview' %}" class="text-[11px] text-[var(--company-color)] hover:underline">Alle →</a>
<p class="text-sm text-slate-400 mb-1">Rechnungen</p>
<a href="{% url 'invoices:invoices_invoices_overview' %}" class="text-sm text-[var(--company-color)] hover:underline">Alle →</a>
</div>
<div style="position:relative;height:120px;">
<canvas id="invoiceChart" role="img" aria-label="Rechnungen nach Status"></canvas>
</div>
<div id="invoiceLegend" class="flex flex-wrap gap-x-2 gap-y-1 mt-3"></div>
<div id="invoiceLegend" class="flex flex-wrap gap-4 mt-3"></div>
</div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold text-slate-600 dark:text-slate-300">Angebote</p>
<a href="{% url 'invoices:invoices_offers_overview' %}" class="text-[11px] text-[var(--company-color)] hover:underline">Alle →</a>
<p class="text-sm text-slate-400 mb-1">Angebote</p>
<a href="{% url 'invoices:invoices_offers_overview' %}" class="text-sm text-[var(--company-color)] hover:underline">Alle →</a>
</div>
<div style="position:relative;height:120px;">
<canvas id="offerChart" role="img" aria-label="Angebote nach Status"></canvas>
</div>
<div id="offerLegend" class="flex flex-wrap gap-x-2 gap-y-1 mt-3"></div>
<div id="offerLegend" class="flex flex-wrap gap-4 mt-3"></div>
</div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<div class="flex items-center justify-between mb-3">
<p class="text-xs font-semibold text-slate-600 dark:text-slate-300">Mahnungen</p>
<a href="{% url 'invoices:invoices_reminders_overview' %}" class="text-[11px] text-[var(--company-color)] hover:underline">Alle →</a>
<p class="text-sm text-slate-400 mb-1">Mahnungen</p>
<a href="{% url 'invoices:invoices_reminders_overview' %}" class="text-sm text-[var(--company-color)] hover:underline">Alle →</a>
</div>
<div style="position:relative;height:120px;">
<canvas id="reminderChart" role="img" aria-label="Mahnungen nach Status"></canvas>
</div>
<div id="reminderLegend" class="flex flex-wrap gap-x-2 gap-y-1 mt-3"></div>
<div id="reminderLegend" class="flex flex-wrap gap-4 mt-3"></div>
</div>
</div>
</div>
{# Kunden #}
<div class="px-5 py-4">
<p class="text-[11px] font-semibold uppercase tracking-widest text-slate-400 mb-3">Kunden</p>
<div class="p-4">
<p class="text-sm font-semibold uppercase tracking-widest text-slate-400 mb-3">Kunden</p>
<div class="grid grid-cols-2 md:grid-cols-4 gap-2" id="customerMetrics">
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 animate-pulse h-16"></div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 animate-pulse h-16"></div>
@@ -124,7 +124,7 @@ function buildDonut(canvasId, legendId, data) {
const entries = Object.entries(data).filter(([, v]) => v > 0);
if (!entries.length) {
document.getElementById(canvasId).parentElement.innerHTML =
'<p class="text-[11px] text-slate-400 text-center py-8">Keine Einträge diesen Monat</p>';
'<p class="text-sm text-slate-400 text-center py-8">Keine Einträge diesen Monat</p>';
return;
}
const keys = entries.map(([k]) => k);
@@ -162,7 +162,7 @@ function buildDonut(canvasId, legendId, data) {
const legend = document.getElementById(legendId);
keys.forEach((k, i) => {
const item = document.createElement('span');
item.className = 'flex items-center gap-1 text-[11px] text-slate-400 dark:text-slate-400';
item.className = 'flex items-center gap-1 text-sm text-slate-400 dark:text-slate-400';
item.innerHTML = `
<span style="width:6px;height:6px;border-radius:50%;background:${colors[i]};display:inline-block;flex-shrink:0;"></span>
${labels[i]}: <span class="font-medium text-slate-700 dark:text-slate-200">${values[i]}</span>
@@ -178,7 +178,7 @@ async function fetchAndRender(url, canvasId, legendId) {
buildDonut(canvasId, legendId, await r.json());
} catch {
document.getElementById(canvasId).parentElement.innerHTML =
'<p class="text-[11px] text-slate-400 text-center py-8">Keine Daten</p>';
'<p class="text-sm text-slate-400 text-center py-8">Keine Daten</p>';
}
}
@@ -190,28 +190,28 @@ async function fetchKpis(url) {
document.getElementById('kpiMetrics').innerHTML = `
<a href="{% url 'invoices:invoices_invoices_overview' %}?status=overdue"
class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 transition-colors block">
<p class="text-[11px] text-slate-400 mb-1">Überfällige Rechnungen</p>
<p class="text-sm text-slate-400 mb-1">Überfällige Rechnungen</p>
<p class="text-2xl font-semibold ${d.overdue_invoices > 0 ? 'text-red-500' : 'text-slate-800 dark:text-white'}">${d.overdue_invoices}</p>
</a>
<a href="{% url 'invoices:invoices_invoices_overview' %}?status=sent"
class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 transition-colors block">
<p class="text-[11px] text-slate-400 mb-1">Offene Rechnungen</p>
<p class="text-sm text-slate-400 mb-1">Offene Rechnungen</p>
<p class="text-2xl font-semibold text-slate-800 dark:text-white">${d.open_invoices}</p>
</a>
<a href="{% url 'invoices:invoices_offers_overview' %}?status=sent"
class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 transition-colors block">
<p class="text-[11px] text-slate-400 mb-1">Offene Angebote</p>
<p class="text-sm text-slate-400 mb-1">Offene Angebote</p>
<p class="text-2xl font-semibold text-slate-800 dark:text-white">${d.open_offers}</p>
</a>
<a href="{% url 'invoices:invoices_reminders_overview' %}?status=sent"
class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4 transition-colors block">
<p class="text-[11px] text-slate-400 mb-1">Offene Mahnungen</p>
<p class="text-sm text-slate-400 mb-1">Offene Mahnungen</p>
<p class="text-2xl font-semibold ${d.open_reminders > 0 ? 'text-amber-500' : 'text-slate-800 dark:text-white'}">${d.open_reminders}</p>
</a>
`;
} catch {
document.getElementById('kpiMetrics').innerHTML =
'<p class="text-[11px] text-slate-400">Keine Daten</p>';
'<p class="text-sm text-slate-400">Keine Daten</p>';
}
}
@@ -222,25 +222,25 @@ async function fetchCustomers(url) {
const d = await r.json();
document.getElementById('customerMetrics').innerHTML = `
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<p class="text-[11px] text-slate-400 mb-1">Gesamt</p>
<p class="text-sm text-slate-400 mb-1">Gesamt</p>
<p class="text-2xl font-semibold text-slate-800 dark:text-white">${d.total}</p>
</div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<p class="text-[11px] text-slate-400 mb-1">Neue diese Woche</p>
<p class="text-sm text-slate-400 mb-1">Neue diese Woche</p>
<p class="text-2xl font-semibold text-slate-800 dark:text-white">${d.new_this_week}</p>
</div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<p class="text-[11px] text-slate-400 mb-1">Privatkunden</p>
<p class="text-sm text-slate-400 mb-1">Privatkunden</p>
<p class="text-2xl font-semibold text-slate-800 dark:text-white">${d.private}</p>
</div>
<div class="rounded-xl bg-slate-100 dark:bg-slate-700 p-4">
<p class="text-[11px] text-slate-400 mb-1">Unternehmen</p>
<p class="text-sm text-slate-400 mb-1">Unternehmen</p>
<p class="text-2xl font-semibold text-slate-800 dark:text-white">${d.companies}</p>
</div>
`;
} catch {
document.getElementById('customerMetrics').innerHTML =
'<p class="text-[11px] text-slate-400">Keine Daten</p>';
'<p class="text-sm text-slate-400">Keine Daten</p>';
}
}
+6 -6
View File
@@ -18,33 +18,33 @@ Angebote, Rechnungen, Mahnungen verwalten
<!-- MODULE GRID -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<a href="{% url 'invoices:invoices_offers_overview' %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'invoices:invoices_offers_overview' %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">📄</div>
<h2 class="text-lg font-bold">Angebote</h2>
<p class="text-slate-400 text-sm mt-1">Angebote erstellen und verwalten</p>
</a>
<a href="{% url 'invoices:invoices_invoices_overview' %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'invoices:invoices_invoices_overview' %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">🧾</div>
<h2 class="text-lg font-bold">Rechnungen</h2>
<p class="text-slate-400 text-sm mt-1">Rechnungen erstellen und verwalten</p>
</a>
<a href="{% url 'invoices:invoices_reminders_overview' %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'invoices:invoices_reminders_overview' %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">⚠️</div>
<h2 class="text-lg font-bold">Mahnungen</h2>
<p class="text-slate-400 text-sm mt-1">Offene Forderungen verfolgen</p>
</a>
<a href="{% url 'invoices:customers_overview' %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'invoices:customers_overview' %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">👥</div>
<h2 class="text-lg font-bold">Kunden</h2>
<p class="text-slate-400 text-sm mt-1">Kundenstammdaten verwalten</p>
</a>
<a href="{% url 'invoices:items_overview' %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'invoices:items_overview' %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">📦</div>
<h2 class="text-lg font-bold">Posten</h2>
<p class="text-slate-400 text-sm mt-1">Leistungen und Artikel verwalten</p>
</a>
<a href="{% url 'invoices:invoices_payments_overview' %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'invoices:invoices_payments_overview' %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">🏦</div>
<h2 class="text-lg font-bold">Zahlungen</h2>
<p class="text-slate-400 text-sm mt-1">Zahlungsvorgänge verfolgen</p>
@@ -34,7 +34,7 @@ Einstellungen der App und Module bearbeiten
<a
href="{% url 'masterdata:detail' entry.model_name %}"
class="bg-slate-100 dark:bg-slate-700 rounded-xl p-6 border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200"
class="bg-slate-100 dark:bg-slate-700 rounded-xl p-6 company-border hover:shadow-sm transition-all duration-200"
>
<h2 class="text-lg font-bold">
{{ entry.name }}
+6 -6
View File
@@ -19,14 +19,14 @@ Projektübersicht und Module
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
<!-- FINANZEN -->
<a href="{% url 'finance:overview' project.id %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'finance:overview' project.id %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">💰</div>
<h2 class="text-lg font-bold">Finanzen</h2>
<p class="text-slate-400 text-sm mt-1">Einnahmen & Ausgaben</p>
</a>
<!-- KASSE -->
<a href="" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 relative p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="" class="company-border hover:shadow-sm transition-all duration-200 relative p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="absolute top-3 right-3 text-xs font-semibold px-2 py-1 rounded-full text-white" style="background-color: {{ company_settings.color }};">
In Arbeit
</div>
@@ -36,28 +36,28 @@ Projektübersicht und Module
</a>
<!-- ZEITERFASSUNG -->
<a href="{% url 'time_tracking:overview' project.id %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'time_tracking:overview' project.id %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">⏱</div>
<h2 class="text-lg font-bold">Zeiterfassung</h2>
<p class="text-slate-400 text-sm mt-1">Arbeitszeiten der Helfer</p>
</a>
<!-- DOKUMENTE -->
<a href="{% url 'documents:overview' project.id %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'documents:overview' project.id %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">📁</div>
<h2 class="text-lg font-bold">Dokumente</h2>
<p class="text-slate-400 text-sm mt-1">Dateien & Bilder</p>
</a>
<!-- LISTE -->
<a href="{% url 'inventory:overview' project.id %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'inventory:overview' project.id %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">🛒</div>
<h2 class="text-lg font-bold">Pack-/Einkaufsliste</h2>
<p class="text-slate-400 text-sm mt-1">Vorhandenen & benötigtes Material</p>
</a>
<!-- Projektinformationen -->
<a href="{% url 'projects:info' project.id %}" class="border border-slate-100 dark:border-slate-700 hover:border-[var(--company-color)]/40 hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<a href="{% url 'projects:info' project.id %}" class="company-border hover:shadow-sm transition-all duration-200 p-6 rounded-xl shadow bg-white dark:bg-slate-800 text-slate-900 dark:text-white transition-colors">
<div class="text-2xl mb-2">ℹ️</div>
<h2 class="text-lg font-bold">Projektinformationen</h2>
<p class="text-slate-400 text-sm mt-1">Standorte & Ansprechpartner</p>
+1 -1
View File
File diff suppressed because one or more lines are too long
+7
View File
@@ -22,6 +22,13 @@
opacity: 0.8;
}
.company-border {
@apply border border-slate-100 dark:border-slate-700;
}
.company-border:hover {
border-color: color-mix(in srgb, var(--company-color) 40%, transparent);
}
.btn {
@apply inline-flex items-center justify-center