139 lines
4.2 KiB
TypeScript
139 lines
4.2 KiB
TypeScript
import {Component, computed, inject, OnInit, signal} from '@angular/core';
|
||
import {CommonModule} from '@angular/common';
|
||
import {MatTableModule} from '@angular/material/table';
|
||
import {MatButtonModule} from '@angular/material/button';
|
||
import {MatIconModule} from '@angular/material/icon';
|
||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||
import {MatSortModule, Sort} from '@angular/material/sort';
|
||
import {SiteService, StaffPlaytime} from '@api';
|
||
import {HeaderComponent} from '@header/header.component';
|
||
|
||
@Component({
|
||
selector: 'app-staff-pt',
|
||
standalone: true,
|
||
imports: [CommonModule, MatTableModule, MatButtonModule, MatIconModule, MatTooltipModule, MatSortModule, HeaderComponent],
|
||
templateUrl: './staff-pt.component.html',
|
||
styleUrl: './staff-pt.component.scss'
|
||
})
|
||
export class StaffPtComponent implements OnInit {
|
||
siteService = inject(SiteService);
|
||
|
||
staffPt = signal<StaffPlaytime[]>([]);
|
||
sort = signal<Sort>({active: 'playtime', direction: 'desc'} as Sort);
|
||
sortedStaffPt = computed<StaffPlaytime[]>(() => {
|
||
const data = [...this.staffPt()];
|
||
const {active, direction} = this.sort();
|
||
if (!direction || !active) return data;
|
||
const dir = direction === 'asc' ? 1 : -1;
|
||
return data.sort((a, b) => {
|
||
switch (active) {
|
||
case 'staff_member':
|
||
return a.staff_member.localeCompare(b.staff_member) * dir;
|
||
case 'role':
|
||
return a.role.localeCompare(b.role) * dir;
|
||
case 'playtime':
|
||
default:
|
||
return ((a.playtime ?? 0) - (b.playtime ?? 0)) * dir;
|
||
}
|
||
});
|
||
});
|
||
|
||
weekStart = signal<Date>(this.getStartOfWeek(new Date()));
|
||
weekEnd = computed(() => this.getEndOfWeek(this.weekStart()));
|
||
|
||
todayStart = signal<Date>(this.startOfDay(new Date()));
|
||
|
||
displayedColumns = ['staff_member', 'playtime', 'role'];
|
||
|
||
ngOnInit(): void {
|
||
this.loadCurrentWeek();
|
||
}
|
||
|
||
private loadCurrentWeek() {
|
||
this.loadStaffData(this.weekStart(), this.weekEnd());
|
||
}
|
||
|
||
prevWeek() {
|
||
const prev = new Date(this.weekStart());
|
||
prev.setDate(prev.getDate() - 7);
|
||
prev.setHours(0, 0, 0, 0);
|
||
this.weekStart.set(prev);
|
||
this.loadCurrentWeek();
|
||
}
|
||
|
||
nextWeek() {
|
||
if (!this.canGoNextWeek()) return;
|
||
const next = new Date(this.weekStart());
|
||
next.setDate(next.getDate() + 7);
|
||
next.setHours(0, 0, 0, 0);
|
||
this.weekStart.set(next);
|
||
this.loadCurrentWeek();
|
||
}
|
||
|
||
canGoNextWeek(): boolean {
|
||
const nextWeekStart = new Date(this.weekStart());
|
||
nextWeekStart.setDate(nextWeekStart.getDate() + 7);
|
||
nextWeekStart.setHours(0, 0, 0, 0);
|
||
return nextWeekStart.getTime() <= this.todayStart().getTime();
|
||
}
|
||
|
||
weekLabel(): string {
|
||
const start = this.weekStart();
|
||
const end = this.weekEnd();
|
||
|
||
const startFmt = start.toLocaleDateString(undefined, {month: 'short', day: 'numeric'});
|
||
const endFmt = end.toLocaleDateString(undefined, {month: 'short', day: 'numeric'});
|
||
const year = end.getFullYear();
|
||
return `Week ${startFmt} – ${endFmt}, ${year}`;
|
||
}
|
||
|
||
minutesToHm(mins?: number): string {
|
||
if (mins == null) return '';
|
||
const d = Math.floor(mins / 1440);
|
||
const h = Math.floor((mins % 1440) / 60);
|
||
const m = mins % 60;
|
||
const parts = [];
|
||
if (d > 0) {
|
||
parts.push(`${d}d`);
|
||
}
|
||
if (h > 0 || d > 0) {
|
||
parts.push(`${h}h`);
|
||
}
|
||
if (m > 0 || (h === 0 && d === 0)) {
|
||
parts.push(`${m}m`);
|
||
}
|
||
return parts.join(' ');
|
||
}
|
||
|
||
private loadStaffData(from: Date, to: Date) {
|
||
const fromUtc = new Date(from.getTime() - from.getTimezoneOffset() * 60000);
|
||
const toUtc = new Date(to.getTime() - to.getTimezoneOffset() * 60000);
|
||
|
||
this.siteService.getStaffPlaytime(fromUtc.toISOString(), toUtc.toISOString())
|
||
.subscribe({
|
||
next: data => this.staffPt.set(data ?? []),
|
||
error: err => console.error('Error getting staff playtime:', err)
|
||
});
|
||
}
|
||
|
||
private getStartOfWeek(date: Date): Date {
|
||
const d = new Date(date);
|
||
d.setDate(d.getDate() - d.getDay()); // Sunday start
|
||
d.setHours(0, 0, 0, 0);
|
||
return d;
|
||
}
|
||
|
||
private getEndOfWeek(start: Date): Date {
|
||
const d = new Date(start);
|
||
d.setDate(start.getDate() + 6);
|
||
d.setHours(23, 59, 59, 999);
|
||
return d;
|
||
}
|
||
|
||
private startOfDay(date: Date): Date {
|
||
const d = new Date(date);
|
||
d.setHours(0, 0, 0, 0);
|
||
return d;
|
||
}
|
||
}
|