diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts
index 6d6caa1..6d13671 100644
--- a/frontend/src/app/app.routes.ts
+++ b/frontend/src/app/app.routes.ts
@@ -16,7 +16,7 @@ export const routes: Routes = [
},
{
path: 'staff-pt',
- loadComponent: () => import('./pages/particles/particles.component').then(m => m.ParticlesComponent),
+ loadComponent: () => import('./pages/head-mod/staff-pt/staff-pt.component').then(m => m.StaffPtComponent),
canActivate: [AuthGuard],
data: {
requiredAuthorizations: ['SCOPE_head_mod']
diff --git a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html
index 882c9ab..c6626fe 100644
--- a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html
+++ b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.html
@@ -1 +1,40 @@
-
staff-pt works!
+
+
+
+
+
+ | Staff Member |
+ {{ row.staff_member }} |
+
+
+
+ Playtime (h:mm) |
+ {{ minutesToHm(row.playtime) }} |
+
+
+
+ Last Played |
+ {{ row.last_played | date:'medium' }} |
+
+
+
+
+
+ @if (!staffPt()?.length) {
+
+ | No data for this week. |
+
+ }
+
+
diff --git a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss
index e69de29..5d28abc 100644
--- a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss
+++ b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.scss
@@ -0,0 +1,26 @@
+.staff-pt-container {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.week-header {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+}
+
+.week-title {
+ font-size: 1.1rem;
+ font-weight: 600;
+}
+
+.full-width {
+ width: 100%;
+}
+
+.no-data td {
+ text-align: center;
+ padding: 16px;
+}
diff --git a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts
index 7174e15..d3bf733 100644
--- a/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts
+++ b/frontend/src/app/pages/head-mod/staff-pt/staff-pt.component.ts
@@ -1,34 +1,104 @@
-import {Component, inject, OnInit, signal} from '@angular/core';
+import {Component, computed, inject, OnInit, signal} from '@angular/core';
+import {CommonModule, DatePipe} 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 {SiteService, StaffPlaytime} from '@api';
@Component({
selector: 'app-staff-pt',
- imports: [],
+ standalone: true,
+ imports: [CommonModule, MatTableModule, MatButtonModule, MatIconModule, MatTooltipModule, DatePipe],
templateUrl: './staff-pt.component.html',
styleUrl: './staff-pt.component.scss'
})
export class StaffPtComponent implements OnInit {
siteService = inject(SiteService);
- staffPt = signal([])
+
+ staffPt = signal([]);
+
+ weekStart = signal(this.getStartOfWeek(new Date()));
+ weekEnd = computed(() => this.getEndOfWeek(this.weekStart()));
+
+ todayStart = signal(this.startOfDay(new Date()));
+
+ displayedColumns = ['staff_member', 'playtime', 'last_played'];
ngOnInit(): void {
- const firstDayOfWeek = new Date();
- firstDayOfWeek.setDate(firstDayOfWeek.getDate() - firstDayOfWeek.getDay());
- firstDayOfWeek.setHours(0, 0, 0, 0);
- const lastDayOfWeek = new Date(firstDayOfWeek);
- lastDayOfWeek.setDate(firstDayOfWeek.getDate() + 6);
- lastDayOfWeek.setHours(23, 59, 59, 999);
-
- this.loadStaffData(firstDayOfWeek, lastDayOfWeek);
+ this.loadCurrentWeek();
}
- loadStaffData(from: Date, to: Date) {
+ 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 h = Math.floor(mins / 60);
+ const m = mins % 60;
+ return `${h}:${m.toString().padStart(2, '0')}`;
+ }
+
+ private loadStaffData(from: Date, to: Date) {
this.siteService.getStaffPlaytime(from.toISOString(), to.toISOString())
.subscribe({
- next: data => {
- this.staffPt.set(data);
- },
+ 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;
+ }
}