From 71bbf50440fae5f33061fcba667c9989284704d3 Mon Sep 17 00:00:00 2001 From: Sebastian Leidig Date: Sat, 5 Sep 2020 17:34:26 +0200 Subject: [PATCH] feat(attendance): overview page for attendance register explaining different options and avoiding an immediate loading of lots of data (hopefully) closes #487 --- src/app/app.routing.ts | 2 + .../attendance-analysis.component.html | 205 +++++++++++++ .../attendance-analysis.component.scss | 19 ++ .../attendance-analysis.component.spec.ts | 81 +++++ .../attendance-analysis.component.ts | 188 ++++++++++++ .../attendance-manager.component.html | 280 ++++-------------- .../attendance-manager.component.scss | 25 +- .../attendance-manager.component.spec.ts | 61 +--- .../attendance-manager.component.ts | 184 +----------- .../children/children.module.ts | 2 + 10 files changed, 580 insertions(+), 467 deletions(-) create mode 100644 src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.html create mode 100644 src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.scss create mode 100644 src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.spec.ts create mode 100644 src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.ts diff --git a/src/app/app.routing.ts b/src/app/app.routing.ts index e3266ac673..6a87fdd4aa 100644 --- a/src/app/app.routing.ts +++ b/src/app/app.routing.ts @@ -32,6 +32,7 @@ import { AddDayAttendanceComponent } from "./child-dev-project/attendance/add-da import { AttendanceManagerComponent } from "./child-dev-project/attendance/attendance-manager/attendance-manager.component"; import { HowToComponent } from "./core/help/how-to/how-to.component"; import { UserListComponent } from "./core/admin/user-list/user-list.component"; +import { AttendanceAnalysisComponent } from "./child-dev-project/attendance/attendance-analysis/attendance-analysis.component"; /** * All routes configured for the main app routing. @@ -46,6 +47,7 @@ export const routes: Routes = [ { path: "child/:id/attendance", component: ChildAttendanceComponent }, { path: "note", component: NotesManagerComponent }, { path: "attendance", component: AttendanceManagerComponent }, + { path: "attendance/analysis", component: AttendanceAnalysisComponent }, { path: "attendance/add/month", component: AddMonthAttendanceComponent }, { path: "attendance/add/day", component: AddDayAttendanceComponent }, { path: "admin", component: AdminComponent, canActivate: [AdminGuard] }, diff --git a/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.html b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.html new file mode 100644 index 0000000000..5ddefa4e47 --- /dev/null +++ b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.html @@ -0,0 +1,205 @@ +

Attendance Analysis

+ + +
+ +
+
+
+ + + + + + + + + + +
+ +
+ + Daily + Monthly + +
+ +
+ + Any + School Attendance + Coaching Attendance + Has No Attendance + +
+ +
+ +
+
+ +
+ + + {{ option.label }} + + +
+ (Showing {{ dataSource.filteredData.length / 2 }} children) +
+
+
+ + {{ filterSelection.name }} + + + {{ option.label }} + + + +
+
+ +
+ +
Loading data ({{ loading }}) ...
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Student + + Type + {{ record.attendanceType }} + Attendance + {{ record.averageAttendance | percent: "1.0-0" }} + Count + {{ record.recordCount }} + Working Days + {{ record.totalWorking }} + Attended + {{ record.totalAttended }} + Absent + {{ record.totalAbsent }} + Late + {{ record.totalLate }} + Attendance + +
diff --git a/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.scss b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.scss new file mode 100644 index 0000000000..5bc8492be6 --- /dev/null +++ b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.scss @@ -0,0 +1,19 @@ +.attendance-line { + margin: 10px; +} + +.table-list{ + margin-top: 10px; +} + +.table-list td { + padding-left: 8px; +} + +.table-list-item:hover{ + background: #f5f5f5; +} + +.filter-panel { + padding-top: 10px; +} diff --git a/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.spec.ts b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.spec.ts new file mode 100644 index 0000000000..9b1c7081ac --- /dev/null +++ b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.spec.ts @@ -0,0 +1,81 @@ +import { async, ComponentFixture, TestBed } from "@angular/core/testing"; + +import { MatButtonModule } from "@angular/material/button"; +import { MatButtonToggleModule } from "@angular/material/button-toggle"; +import { MatExpansionModule } from "@angular/material/expansion"; +import { MatFormFieldModule } from "@angular/material/form-field"; +import { MatIconModule } from "@angular/material/icon"; +import { MatInputModule } from "@angular/material/input"; +import { MatProgressBarModule } from "@angular/material/progress-bar"; +import { MatSelectModule } from "@angular/material/select"; +import { MatTableModule } from "@angular/material/table"; +import { MatTooltipModule } from "@angular/material/tooltip"; +import { ChildBlockComponent } from "../../children/child-block/child-block.component"; +import { AttendanceBlockComponent } from "../attendance-block/attendance-block.component"; +import { AttendanceDayBlockComponent } from "../attendance-days/attendance-day-block.component"; +import { SchoolBlockComponent } from "../../schools/school-block/school-block.component"; +import { AttendanceDaysComponent } from "../attendance-days/attendance-days.component"; +import { FormsModule } from "@angular/forms"; +import { EntitySubrecordModule } from "../../../core/entity-subrecord/entity-subrecord.module"; +import { ChildrenService } from "../../children/children.service"; +import { EntityModule } from "../../../core/entity/entity.module"; +import { NoopAnimationsModule } from "@angular/platform-browser/animations"; +import { MatDatepickerModule } from "@angular/material/datepicker"; +import { MatNativeDateModule } from "@angular/material/core"; +import { BehaviorSubject } from "rxjs"; +import { AttendanceAnalysisComponent } from "./attendance-analysis.component"; + +describe("AttendanceRegisterComponent", () => { + let component: AttendanceAnalysisComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ + AttendanceAnalysisComponent, + ChildBlockComponent, + AttendanceBlockComponent, + AttendanceDayBlockComponent, + AttendanceDaysComponent, + SchoolBlockComponent, + ], + imports: [ + MatFormFieldModule, + MatInputModule, + MatButtonToggleModule, + MatExpansionModule, + MatButtonModule, + MatTableModule, + MatProgressBarModule, + MatTooltipModule, + MatSelectModule, + MatIconModule, + MatDatepickerModule, + MatNativeDateModule, + FormsModule, + NoopAnimationsModule, + EntitySubrecordModule, + EntityModule, + ], + providers: [ + { + provide: ChildrenService, + useValue: { + getChildren: () => new BehaviorSubject([]), + getAttendancesOfChild: () => new BehaviorSubject([]), + }, + }, + ], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(AttendanceAnalysisComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it("should create", () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.ts b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.ts new file mode 100644 index 0000000000..07e3b9dcdd --- /dev/null +++ b/src/app/child-dev-project/attendance/attendance-analysis/attendance-analysis.component.ts @@ -0,0 +1,188 @@ +import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; +import { FilterSelection } from "../../../core/filter/filter-selection/filter-selection"; +import { Child } from "../../children/model/child"; +import { ChildrenService } from "../../children/children.service"; +import { MatSort } from "@angular/material/sort"; +import { MatTableDataSource } from "@angular/material/table"; +import { AttendanceMonth } from "../model/attendance-month"; +import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; + +@UntilDestroy() +@Component({ + selector: "app-attendance-analysis", + templateUrl: "./attendance-analysis.component.html", + styleUrls: ["./attendance-analysis.component.scss"], +}) +export class AttendanceAnalysisComponent implements OnInit, AfterViewInit { + filterFrom: Date; + filterUntil: Date; + attendanceType = ""; + displayType = "daily"; + + childrenAll: Child[]; + + dataSource = new MatTableDataSource(); + columnsToDisplay = [ + "child", + "attendanceType", + "averageAttendance", + "totalWorking", + "totalAttended", + "totalAbsent", + "totalLate", + "attendance", + "recordCount", + ]; + @ViewChild(MatSort) sort: MatSort; + loading = 0; + + centerFS = new FilterSelection("center", []); + dropoutFS = new FilterSelection("status", [ + { + key: "active", + label: "Current Project Children", + filterFun: (c: Child) => c.isActive(), + }, + { + key: "dropout", + label: "Dropouts", + filterFun: (c: Child) => !c.isActive(), + }, + { key: "", label: "All", filterFun: () => true }, + ]); + filterSelections = [this.dropoutFS, this.centerFS]; + + constructor(private childrenService: ChildrenService) {} + + ngAfterViewInit() { + this.dataSource.sort = this.sort; + } + + ngOnInit() { + this.filterFrom = new Date(); + this.filterFrom.setDate(1); + this.filterUntil = new Date(); + this.filterUntil.setDate(1); + this.filterUntil.setMonth(this.filterUntil.getMonth() + 1); + + this.childrenService + .getChildren() + .pipe(untilDestroyed(this)) + .subscribe((data) => { + this.childrenAll = data.filter((c) => c.isActive()); + this.initCenterFilterOptions(); + this.applyFilterSelections(); + }); + } + + private initCenterFilterOptions() { + const centers = this.childrenAll + .map((c) => c.center) + .filter((value, index, arr) => arr.indexOf(value) === index); + + const options = [{ key: "", label: "All", filterFun: (c: Child) => true }]; + + centers.forEach((center) => { + options.push({ + key: center.toLowerCase(), + label: center, + filterFun: (c: Child) => c.center === center, + }); + }); + + this.centerFS.options = options; + } + + applyFilterSelections() { + this.loading = 0; + let filteredData = this.childrenAll; + + this.filterSelections.forEach((f) => { + filteredData = filteredData.filter(f.getSelectedFilterFunction()); + }); + + let data = []; + filteredData.forEach( + (child) => (data = data.concat(this.loadChildRecords(child))) + ); + + this.dataSource.data = data; + } + + loadChildRecords(child: Child): any[] { + this.loading++; + const recordCoaching = { + child: child, + attendanceType: "coaching", + attendance: [], + averageAttendance: 0, + }; + const recordSchool = { + child: child, + attendanceType: "school", + attendance: [], + averageAttendance: 0, + }; + + this.childrenService + .getAttendancesOfChild(child.getId()) + .pipe(untilDestroyed(this)) + .subscribe((attendances) => { + attendances.forEach((att) => { + if ( + this.isLaterOrEqualMonth(att.month, this.filterFrom) && + this.isEarlierOrEqualMonth(att.month, this.filterUntil) + ) { + if (att.institution === "school") { + recordSchool.attendance.push(att); + } else if (att.institution === "coaching") { + recordCoaching.attendance.push(att); + } + } + }); + + this.calculateRecordStats(recordSchool); + this.calculateRecordStats(recordCoaching); + + this.loading--; + }); + + return [recordSchool, recordCoaching]; + } + + calculateRecordStats(record) { + const stats = record.attendance.reduce( + (acc, a: AttendanceMonth) => { + if (a.daysWorking > 0) { + acc.count++; + acc.daysWorking += a.daysWorking; + acc.daysAttended += a.daysAttended; + acc.daysLate += a.daysLate; + } + return acc; + }, + { sum: 0, count: 0, daysWorking: 0, daysAttended: 0, daysLate: 0 } + ); + record.recordCount = stats.count; + record.averageAttendance = stats.daysAttended / stats.daysWorking; + record.totalWorking = stats.daysWorking; + record.totalAttended = stats.daysAttended; + record.totalAbsent = stats.daysWorking - stats.daysAttended; + record.totalLate = stats.daysLate; + } + + private isLaterOrEqualMonth(month: Date, filterFrom: Date) { + return ( + month.getFullYear() > filterFrom.getFullYear() || + (month.getFullYear() === filterFrom.getFullYear() && + month.getMonth() >= filterFrom.getMonth()) + ); + } + private isEarlierOrEqualMonth(month: Date, filterUntil: Date) { + return ( + month.getFullYear() < filterUntil.getFullYear() || + (month.getFullYear() === filterUntil.getFullYear() && + month.getMonth() <= filterUntil.getMonth()) + ); + } +} diff --git a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.html b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.html index 5c4bf8ec88..4396cd2f33 100644 --- a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.html +++ b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.html @@ -1,226 +1,68 @@

Attendance Register

-
- - -
- -
- - -
- -
-
-
- - - - - - - - - - -
- -
- - Daily - Monthly - -
+

+ Attendance data can be seen and edited in an individual's details as well as here across groups. +

-
- - Any - School Attendance - Coaching Attendance - Has No Attendance - -
- -
- -
-
+ + -
- - - {{ option.label }} - - -
- (Showing {{ dataSource.filteredData.length / 2 }} children) -
-
-
- - {{ filterSelection.name }} - - - {{ option.label }} - - - -
-
+ + + Enter Monthly Attendance + add a month's attendance + + + Enter attendance numbers for a whole month in a table format for a group of children. + This allows you to quickly record attendance that was collected on paper. + However, as you only enter a monthly total for each child you cannot see attendance in the day-wise calender. + + + + + -
- -
Loading data ({{ loading }}) ...
+ + + Analyse Attendance + calculate summaries and averages + + + Analyse and compare attendance for all children. + To see an individual's attendance history you can open the child's overall details page. + + + + +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Student - - Type - {{ record.attendanceType }} - Attendance - {{ record.averageAttendance | percent: "1.0-0" }} - Count - {{ record.recordCount }} - Working Days - {{ record.totalWorking }} - Attended - {{ record.totalAttended }} - Absent - {{ record.totalAbsent }} - Late - {{ record.totalLate }} - Attendance - -
diff --git a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.scss b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.scss index 5bc8492be6..36c9bed702 100644 --- a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.scss +++ b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.scss @@ -1,19 +1,24 @@ -.attendance-line { - margin: 10px; +.general-description { + font-style: italic; } -.table-list{ - margin-top: 10px; +.action-button { + width: 100%; } -.table-list td { - padding-left: 8px; +.mat-card { + display:flex; + flex-direction: column; + min-width: 250px; + margin-right: 24px; + margin-bottom: 24px; } -.table-list-item:hover{ - background: #f5f5f5; +.mat-card-header { + flex-shrink: 0; } -.filter-panel { - padding-top: 10px; +.mat-card-content { + flex-grow: 1; + overflow: auto; } diff --git a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.spec.ts b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.spec.ts index a080622f62..93796969be 100644 --- a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.spec.ts +++ b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.spec.ts @@ -2,28 +2,8 @@ import { async, ComponentFixture, TestBed } from "@angular/core/testing"; import { AttendanceManagerComponent } from "./attendance-manager.component"; import { MatButtonModule } from "@angular/material/button"; -import { MatButtonToggleModule } from "@angular/material/button-toggle"; -import { MatExpansionModule } from "@angular/material/expansion"; -import { MatFormFieldModule } from "@angular/material/form-field"; -import { MatIconModule } from "@angular/material/icon"; -import { MatInputModule } from "@angular/material/input"; -import { MatProgressBarModule } from "@angular/material/progress-bar"; -import { MatSelectModule } from "@angular/material/select"; -import { MatTableModule } from "@angular/material/table"; -import { MatTooltipModule } from "@angular/material/tooltip"; -import { ChildBlockComponent } from "../../children/child-block/child-block.component"; -import { AttendanceBlockComponent } from "../attendance-block/attendance-block.component"; -import { AttendanceDayBlockComponent } from "../attendance-days/attendance-day-block.component"; -import { SchoolBlockComponent } from "../../schools/school-block/school-block.component"; -import { AttendanceDaysComponent } from "../attendance-days/attendance-days.component"; -import { FormsModule } from "@angular/forms"; -import { EntitySubrecordModule } from "../../../core/entity-subrecord/entity-subrecord.module"; -import { ChildrenService } from "../../children/children.service"; -import { EntityModule } from "../../../core/entity/entity.module"; -import { NoopAnimationsModule } from "@angular/platform-browser/animations"; -import { MatDatepickerModule } from "@angular/material/datepicker"; -import { MatNativeDateModule } from "@angular/material/core"; -import { BehaviorSubject } from "rxjs"; +import { MatCardModule } from "@angular/material/card"; +import { RouterTestingModule } from "@angular/router/testing"; describe("AttendanceManagerComponent", () => { let component: AttendanceManagerComponent; @@ -31,41 +11,8 @@ describe("AttendanceManagerComponent", () => { beforeEach(async(() => { TestBed.configureTestingModule({ - declarations: [ - AttendanceManagerComponent, - ChildBlockComponent, - AttendanceBlockComponent, - AttendanceDayBlockComponent, - AttendanceDaysComponent, - SchoolBlockComponent, - ], - imports: [ - MatFormFieldModule, - MatInputModule, - MatButtonToggleModule, - MatExpansionModule, - MatButtonModule, - MatTableModule, - MatProgressBarModule, - MatTooltipModule, - MatSelectModule, - MatIconModule, - MatDatepickerModule, - MatNativeDateModule, - FormsModule, - NoopAnimationsModule, - EntitySubrecordModule, - EntityModule, - ], - providers: [ - { - provide: ChildrenService, - useValue: { - getChildren: () => new BehaviorSubject([]), - getAttendancesOfChild: () => new BehaviorSubject([]), - }, - }, - ], + declarations: [AttendanceManagerComponent], + imports: [MatButtonModule, MatCardModule, RouterTestingModule], }).compileComponents(); })); diff --git a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.ts b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.ts index 381de751a4..ff4e2c73fd 100644 --- a/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.ts +++ b/src/app/child-dev-project/attendance/attendance-manager/attendance-manager.component.ts @@ -1,188 +1,10 @@ -import { AfterViewInit, Component, OnInit, ViewChild } from "@angular/core"; -import { FilterSelection } from "../../../core/filter/filter-selection/filter-selection"; -import { Child } from "../../children/model/child"; -import { ChildrenService } from "../../children/children.service"; -import { MatSort } from "@angular/material/sort"; -import { MatTableDataSource } from "@angular/material/table"; -import { AttendanceMonth } from "../model/attendance-month"; -import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy"; +import { Component } from "@angular/core"; -@UntilDestroy() @Component({ selector: "app-attendance-manager", templateUrl: "./attendance-manager.component.html", styleUrls: ["./attendance-manager.component.scss"], }) -export class AttendanceManagerComponent implements OnInit, AfterViewInit { - filterFrom: Date; - filterUntil: Date; - attendanceType = ""; - displayType = "daily"; - - childrenAll: Child[]; - - dataSource = new MatTableDataSource(); - columnsToDisplay = [ - "child", - "attendanceType", - "averageAttendance", - "totalWorking", - "totalAttended", - "totalAbsent", - "totalLate", - "attendance", - "recordCount", - ]; - @ViewChild(MatSort) sort: MatSort; - loading = 0; - - centerFS = new FilterSelection("center", []); - dropoutFS = new FilterSelection("status", [ - { - key: "active", - label: "Current Project Children", - filterFun: (c: Child) => c.isActive(), - }, - { - key: "dropout", - label: "Dropouts", - filterFun: (c: Child) => !c.isActive(), - }, - { key: "", label: "All", filterFun: () => true }, - ]); - filterSelections = [this.dropoutFS, this.centerFS]; - - constructor(private childrenService: ChildrenService) {} - - ngAfterViewInit() { - this.dataSource.sort = this.sort; - } - - ngOnInit() { - this.filterFrom = new Date(); - this.filterFrom.setDate(1); - this.filterUntil = new Date(); - this.filterUntil.setDate(1); - this.filterUntil.setMonth(this.filterUntil.getMonth() + 1); - - this.childrenService - .getChildren() - .pipe(untilDestroyed(this)) - .subscribe((data) => { - this.childrenAll = data.filter((c) => c.isActive()); - this.initCenterFilterOptions(); - this.applyFilterSelections(); - }); - } - - private initCenterFilterOptions() { - const centers = this.childrenAll - .map((c) => c.center) - .filter((value, index, arr) => arr.indexOf(value) === index); - - const options = [{ key: "", label: "All", filterFun: (c: Child) => true }]; - - centers.forEach((center) => { - options.push({ - key: center.toLowerCase(), - label: center, - filterFun: (c: Child) => c.center === center, - }); - }); - - this.centerFS.options = options; - } - - applyFilterSelections() { - this.loading = 0; - let filteredData = this.childrenAll; - - this.filterSelections.forEach((f) => { - filteredData = filteredData.filter(f.getSelectedFilterFunction()); - }); - - let data = []; - filteredData.forEach( - (child) => (data = data.concat(this.loadChildRecords(child))) - ); - - this.dataSource.data = data; - } - - loadChildRecords(child: Child): any[] { - this.loading++; - const recordCoaching = { - child: child, - attendanceType: "coaching", - attendance: [], - averageAttendance: 0, - }; - const recordSchool = { - child: child, - attendanceType: "school", - attendance: [], - averageAttendance: 0, - }; - - this.childrenService - .getAttendancesOfChild(child.getId()) - .pipe(untilDestroyed(this)) - .subscribe((attendances) => { - attendances.forEach((att) => { - if ( - this.isLaterOrEqualMonth(att.month, this.filterFrom) && - this.isEarlierOrEqualMonth(att.month, this.filterUntil) - ) { - if (att.institution === "school") { - recordSchool.attendance.push(att); - } else if (att.institution === "coaching") { - recordCoaching.attendance.push(att); - } - } - }); - - this.calculateRecordStats(recordSchool); - this.calculateRecordStats(recordCoaching); - - this.loading--; - }); - - return [recordSchool, recordCoaching]; - } - - calculateRecordStats(record) { - const stats = record.attendance.reduce( - (acc, a: AttendanceMonth) => { - if (a.daysWorking > 0) { - acc.count++; - acc.daysWorking += a.daysWorking; - acc.daysAttended += a.daysAttended; - acc.daysLate += a.daysLate; - } - return acc; - }, - { sum: 0, count: 0, daysWorking: 0, daysAttended: 0, daysLate: 0 } - ); - record.recordCount = stats.count; - record.averageAttendance = stats.daysAttended / stats.daysWorking; - record.totalWorking = stats.daysWorking; - record.totalAttended = stats.daysAttended; - record.totalAbsent = stats.daysWorking - stats.daysAttended; - record.totalLate = stats.daysLate; - } - - private isLaterOrEqualMonth(month: Date, filterFrom: Date) { - return ( - month.getFullYear() > filterFrom.getFullYear() || - (month.getFullYear() === filterFrom.getFullYear() && - month.getMonth() >= filterFrom.getMonth()) - ); - } - private isEarlierOrEqualMonth(month: Date, filterUntil: Date) { - return ( - month.getFullYear() < filterUntil.getFullYear() || - (month.getFullYear() === filterUntil.getFullYear() && - month.getMonth() <= filterUntil.getMonth()) - ); - } +export class AttendanceManagerComponent { + constructor() {} } diff --git a/src/app/child-dev-project/children/children.module.ts b/src/app/child-dev-project/children/children.module.ts index 7133ecd28a..c471ad4fe7 100644 --- a/src/app/child-dev-project/children/children.module.ts +++ b/src/app/child-dev-project/children/children.module.ts @@ -78,6 +78,7 @@ import { CONFLICT_RESOLUTION_STRATEGY } from "../../conflict-resolution/auto-res import { AttendanceMonthConflictResolutionStrategy } from "../attendance/attendance-month-conflict-resolution-strategy"; import { MatPaginatorModule } from "@angular/material/paginator"; import { Angulartics2Module } from "angulartics2"; +import { AttendanceAnalysisComponent } from "../attendance/attendance-analysis/attendance-analysis.component"; @NgModule({ imports: [ @@ -142,6 +143,7 @@ import { Angulartics2Module } from "angulartics2"; NoRecentNotesDashboardComponent, RecentNotesDashboardComponent, AttendanceManagerComponent, + AttendanceAnalysisComponent, HealthCheckupComponent, PreviousSchoolsComponent, ],