Adds time reporting UI with filtering and charts

Implements comprehensive hours report tab with:
- Period and employee filtering
- Statistical overview cards
- Hours per week and absence distribution charts
- Detailed employee hours table

Enhances reports page interactivity and data visualization
This commit is contained in:
Janus C. H. Knudsen 2026-01-21 22:45:47 +01:00
parent 2f92b0eb7b
commit 0144e1ae17
4 changed files with 605 additions and 49 deletions

View file

@ -373,17 +373,126 @@
<!-- Tab Content: Timerapport -->
<swp-tab-content data-tab="hours">
<swp-page-container>
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-clock"></i>
<span>Timerapport</span>
</swp-card-title>
</swp-card-header>
<swp-empty-state>
<i class="ph ph-clock-counter-clockwise"></i>
<span>Timerapport kommer snart</span>
</swp-empty-state>
<!-- Filter Bar -->
<swp-filter-bar>
<swp-period-selector>
<button data-period="week">Uge</button>
<button data-period="month" class="active">Måned</button>
<button data-period="quarter">Kvartal</button>
<button data-period="year">År</button>
</swp-period-selector>
<swp-filter-group>
<swp-filter-label>Medarbejder</swp-filter-label>
<select id="employeeFilter">
<option value="">Alle medarbejdere</option>
<option value="anna">Anna Jensen</option>
<option value="martin">Martin Nielsen</option>
<option value="sofie">Sofie Larsen</option>
<option value="peter">Peter Hansen</option>
</select>
</swp-filter-group>
</swp-filter-bar>
<!-- Stats Bar -->
<swp-stats-row class="cols-4">
<swp-stat-card class="highlight">
<swp-stat-value>320 t</swp-stat-value>
<swp-stat-label>Planlagte timer</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="danger">
<swp-stat-value>24 t</swp-stat-value>
<swp-stat-label>Fravær total</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="warning">
<swp-stat-value>8 t</swp-stat-value>
<swp-stat-label>Overarbejde</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>7.5%</swp-stat-value>
<swp-stat-label>Fraværsprocent</swp-stat-label>
</swp-stat-card>
</swp-stats-row>
<!-- Charts Grid -->
<swp-charts-grid>
<swp-chart-card>
<swp-chart-header>
<swp-chart-title>Timer pr. uge</swp-chart-title>
<swp-chart-hint>Sidste 5 uger</swp-chart-hint>
</swp-chart-header>
<swp-chart-container id="hoursChart"></swp-chart-container>
</swp-chart-card>
<swp-chart-card>
<swp-chart-header>
<swp-chart-title>Fraværsfordeling</swp-chart-title>
<swp-chart-hint>Efter type</swp-chart-hint>
</swp-chart-header>
<swp-chart-container id="absenceChart"></swp-chart-container>
</swp-chart-card>
</swp-charts-grid>
<!-- Hours Table -->
<swp-card class="hours-table">
<swp-data-table>
<swp-data-table-header>
<swp-data-table-cell>Medarbejder</swp-data-table-cell>
<swp-data-table-cell class="right">Planlagt</swp-data-table-cell>
<swp-data-table-cell class="right">Fravær</swp-data-table-cell>
<swp-data-table-cell class="right">Syg</swp-data-table-cell>
<swp-data-table-cell class="right">Ferie</swp-data-table-cell>
<swp-data-table-cell class="right">Fri</swp-data-table-cell>
<swp-data-table-cell class="right">Overarbejde</swp-data-table-cell>
<swp-data-table-cell class="right">Fraværs-%</swp-data-table-cell>
</swp-data-table-header>
<!-- Row 1 -->
<swp-data-table-row>
<swp-data-table-cell class="name">Anna Jensen</swp-data-table-cell>
<swp-data-table-cell class="number right">80 t</swp-data-table-cell>
<swp-data-table-cell class="number right">4 t</swp-data-table-cell>
<swp-data-table-cell class="number right danger">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right warning">4 t</swp-data-table-cell>
<swp-data-table-cell class="number right purple">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right">2 t</swp-data-table-cell>
<swp-data-table-cell class="right"><swp-status-badge class="low">5.0%</swp-status-badge></swp-data-table-cell>
</swp-data-table-row>
<!-- Row 2 -->
<swp-data-table-row>
<swp-data-table-cell class="name">Martin Nielsen</swp-data-table-cell>
<swp-data-table-cell class="number right">80 t</swp-data-table-cell>
<swp-data-table-cell class="number right">8 t</swp-data-table-cell>
<swp-data-table-cell class="number right danger">8 t</swp-data-table-cell>
<swp-data-table-cell class="number right warning">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right purple">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right">0 t</swp-data-table-cell>
<swp-data-table-cell class="right"><swp-status-badge class="medium">10.0%</swp-status-badge></swp-data-table-cell>
</swp-data-table-row>
<!-- Row 3 -->
<swp-data-table-row>
<swp-data-table-cell class="name">Sofie Larsen</swp-data-table-cell>
<swp-data-table-cell class="number right">80 t</swp-data-table-cell>
<swp-data-table-cell class="number right">4 t</swp-data-table-cell>
<swp-data-table-cell class="number right danger">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right warning">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right purple">4 t</swp-data-table-cell>
<swp-data-table-cell class="number right">4 t</swp-data-table-cell>
<swp-data-table-cell class="right"><swp-status-badge class="low">5.0%</swp-status-badge></swp-data-table-cell>
</swp-data-table-row>
<!-- Row 4 -->
<swp-data-table-row>
<swp-data-table-cell class="name">Peter Hansen</swp-data-table-cell>
<swp-data-table-cell class="number right">80 t</swp-data-table-cell>
<swp-data-table-cell class="number right">8 t</swp-data-table-cell>
<swp-data-table-cell class="number right danger">4 t</swp-data-table-cell>
<swp-data-table-cell class="number right warning">4 t</swp-data-table-cell>
<swp-data-table-cell class="number right purple">0 t</swp-data-table-cell>
<swp-data-table-cell class="number right">2 t</swp-data-table-cell>
<swp-data-table-cell class="right"><swp-status-badge class="medium">10.0%</swp-status-badge></swp-data-table-cell>
</swp-data-table-row>
</swp-data-table>
<swp-table-footer>
<span>Viser 4 medarbejdere</span>
<span>Total: 320 t planlagt, 24 t fravær, 8 t overarbejde</span>
</swp-table-footer>
</swp-card>
</swp-page-container>
</swp-tab-content>
@ -436,5 +545,111 @@
tooltip: true,
legend: { position: 'right', align: 'center' }
});
// Hours per week grouped bar chart (Timerapport)
createChart(document.getElementById('hoursChart'), {
height: 240,
xAxis: { categories: ['Uge 48', 'Uge 49', 'Uge 50', 'Uge 51', 'Uge 52'] },
yAxis: { format: (v) => v + ' t' },
series: [
{
name: 'Anna Jensen',
color: '#00897b',
type: 'bar',
data: [
{ x: 'Uge 48', y: 32 },
{ x: 'Uge 49', y: 40 },
{ x: 'Uge 50', y: 38 },
{ x: 'Uge 51', y: 40 },
{ x: 'Uge 52', y: 20 }
]
},
{
name: 'Martin Nielsen',
color: '#3b82f6',
type: 'bar',
data: [
{ x: 'Uge 48', y: 30 },
{ x: 'Uge 49', y: 40 },
{ x: 'Uge 50', y: 35 },
{ x: 'Uge 51', y: 40 },
{ x: 'Uge 52', y: 16 }
]
},
{
name: 'Sofie Larsen',
color: '#8b5cf6',
type: 'bar',
data: [
{ x: 'Uge 48', y: 28 },
{ x: 'Uge 49', y: 36 },
{ x: 'Uge 50', y: 40 },
{ x: 'Uge 51', y: 40 },
{ x: 'Uge 52', y: 18 }
]
},
{
name: 'Peter Hansen',
color: '#f59e0b',
type: 'bar',
data: [
{ x: 'Uge 48', y: 34 },
{ x: 'Uge 49', y: 38 },
{ x: 'Uge 50', y: 32 },
{ x: 'Uge 51', y: 40 },
{ x: 'Uge 52', y: 14 }
]
}
],
legend: { position: 'bottom', align: 'center', gap: 0 }
});
// Absence distribution pie chart (Timerapport)
createChart(document.getElementById('absenceChart'), {
height: 240,
series: [
{
name: 'Syg',
color: '#e53935',
type: 'pie',
unit: ' t',
data: [
{ x: 'Martin Nielsen', y: 8 },
{ x: 'Peter Hansen', y: 4 }
],
pie: { innerRadius: 25, outerRadius: 90 }
},
{
name: 'Ferie',
color: '#f59e0b',
type: 'pie',
unit: ' t',
data: [
{ x: 'Anna Jensen', y: 4 },
{ x: 'Peter Hansen', y: 4 }
],
pie: { innerRadius: 25, outerRadius: 90 }
},
{
name: 'Fri',
color: '#8b5cf6',
type: 'pie',
unit: ' t',
data: [
{ x: 'Sofie Larsen', y: 4 }
],
pie: { innerRadius: 25, outerRadius: 90 }
}
],
legend: { position: 'right', align: 'center' }
});
// Period selector functionality
document.querySelectorAll('swp-period-selector button').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('swp-period-selector button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
});
});
</script>
}