Skip to content

Commit

Permalink
feat: scorecard view
Browse files Browse the repository at this point in the history
Improved scorecard header
  • Loading branch information
nnkogift committed Aug 8, 2024
1 parent 73738ea commit bcb518f
Show file tree
Hide file tree
Showing 17 changed files with 301 additions and 8 deletions.
13 changes: 11 additions & 2 deletions packages/app/i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"POT-Creation-Date: 2024-08-08T12:12:32.681Z\n"
"PO-Revision-Date: 2024-08-08T12:12:32.681Z\n"
"POT-Creation-Date: 2024-08-08T12:57:40.085Z\n"
"PO-Revision-Date: 2024-08-08T12:57:40.086Z\n"

msgid "Welcome to Scorecard App!"
msgstr "Welcome to Scorecard App!"
Expand Down Expand Up @@ -333,6 +333,9 @@ msgstr "of"
msgid "Getting your scorecard configuration..."
msgstr "Getting your scorecard configuration..."

msgid "Back to all scorecards"
msgstr "Back to all scorecards"

msgid "Select organisation unit"
msgstr "Select organisation unit"

Expand All @@ -342,6 +345,12 @@ msgstr "Select period"
msgid "and {{number}} more"
msgstr "and {{number}} more"

msgid "Download"
msgstr "Download"

msgid "Reset"
msgstr "Reset"

msgid "Create a new scorecard in the scorecard app to see it here."
msgstr "Create a new scorecard in the scorecard app to see it here."

Expand Down
2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"dependencies": {
"@dhis2/app-runtime": "^3.10.6",
"@dhis2/app-service-datastore": "^1.0.0-alpha.2",
"@dhis2/multi-calendar-dates": "^1.2.3",
"@dhis2/multi-calendar-dates": "^1.2.4",
"@dhis2/ui": "^9.11.0",
"@hisptz/dhis2-analytics": "^2.0.16",
"@hisptz/dhis2-ui": "^2.0.14",
Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,12 @@
"Migrating scorecards": "Migrating scorecards",
"of": "of",
"Getting your scorecard configuration...": "Getting your scorecard configuration...",
"Back to all scorecards": "Back to all scorecards",
"Select organisation unit": "Select organisation unit",
"Select period": "Select period",
"and {{number}} more": "and {{number}} more",
"Download": "Download",
"Reset": "Reset",
"Create a new scorecard in the scorecard app to see it here.": "Create a new scorecard in the scorecard app to see it here.",
"Confirm scorecard selection": "Confirm scorecard selection",
"Are you sure you want to select this scorecard for this dashboard?": "Are you sure you want to select this scorecard for this dashboard?",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import i18n from "@dhis2/d2-i18n";
import { useEffect } from "react";
import { useDimensions } from "./hooks/dimensions";
import { OrgUnitSelection } from "@hisptz/dhis2-utils";
import { ScorecardActions } from "./components/ScorecardActions/ScorecardActions";
import { ScorecardStateProvider } from "./state/state";
import { ScorecardView } from "./components/ScorecardView";
import { ScorecardConfigProvider } from "./state/config";
import { ScorecardHeader } from "./components/ScorecardHeader";

export function ScorecardViewPage() {
const { setDimensions } = useDimensions();
const { setDimensions, orgUnit, periods } = useDimensions();
const { config, loading, error, refetch } = useScorecardConfig();

useEffect(() => {
Expand Down Expand Up @@ -36,6 +41,16 @@ export function ScorecardViewPage() {
/>
);
}
if (!config) {
return (
<FullPageError
resetErrorBoundary={() => {
refetch();
}}
error={Error("Could not get information about the scorecard")}
/>
);
}

return (
<div
Expand All @@ -47,7 +62,32 @@ export function ScorecardViewPage() {
gap: 16,
}}
>
<DimensionFilterArea />
<ScorecardConfigProvider config={config}>
<ScorecardStateProvider
initialState={{
...config,
periodSelection: {
...config.periodSelection,
periods:
periods?.map((period) => ({ id: period })) ??
[],
},
orgUnitSelection: {
...orgUnit,
orgUnits: orgUnit.orgUnits ?? [],
groups: orgUnit.groups ?? [],
levels: orgUnit.levels ?? [],
},
}}
>
<DimensionFilterArea />
<ScorecardActions />
<ScorecardHeader />
<div className="flex-1">
<ScorecardView config={config} />
</div>
</ScorecardStateProvider>
</ScorecardConfigProvider>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,29 @@ import { Card } from "@dhis2/ui";
import classes from "./DimensionFilterArea.module.css";
import { OrgUnitDimensionSelection } from "./components/CustomOrgUnitSelectorModal";
import { PeriodDimensionSelector } from "./components/PeriodDimensionSelector";
import { BackButton } from "./components/BackButton";
import { HelpButton } from "./components/HelpButton";
import { SCORECARD_VIEW_HELP_STEPS } from "@scorecard/shared";

export function DimensionFilterArea() {
return (
<div className={classes["selection-card"]}>
<Card>
<div className="row space-between align-center ph-16">
<div
style={{ padding: "0 16px" }}
className="row space-between align-items-center ph-16"
>
<div className="row align-items-center">
<OrgUnitDimensionSelection />
<PeriodDimensionSelector />
</div>
<div
style={{ gap: 8, justifyContent: "flex-end" }}
className="row align-items-center"
>
<BackButton />
<HelpButton steps={SCORECARD_VIEW_HELP_STEPS} />
</div>
</div>
</Card>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import i18n from "@dhis2/d2-i18n";
import { Button } from "@dhis2/ui";
import React from "react";
import { useNavigate } from "react-router-dom";

export function BackButton() {
const navigate = useNavigate();
const onBackClick = () => {
navigate("/");
};

return (
<Button onClick={onBackClick}>
{i18n.t("Back to all scorecards")}
</Button>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import { Button, IconQuestion24 } from "@dhis2/ui";
import i18n from "@dhis2/d2-i18n";
import { useBoolean } from "usehooks-ts";
import { Steps } from "intro.js-react";
import { STEP_OPTIONS } from "@scorecard/shared";

export interface HelpButtonProps {
steps: any[];
}

export function HelpButton({ steps }: HelpButtonProps) {
const { value: hide, setTrue: onHide, setFalse: onShow } = useBoolean(true);

return (
<>
<Steps
enabled={!hide}
options={STEP_OPTIONS}
initialStep={0}
steps={steps}
onExit={onHide}
/>
<Button onClick={onShow} icon={<IconQuestion24 />}>
{i18n.t("Help")}
</Button>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ButtonStrip } from "@dhis2/ui";
import { ScorecardOptionsControlButton } from "./components/ScorecardOptionsControlButton";
import { ScorecardEditButton } from "./components/ScorecardEditButton";
import { ScorecardDownloadButton } from "./components/ScorecardDownloadButton";
import { ScorecardResetButton } from "./components/ScorecardResetButton";

export function ScorecardActions() {
return (
<div style={{ width: "100%", padding: "0 16px" }}>
<ButtonStrip end>
<ScorecardOptionsControlButton />
<ScorecardEditButton />
<ScorecardDownloadButton />
<ScorecardResetButton />
</ButtonStrip>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Button } from "@dhis2/ui";
import i18n from "@dhis2/d2-i18n";

export function ScorecardDownloadButton() {
return <Button>{i18n.t("Download")}</Button>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Button } from "@dhis2/ui";
import i18n from "@dhis2/d2-i18n";

export function ScorecardEditButton() {
return <Button>{i18n.t("Edit")}</Button>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import i18n from "@dhis2/d2-i18n";
import { Button } from "@dhis2/ui";

export function ScorecardOptionsControlButton() {
return (
<>
<Button>{i18n.t("Options")}</Button>
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Button } from "@dhis2/ui";
import i18n from "@dhis2/d2-i18n";

export function ScorecardResetButton() {
return <Button>{i18n.t("Reset")}</Button>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import JsxParser from "react-jsx-parser";
import { useScorecardConfigFromContext } from "../state/config";
import { head } from "lodash";
import { colors } from "@dhis2/ui";
import { useMemo } from "react";
import { PeriodUtility } from "@hisptz/dhis2-utils";
import { useScorecardState } from "../state/state";

export function ScorecardHeader() {
const config = useScorecardConfigFromContext();
const { customHeader, title, subtitle, periodSelection } = config ?? {};
const periods = periodSelection.periods ?? [];

const [state] = useScorecardState();

const period = useMemo(() => {
if (periods.length > 1) {
return;
}
return PeriodUtility.getPeriodById(head(periods)?.id as string);
}, [periods]);

if (!state.options.title) {
return null;
}

return (
<div className="row space-between" id={"scorecard-header"}>
<div className="row">
{customHeader ? (
<JsxParser
autoCloseVoidElements
className="w-100"
onError={console.error}
bindings={{
title,
subtitle,
period: periods.length === 1 ? period?.name : "",
}}
jsx={customHeader}
/>
) : (
<div className="column center align-items-center">
<h1
style={{ margin: 8 }}
id={"data-test-score-card-title"}
>
{title}{" "}
{`${periods.length === 1 ? ` - ${period?.name}` : ""}`}
</h1>
<h3 style={{ color: colors.grey600, margin: 0 }}>
{subtitle}
</h3>
</div>
)}
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useScorecardState } from "../state/state";
import { ScorecardConfig } from "@hisptz/dhis2-analytics";
import { useDimensions } from "../hooks/dimensions";
import i18n from "@dhis2/d2-i18n";
import { colors } from "@dhis2/ui";

export interface ScorecardViewProps {
config: ScorecardConfig;
}

export function ScorecardView({ config }: ScorecardViewProps) {
const { noDimensionsSelected } = useDimensions();
const [state, setState] = useScorecardState();

if (noDimensionsSelected) {
return (
<div className="h-100 w-100 column align-items-center justify-content-center">
<span
style={{
color: colors.grey700,
fontWeight: "bold",
fontSize: 24,
}}
>
{i18n.t(
"Select organisation unit and period to view scorecard",
)}
</span>
</div>
);
}

return (
<div className="h-100 w-100 column align-items-center justify-content-center">
{/*<Scorecard config={config} state={state} setState={setState} />*/}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,14 @@ export function useDimensions() {
setParam("ou")(ous.join(";"));
};

const noDimensionsSelected = useMemo(() => {
return !params.get("ou") || !params.get("pe");
}, [params.get("ou"), params.get("pe")]);

return {
periods,
orgUnit,
noDimensionsSelected,
setPeriod,
setOrgUnit,
setDimensions,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { createContext, ReactNode, useContext } from "react";
import { ScorecardConfig } from "@hisptz/dhis2-analytics";
import i18n from "@dhis2/d2-i18n";

const ScorecardConfigContext = createContext<ScorecardConfig | null>(null);

export function useScorecardConfigFromContext() {
const config = useContext(ScorecardConfigContext);
if (!config) {
throw Error(i18n.t("Could not get scorecard config"));
}

return config;
}

export function ScorecardConfigProvider({
children,
config,
}: {
children: ReactNode;
config: ScorecardConfig;
}) {
return (
<ScorecardConfigContext.Provider value={config}>
{children}
</ScorecardConfigContext.Provider>
);
}
Loading

0 comments on commit bcb518f

Please sign in to comment.