Skip to content

Commit

Permalink
Feature/963 report behavior has new collectible info about transporte…
Browse files Browse the repository at this point in the history
…d patients (#978)

* Add transfer counts radiogram

* Add empty radiogram component

* Make transfer counts radiogram reportable

* Display information of transfer counts radiogram

* Add changes to changelog

* Add test scenario

* Use more descriptive radiogram title

* Use more descriptive table header

* Support all triage categories

* Update test scenarios to use all triage categories

* Extract scope type to utils
  • Loading branch information
lukasrad02 authored May 11, 2023
1 parent dd46e03 commit d3e33b7
Show file tree
Hide file tree
Showing 15 changed files with 224 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project does **not** adhere to [Semantic Versioning](https://semver.org
- Selected material, personnel and vehicles are now highlighted on the map.
- When material or personnel is selected, the corresponding vehicle is highlighted as well.
- When a vehicle is selected, the corresponding material and personnel are highlighted as well.
- The reports behavior can generate reports on the counts of transferred patients per triage category.

### Changed

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const map: { [Key in ExerciseRadiogram['type']]: string } = {
treatmentStatusRadiogram: 'Behandlungsstatus',
vehicleCountRadiogram: 'Anzahl an Fahrzeugen',
resourceRequestRadiogram: 'Anfrage nach Fahrzeugen',
transferCountsRadiogram: 'Anzahl abtransportierter Patienten',
};

@Pipe({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<h5>Transportstatus</h5>

<ng-container *appLet="radiogram$ | async as radiogram">
<p *ngIf="radiogram.scope === 'singleRegion'">Für diese Patientenablage.</p>
<p *ngIf="radiogram.scope === 'transportManagement'">
Für alle von dieser Transportorganisation verwalteten Patientenablagen.
</p>

<table class="table table-sm w-100">
<thead>
<tr>
<th>SK</th>
<th>Abtransportiert</th>
<th>Verbleibend</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let category of alwaysShowCategories">
<td>
<app-patient-status-badge [status]="category" />
</td>
<td>
{{ radiogram.transferredPatientsCounts[category] }}
</td>
<td>
{{ radiogram.remainingPatientsCounts[category] }}
</td>
</tr>
<ng-container
*ngFor="let category of showIfTransferredOrRemainingCategories"
>
<tr
*ngIf="
radiogram.transferredPatientsCounts[category] > 0 ||
radiogram.remainingPatientsCounts[category] > 0
"
>
<td>
<app-patient-status-badge [status]="category" />
</td>
<td>
{{ radiogram.transferredPatientsCounts[category] }}
</td>
<td>
{{ radiogram.remainingPatientsCounts[category] }}
</td>
</tr>
</ng-container>
<ng-container *ngFor="let category of showIfTransferredCategories">
<tr *ngIf="radiogram.transferredPatientsCounts[category] > 0">
<td>
<app-patient-status-badge [status]="category" />
</td>
<td>
{{ radiogram.transferredPatientsCounts[category] }}
</td>
<td>
{{ radiogram.remainingPatientsCounts[category] }}
</td>
</tr>
</ng-container>
</tbody>
</table>
</ng-container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { OnInit } from '@angular/core';
import { Component, Input } from '@angular/core';
import { Store } from '@ngrx/store';
import type { TransferCountsRadiogram } from 'digital-fuesim-manv-shared';
import { UUID } from 'digital-fuesim-manv-shared';
import type { Observable } from 'rxjs';
import type { AppState } from 'src/app/state/app.state';
import { createSelectRadiogram } from 'src/app/state/application/selectors/exercise.selectors';

@Component({
selector: 'app-radiogram-card-content-transfer-counts',
templateUrl: './radiogram-card-content-transfer-counts.component.html',
styleUrls: ['./radiogram-card-content-transfer-counts.component.scss'],
})
export class RadiogramCardContentTransferCountsComponent implements OnInit {
/**
* Categories that should always be listed in the table.
*/
readonly alwaysShowCategories = ['red', 'yellow', 'green'] as const;

/**
* Categories that should be listed in the table if patients of these categories have been transferred and/or are remaining.
*/
readonly showIfTransferredOrRemainingCategories = [
'blue',
'white',
] as const;

/**
* Categories that should only be listed in the table if patients of these categories have been transferred.
* (Black patients should usually never be transferred, so its okay to not show their remaining number.)
*/
readonly showIfTransferredCategories = ['black'] as const;

@Input() radiogramId!: UUID;

radiogram$!: Observable<TransferCountsRadiogram>;

constructor(private readonly store: Store<AppState>) {}

ngOnInit(): void {
this.radiogram$ = this.store.select(
createSelectRadiogram<TransferCountsRadiogram>(this.radiogramId)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,42 @@
<app-radiogram-card-content-vehicle-count
*ngSwitchCase="'vehicleCountRadiogram'"
[radiogramId]="radiogram.id"
></app-radiogram-card-content-vehicle-count>
/>
<app-radiogram-card-content-patient-count
*ngSwitchCase="'patientCountRadiogram'"
[radiogramId]="radiogram.id"
>
</app-radiogram-card-content-patient-count>
/>
<app-radiogram-card-content-treatment-status
*ngSwitchCase="'treatmentStatusRadiogram'"
[radiogramId]="radiogram.id"
></app-radiogram-card-content-treatment-status>
/>
<app-radiogram-card-content-personnel-count
*ngSwitchCase="'personnelCountRadiogram'"
[radiogramId]="radiogram.id"
></app-radiogram-card-content-personnel-count>
/>
<app-radiogram-card-content-material-count
*ngSwitchCase="'materialCountRadiogram'"
[radiogramId]="radiogram.id"
></app-radiogram-card-content-material-count>
/>
<app-radigoram-card-content-missing-transfer-connection
*ngSwitchCase="'missingTransferConnectionRadiogram'"
[radiogramId]="radiogram.id"
></app-radigoram-card-content-missing-transfer-connection>
/>
<app-radigoram-card-content-resource-request
*ngSwitchCase="'resourceRequestRadiogram'"
[radiogramId]="radiogram.id"
></app-radigoram-card-content-resource-request>
/>
<app-radiogram-card-content-transfer-counts
*ngSwitchCase="'transferCountsRadiogram'"
[radiogramId]="radiogram.id"
/>
<app-radiogram-card-content-fallback
*ngSwitchDefault
[radiogramType]="radiogram.type"
></app-radiogram-card-content-fallback>
/>
</ng-container>
<ng-template #informationUnavailable>
<app-radiogram-card-content-information-unavailable
[radiogramType]="radiogram.type"
></app-radiogram-card-content-information-unavailable>
/>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import { SimulatedRegionOverviewVehiclesTabComponent } from './tabs/vehicles-tab
import { SimulatedRegionOverviewPatientsTableComponent } from './patients-table/simulated-region-overview-patients-table.component';
import { StartTransferService } from './start-transfer.service';
import { SimulatedRegionOverviewBehaviorTransferVehiclesComponent } from './tabs/behavior-tab/behaviors/transfer-vehicles/simulated-region-overview-behavior-transfer-vehicles.component';
import { RadiogramCardContentTransferCountsComponent } from './radiogram-list/radiogram-card/radiogram-card-content-transfer-counts/radiogram-card-content-transfer-counts.component';

@NgModule({
declarations: [
Expand Down Expand Up @@ -90,6 +91,7 @@ import { SimulatedRegionOverviewBehaviorTransferVehiclesComponent } from './tabs
SimulatedRegionOverviewVehiclesTabComponent,
SimulatedRegionOverviewPatientsTableComponent,
SimulatedRegionOverviewBehaviorTransferVehiclesComponent,
RadiogramCardContentTransferCountsComponent,
],
imports: [
FormsModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class SimulatedRegionOverviewBehaviorReportComponent implements OnInit {
personnelCount: 'Anzahl an Rettungskräften',
materialCount: 'Anzahl an Material',
treatmentStatus: 'Behandlungsstatus',
transferCounts: 'Anzahl der ins Krankenhaus transportierten Patienten',
};

createReportCollapsed = true;
Expand Down
3 changes: 3 additions & 0 deletions shared/src/models/radiogram/exercise-radiogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import { Radiogram } from './radiogram';
import { TreatmentStatusRadiogram } from './treatment-status-radiogram';
import { VehicleCountRadiogram } from './vehicle-count-radiogram';
import { ResourceRequestRadiogram } from './resource-request-radiogram';
import { TransferCountsRadiogram } from './transfer-counts-radiogram';

export const radiograms = {
MaterialCountRadiogram,
MissingTransferConnectionRadiogram,
PatientCountRadiogram,
PersonnelCountRadiogram,
ResourceRequestRadiogram,
TransferCountsRadiogram,
TreatmentStatusRadiogram,
VehicleCountRadiogram,
};
Expand All @@ -33,6 +35,7 @@ export const radiogramDictionary: ExerciseRadiogramDictionary = {
patientCountRadiogram: PatientCountRadiogram,
personnelCountRadiogram: PersonnelCountRadiogram,
resourceRequestRadiogram: ResourceRequestRadiogram,
transferCountsRadiogram: TransferCountsRadiogram,
treatmentStatusRadiogram: TreatmentStatusRadiogram,
vehicleCountRadiogram: VehicleCountRadiogram,
};
Expand Down
2 changes: 2 additions & 0 deletions shared/src/models/radiogram/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from './treatment-status-radiogram';
export * from './vehicle-count-radiogram';
export * from './resource-request-radiogram';
export * from './status';
export * from './transfer-counts-radiogram';
export * from './utils';
77 changes: 77 additions & 0 deletions shared/src/models/radiogram/transfer-counts-radiogram.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { IsBoolean, IsUUID, ValidateNested } from 'class-validator';
import { UUID, uuidValidationOptions } from '../../utils';
import { IsLiteralUnion, IsValue } from '../../utils/validators';
import { IsRadiogramStatus } from '../../utils/validators/is-radiogram-status';
import type { PatientStatus } from '../utils';
import { getCreate } from '../utils';
import { ResourceDescription } from '../utils/resource-description';
import { IsResourceDescription } from '../../utils/validators/is-resource-description';
import type { Radiogram } from './radiogram';
import { ExerciseRadiogramStatus } from './status/exercise-radiogram-status';
import { Scope, scopeAllowedValues } from './utils/scope';

export class TransferCountsRadiogram implements Radiogram {
@IsUUID(4, uuidValidationOptions)
readonly id: UUID;

@IsValue('transferCountsRadiogram')
readonly type = 'transferCountsRadiogram';

@IsUUID(4, uuidValidationOptions)
readonly simulatedRegionId: UUID;

/**
* @deprecated use the helpers from {@link radiogram-helpers.ts}
* or {@link radiogram-helpers-mutable.ts} instead
*/
@IsRadiogramStatus()
@ValidateNested()
readonly status: ExerciseRadiogramStatus;

@IsBoolean()
readonly informationAvailable: boolean = false;

@IsResourceDescription()
readonly transferredPatientsCounts: ResourceDescription<PatientStatus> = {
red: 0,
yellow: 0,
green: 0,
blue: 0,
black: 0,
white: 0,
};

@IsResourceDescription()
readonly remainingPatientsCounts: ResourceDescription<PatientStatus> = {
red: 0,
yellow: 0,
green: 0,
blue: 0,
black: 0,
white: 0,
};

/**
* Defines the scope of the counts reported with this radiogram.
* * `singleRegion`: The patient counts refer only to the simulated region that sent the radiogram
* * `transportManagement`: The patient counts refer to all simulated regions
* that are managed by the transport management behavior of the simulated region that sent the radiogram
*/
@IsLiteralUnion(scopeAllowedValues)
readonly scope: Scope = 'singleRegion';

/**
* @deprecated Use {@link create} instead
*/
constructor(
id: UUID,
simulatedRegionId: UUID,
status: ExerciseRadiogramStatus
) {
this.id = id;
this.simulatedRegionId = simulatedRegionId;
this.status = status;
}

static readonly create = getCreate(this);
}
1 change: 1 addition & 0 deletions shared/src/models/radiogram/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './scope';
8 changes: 8 additions & 0 deletions shared/src/models/radiogram/utils/scope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { AllowedValues } from '../../../utils/validators';

export type Scope = 'singleRegion' | 'transportManagement';

export const scopeAllowedValues: AllowedValues<Scope> = {
singleRegion: true,
transportManagement: true,
};
4 changes: 4 additions & 0 deletions shared/src/simulation/behaviors/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TransferCountsRadiogram } from '../../models/radiogram';
import type { ExerciseRadiogram } from '../../models/radiogram/exercise-radiogram';
import { MaterialCountRadiogram } from '../../models/radiogram/material-count-radiogram';
import { PatientCountRadiogram } from '../../models/radiogram/patient-count-radiogram';
Expand All @@ -14,6 +15,7 @@ export const reportableInformationAllowedValues: AllowedValues<ReportableInforma
patientCount: true,
personnelCount: true,
vehicleCount: true,
transferCounts: true,
treatmentStatus: true,
materialCount: true,
};
Expand All @@ -26,6 +28,7 @@ export type ReportableInformation =
| 'materialCount'
| 'patientCount'
| 'personnelCount'
| 'transferCounts'
| 'treatmentStatus'
| 'vehicleCount';

Expand All @@ -39,6 +42,7 @@ export const createRadiogramMap: {
patientCount: PatientCountRadiogram.create,
personnelCount: PersonnelCountRadiogram.create,
vehicleCount: VehicleCountRadiogram.create,
transferCounts: TransferCountsRadiogram.create,
treatmentStatus: TreatmentStatusRadiogram.create,
materialCount: MaterialCountRadiogram.create,
};

0 comments on commit d3e33b7

Please sign in to comment.