Files
HIPCTF2/frontend/src/app/features/scoreboard/tabs.component.ts
T
2026-07-24 12:58:34 +02:00

78 lines
2.1 KiB
TypeScript

import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SCOREBOARD_TABS, ScoreboardTab } from './scoreboard.pure';
interface TabSpec {
id: ScoreboardTab;
label: string;
icon: string;
}
const TAB_SPECS: Readonly<Record<ScoreboardTab, { label: string; icon: string }>> = {
ranking: { label: 'RANKINGS', icon: '🏆' },
matrix: { label: 'MATRIX', icon: '▦' },
'event-log': { label: 'EVENT LOG', icon: '≡' },
graph: { label: 'SCORE GRAPH', icon: '📈' },
};
@Component({
selector: 'app-scoreboard-tabs',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CommonModule],
styles: [`
:host { display: block; }
nav {
display: flex; gap: 10px; justify-content: center;
margin-bottom: 24px; flex-wrap: wrap;
}
button {
padding: 10px 20px;
background: #000000;
color: #aaaaee;
border: 2px solid #22222e;
cursor: pointer;
font-family: var(--font-mono);
font-weight: 800;
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.5px;
display: flex; align-items: center; gap: 8px;
transition: all 0.15s ease;
}
button:hover:not(.active) {
border-color: var(--neon-purple);
color: #ffffff;
}
button.active {
background: var(--neon-red);
color: #000000;
border-color: var(--neon-red);
box-shadow: 0 0 15px rgba(255, 0, 51, 0.4);
}
`],
template: `
<nav data-testid="scoreboard-tabs">
<button
*ngFor="let t of tabs"
type="button"
[class.active]="t.id === active"
[attr.data-testid]="'scoreboard-tab-' + t.id"
(click)="select.emit(t.id)"
>
<span>{{ t.icon }}</span>
<span>{{ t.label }}</span>
</button>
</nav>
`,
})
export class ScoreboardTabsComponent {
@Input({ required: true }) active!: ScoreboardTab;
@Output() select = new EventEmitter<ScoreboardTab>();
readonly tabs: TabSpec[] = SCOREBOARD_TABS.map((id) => ({
id,
label: TAB_SPECS[id].label,
icon: TAB_SPECS[id].icon,
}));
}