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([]); sort = signal({active: 'playtime', direction: 'desc'} as Sort); sortedStaffPt = computed(() => { 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(this.getStartOfWeek(new Date())); weekEnd = computed(() => this.getEndOfWeek(this.weekStart())); todayStart = signal(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; } }