From 92de4001da3295c3f5dd7d09e823012794a98b5a Mon Sep 17 00:00:00 2001 From: Gift Nnko Date: Fri, 6 Sep 2024 15:23:57 +0300 Subject: [PATCH] fix: scorecard form Fixed issues with additional labels input field --- .../components/AdditionalLabelsField.tsx | 48 ++++++++++++++ .../General/components/GeneralForm.tsx | 13 +--- .../components/General/utils/utils.ts | 31 +++++----- .../modules/ScorecardManagement/hooks/meta.ts | 62 ++++++++++++++++++- .../ScorecardManagement/hooks/schema.ts | 2 +- packages/shared/src/models/base.ts | 3 +- 6 files changed, 128 insertions(+), 31 deletions(-) create mode 100644 packages/app/src/modules/ScorecardManagement/components/General/components/AdditionalLabelsField.tsx diff --git a/packages/app/src/modules/ScorecardManagement/components/General/components/AdditionalLabelsField.tsx b/packages/app/src/modules/ScorecardManagement/components/General/components/AdditionalLabelsField.tsx new file mode 100644 index 000000000..1e3c2d021 --- /dev/null +++ b/packages/app/src/modules/ScorecardManagement/components/General/components/AdditionalLabelsField.tsx @@ -0,0 +1,48 @@ +import { useFieldArray } from "react-hook-form"; +import { Button, Field, InputField } from "@dhis2/ui"; +import i18n from "@dhis2/d2-i18n"; +import { RHFTextInputField } from "@hisptz/dhis2-ui"; +import { useState } from "react"; +import { IconAdd24, IconDelete24 } from "@dhis2/ui-icons"; + + +export function AdditionalLabelsField() { + const [addFieldValue, setAddFieldValue] = useState(); + const { fields, append, remove } = useFieldArray({ + name: "additionalLabels" + }); + + const onAdd = () => { + if (addFieldValue) { + append(addFieldValue as string); + setAddFieldValue(undefined); + } + }; + + return ( + +
+
+ { + fields.map((field, i) => { + return ( +
+
+ +
+ +
+ ); + }) + } +
+
+
+ setAddFieldValue(value)} /> +
+ +
+
+
+ ); +} diff --git a/packages/app/src/modules/ScorecardManagement/components/General/components/GeneralForm.tsx b/packages/app/src/modules/ScorecardManagement/components/General/components/GeneralForm.tsx index 726ee5784..5b4e65c95 100644 --- a/packages/app/src/modules/ScorecardManagement/components/General/components/GeneralForm.tsx +++ b/packages/app/src/modules/ScorecardManagement/components/General/components/GeneralForm.tsx @@ -5,6 +5,7 @@ import "../../../ScorecardManagement.module.css"; import { PeriodSelector } from "./PeriodSelector"; import LegendDefinitionFormField from "./LegendDefinitionFormField"; import { PeriodTypeSelector } from "./PeriodTypeSelector"; +import { AdditionalLabelsField } from "./AdditionalLabelsField"; export default function GeneralForm() { @@ -50,17 +51,7 @@ export default function GeneralForm() {
- +
); diff --git a/packages/app/src/modules/ScorecardManagement/components/General/utils/utils.ts b/packages/app/src/modules/ScorecardManagement/components/General/utils/utils.ts index 7321fda57..235dc5ec5 100644 --- a/packages/app/src/modules/ScorecardManagement/components/General/utils/utils.ts +++ b/packages/app/src/modules/ScorecardManagement/components/General/utils/utils.ts @@ -1,32 +1,37 @@ import { generateLegendDefaults, getScorecardSummary } from "@scorecard/shared"; import { cloneDeep, find, isEmpty, set } from "lodash"; +import { LegendDefinition, ScorecardDataGroup, ScorecardDataHolder, ScorecardDataSource, SpecificTarget } from "@hisptz/dhis2-analytics"; -export function resetLegends(groups: any, legendDefinitions: any) { +export function resetLegends(groups: ScorecardDataGroup[], legendDefinitions: LegendDefinition[]) { const newGroups = cloneDeep(groups); if (newGroups) { newGroups?.forEach((group: any) => { - group?.dataHolders?.forEach((dataHolder: any) => { - dataHolder?.dataSources?.forEach((dataSource: any) => { + group?.dataHolders?.forEach((dataHolder: ScorecardDataHolder) => { + dataHolder?.dataSources?.forEach((dataSource: ScorecardDataSource) => { set( dataSource, "legends", generateLegendDefaults( getNonDefaultLegendDefinitions(legendDefinitions), - ), + dataSource.weight, + dataSource.highIsGood + ) ); if (!isEmpty(dataSource.specificTargets)) { dataSource.specificTargets.forEach( - (specificTarget: any) => { + (specificTarget: SpecificTarget) => { set( specificTarget, "legends", generateLegendDefaults( getNonDefaultLegendDefinitions( - legendDefinitions, + legendDefinitions ), - ), + dataSource.weight, + dataSource.highIsGood + ) ); - }, + } ); } }); @@ -39,15 +44,7 @@ export function resetLegends(groups: any, legendDefinitions: any) { export function getNonDefaultLegendDefinitions(legendDefinitions: any) { return ( legendDefinitions?.filter( - (legendDefinition: any) => !legendDefinition.isDefault, - ) ?? [] - ); -} - -export function getDefaultLegendDefinitions(legendDefinitions: any) { - return ( - legendDefinitions?.filter( - (legendDefinition: any) => legendDefinition.isDefault, + (legendDefinition: any) => !legendDefinition.isDefault ) ?? [] ); } diff --git a/packages/app/src/modules/ScorecardManagement/hooks/meta.ts b/packages/app/src/modules/ScorecardManagement/hooks/meta.ts index 218cde75e..19c482987 100644 --- a/packages/app/src/modules/ScorecardManagement/hooks/meta.ts +++ b/packages/app/src/modules/ScorecardManagement/hooks/meta.ts @@ -6,6 +6,8 @@ import { useDataQuery } from "@dhis2/app-runtime"; import { useGetScorecardSharingSettings } from "../../ScorecardList/hooks/authority"; import { useEffect, useState } from "react"; import { useFormSchema } from "./schema"; +import { uid } from "@hisptz/dhis2-utils"; +import i18n from "@dhis2/d2-i18n"; const query: any = { scorecard: { @@ -15,6 +17,64 @@ const query: any = { } }; +const defaultValue: Partial = { + id: uid(), + legendDefinitions: [ + { + color: "#D3D3D3", + name: i18n.t("N/A"), + isDefault: true, + id: "N/A" + }, + { + color: "#FFFFFF", + name: i18n.t("No Data"), + isDefault: true, + id: "No Data" + }, + { + id: uid(), + color: "#008000", + name: i18n.t("Target Reached/ On Track") + }, + { + id: uid(), + color: "#FFFF00", + name: i18n.t("Progress, but more effort required") + }, + { + id: uid(), + color: "#FF0000", + name: i18n.t("Not on track") + } + ], + options: { + averageDisplayType: "ALL", + legend: true, + title: true, + itemNumber: true, + emptyRows: true, + showHierarchy: false, + averageColumn: false, + averageRow: false, + highlightedIndicators: false, + arrows: false, + showDataInRows: false + }, + orgUnitSelection: { + levels: [], + groups: [], + orgUnits: [], + userSubX2Unit: false, + userSubUnit: false, + userOrgUnit: false + }, + highlightedIndicators: [], + dataSelection: { + dataGroups: [] + } +}; + export default function useScorecardFormMetadata() { const { id } = useParams<{ id: string }>(); @@ -34,7 +94,7 @@ export default function useScorecardFormMetadata() { const scorecardDefaultValues = await refetch() as { scorecard: ScorecardConfig }; return scorecardDefaultValues.scorecard; } - return {} as ScorecardConfig; + return defaultValue as ScorecardConfig; }, mode: "onSubmit", reValidateMode: "onSubmit", diff --git a/packages/app/src/modules/ScorecardManagement/hooks/schema.ts b/packages/app/src/modules/ScorecardManagement/hooks/schema.ts index c86bdc09c..e31a6d773 100644 --- a/packages/app/src/modules/ScorecardManagement/hooks/schema.ts +++ b/packages/app/src/modules/ScorecardManagement/hooks/schema.ts @@ -11,13 +11,13 @@ export function useFormSchema() { const engine = useDataEngine(); return scorecardConfigSchema.extend({ title: z.string({ required_error: i18n.t("Title is required") }).min(4, i18n.t("Title must have at least 4 characters")).refine(async (value) => { - console.log(value); const titleExists = await titleDoesNotExist(engine, id, value); return !titleExists || i18n.t( `A scorecard with the title '{{value}}' already exists. Please select another title`, { value } ); }), + additionalLabels: z.array(z.string()).optional(), subtitle: z.string().optional(), customHeader: z.string().optional(), description: z.string().optional() diff --git a/packages/shared/src/models/base.ts b/packages/shared/src/models/base.ts index a8236d91a..1f5d776e1 100644 --- a/packages/shared/src/models/base.ts +++ b/packages/shared/src/models/base.ts @@ -1,5 +1,6 @@ import produce from "immer"; import { cloneDeep, defaultsDeep } from "lodash"; +import { ScorecardOptions } from "./index"; export default class DataModel { constructor(attributes = {}) { @@ -20,7 +21,7 @@ export default class DataModel { } static setObject(object: any, values: any = {}) { - const updatedObject = cloneDeep(object); + const updatedObject =new ScorecardOptions cloneDeep(object); for (const key of Object.keys(values)) { updatedObject[key] = values[key]; }