Invallers
All checks were successful
Gitea/swiss-client/pipeline/head This commit looks good

This commit is contained in:
2025-09-23 22:45:44 +02:00
parent 181aebf16a
commit 2c33c9a68d
9 changed files with 127 additions and 54 deletions

View File

@@ -32,11 +32,11 @@
Player-registrations: oude toernooien verbergen via knop Player-registrations: oude toernooien verbergen via knop
Onderdeel afsluiten Onderdeel afsluiten
Wedstrijd opgave Wedstrijd opgave
Blessures Invallers
Titels pagina's Titels pagina's
Authenticatie Authenticatie
Progress indicator tijdens communicatie backend Progress indicator tijdens communicatie backend
Bij tellers rekening houden met invallers
https://blog.shhdharmen.me/browser-storage-in-angular-ssr https://blog.shhdharmen.me/browser-storage-in-angular-ssr
Won't do / later: Won't do / later:

View File

@@ -0,0 +1,4 @@
.has-substitute {
text-decoration-line: underline;
text-decoration-style: dotted;
}

View File

@@ -0,0 +1,42 @@
import {Component, Input} from '@angular/core';
import {Player} from '../../model/player';
import {Event} from '../../model/event';
import {Tournament} from '../../model/tournament';
import {FullNamePipe} from '../../pipes/fullname-pipe';
import {MatTooltip} from '@angular/material/tooltip';
@Component({
selector: 'app-player-display',
standalone: true,
imports: [FullNamePipe, MatTooltip],
styleUrls: ['./player-display.component.scss'],
template: `
@let substitute = getSubstituteForEvent(player, event);
<span [class.has-substitute]="substitute"
[matTooltip]="substitute ? 'Valt in voor ' + (player | fullName) : ''"
matTooltipPosition="below">
{{ substitute || (player | fullName) }}
</span>
`
})
export class PlayerDisplayComponent {
@Input({ required: true }) player!: Player;
@Input({ required: true }) event!: Event;
@Input({ required: true }) tournament!: Tournament;
getSubstituteForEvent(player: Player, event: Event): string | undefined {
const tournamentPlayer = this.tournament.tournamentPlayers.find(
tp => tp.playerId === player.id
);
if (!tournamentPlayer) return undefined;
const substitution = tournamentPlayer.substitutions.find(
s => s.event === event.type
);
if (!substitution) return undefined;
return this.tournament.tournamentPlayers.find(
p => p.id === substitution.substitute
)?.name;
}
}

View File

@@ -0,0 +1,32 @@
import {Component, Input} from '@angular/core';
import {Event} from '../../model/event';
import {Tournament} from '../../model/tournament';
import {PlayerDisplayComponent} from '../player-display/player-display.component';
import {Team} from "../../model/team";
@Component({
selector: 'app-team-display',
standalone: true,
imports: [PlayerDisplayComponent],
template: `
<app-player-display
[player]="team.player1"
[event]="event"
[tournament]="tournament">
</app-player-display>
@if (event.doublesEvent && team.player2) {
/
<app-player-display
[player]="team.player2"
[event]="event"
[tournament]="tournament">
</app-player-display>
}
`
})
export class TeamDisplayComponent {
@Input({ required: true }) team!: Team;
@Input({ required: true }) event!: Event;
@Input({ required: true }) tournament!: Tournament;
}

View File

@@ -255,39 +255,53 @@
@for (match of round.matches; track match.id) { @for (match of round.matches; track match.id) {
<tr> <tr>
<td class="align-middle w-team"> <td class="align-middle w-team">
@if (playerHasSubstituteForEvent(match.team1.player1, event)) { <app-team-display
<span class="has-substitute" matTooltip="Valt in voor {{ match.team1.player1 | fullName }}" matTooltipPosition="below"> [team]="match.team1"
{{ getSubstituteForEvent(match.team1.player1, event) }} [event]="event"
</span> [tournament]="tournament">
} @else { </app-team-display>
{{ match.team1.player1 | fullName }}
}
@if (event.doublesEvent && match.team1.player2 != null) {
<span [ngClass]="playerHasSubstituteForEvent(match.team1.player2, event) ? 'has-substitute' : ''">
/ {{ match.team1.player2 | fullName }}
</span>
}
</td> </td>
<td class="align-middle w-sep">-</td> <td class="align-middle w-sep">-</td>
<td class="align-middle w-team">{{ match.team2 | teamText }}</td> <td class="align-middle w-team">
<app-team-display
[team]="match.team2"
[event]="event"
[tournament]="tournament">
</app-team-display>
</td>
<td class="align-middle w-fill"></td> <td class="align-middle w-fill"></td>
</tr> </tr>
} }
@if (round.drawnOut) { @if (round.drawnOut) {
<tr> <tr>
<td class="align-middle w-100" colspan="4"><b>Deze ronde uitgeloot:</b> {{ round.drawnOut | teamText }}</td> <td class="align-middle w-100" colspan="4">
<b>Deze ronde uitgeloot:</b> {{ round.drawnOut | teamText }}
</td>
</tr> </tr>
} }
</tbody> </tbody>
</table> </table>
<!-- }-->
} @else if (round.status == 'IN_PROGRESS') { } @else if (round.status == 'IN_PROGRESS') {
<table class="table table-hover m-4 wide w-95"> <table class="table table-hover m-4 wide w-95">
<tbody> <tbody>
@for (match of round.matches; track match.id) { @for (match of round.matches; track match.id) {
<tr> <tr>
<td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 1}">{{ match.team1 | teamText }}</td> <td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 1}">
<app-team-display
[team]="match.team1"
[event]="event"
[tournament]="tournament">
</app-team-display>
</td>
<td class="align-middle w-sep">-</td> <td class="align-middle w-sep">-</td>
<td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 2}">{{ match.team2 | teamText }}</td> <td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 2}">
<app-team-display
[team]="match.team2"
[event]="event"
[tournament]="tournament">
</app-team-display>
</td>
<td class="align-middle w-fill"> <td class="align-middle w-fill">
@if (match.status == 'NOT_STARTED') { @if (match.status == 'NOT_STARTED') {
<button mat-button (click)="startMatch(match)"> <button mat-button (click)="startMatch(match)">
@@ -338,9 +352,21 @@
<tbody> <tbody>
@for (match of round.matches; track match.id) { @for (match of round.matches; track match.id) {
<tr> <tr>
<td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 1}">{{ match.team1 | teamText }}</td> <td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 1}">
<app-team-display
[team]="match.team1"
[event]="event"
[tournament]="tournament">
</app-team-display>
</td>
<td class="align-middle w-sep">-</td> <td class="align-middle w-sep">-</td>
<td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 2}">{{ match.team2 | teamText }}</td> <td class="align-middle w-team" [ngClass]="{'winner': checkWinner(match) == 2}">
<app-team-display
[team]="match.team2"
[event]="event"
[tournament]="tournament">
</app-team-display>
</td>
<td class="align-middle w-fill"> <td class="align-middle w-fill">
<div class="row result align-items-center"> <div class="row result align-items-center">
@for (game of match.games; track game.id) { @for (game of match.games; track game.id) {

View File

@@ -39,7 +39,3 @@ td.w-fill {
z-index: 1000 !important; z-index: 1000 !important;
} }
.has-substitute {
text-decoration-line: underline;
text-decoration-style: dotted;
}

View File

@@ -34,6 +34,7 @@ import {HeaderService} from "../../service/header.service";
import {TournamentPlayersComponent} from "../tournament-players/tournament-players.component"; import {TournamentPlayersComponent} from "../tournament-players/tournament-players.component";
import {TournamentPlayer} from "../../model/tournamentPlayer"; import {TournamentPlayer} from "../../model/tournamentPlayer";
import {MatTooltip} from "@angular/material/tooltip"; import {MatTooltip} from "@angular/material/tooltip";
import {TeamDisplayComponent} from "../team-display/team-display.component";
@Component({ @Component({
selector: 'app-tournament-manage', selector: 'app-tournament-manage',
@@ -64,6 +65,7 @@ import {MatTooltip} from "@angular/material/tooltip";
TournamentPlayersComponent, TournamentPlayersComponent,
MatExpansionPanelActionRow, MatExpansionPanelActionRow,
MatTooltip, MatTooltip,
TeamDisplayComponent,
], ],
providers: [ providers: [
FullNamePipe, FullNamePipe,
@@ -415,34 +417,6 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
return count; return count;
} }
playerHasSubstituteForEvent(player: Player, event: Event) : boolean {
return this.getSubstituteForEvent(player, event) != undefined;
}
getSubstituteForEvent(player: Player, event: Event) : string | undefined {
var tournamentPlayer = this.getTournamentPlayerFromPlayer(player);
if (tournamentPlayer === null) return undefined;
if (tournamentPlayer.name == 'Inge Brehler') console.log(tournamentPlayer.name);
for (let substitution of tournamentPlayer.substitutions) {
if (substitution.event == event.type) {
var substitute = this.tournament.tournamentPlayers.find(p => p.id == substitution.substitute);
return substitute?.name;
}
}
return undefined;
}
getTournamentPlayerFromPlayer(player: Player) : TournamentPlayer | null {
for (let tournamentPlayer of this.tournament.tournamentPlayers) {
if (tournamentPlayer.playerId == player.id) {
return tournamentPlayer;
}
}
return null;
}
} }
class ActiveMatch { class ActiveMatch {

View File

@@ -90,7 +90,7 @@
<mat-menu #dividedTournamentMenu="matMenu"> <mat-menu #dividedTournamentMenu="matMenu">
<button mat-menu-item (click)="findSubstitute(tournamentPlayer)"> <button mat-menu-item (click)="findSubstitute(tournamentPlayer)">
<mat-icon>autorenew</mat-icon> <mat-icon>autorenew</mat-icon>
Invaller kiezen Invallers
</button> </button>
<button mat-menu-item> <!--(click)="drawTournament()"--> <button mat-menu-item> <!--(click)="drawTournament()"-->
<mat-icon>do_not_disturb_on</mat-icon> <mat-icon>do_not_disturb_on</mat-icon>

View File

@@ -14,6 +14,5 @@ export class TournamentPlayer {
export class TournamentPlayerSubstitution { export class TournamentPlayerSubstitution {
substitutionId: number; substitutionId: number;
event: string; event: string;
// substitute: TournamentPlayer;
substitute: number = -1; substitute: number = -1;
} }