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..727ac3e31f 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,17 @@
>
-
- 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..a789f671ba 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
@@ -6,8 +6,10 @@ import { MockedTestingModule } from "../../../../utils/mocked-testing.module";
import { EducationalMaterial } from "../model/educational-material";
import { ConfigurableEnumValue } from "../../../../core/basic-datatypes/configurable-enum/configurable-enum.interface";
import { EntityMapperService } from "../../../../core/entity/entity-mapper/entity-mapper.service";
-import { Subject } from "rxjs";
+import { of, Subject } from "rxjs";
import { UpdatedEntity } from "../../../../core/entity/model/entity-update";
+import { ActivatedRoute } from "@angular/router";
+import { RouteData } from "app/core/config/dynamic-routing/view-config.interface";
describe("EducationalMaterialComponent", () => {
let component: EducationalMaterialComponent;
@@ -26,7 +28,33 @@ describe("EducationalMaterialComponent", () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [EducationalMaterialComponent, MockedTestingModule.withState()],
+ providers: [
+ {
+ provide: ActivatedRoute,
+ useValue: {
+ data: of({
+ config: {
+ entity: "Child",
+ panels: [
+ {
+ title: "Educational Materials",
+ summary: [
+ {
+ Total: "Total",
+ },
+ {
+ Average: "Average",
+ },
+ ],
+ },
+ ],
+ },
+ }),
+ },
+ },
+ ],
}).compileComponents();
+
const entityMapper = TestBed.inject(EntityMapperService);
spyOn(entityMapper, "receiveUpdates").and.returnValue(updates);
}));
@@ -95,6 +123,36 @@ describe("EducationalMaterialComponent", () => {
const newRecord = component.newRecordFactory();
expect(newRecord.child).toBe(child.getId());
});
+ it("produces an empty summary when there are no records", () => {
+ component.records = [];
+ component.updateSummary();
+ expect(component.summary).toHaveSize(0);
+ });
+
+ it("should set summaryTitle based on panel title", () => {
+ setRecordsAndGenerateSummary([{ Total: "Total" }, { Average: "Average" }])
+
+ const routeData: RouteData = {
+ config: {
+ panels: [
+ {
+ title: "Educational Materials",
+ summary: [
+ {
+ Total: "Total",
+ },
+ {
+ Average: "Average",
+ },
+ ],
+ },
+ ],
+ },
+ };
+
+ component.getSummaryList();
+ expect(component.summaryTitle).toEqual([{ Total: "Total" }, { Average: "Average" }]);
+ });
it("should update the summary when entity updates are received", async () => {
const update1 = EducationalMaterial.create({
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..953a012890 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";
@@ -8,6 +9,9 @@ import { applyUpdate } from "../../../../core/entity/model/entity-update";
import { filter } from "rxjs/operators";
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
import { EntitySubrecordComponent } from "../../../../core/common-components/entity-subrecord/entity-subrecord/entity-subrecord.component";
+import { EntityListConfig } from "app/core/entity-list/EntityListConfig";
+import { ActivatedRoute } from "@angular/router";
+import { RouteData } from "app/core/config/dynamic-routing/view-config.interface";
/**
* Displays educational materials of a child, such as a pencil, rulers, e.t.c
@@ -18,13 +22,16 @@ 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;
records: EducationalMaterial[] = [];
summary = "";
+ avgSummary = "";
+ summaryTitle: { [key: string]: string }[]
+ listConfig: EntityListConfig;
@Input() config: { columns: FormFieldConfig[] } = {
columns: [
@@ -35,7 +42,8 @@ export class EducationalMaterialComponent implements OnInit {
],
};
- constructor(private entityMapper: EntityMapperService) {
+ constructor(private entityMapper: EntityMapperService,
+ private route: ActivatedRoute ) {
this.entityMapper
.receiveUpdates(EducationalMaterial)
.pipe(
@@ -65,6 +73,7 @@ export class EducationalMaterialComponent implements OnInit {
(mat) => mat.child === this.entity.getId(),
);
this.updateSummary();
+
}
newRecordFactory = () => {
@@ -83,15 +92,49 @@ export class EducationalMaterialComponent implements OnInit {
* human-readable format
*/
updateSummary() {
- const summary = 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);
- });
- this.summary = [...summary]
- .map(([key, value]) => key + ": " + value)
- .join(", ");
+ const summary = new Map();
+ const average = new Map();
+
+ // Initialize summary and average maps in a single loop
+ for (const m of this.records) {
+ if (m.materialType) {
+ const label = m.materialType.label;
+ const amount = m.materialAmount;
+
+ if (!summary.has(label)) {
+ summary.set(label, { count: 0, sum: 0 });
+ }
+
+ const labelData = summary.get(label);
+ labelData.count++;
+ labelData.sum += amount;
+ }
+ }
+
+ // Calculate averages and build summary strings
+ const summaryArray: string[] = [];
+ const avgSummaryArray: string[] = [];
+
+ for (const [label, labelData] of summary.entries()) {
+ const avg = labelData.sum / labelData.count;
+ average.set(label, avg);
+
+ summaryArray.push(`${label}: ${labelData.sum}`);
+ avgSummaryArray.push(`${label}: ${avg}`);
+ }
+
+ this.summary = summaryArray.join(", ");
+ this.avgSummary = avgSummaryArray.join(", ");
+ this.getSummaryList();
+ }
+
+
+ getSummaryList(){
+ this.route.data.subscribe(
+ (data: RouteData) => (this.listConfig = data.config),
+ );
+ this.summaryTitle = this.listConfig['panels']
+ .find((panel: { title: string })=> panel.title === "Educational Materials").summary;
+
}
}
diff --git a/src/app/core/config/config-fix.ts b/src/app/core/config/config-fix.ts
index b179821a6d..0e03c98188 100644
--- a/src/app/core/config/config-fix.ts
+++ b/src/app/core/config/config-fix.ts
@@ -714,6 +714,15 @@ export const defaultJsonConfig = {
"title": "",
"component": "EducationalMaterial"
}
+ ],
+ "summary": [
+ {
+ "Total": $localize `:Total item Count:Total`
+ },
+
+ {
+ "Average": $localize `:Average Per Item:Average`
+ }
]
},
{