Compare commits
2 Commits
71c3733363
...
d317ce6179
| Author | SHA1 | Date | |
|---|---|---|---|
| d317ce6179 | |||
| 0c071c0621 |
@@ -1,5 +1,4 @@
|
|||||||
import Dexie, { type EntityTable } from 'dexie';
|
import Dexie, { type EntityTable } from 'dexie';
|
||||||
import { settings } from 'ionicons/icons';
|
|
||||||
|
|
||||||
export interface Umpire {
|
export interface Umpire {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -7,13 +6,19 @@ export interface Umpire {
|
|||||||
lastName: string;
|
lastName: string;
|
||||||
country: string;
|
country: string;
|
||||||
gender: string;
|
gender: string;
|
||||||
|
courtNo?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Court {
|
export interface CourtUmpire {
|
||||||
id: number;
|
id: number;
|
||||||
umpireId: number | null;
|
umpireId: number | null;
|
||||||
serviceJudgeId: number | null;
|
courtNo: number;
|
||||||
order: number;
|
}
|
||||||
|
|
||||||
|
export interface CourtServiceJudge {
|
||||||
|
id: number;
|
||||||
|
umpireId: number | null;
|
||||||
|
courtNo: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface WaitingAsUmpire {
|
export interface WaitingAsUmpire {
|
||||||
@@ -36,7 +41,8 @@ export interface Settings {
|
|||||||
|
|
||||||
const db = new Dexie('CourtPilot') as Dexie & {
|
const db = new Dexie('CourtPilot') as Dexie & {
|
||||||
umpires: EntityTable<Umpire, 'id'>;
|
umpires: EntityTable<Umpire, 'id'>;
|
||||||
courts: EntityTable<Court, 'id'>;
|
courtUmpires: EntityTable<CourtUmpire, 'id'>;
|
||||||
|
courtServiceJudges: EntityTable<CourtServiceJudge, 'id'>;
|
||||||
settings: EntityTable<Settings, 'id'>;
|
settings: EntityTable<Settings, 'id'>;
|
||||||
waitingUmpires: EntityTable<WaitingAsUmpire, 'id'>;
|
waitingUmpires: EntityTable<WaitingAsUmpire, 'id'>;
|
||||||
waitingServiceJudges: EntityTable<WaitingAsServiceJudge, 'id'>;
|
waitingServiceJudges: EntityTable<WaitingAsServiceJudge, 'id'>;
|
||||||
@@ -44,7 +50,8 @@ const db = new Dexie('CourtPilot') as Dexie & {
|
|||||||
|
|
||||||
db.version(1).stores({
|
db.version(1).stores({
|
||||||
umpires: '++id, lastName',
|
umpires: '++id, lastName',
|
||||||
courts: '++id, umpireId, serviceJudgeId',
|
courtUmpires: '++id, courtNo, umpireId',
|
||||||
|
courtServiceJudges: '++id, courtNo, umpireId',
|
||||||
settings: '++id',
|
settings: '++id',
|
||||||
waitingUmpires: '++id, order, umpireId',
|
waitingUmpires: '++id, order, umpireId',
|
||||||
waitingServiceJudges: '++id, order, serviceJudgeId'
|
waitingServiceJudges: '++id, order, serviceJudgeId'
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
"app": {
|
"app": {
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
|
"minHeight": 600,
|
||||||
|
"minWidth": 800,
|
||||||
"title": "Court Pilot",
|
"title": "Court Pilot",
|
||||||
"width": 800,
|
"width": 800,
|
||||||
"height": 600,
|
"height": 600,
|
||||||
|
|||||||
@@ -6,7 +6,10 @@ import { Umpire } from 'db';
|
|||||||
standalone: true
|
standalone: true
|
||||||
})
|
})
|
||||||
export class FullnamePipe implements PipeTransform {
|
export class FullnamePipe implements PipeTransform {
|
||||||
transform(value: Umpire, ...args: unknown[]): string {
|
transform(value: Umpire | undefined, ...args: unknown[]): string {
|
||||||
|
if (typeof value === 'undefined') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
// TODO: in case of multilang, change here
|
// TODO: in case of multilang, change here
|
||||||
return value.lastName + ' ' + value.firstName;
|
return value.lastName + ' ' + value.firstName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CourtServiceJudgeService } from './court.service.judge.service';
|
||||||
|
|
||||||
|
describe('CourtServiceJudgeService', () => {
|
||||||
|
let service: CourtServiceJudgeService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(CourtServiceJudgeService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
import { CourtServiceJudge, db } from 'db';
|
||||||
|
import { liveQuery } from 'dexie';
|
||||||
|
import { from } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CourtServiceJudgeService {
|
||||||
|
/**
|
||||||
|
* All service judges (reactive)
|
||||||
|
*/
|
||||||
|
readonly umpires = toSignal(
|
||||||
|
from(liveQuery(() => db.courtServiceJudges.orderBy('courtNo').toArray())),
|
||||||
|
{ initialValue: [] }
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get by court number (reactive)
|
||||||
|
*/
|
||||||
|
getByCourtNo(courtNo: number) {
|
||||||
|
return toSignal<CourtServiceJudge | undefined>(
|
||||||
|
liveQuery(() =>
|
||||||
|
db.courtServiceJudges.where('courtNo').equals(courtNo).first()
|
||||||
|
),
|
||||||
|
{ initialValue: undefined }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create / update
|
||||||
|
*/
|
||||||
|
async save(item: Omit<CourtServiceJudge, 'id'>): Promise<number> {
|
||||||
|
return db.courtServiceJudges.add(item as CourtServiceJudge);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
id: number,
|
||||||
|
changes: Partial<CourtServiceJudge>
|
||||||
|
): Promise<number> {
|
||||||
|
return db.courtServiceJudges.update(id, changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: number): Promise<void> {
|
||||||
|
await db.courtServiceJudges.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CourtUmpireService } from './court.umpire.service';
|
||||||
|
|
||||||
|
describe('CourtUmpireService', () => {
|
||||||
|
let service: CourtUmpireService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(CourtUmpireService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
import { CourtUmpire, db } from 'db';
|
||||||
|
import { liveQuery } from 'dexie';
|
||||||
|
import { from } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class CourtUmpireService {
|
||||||
|
/**
|
||||||
|
* All court umpires (reactive)
|
||||||
|
*/
|
||||||
|
readonly umpires = toSignal(
|
||||||
|
from(liveQuery(() => db.courtUmpires.orderBy('courtNo').toArray())),
|
||||||
|
{ initialValue: [] }
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get by court number (reactive single)
|
||||||
|
*/
|
||||||
|
getByCourtNo(courtNo: number) {
|
||||||
|
return toSignal<CourtUmpire | undefined>(
|
||||||
|
liveQuery(() => db.courtUmpires.where('courtNo').equals(courtNo).first()),
|
||||||
|
{ initialValue: undefined }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create / update
|
||||||
|
*/
|
||||||
|
async save(item: Omit<CourtUmpire, 'id'>): Promise<number> {
|
||||||
|
return db.courtUmpires.add(item as CourtUmpire);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: number, changes: Partial<CourtUmpire>): Promise<number> {
|
||||||
|
return db.courtUmpires.update(id, changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: number): Promise<void> {
|
||||||
|
await db.courtUmpires.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeByUmpireId(umpireId: number): Promise<void> {
|
||||||
|
const item = await db.courtUmpires
|
||||||
|
.where('umpireId')
|
||||||
|
.equals(umpireId)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (!item?.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.courtUmpires.delete(item.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
-35
@@ -4,32 +4,72 @@
|
|||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content [fullscreen]="true">
|
<ion-content [fullscreen]="true" cdkDropListGroup>
|
||||||
<ion-header collapse="condense">
|
<ion-header collapse="condense">
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-title size="large">Pályák</ion-title>
|
<ion-title size="large">Pályák</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-grid [fixed]="'fixed'">
|
<ion-grid [fixed]="'fixed'" class="bottom-lists">
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col [size]="1">Pálya</ion-col>
|
<ion-col [size]="1" class="ion-display-none ion-display-xl-block">
|
||||||
<ion-col>Játékvezető</ion-col>
|
<ion-item [lines]="'none'">Pálya</ion-item>
|
||||||
<ion-col>Adogatásbíró</ion-col>
|
</ion-col>
|
||||||
|
<ion-col [size]="1" class="ion-display-xl-none">
|
||||||
|
<ion-item [lines]="'none'">P</ion-item>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col><ion-item [lines]="'none'">Játékvezető</ion-item></ion-col>
|
||||||
|
<ion-col><ion-item [lines]="'none'">Adogatásbíró</ion-item></ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
@for (item of [].constructor(settings()?.numberOfCourts); track $index) {
|
@for (item of [].constructor(settings()?.numberOfCourts); track $index) {
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col [size]="1">{{ $index + 1 }}.</ion-col>
|
<ion-col [size]="1">
|
||||||
<ion-col>név1</ion-col>
|
<ion-list>
|
||||||
<ion-col>név2</ion-col>
|
<ion-item [lines]="'none'"> {{ $index + 1 }}. </ion-item>
|
||||||
|
</ion-list>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col>
|
||||||
|
<ion-list
|
||||||
|
[lines]="'none'"
|
||||||
|
cdkDropList
|
||||||
|
[id]="`court-umpire-${$index + 1}`"
|
||||||
|
cdkDropListSortingDisabled
|
||||||
|
[cdkDropListData]="waitingServiceJudges()"
|
||||||
|
(cdkDropListDropped)="dropToUmpire($event, $index + 1)"
|
||||||
|
[cdkDropListConnectedTo]="['list-on-rest', 'list-waiting-umpires']">
|
||||||
|
@if (umpireByCourt().get($index + 1); as umpire) {
|
||||||
|
|
||||||
|
<ion-item cdkDrag [cdkDragData]="umpire">
|
||||||
|
<ion-label>{{ umpire | fullname }}</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
}
|
||||||
|
</ion-list>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col>
|
||||||
|
<ion-item [lines]="'none'"> aaa </ion-item>
|
||||||
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
}
|
}
|
||||||
</ion-grid>
|
</ion-grid>
|
||||||
<ion-grid [fixed]="'fixed'" class="ion-margin-top">
|
<ion-grid [fixed]="'fixed'" class="ion-margin-top bottom-lists">
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col [size]="4">Játékvezetők</ion-col>
|
<ion-col [size]="4">
|
||||||
<ion-col [size]="4">Adogatásbírók</ion-col>
|
<ion-item color="primary">
|
||||||
<ion-col [size]="4">Pihenők</ion-col>
|
<ion-label class="ion-text-center"> Játékvezetők </ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col [size]="4">
|
||||||
|
<ion-item color="primary">
|
||||||
|
<ion-label class="ion-text-center"> Adogatásbírók </ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-col>
|
||||||
|
<ion-col [size]="4">
|
||||||
|
<ion-item color="primary">
|
||||||
|
<ion-label class="ion-text-center"> Pihenők </ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
<ion-row>
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
@@ -38,19 +78,12 @@
|
|||||||
cdkDropList
|
cdkDropList
|
||||||
cdkDropListSortingDisabled
|
cdkDropListSortingDisabled
|
||||||
id="list-waiting-umpires"
|
id="list-waiting-umpires"
|
||||||
[cdkDropListData]="waitingUmpires"
|
[cdkDropListData]="waitingUmpires()"
|
||||||
(cdkDropListDropped)="dropToWaitingUmpire($event)"
|
(cdkDropListDropped)="dropToWaitingUmpire($event)">
|
||||||
[cdkDropListConnectedTo]="['list-on-rest', 'list-waiting-service-judges']">
|
@for (umpire of waitingUmpires(); track umpire.id) {
|
||||||
@for (umpire of waitingUmpires; track umpire.id) {
|
|
||||||
<ion-item cdkDrag [cdkDragData]="umpire">
|
<ion-item cdkDrag [cdkDragData]="umpire">
|
||||||
<ion-label>{{ umpire|fullname }}</ion-label>
|
<ion-label>{{ umpire|fullname }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
} @empty {
|
|
||||||
<ion-item>
|
|
||||||
<ion-label class="ion-text-center">
|
|
||||||
<ion-icon [color]="'primary'" name="add"></ion-icon>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
}
|
}
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
@@ -60,19 +93,12 @@
|
|||||||
cdkDropList
|
cdkDropList
|
||||||
cdkDropListSortingDisabled
|
cdkDropListSortingDisabled
|
||||||
id="list-waiting-service-judges"
|
id="list-waiting-service-judges"
|
||||||
[cdkDropListData]="waitingServiceJudges"
|
[cdkDropListData]="waitingServiceJudges()"
|
||||||
(cdkDropListDropped)="dropToWaitingServiceJudge($event)"
|
(cdkDropListDropped)="dropToWaitingServiceJudge($event)">
|
||||||
[cdkDropListConnectedTo]="['list-on-rest', 'list-waiting-umpires']">
|
@for (umpire of waitingServiceJudges(); track umpire.id) {
|
||||||
@for (umpire of waitingServiceJudges; track umpire.id) {
|
|
||||||
<ion-item cdkDrag [cdkDragData]="umpire">
|
<ion-item cdkDrag [cdkDragData]="umpire">
|
||||||
<ion-label>{{ umpire|fullname }}</ion-label>
|
<ion-label>{{ umpire|fullname }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
} @empty {
|
|
||||||
<ion-item>
|
|
||||||
<ion-label class="ion-text-center">
|
|
||||||
<ion-icon [color]="'primary'" name="add"></ion-icon>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
}
|
}
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
@@ -83,9 +109,8 @@
|
|||||||
cdkDropListSortingDisabled
|
cdkDropListSortingDisabled
|
||||||
id="list-on-rest"
|
id="list-on-rest"
|
||||||
(cdkDropListDropped)="dropToRest($event)"
|
(cdkDropListDropped)="dropToRest($event)"
|
||||||
[cdkDropListData]="onRest"
|
[cdkDropListData]="onRest()">
|
||||||
[cdkDropListConnectedTo]="['list-waiting-service-judges', 'list-waiting-umpires']">
|
@for (umpire of onRest(); track umpire.id) {
|
||||||
@for (umpire of onRest; track umpire.id) {
|
|
||||||
<ion-item cdkDrag [cdkDragData]="umpire">
|
<ion-item cdkDrag [cdkDragData]="umpire">
|
||||||
<ion-label>{{ umpire|fullname }}</ion-label>
|
<ion-label>{{ umpire|fullname }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.bottom-lists ion-list {
|
||||||
|
min-height: 64px;
|
||||||
|
}
|
||||||
+212
-41
@@ -1,4 +1,4 @@
|
|||||||
import { Component, effect, inject } from '@angular/core';
|
import { Component, computed, effect, inject } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
IonHeader,
|
IonHeader,
|
||||||
IonToolbar,
|
IonToolbar,
|
||||||
@@ -25,15 +25,14 @@ import {
|
|||||||
DragDropModule
|
DragDropModule
|
||||||
} from '@angular/cdk/drag-drop';
|
} from '@angular/cdk/drag-drop';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { addIcons } from 'ionicons';
|
import { CourtUmpireService } from '../services/court.umpire.service';
|
||||||
import { add } from 'ionicons/icons';
|
import { CourtServiceJudgeService } from '../services/court.service.judge.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tab1',
|
selector: 'app-tab1',
|
||||||
templateUrl: 'tab1.page.html',
|
templateUrl: 'tab1.page.html',
|
||||||
styleUrls: ['tab1.page.scss'],
|
styleUrls: ['tab1.page.scss'],
|
||||||
imports: [
|
imports: [
|
||||||
IonIcon,
|
|
||||||
IonLabel,
|
IonLabel,
|
||||||
IonItem,
|
IonItem,
|
||||||
IonList,
|
IonList,
|
||||||
@@ -56,63 +55,207 @@ export class Tab1Page {
|
|||||||
readonly umpireService = inject(UmpireService);
|
readonly umpireService = inject(UmpireService);
|
||||||
readonly waitingUmpireService = inject(WaitingUmpiresService);
|
readonly waitingUmpireService = inject(WaitingUmpiresService);
|
||||||
readonly waitingServiceJudgeService = inject(WaitingServiceJudgesService);
|
readonly waitingServiceJudgeService = inject(WaitingServiceJudgesService);
|
||||||
|
readonly courtUmpireService = inject(CourtUmpireService);
|
||||||
|
readonly courtServiceJudgeService = inject(CourtServiceJudgeService);
|
||||||
|
|
||||||
public readonly settings = this.settingsService.settings;
|
/**
|
||||||
public readonly _umpires = this.umpireService.umpires;
|
* Raw signals from services
|
||||||
public readonly _waitingUmpires = this.waitingUmpireService.waitingUmpires;
|
*/
|
||||||
public readonly _waitingServiceJudges =
|
readonly settings = this.settingsService.settings;
|
||||||
|
|
||||||
|
readonly _umpires = this.umpireService.umpires;
|
||||||
|
|
||||||
|
readonly _waitingUmpires = this.waitingUmpireService.waitingUmpires;
|
||||||
|
|
||||||
|
readonly _waitingServiceJudges =
|
||||||
this.waitingServiceJudgeService.waitingServiceJudges;
|
this.waitingServiceJudgeService.waitingServiceJudges;
|
||||||
|
|
||||||
public onRest: Umpire[] = [];
|
readonly _courtUmpires = this.courtUmpireService.umpires;
|
||||||
public waitingUmpires: Umpire[] = [];
|
|
||||||
public waitingServiceJudges: Umpire[] = [];
|
|
||||||
|
|
||||||
constructor() {
|
readonly _courtServiceJudges = this.courtServiceJudgeService.umpires;
|
||||||
addIcons({ add });
|
|
||||||
|
|
||||||
effect(() => {
|
/**
|
||||||
this.onRest = this._umpires().filter((umpire) => {
|
* Fast O(1) umpire lookup
|
||||||
return (
|
*/
|
||||||
!this.isUmpireOnCourt(umpire) &&
|
readonly umpireMap = computed(() => {
|
||||||
!this.isWaitingUmpire(umpire) &&
|
return new Map<number, Umpire>(this._umpires().map((u) => [u.id, u]));
|
||||||
!this.isWaitingServiceJudge(umpire)
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waiting umpire IDs
|
||||||
|
*/
|
||||||
|
readonly waitingUmpireIds = computed(() => {
|
||||||
|
return new Set(this._waitingUmpires().map((w) => w.umpireId));
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waiting service judge IDs
|
||||||
|
*/
|
||||||
|
readonly waitingServiceJudgeIds = computed(() => {
|
||||||
|
return new Set(this._waitingServiceJudges().map((w) => w.serviceJudgeId));
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Court umpire IDs
|
||||||
|
*/
|
||||||
|
readonly courtUmpireIds = computed(() => {
|
||||||
|
return new Set(
|
||||||
|
this._courtUmpires()
|
||||||
|
.map((c) => c.umpireId)
|
||||||
|
.filter((id): id is number => id !== null)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.waitingUmpires = this._waitingUmpires()
|
/**
|
||||||
.map((_wa) => {
|
* Court service judge IDs
|
||||||
return this._umpires().find((u) => u.id === _wa.umpireId);
|
*/
|
||||||
})
|
readonly courtServiceJudgeIds = computed(() => {
|
||||||
.filter((u) => typeof u !== 'undefined');
|
return new Set(
|
||||||
|
this._courtServiceJudges()
|
||||||
this.waitingServiceJudges = this._waitingServiceJudges()
|
.map((c) => c.umpireId)
|
||||||
.map((_wsj) => {
|
.filter((id): id is number => id !== null)
|
||||||
return this._umpires().find((u) => u.id === _wsj.serviceJudgeId);
|
);
|
||||||
})
|
|
||||||
.filter((u) => typeof u !== 'undefined');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Umpires waiting as umpire
|
||||||
|
*/
|
||||||
|
readonly waitingUmpires = computed(() => {
|
||||||
|
const umpireMap = this.umpireMap();
|
||||||
|
|
||||||
|
return this._waitingUmpires()
|
||||||
|
.map((wu) => umpireMap.get(wu.umpireId))
|
||||||
|
.filter((u): u is Umpire => !!u);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Umpires waiting as service judge
|
||||||
|
*/
|
||||||
|
readonly waitingServiceJudges = computed(() => {
|
||||||
|
const umpireMap = this.umpireMap();
|
||||||
|
|
||||||
|
return this._waitingServiceJudges()
|
||||||
|
.map((wsj) => umpireMap.get(wsj.serviceJudgeId))
|
||||||
|
.filter((u): u is Umpire => !!u);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Court umpires
|
||||||
|
*/
|
||||||
|
readonly courtUmpires = computed(() => {
|
||||||
|
const umpireMap = this.umpireMap();
|
||||||
|
|
||||||
|
return this._courtUmpires()
|
||||||
|
.map((cu) => {
|
||||||
|
if (cu.umpireId == null) {
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isUmpireOnCourt(umpire: Umpire): boolean {
|
return umpireMap.get(cu.umpireId);
|
||||||
return false;
|
})
|
||||||
|
.filter((u): u is Umpire => !!u);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Court service judges
|
||||||
|
*/
|
||||||
|
readonly courtServiceJudges = computed(() => {
|
||||||
|
const umpireMap = this.umpireMap();
|
||||||
|
|
||||||
|
return this._courtServiceJudges()
|
||||||
|
.map((csj) => {
|
||||||
|
if (csj.umpireId == null) {
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isWaitingUmpire(umpire: Umpire): boolean {
|
return umpireMap.get(csj.umpireId);
|
||||||
|
})
|
||||||
|
.filter((u): u is Umpire => !!u);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Umpires resting
|
||||||
|
*/
|
||||||
|
readonly onRest = computed(() => {
|
||||||
|
const waitingUmpireIds = this.waitingUmpireIds();
|
||||||
|
|
||||||
|
const waitingServiceJudgeIds = this.waitingServiceJudgeIds();
|
||||||
|
|
||||||
|
const courtUmpireIds = this.courtUmpireIds();
|
||||||
|
|
||||||
|
const courtServiceJudgeIds = this.courtServiceJudgeIds();
|
||||||
|
|
||||||
|
return this._umpires().filter((umpire) => {
|
||||||
return (
|
return (
|
||||||
typeof this._waitingUmpires().find((wu) => wu.umpireId === umpire.id) !==
|
!waitingUmpireIds.has(umpire.id) &&
|
||||||
'undefined'
|
!waitingServiceJudgeIds.has(umpire.id) &&
|
||||||
|
!courtUmpireIds.has(umpire.id) &&
|
||||||
|
!courtServiceJudgeIds.has(umpire.id)
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Court -> umpire map
|
||||||
|
*/
|
||||||
|
readonly umpireByCourt = computed(() => {
|
||||||
|
const map = new Map<number, Umpire>();
|
||||||
|
|
||||||
|
const umpireMap = this.umpireMap();
|
||||||
|
|
||||||
|
for (const item of this._courtUmpires()) {
|
||||||
|
if (item.umpireId == null) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private isWaitingServiceJudge(umpire: Umpire): boolean {
|
const umpire = umpireMap.get(item.umpireId);
|
||||||
return (
|
|
||||||
typeof this._waitingServiceJudges().find(
|
if (!umpire) {
|
||||||
(wsj) => wsj.serviceJudgeId === umpire.id
|
continue;
|
||||||
) !== 'undefined'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map.set(item.courtNo, umpire);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Court -> service judge map
|
||||||
|
*/
|
||||||
|
readonly serviceJudgeByCourt = computed(() => {
|
||||||
|
const map = new Map<number, Umpire>();
|
||||||
|
|
||||||
|
const umpireMap = this.umpireMap();
|
||||||
|
|
||||||
|
for (const item of this._courtServiceJudges()) {
|
||||||
|
if (item.umpireId == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const umpire = umpireMap.get(item.umpireId);
|
||||||
|
|
||||||
|
if (!umpire) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
map.set(item.courtNo, umpire);
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Court indexes for template
|
||||||
|
*/
|
||||||
|
readonly courtIndexes = computed(() => {
|
||||||
|
const count = this.settings()?.numberOfCourts ?? 0;
|
||||||
|
|
||||||
|
return Array.from({ length: count }, (_, i) => i + 1);
|
||||||
|
});
|
||||||
|
|
||||||
dropToRest(event: CdkDragDrop<Umpire[]>) {
|
dropToRest(event: CdkDragDrop<Umpire[]>) {
|
||||||
|
console.log('drop to rest');
|
||||||
if (event.previousContainer === event.container) {
|
if (event.previousContainer === event.container) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@@ -126,6 +269,10 @@ export class Tab1Page {
|
|||||||
if ('list-waiting-umpires' === comingFrom) {
|
if ('list-waiting-umpires' === comingFrom) {
|
||||||
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
|
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comingFrom.startsWith('court-umpire')) {
|
||||||
|
this.courtUmpireService.removeByUmpireId(umpireToMove.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +287,10 @@ export class Tab1Page {
|
|||||||
if ('list-waiting-umpires' === comingFrom) {
|
if ('list-waiting-umpires' === comingFrom) {
|
||||||
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
|
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comingFrom.startsWith('court-umpire')) {
|
||||||
|
this.courtUmpireService.removeByUmpireId(umpireToMove.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,6 +312,26 @@ export class Tab1Page {
|
|||||||
// Remove from waiting service judges
|
// Remove from waiting service judges
|
||||||
this.waitingServiceJudgeService.removeByUmpireId(umpireToMove.id);
|
this.waitingServiceJudgeService.removeByUmpireId(umpireToMove.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comingFrom.startsWith('court-umpire')) {
|
||||||
|
this.courtUmpireService.removeByUmpireId(umpireToMove.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dropToUmpire(event: CdkDragDrop<Umpire[]>, courtNo: number) {
|
||||||
|
// TODO: stop dropping if there is already another umpire
|
||||||
|
|
||||||
|
const comingFrom = event.previousContainer.id;
|
||||||
|
const umpireToMove = event.item.data;
|
||||||
|
this.courtUmpireService.save({ umpireId: umpireToMove.id, courtNo });
|
||||||
|
|
||||||
|
if ('list-waiting-service-judges' === comingFrom) {
|
||||||
|
this.waitingServiceJudgeService.removeByUmpireId(umpireToMove.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('list-waiting-umpires' === comingFrom) {
|
||||||
|
this.waitingUmpireService.removeByUmpireId(umpireToMove.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
// For information on how to create your own theme, please refer to:
|
// For information on how to create your own theme, please refer to:
|
||||||
// https://ionicframework.com/docs/theming/
|
// https://ionicframework.com/docs/theming/
|
||||||
|
@import '@ionic/angular/css/palettes/dark.always.css';
|
||||||
Reference in New Issue
Block a user