diff --git a/eslint.config.mjs b/eslint.config.mjs index 95282f7..9e9bfda 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,5 +1,6 @@ import globals from "globals"; import pluginReactConfig from "eslint-plugin-react/configs/recommended.js"; +import pluginReactHooks from "eslint-plugin-react-hooks"; import path from "path"; import { fileURLToPath } from "url"; @@ -16,8 +17,22 @@ export default [ ...compat.extends("standard-with-typescript"), pluginReactConfig, { + settings: { + react: { + version: "detect", + }, + }, + plugins: { + "react-hooks": pluginReactHooks, + }, rules: { - "eslint-plugin-react-hooks/rules-of-hooks": "error", + "react-hooks/rules-of-hooks": "error", } + }, + { + files: ["src/locales/index.js"], + rules: { + "spaced-comment": "off", + }, } ]; diff --git a/i18n/en.pot b/i18n/en.pot index 492f37f..1225553 100644 --- a/i18n/en.pot +++ b/i18n/en.pot @@ -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: 2025-11-15T14:56:01.306Z\n" -"PO-Revision-Date: 2025-11-15T14:56:01.306Z\n" +"POT-Creation-Date: 2026-06-02T09:10:34.358Z\n" +"PO-Revision-Date: 2026-06-02T09:10:34.359Z\n" msgid "Data store keys created!" msgstr "Data store keys created!" @@ -111,12 +111,12 @@ msgstr "Enrollment configuration saved" msgid "Failed to save enrollment configuration" msgstr "Failed to save enrollment configuration" -msgid "Add" -msgstr "Add" - msgid "Add widget" msgstr "Add widget" +msgid "Add" +msgstr "Add" + msgid "Add a widget from the list below to add it to the column" msgstr "Add a widget from the list below to add it to the column" @@ -181,23 +181,18 @@ msgstr "Edit event" msgid "Edit" msgstr "Edit" -msgid "Make the enrollment page your own" -msgstr "Make the enrollment page your own" +msgid "No custom layout yet" +msgstr "No custom layout yet" msgid "" -"Switch to edit mode to build a layout that surfaces the data your team " -"needs most. Rearrange widgets, spotlight key indicators, and guide users " -"with a tailored flow." +"This page still uses the default layout. Jump into edit mode to add " +"widgets, reorder columns and create an experience that fits your workflows." msgstr "" -"Switch to edit mode to build a layout that surfaces the data your team " -"needs most. Rearrange widgets, spotlight key indicators, and guide users " -"with a tailored flow." - -msgid "Start designing" -msgstr "Start designing" +"This page still uses the default layout. Jump into edit mode to add " +"widgets, reorder columns and create an experience that fits your workflows." -msgid "You can always revert back to the default layout later." -msgstr "You can always revert back to the default layout later." +msgid "Start" +msgstr "Start" msgid "Quick actions" msgstr "Quick actions" diff --git a/package.json b/package.json index 6bd5646..aff20c2 100644 --- a/package.json +++ b/package.json @@ -34,34 +34,34 @@ }, "dependencies": { "@dhis2/app-runtime": "^3.14.1", - "@hookform/resolvers": "^3.3.4", - "@radix-ui/react-accordion": "^1.1.2", - "@radix-ui/react-alert-dialog": "^1.0.5", - "@radix-ui/react-dialog": "^1.0.5", - "@radix-ui/react-dropdown-menu": "^2.0.6", - "@radix-ui/react-label": "^2.0.2", - "@radix-ui/react-scroll-area": "^1.0.5", - "@radix-ui/react-select": "^2.0.0", - "@radix-ui/react-separator": "^1.0.3", - "@radix-ui/react-slot": "^1.0.2", - "@radix-ui/react-switch": "^1.1.3", - "@radix-ui/react-tooltip": "^1.0.7", + "@hookform/resolvers": "^5.4.0", + "@radix-ui/react-accordion": "^1.2.12", + "@radix-ui/react-alert-dialog": "^1.1.15", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-label": "^2.1.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", + "@radix-ui/react-tooltip": "^1.2.8", "@tanstack/react-query": "^4.36.1", "@tanstack/react-query-devtools": "^v4", "@types/react-beautiful-dnd": "^13.1.8", "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "lucide-react": "^0.364.0", - "next-themes": "^0.3.0", + "next-themes": "^0.4.6", "react-beautiful-dnd": "^13.1.1", "react-dom": "^16", - "react-hook-form": "^7.51.2", - "react-resizable-panels": "^2.0.17", + "react-hook-form": "^7.77.0", + "react-resizable-panels": "^4.11.2", "react-router-dom": "6.3.0", - "sonner": "^1.4.41", + "sonner": "^2.0.7", "tailwind-merge": "^2.2.2", "tailwindcss-animate": "^1.0.7", "typescript": "*", - "zod": "^3.22.4" + "zod": "^4.4.3" } } diff --git a/src/components/DataStoreKeyProvider/DataStoreKeyProvider.tsx b/src/components/DataStoreKeyProvider/DataStoreKeyProvider.tsx index 9a8e12a..e99bcb1 100644 --- a/src/components/DataStoreKeyProvider/DataStoreKeyProvider.tsx +++ b/src/components/DataStoreKeyProvider/DataStoreKeyProvider.tsx @@ -60,8 +60,8 @@ export const DataStoreKeyProvider = ({ children }: Props) => { if (!keysAreValid) { return ( -
{i18n.t('It seems like you are missing some required data store keys.')}
{i18n.t('Do you want to create them?')}
diff --git a/src/components/MobileNavigation/MobileNavigation.tsx b/src/components/MobileNavigation/MobileNavigation.tsx index 7995d50..a64d03e 100644 --- a/src/components/MobileNavigation/MobileNavigation.tsx +++ b/src/components/MobileNavigation/MobileNavigation.tsx @@ -1,9 +1,34 @@ import React from "react"; -import {Sheet, SheetContent, SheetTrigger} from "../ui/sheet"; +import {Sheet, SheetClose, SheetContent, SheetTrigger} from "../ui/sheet"; import {Button} from "../ui/button"; -import {HomeIcon, Package2Icon, PanelLeftIcon} from "lucide-react"; +import {BoxSelectIcon, ClipboardPenLineIcon, Package2Icon, PanelLeftIcon} from "lucide-react"; +import {useLocation, useNavigate} from "react-router-dom"; + +const navigation = [ + { + label: "Dashboard", + icon: Package2Icon, + path: "/", + activePath: "" + }, + { + label: "Form Field Plugin", + icon: ClipboardPenLineIcon, + path: "/formField", + activePath: "formField" + }, + { + label: "Enrollment Overview Plugin", + icon: BoxSelectIcon, + path: "/enrollmentOverview", + activePath: "enrollmentOverview" + } +] export const MobileNavigation = () => { + const navigate = useNavigate(); + const location = useLocation(); + return (
diff --git a/src/components/Pages/EditEnrollmentOverview/FormComponents/AddComponent/AddComponent.tsx b/src/components/Pages/EditEnrollmentOverview/FormComponents/AddComponent/AddComponent.tsx
index 84a1fb6..cefdaff 100644
--- a/src/components/Pages/EditEnrollmentOverview/FormComponents/AddComponent/AddComponent.tsx
+++ b/src/components/Pages/EditEnrollmentOverview/FormComponents/AddComponent/AddComponent.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useMemo, useState } from "react";
import i18n from "@dhis2/d2-i18n";
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from "../../../../ui/sheet";
import { PlusCircleIcon } from "lucide-react";
@@ -22,12 +22,45 @@ type Props = {
page: 'overview' | 'newEvent' | 'editEvent';
}
+const shouldMockLongSidebar = () => {
+ const isLocalhost = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1';
+ const queryString = window.location.hash.split('?')[1] ?? '';
+ return isLocalhost && new URLSearchParams(queryString).get('mockLongSidebar') === 'true';
+}
+
export const AddComponent = ({ columnName, availablePlugins, availableWidgets, allPlugins, page }: Props) => {
const [open, setOpen] = useState(false);
const {
setValue,
getValues,
} = useFormContext {plugin.displayName} {widget.title}
- {form.formState.errors.localPluginUrl.message}
-
+ {form.formState.errors.localPluginUrl.message}
+
{i18n.t('Something went wrong while fetching the configurations. Please try again later.')}
{i18n.t('It looks like you don\'t have any existing configurations. Get started by clicking the button in the right hand corner!')}
{children}
- {i18n.t('Add Local Plugin')}
{i18n.t('Widgets')}
+
diff --git a/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/constants.ts b/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/constants.ts
index b4536b8..1b65197 100644
--- a/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/constants.ts
+++ b/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/constants.ts
@@ -24,7 +24,7 @@ export const FormSection = z.object({
})
export const ConvertedMetadataSchema = z.object({
- id: z.string({ coerce: true }).min(1),
+ id: z.coerce.string().min(1),
displayName: z.string(),
access: z.object({
read: z.boolean(),
diff --git a/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackedEntityType.ts b/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackedEntityType.ts
index 30e17aa..99571dd 100644
--- a/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackedEntityType.ts
+++ b/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackedEntityType.ts
@@ -3,21 +3,21 @@ import i18n from '@dhis2/d2-i18n';
import {z} from "zod";
const ApiTrackedEntityTypeSchema = z.object({
- id: z.string({ required_error: 'Tracked entity type id is missing in the API Payload. Please report the issue to the app maintainer.' }),
- displayName: z.string({ required_error: 'Tracked entity type display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ id: z.string({ error: 'Tracked entity type id is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ displayName: z.string({ error: 'Tracked entity type display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
trackedEntityTypeAttributes: z.array(z.object({
trackedEntityAttribute: z.object({
- id: z.string({ required_error: 'Tracked entity type attribute id is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ id: z.string({ error: 'Tracked entity type attribute id is missing in the API Payload. Please report the issue to the app maintainer.' }),
}),
- displayName: z.string({ required_error: 'Tracked entity type attribute display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
- valueType: z.string({ required_error: 'Tracked entity type attribute value type is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ displayName: z.string({ error: 'Tracked entity type attribute display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ valueType: z.string({ error: 'Tracked entity type attribute value type is missing in the API Payload. Please report the issue to the app maintainer.' }),
})),
access: z.object({
- read: z.boolean({ required_error: 'Read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
- write: z.boolean({ required_error: 'Write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ read: z.boolean({ error: 'Read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ write: z.boolean({ error: 'Write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
data: z.object({
- read: z.boolean({ required_error: 'Data read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
- write: z.boolean({ required_error: 'Data write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ read: z.boolean({ error: 'Data read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ write: z.boolean({ error: 'Data write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
}),
}),
});
diff --git a/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackerProgramById.ts b/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackerProgramById.ts
index 1f86258..4743b50 100644
--- a/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackerProgramById.ts
+++ b/src/components/Pages/FormFieldConfigurator/hooks/useMetadataFromType/Constants/getTrackerProgramById.ts
@@ -2,29 +2,29 @@ import {ConvertedMetadataSchema, FormField, FunctionProps} from "./constants";
import {z} from "zod";
const ApiTrackerProgramSchema = z.object({
- id: z.string({ required_error: 'Tracked entity type id is missing in the API Payload. Please report the issue to the app maintainer.' }),
- displayName: z.string({ required_error: 'Tracked entity type display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ id: z.string({ error: 'Tracked entity type id is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ displayName: z.string({ error: 'Tracked entity type display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
programTrackedEntityAttributes: z.array(z.object({
trackedEntityAttribute: z.object({
- id: z.string({ required_error: 'Tracked entity attribute id is missing in the API Payload. Please report the issue to the app maintainer.' }),
- displayName: z.string({ required_error: 'Tracked entity attribute display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
- valueType: z.string({ required_error: 'Tracked entity attribute value type is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ id: z.string({ error: 'Tracked entity attribute id is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ displayName: z.string({ error: 'Tracked entity attribute display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ valueType: z.string({ error: 'Tracked entity attribute value type is missing in the API Payload. Please report the issue to the app maintainer.' }),
}),
})),
access: z.object({
- read: z.boolean({ required_error: 'Read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
- write: z.boolean({ required_error: 'Write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ read: z.boolean({ error: 'Read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ write: z.boolean({ error: 'Write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
data: z.object({
- read: z.boolean({ required_error: 'Data read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
- write: z.boolean({ required_error: 'Data write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ read: z.boolean({ error: 'Data read access is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ write: z.boolean({ error: 'Data write access is missing in the API Payload. Please report the issue to the app maintainer.' }),
}),
}),
programSections: z.array(z.object({
- id: z.string({ required_error: 'Program section id is missing in the API Payload. Please report the issue to the app maintainer.' }),
- displayName: z.string({ required_error: 'Program section display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
- sortOrder: z.number({ required_error: 'Program section sort order is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ id: z.string({ error: 'Program section id is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ displayName: z.string({ error: 'Program section display name is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ sortOrder: z.number({ error: 'Program section sort order is missing in the API Payload. Please report the issue to the app maintainer.' }),
trackedEntityAttributes: z.array(z.object({
- id: z.string({ required_error: 'Tracked entity attribute id is missing in the API Payload. Please report the issue to the app maintainer.' }),
+ id: z.string({ error: 'Tracked entity attribute id is missing in the API Payload. Please report the issue to the app maintainer.' }),
})),
})),
});
diff --git a/src/components/Pages/FormFieldPlugins/DataTable/FormFieldTable.tsx b/src/components/Pages/FormFieldPlugins/DataTable/FormFieldTable.tsx
index c60d845..ba55148 100644
--- a/src/components/Pages/FormFieldPlugins/DataTable/FormFieldTable.tsx
+++ b/src/components/Pages/FormFieldPlugins/DataTable/FormFieldTable.tsx
@@ -151,7 +151,7 @@ export const FormFieldTable = ({
}
return (
-
+
+ HTMLDivElement,
+ React.HTMLAttributes