1
0
Fork 0
mirror of https://codeberg.org/beerbrawl/beerbrawl.git synced 2024-09-23 05:40:51 +02:00

feat(#85): add checkin functionality on score table

This commit is contained in:
Moritz Kepplinger 2024-05-27 14:00:07 +02:00
parent 363ff338e1
commit b33199e991
10 changed files with 110 additions and 9 deletions

View file

@ -20,6 +20,7 @@
"@angular/platform-browser-dynamic": "17.3.4",
"@angular/router": "17.3.4",
"@fontsource/material-icons": "^5.0.18",
"@fontsource/material-icons-outlined": "^5.0.12",
"@fontsource/roboto": "^5.0.13",
"@popperjs/core": "2.11.8",
"core-js": "3.36.1",
@ -3082,6 +3083,11 @@
"resolved": "https://registry.npmjs.org/@fontsource/material-icons/-/material-icons-5.0.18.tgz",
"integrity": "sha512-2DL5z2yKWE+kXQrBiUTwIOMQjhs6t+EoPql8Ai4N6t2mjUhBdi2RChW44V3z1WgwupoqILXrAa4/id4/AuruMQ=="
},
"node_modules/@fontsource/material-icons-outlined": {
"version": "5.0.12",
"resolved": "https://registry.npmjs.org/@fontsource/material-icons-outlined/-/material-icons-outlined-5.0.12.tgz",
"integrity": "sha512-Zi8qYVOCtSS6CFGZzjUY+ENYmVtSgH1GDQBeGllwXJ2Ny/TmCTsO+tjHpr74nV4u63JSAAl72QnX0eOhOcldJw=="
},
"node_modules/@fontsource/roboto": {
"version": "5.0.13",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.13.tgz",

View file

@ -27,6 +27,7 @@
"@angular/platform-browser-dynamic": "17.3.4",
"@angular/router": "17.3.4",
"@fontsource/material-icons": "^5.0.18",
"@fontsource/material-icons-outlined": "^5.0.12",
"@fontsource/roboto": "^5.0.13",
"@popperjs/core": "2.11.8",
"core-js": "3.36.1",

View file

@ -1,5 +1,4 @@
.header-card {
//background-color: red;
height: 10vh;
box-shadow: 0 0 5px 0 rgba(50, 50, 50, 0.75);
display: flex;

View file

@ -7,7 +7,22 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>Name</th>
<td mat-cell *matCellDef="let element">
<span [ngClass]="{ 'grey-text': asScoreDto(element) }">{{ element.name }}</span>
<div class="name-container">
<span class="name-text" [ngClass]="{ 'grey-text': !asScoreDto(element).ready }">
{{ asScoreDto(element).name }}
@if (!asScoreDto(element).ready) {
<button
class="check-in-button"
mat-icon-button
aria-label="mark team as ready"
(click)="checkInTeam.emit(element)"
[matTooltip]="'Mark team as ready'"
>
<mat-icon class="material-icons-outlined">waving_hand</mat-icon>
</button>
}
</span>
</div>
</td>
</ng-container>

View file

@ -1,5 +1,5 @@
.grey-text {
color: grey;
color: darkgrey;
}
.mat-mdc-header-cell,
@ -7,3 +7,15 @@
justify-content: center;
text-align: center;
}
.check-in-button {
position: absolute;
top: -1.5rem;
right: -2.2rem;
scale: 0.8;
color: black;
}
.name-text {
position: relative;
}

View file

@ -1,4 +1,4 @@
import { Component, input } from '@angular/core';
import { Component, inject, input, output } from '@angular/core';
import {
MatCell,
MatCellDef,
@ -12,7 +12,13 @@ import {
MatTable,
} from '@angular/material/table';
import { NgClass, NgStyle } from '@angular/common';
import { QualificationTeamScoreDto } from '@api';
import { QualificationTeamScoreDto, TeamDto, TournamentEndpointService } from '@api';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
import { catchError, of } from 'rxjs';
import { ConfirmationService } from '../../services/confirmation.service';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-tournament-score-table',
@ -30,12 +36,17 @@ import { QualificationTeamScoreDto } from '@api';
MatHeaderRowDef,
NgStyle,
NgClass,
MatIconButton,
MatIcon,
MatTooltip,
],
templateUrl: './tournament-score-table.component.html',
styleUrl: './tournament-score-table.component.scss',
})
export class TournamentScoreTableComponent {
scoreDtos = input<QualificationTeamScoreDto[]>();
tournamentId = input<number>();
checkInTeam = output<QualificationTeamScoreDto>();
displayedColumns = ['position', 'name', 'gamesPlayed', 'wins', 'losses', 'points'];
asScoreDto(element: QualificationTeamScoreDto): QualificationTeamScoreDto {

View file

@ -10,6 +10,9 @@
}
</div>
<div class="score-table mat-elevation-z8">
<app-tournament-score-table [scoreDtos]="scoreDtos()"></app-tournament-score-table>
<app-tournament-score-table
(checkInTeam)="checkInTeam($event)"
[scoreDtos]="scoreDtos()"
></app-tournament-score-table>
</div>
</div>

View file

@ -5,14 +5,16 @@ import { MatCard } from '@angular/material/card';
import { TournamentTeamsComponent } from '../../tournament-teams/tournament-teams.component';
import {
QualificationTeamScoreDto,
TeamDto,
TournamentEndpointService,
TournamentQualificationMatchDto,
} from '@api';
import { catchError, of } from 'rxjs';
import { catchError, firstValueFrom, of } from 'rxjs';
import { MatSnackBar } from '@angular/material/snack-bar';
import { TournamentScoreTableComponent } from '../../tournament-score-table/tournament-score-table.component';
import { QualificationMatchLineComponent } from '../../qualification-match-line/qualification-match-line.component';
import { DatePipe } from '@angular/common';
import { ConfirmationService } from '../../../services/confirmation.service';
@Component({
selector: 'app-tournament-qualification-phase',
@ -32,12 +34,13 @@ import { DatePipe } from '@angular/common';
export class TournamentQualificationPhaseComponent implements OnInit, OnDestroy {
tournamentService = inject(TournamentEndpointService);
snackBar = inject(MatSnackBar);
deleteConfirmationService = inject(ConfirmationService);
tournamentId = input<number>();
scoreDtos = signal<QualificationTeamScoreDto[]>([]);
qualificationMatches = signal<TournamentQualificationMatchDto[]>([]);
// @ts-ignore
// @ts-ignore - ts does not 'know' NodeJS types for some reason
refreshInterval: NodeJS.Timeout | undefined;
ngOnInit(): void {
@ -89,4 +92,28 @@ export class TournamentQualificationPhaseComponent implements OnInit, OnDestroy
});
}
}
async checkInTeam(team: QualificationTeamScoreDto): Promise<void> {
if (this.tournamentId() !== undefined && team.id !== undefined) {
const answer = await this.deleteConfirmationService.openConfirmationDialog(
`check in team ${team.name}?`,
'This action cannot be undone.',
);
if (answer) {
firstValueFrom(
this.tournamentService.markTeamAsReady(this.tournamentId()!, team.id).pipe(
catchError(error => {
console.error(error);
this.snackBar.open('Failed to check in team: ' + error.message, 'Close');
return of([]);
}),
),
).then(() => {
this.loadScores();
this.loadQualificationMatches();
});
}
}
}
}

View file

@ -4,6 +4,7 @@
@import '@fontsource/roboto';
@import '@fontsource/material-icons';
@import '@fontsource/material-icons-outlined';
html,
body {
@ -45,3 +46,29 @@ a.no-decoration {
/* Support for IE. */
font-feature-settings: 'liga';
}
// for using material outlined icons with fontsource
.material-icons-outlined {
font-family: 'Material Icons Outlined', serif;
font-weight: normal;
font-style: normal;
font-size: 24px; /* Preferred icon size */
display: inline-block;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
white-space: nowrap;
direction: ltr;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
}

View file

@ -13,7 +13,7 @@
"experimentalDecorators": true,
"target": "es2022",
"typeRoots": ["node_modules/@types"],
"lib": ["es2018", "dom", "ES2020.Intl"],
"lib": ["es2018", "dom"],
"useDefineForClassFields": false,
"strict": true,
"paths": { "@api": ["./openapi-generated"] }