init dashboard
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
.month-picker .mat-calendar-period-button {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.month-picker .mat-calendar-arrow {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
<ng-container *ngIf="vm$ | async as vm; else loadingTmpl">
|
||||
<div class="flex flex-col m-0 md:m-4" *ngIf="!vm.isLoading; else loadingTmpl">
|
||||
<!-- Top row with user input elements -->
|
||||
<div class="flex flex-wrap md:flex-nowrap justify-between items-center">
|
||||
<div class="flex items-center m-2">
|
||||
<button mat-icon-button (click)="addMonthToSelectedDate(-1)">
|
||||
<mat-icon>chevron_left</mat-icon>
|
||||
</button>
|
||||
<div class="flex items-center">
|
||||
<span class="pr-2">
|
||||
{{ vm.selectedDate | date : 'MM.yyyy' }}
|
||||
</span>
|
||||
<input
|
||||
[formControl]="selectedDate"
|
||||
[matDatepicker]="picker"
|
||||
[matDatepickerFilter]="notSunday"
|
||||
[min]="minSelectableDate"
|
||||
class="invisible w-0"
|
||||
/>
|
||||
<button mat-icon-button (click)="picker.open()">
|
||||
<mat-icon>today</mat-icon>
|
||||
</button>
|
||||
<mat-datepicker
|
||||
#picker
|
||||
startView="multi-year"
|
||||
(monthSelected)="setMonthAndYear($event, picker)"
|
||||
class="month-picker"
|
||||
></mat-datepicker>
|
||||
</div>
|
||||
<button mat-icon-button (click)="addMonthToSelectedDate(1)">
|
||||
<mat-icon>chevron_right</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<mat-chip-listbox (change)="changeSelectedType($event)">
|
||||
<mat-chip-option
|
||||
[value]="DiagrammType.TimePerTour"
|
||||
[selected]="vm.selectedMetric === DiagrammType.TimePerTour"
|
||||
>
|
||||
Kapazität pro Tour
|
||||
</mat-chip-option>
|
||||
<mat-chip-option
|
||||
[value]="DiagrammType.BreakEven"
|
||||
[selected]="vm.selectedMetric === DiagrammType.BreakEven"
|
||||
>
|
||||
Deckungsbeitrag
|
||||
</mat-chip-option>
|
||||
<mat-chip-option
|
||||
[value]="DiagrammType.AverageRevenue"
|
||||
[selected]="vm.selectedMetric === DiagrammType.AverageRevenue"
|
||||
>
|
||||
Durchschnittsumsatz
|
||||
</mat-chip-option>
|
||||
</mat-chip-listbox>
|
||||
</div>
|
||||
<div
|
||||
class="my-5 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2 lg:gap-4"
|
||||
>
|
||||
<dks-view-type-selector
|
||||
[viewType]="DashboardViewType.BTW"
|
||||
[currentMetric]="vm.selectedMetric"
|
||||
[metrics]="vm.btwMetrics"
|
||||
[selected]="vm.selectedViewType === DashboardViewType.BTW"
|
||||
(viewTypeSelected)="setSelectedViewType(DashboardViewType.BTW)"
|
||||
></dks-view-type-selector>
|
||||
<dks-view-type-selector
|
||||
[viewType]="DashboardViewType.TSW"
|
||||
[currentMetric]="vm.selectedMetric"
|
||||
[metrics]="vm.tswMetrics"
|
||||
[selected]="vm.selectedViewType === DashboardViewType.TSW"
|
||||
(viewTypeSelected)="setSelectedViewType(DashboardViewType.TSW)"
|
||||
></dks-view-type-selector>
|
||||
<dks-view-type-selector
|
||||
[viewType]="DashboardViewType.KTW"
|
||||
[currentMetric]="vm.selectedMetric"
|
||||
[metrics]="vm.ktwMetrics"
|
||||
[selected]="vm.selectedViewType === DashboardViewType.KTW"
|
||||
(viewTypeSelected)="setSelectedViewType(DashboardViewType.KTW)"
|
||||
></dks-view-type-selector>
|
||||
<dks-view-type-selector
|
||||
[viewType]="DashboardViewType.Gesamt"
|
||||
[currentMetric]="vm.selectedMetric"
|
||||
[metrics]="vm.combinedMetrics"
|
||||
[selected]="vm.selectedViewType === DashboardViewType.Gesamt"
|
||||
(viewTypeSelected)="setSelectedViewType(DashboardViewType.Gesamt)"
|
||||
></dks-view-type-selector>
|
||||
</div>
|
||||
<div
|
||||
class="grid grid-cols-2 lg:grid-cols-4 gap-2 lg:gap-4"
|
||||
[ngSwitch]="vm.selectedViewType"
|
||||
>
|
||||
<div
|
||||
*ngSwitchCase="DashboardViewType.BTW"
|
||||
class="col-span-2 lg:col-span-4 w-full rounded p-2 bg-white shadow"
|
||||
>
|
||||
<dks-metric-summary
|
||||
[metrics]="vm.btwMetrics"
|
||||
[metricTimeScale]="metricTimeScale"
|
||||
[selectedMetric]="vm.selectedMetric"
|
||||
[labelFormat]="'d.M.yy'"
|
||||
></dks-metric-summary>
|
||||
</div>
|
||||
<div
|
||||
*ngSwitchCase="DashboardViewType.TSW"
|
||||
class="col-span-2 lg:col-span-4 w-full rounded p-2 bg-white shadow"
|
||||
>
|
||||
<dks-metric-summary
|
||||
[metrics]="vm.tswMetrics"
|
||||
[metricTimeScale]="metricTimeScale"
|
||||
[selectedMetric]="vm.selectedMetric"
|
||||
[labelFormat]="'d.M.yy'"
|
||||
></dks-metric-summary>
|
||||
</div>
|
||||
<div
|
||||
*ngSwitchCase="DashboardViewType.KTW"
|
||||
class="col-span-2 lg:col-span-4 w-full rounded p-2 bg-white shadow"
|
||||
>
|
||||
<dks-metric-summary
|
||||
[metrics]="vm.ktwMetrics"
|
||||
[metricTimeScale]="metricTimeScale"
|
||||
[selectedMetric]="vm.selectedMetric"
|
||||
[labelFormat]="'d.M.yy'"
|
||||
></dks-metric-summary>
|
||||
</div>
|
||||
<div
|
||||
*ngSwitchCase="DashboardViewType.Gesamt"
|
||||
class="col-span-2 lg:col-span-4 w-full rounded p-2 bg-white shadow"
|
||||
>
|
||||
<dks-metric-summary
|
||||
[metrics]="vm.combinedMetrics"
|
||||
[metricTimeScale]="metricTimeScale"
|
||||
[selectedMetric]="vm.selectedMetric"
|
||||
[labelFormat]="'d.M.yy'"
|
||||
></dks-metric-summary>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #loadingTmpl>
|
||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MonthviewComponent } from './monthview.component';
|
||||
|
||||
describe('MonthviewComponent', () => {
|
||||
let component: MonthviewComponent;
|
||||
let fixture: ComponentFixture<MonthviewComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [MonthviewComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MonthviewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,139 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { MatChipListboxChange } from '@angular/material/chips';
|
||||
import { MatDatepicker } from '@angular/material/datepicker';
|
||||
import { addDays, addMonths, format, isSunday, startOfMonth } from 'date-fns';
|
||||
import {
|
||||
BehaviorSubject,
|
||||
combineLatest,
|
||||
map,
|
||||
startWith,
|
||||
switchMap,
|
||||
} from 'rxjs';
|
||||
import { groupBy } from '../../../core/util/group-by';
|
||||
import { ManagerDashboardService } from '../manager-dashboard.service';
|
||||
import {
|
||||
DashboardViewType,
|
||||
DiagrammType,
|
||||
MetricTimeScale,
|
||||
OrdinanceTypes,
|
||||
} from '../types';
|
||||
import { mergeMetrics } from '../util/merge-metric';
|
||||
|
||||
@Component({
|
||||
selector: 'dks-monthview',
|
||||
templateUrl: './monthview.component.html',
|
||||
styleUrls: ['./monthview.component.css'],
|
||||
})
|
||||
export class MonthviewComponent {
|
||||
OrdinanceTypes = OrdinanceTypes;
|
||||
DiagrammType = DiagrammType;
|
||||
DashboardViewType = DashboardViewType;
|
||||
minSelectableDate = new Date('2022-08-01');
|
||||
metricTimeScale = MetricTimeScale.Monthview;
|
||||
selectedDate = new FormControl<Date>(addDays(startOfMonth(new Date()), 1));
|
||||
selectedDate$ = this.selectedDate.valueChanges.pipe(
|
||||
startWith(this.selectedDate.value)
|
||||
);
|
||||
selectedMetric$ = new BehaviorSubject<DiagrammType>(DiagrammType.TimePerTour);
|
||||
selectedViewType$ = new BehaviorSubject<DashboardViewType>(
|
||||
DashboardViewType.Gesamt
|
||||
);
|
||||
|
||||
vm$;
|
||||
|
||||
constructor(
|
||||
private readonly managerDashboardService: ManagerDashboardService
|
||||
) {
|
||||
this.vm$ = combineLatest([
|
||||
this.selectedDate$.pipe(
|
||||
switchMap((selectedDate) =>
|
||||
this.managerDashboardService.getTimePerTourMetricByOrdinanceTypeForMonth(
|
||||
OrdinanceTypes.BTW,
|
||||
selectedDate ?? new Date()
|
||||
)
|
||||
)
|
||||
),
|
||||
this.selectedDate$.pipe(
|
||||
switchMap((selectedDate) =>
|
||||
this.managerDashboardService.getTimePerTourMetricByOrdinanceTypeForMonth(
|
||||
OrdinanceTypes.TSW,
|
||||
selectedDate ?? new Date()
|
||||
)
|
||||
)
|
||||
),
|
||||
this.selectedDate$.pipe(
|
||||
switchMap((selectedDate) =>
|
||||
this.managerDashboardService.getTimePerTourMetricByOrdinanceTypeForMonth(
|
||||
OrdinanceTypes.KTW,
|
||||
selectedDate ?? new Date()
|
||||
)
|
||||
)
|
||||
),
|
||||
this.selectedMetric$,
|
||||
this.selectedDate$,
|
||||
this.managerDashboardService.isLoadingMonthview$,
|
||||
this.selectedViewType$,
|
||||
]).pipe(
|
||||
map(
|
||||
([
|
||||
btwMetrics,
|
||||
tswMetrics,
|
||||
ktwMetrics,
|
||||
selectedMetric,
|
||||
selectedDate,
|
||||
isLoading,
|
||||
selectedViewType,
|
||||
]) => ({
|
||||
btwMetrics,
|
||||
tswMetrics,
|
||||
ktwMetrics,
|
||||
selectedMetric,
|
||||
selectedDate,
|
||||
isLoading,
|
||||
selectedViewType,
|
||||
combinedMetrics: mergeMetrics(
|
||||
Object.values(
|
||||
groupBy(
|
||||
[...btwMetrics, ...tswMetrics, ...ktwMetrics],
|
||||
({ interval: { start } }) => format(new Date(start), 'd.M.yy')
|
||||
)
|
||||
)
|
||||
),
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
notSunday = (date: Date | null): boolean => {
|
||||
return !isSunday(date ?? new Date());
|
||||
};
|
||||
|
||||
addMonthToSelectedDate(months: number): void {
|
||||
const nextSelectedDate = addMonths(
|
||||
this.selectedDate.value ?? new Date(),
|
||||
months
|
||||
);
|
||||
if (isSunday(nextSelectedDate)) {
|
||||
this.selectedDate.setValue(addDays(nextSelectedDate, 1));
|
||||
} else {
|
||||
this.selectedDate.setValue(nextSelectedDate);
|
||||
}
|
||||
}
|
||||
|
||||
changeSelectedType(event: MatChipListboxChange) {
|
||||
this.selectedMetric$.next(event.value);
|
||||
}
|
||||
|
||||
setMonthAndYear(
|
||||
normalizedMonthAndYear: Date,
|
||||
datepicker: MatDatepicker<Date>
|
||||
) {
|
||||
this.selectedDate.setValue(addDays(normalizedMonthAndYear, 1));
|
||||
datepicker.close();
|
||||
}
|
||||
|
||||
setSelectedViewType(viewType: DashboardViewType) {
|
||||
this.selectedViewType$.next(viewType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user