diff --git a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html index 289052eca4..abfd833c5c 100644 --- a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html +++ b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.html @@ -5,9 +5,11 @@ > -
- Total: {{ summary }} +
+ + Total: {{ summary }}
+
+ + Average: {{ avgSummary }}
+
diff --git a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts index 2e8e639b56..9068e33c8e 100644 --- a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts +++ b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.spec.ts @@ -35,6 +35,7 @@ describe("EducationalMaterialComponent", () => { fixture = TestBed.createComponent(EducationalMaterialComponent); component = fixture.componentInstance; component.entity = child; + component.summaries = {total: true, average: true}; fixture.detectChanges(); }); @@ -46,6 +47,7 @@ describe("EducationalMaterialComponent", () => { component.records = []; component.updateSummary(); expect(component.summary).toHaveSize(0); + expect(component.avgSummary).toHaveSize(0); }); function setRecordsAndGenerateSummary( @@ -58,6 +60,7 @@ describe("EducationalMaterialComponent", () => { it("produces a singleton summary when there is a single record", () => { setRecordsAndGenerateSummary({ materialType: PENCIL, materialAmount: 1 }); expect(component.summary).toEqual(`${PENCIL.label}: 1`); + expect(component.avgSummary).toEqual(`${PENCIL.label}: 1`); }); it("produces a summary of all records when they are all different", () => { @@ -66,6 +69,7 @@ describe("EducationalMaterialComponent", () => { { materialType: RULER, materialAmount: 1 }, ); expect(component.summary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`); + expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`); }); it("produces a summary of all records when there are duplicates", () => { @@ -74,7 +78,57 @@ describe("EducationalMaterialComponent", () => { { materialType: RULER, materialAmount: 1 }, { materialType: PENCIL, materialAmount: 3 }, ); + + expect(component.summary).toEqual(`${PENCIL.label}: 4, ${RULER.label}: 1`); + expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`); + }); + + it("produces summary of all records when average is false and total is true", () => { + component.summaries = { total: true, average: false } + setRecordsAndGenerateSummary( + { materialType: PENCIL, materialAmount: 1 }, + { materialType: RULER, materialAmount: 1 }, + { materialType: PENCIL, materialAmount: 3 }, + ); + + expect(component.summary).toEqual(`${PENCIL.label}: 4, ${RULER.label}: 1`); + expect(component.avgSummary).toEqual(``); + }); + + it("produces summary of all records when average is true and total is false", () => { + component.summaries = { total: false, average: true }; + setRecordsAndGenerateSummary( + { materialType: PENCIL, materialAmount: 1 }, + { materialType: RULER, materialAmount: 1 }, + { materialType: PENCIL, materialAmount: 3 }, + ); + + expect(component.summary).toEqual(``); + expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`); + }); + + it("does not produces summary of all records when both average and total are false", () => { + component.summaries = { total: false, average: false }; + setRecordsAndGenerateSummary( + { materialType: PENCIL, materialAmount: 1 }, + { materialType: RULER, materialAmount: 1 }, + { materialType: PENCIL, materialAmount: 3 }, + ); + + expect(component.summary).toEqual(``); + expect(component.avgSummary).toEqual(``); + }); + + it("produces summary of all records when both average and total are true", () => { + component.summaries = { total: true, average: true }; + setRecordsAndGenerateSummary( + { materialType: PENCIL, materialAmount: 1 }, + { materialType: RULER, materialAmount: 1 }, + { materialType: PENCIL, materialAmount: 3 }, + ); + expect(component.summary).toEqual(`${PENCIL.label}: 4, ${RULER.label}: 1`); + expect(component.avgSummary).toEqual(`${PENCIL.label}: 2, ${RULER.label}: 1`); }); it("loads all education data associated with a child and updates the summary", async () => { diff --git a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts index feba170e3e..5a065632c3 100644 --- a/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts +++ b/src/app/child-dev-project/children/educational-material/educational-material-component/educational-material.component.ts @@ -1,4 +1,5 @@ import { Component, Input, OnInit } from "@angular/core"; +import { NgFor, NgIf } from "@angular/common"; import { EducationalMaterial } from "../model/educational-material"; import { Child } from "../../model/child"; import { FormFieldConfig } from "../../../../core/common-components/entity-form/entity-form/FormConfig"; @@ -18,13 +19,19 @@ import { EntitySubrecordComponent } from "../../../../core/common-components/ent @Component({ selector: "app-educational-material", templateUrl: "./educational-material.component.html", - imports: [EntitySubrecordComponent], + imports: [ + EntitySubrecordComponent, + NgIf, + NgFor + ], standalone: true, }) export class EducationalMaterialComponent implements OnInit { @Input() entity: Child; + @Input() summaries: { total?: boolean; average?: boolean } = { total: true }; records: EducationalMaterial[] = []; summary = ""; + avgSummary = ""; @Input() config: { columns: FormFieldConfig[] } = { columns: [ @@ -83,15 +90,32 @@ export class EducationalMaterialComponent implements OnInit { * human-readable format */ updateSummary() { - const summary = new Map(); + const summary = new Map(); + const average = new Map(); + this.records.forEach((m) => { - const previousValue = summary.has(m.materialType.label) - ? summary.get(m.materialType.label) - : 0; - summary.set(m.materialType.label, previousValue + m.materialAmount); + const { materialType, materialAmount } = m; + const label = materialType?.label; + + if (label) { + summary.set(label, (summary.get(label) || { count: 0, sum: 0 })); + summary.get(label)!.count++; + summary.get(label)!.sum += materialAmount; + } }); - this.summary = [...summary] - .map(([key, value]) => key + ": " + value) - .join(", "); + + if(this.summaries.total) { + const summaryArray = Array.from(summary.entries(), ([label, { sum }]) => `${label}: ${sum}`); + this.summary = summaryArray.join(", "); + } + + if(this.summaries.average) { + const avgSummaryArray = Array.from(summary.entries(), ([label, { count, sum }]) => { + const avg = parseFloat((sum / count).toFixed(2)); + average.set(label, avg); + return `${label}: ${avg}`; + }); + this.avgSummary = avgSummaryArray.join(", "); + } } } diff --git a/src/app/core/config/config-fix.ts b/src/app/core/config/config-fix.ts index b179821a6d..afdb7f9881 100644 --- a/src/app/core/config/config-fix.ts +++ b/src/app/core/config/config-fix.ts @@ -712,8 +712,14 @@ export const defaultJsonConfig = { "components": [ { "title": "", - "component": "EducationalMaterial" - } + "component": "EducationalMaterial", + "config": { + "summaries": { + total: true, + average: true, + } + } + } ] }, {