Compare commits

..

2 Commits

Author SHA1 Message Date
michel 2c33c9a68d Invallers
Gitea/swiss-client/pipeline/head This commit looks good
2025-09-23 22:45:44 +02:00
michel 181aebf16a Invallers 2025-09-23 20:47:11 +02:00
11 changed files with 145 additions and 31 deletions
+2 -2
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:
@@ -0,0 +1,4 @@
.has-substitute {
text-decoration-line: underline;
text-decoration-style: dotted;
}
@@ -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;
}
}
@@ -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;
}
@@ -25,16 +25,8 @@
<mat-icon>settings</mat-icon> <mat-icon>settings</mat-icon>
&nbsp;Beheer &nbsp;Beheer
</ng-template> </ng-template>
<mat-tab-group animationDuration="0ms" disableRipple="true">
<mat-tab>
<ng-template mat-tab-label>
<mat-icon>group</mat-icon>
&nbsp;Spelerslijst
</ng-template>
<app-tournament-players [tournament]="tournament"></app-tournament-players> <app-tournament-players [tournament]="tournament"></app-tournament-players>
</mat-tab> </mat-tab>
</mat-tab-group>
</mat-tab>
} }
@if (tournament.status == 'DIVIDED') { @if (tournament.status == 'DIVIDED') {
@@ -117,16 +109,8 @@
<mat-icon>settings</mat-icon> <mat-icon>settings</mat-icon>
&nbsp;Beheer &nbsp;Beheer
</ng-template> </ng-template>
<mat-tab-group animationDuration="0ms" disableRipple="true">
<mat-tab>
<ng-template mat-tab-label>
<mat-icon>group</mat-icon>
&nbsp;Spelerslijst
</ng-template>
<app-tournament-players [tournament]="tournament"></app-tournament-players> <app-tournament-players [tournament]="tournament"></app-tournament-players>
</mat-tab> </mat-tab>
</mat-tab-group>
</mat-tab>
} }
@if (tournament.status == 'ONGOING') { @if (tournament.status == 'ONGOING') {
@@ -270,27 +254,54 @@
<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">{{ match.team1 | teamText }}</td> <td class="align-middle w-team">
<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">{{ 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)">
@@ -341,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) {
@@ -35,7 +35,7 @@ td.w-fill {
width: 95% !important; width: 95% !important;
} }
.mat-menu-panel { .mat-menu-panel {
z-index: 1000 !important; z-index: 1000 !important;
} }
@@ -26,13 +26,15 @@ import {MatDialog} from "@angular/material/dialog";
import {MatchResultPipe} from "../../pipes/match-result-pipe"; import {MatchResultPipe} from "../../pipes/match-result-pipe";
import {Event} from "../../model/event"; import {Event} from "../../model/event";
import {TournamentValidateComponent} from "../tournament-validate/tournament-validate.component"; import {TournamentValidateComponent} from "../tournament-validate/tournament-validate.component";
import {Strength} from "../../model/player"; import {Player, Strength} from "../../model/player";
import {MatSnackBar} from "@angular/material/snack-bar"; import {MatSnackBar} from "@angular/material/snack-bar";
import {CourtSelectionComponent} from "../court-selection/court-selection.component"; import {CourtSelectionComponent} from "../court-selection/court-selection.component";
import {Standings} from "../../model/standings"; import {Standings} from "../../model/standings";
import {HeaderService} from "../../service/header.service"; 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 {TeamDisplayComponent} from "../team-display/team-display.component";
@Component({ @Component({
selector: 'app-tournament-manage', selector: 'app-tournament-manage',
@@ -62,6 +64,8 @@ import {TournamentPlayer} from "../../model/tournamentPlayer";
TournamentValidateComponent, TournamentValidateComponent,
TournamentPlayersComponent, TournamentPlayersComponent,
MatExpansionPanelActionRow, MatExpansionPanelActionRow,
MatTooltip,
TeamDisplayComponent,
], ],
providers: [ providers: [
FullNamePipe, FullNamePipe,
@@ -412,6 +416,7 @@ export class TournamentManageComponent implements OnInit, OnDestroy {
} }
return count; return count;
} }
} }
class ActiveMatch { class ActiveMatch {
@@ -68,6 +68,7 @@
<th>Naam</th> <th>Naam</th>
<th>Wedstrijden geteld</th> <th>Wedstrijden geteld</th>
<th>Onderdelen</th> <th>Onderdelen</th>
<th>Invallers</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
@@ -81,6 +82,7 @@
{{ event }}&nbsp; {{ event }}&nbsp;
} }
</td> </td>
<td>{{ hasSubstitutes(tournamentPlayer) ? 'Ja' : 'Nee' }}</td>
<td> <td>
<button mat-icon-button [matMenuTriggerFor]="dividedTournamentMenu" class="menu-button"> <button mat-icon-button [matMenuTriggerFor]="dividedTournamentMenu" class="menu-button">
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
@@ -88,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>
@@ -1,3 +1,7 @@
td, th { td, th {
background-color: transparent !important; background-color: transparent !important;
} }
td {
vertical-align: middle;
}
@@ -90,4 +90,7 @@ export class TournamentPlayersComponent implements OnInit {
} }
hasSubstitutes(tournamentPlayer: TournamentPlayer) {
return tournamentPlayer.substitutions.filter(s => s.substitute != null && s.substitute >= 0).length > 0;
}
} }
-1
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;
} }