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:
parent
2f92b0eb7b
commit
0144e1ae17
4 changed files with 605 additions and 49 deletions
|
|
@ -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>
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue