diff --git a/.example.env b/.example.env index 862f05eb5c4..79e826ad65f 100644 --- a/.example.env +++ b/.example.env @@ -62,3 +62,6 @@ REACT_ALLOWED_LOCALES="en,hi,ta,ml,mr,kn" # ISO 3166-1 Alpha-2 code for the default country code (default: "IN") REACT_DEFAULT_COUNTRY= + +# Maps fallback URL template (default:"https://www.openstreetmap.org/?mlat={lat}&mlon={long}&zoom=15") +REACT_MAPS_FALLBACK_URL_TEMPLATE= \ No newline at end of file diff --git a/.github/workflows/issue-automation.yml b/.github/workflows/issue-automation.yml deleted file mode 100644 index 59f164781b8..00000000000 --- a/.github/workflows/issue-automation.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Automate Issues to Project -on: - issues: - types: - - opened - - reopened - - closed - - assigned -jobs: - issue_opened_and_reopened: - name: issue_opened_and_reopened - runs-on: ubuntu-24.04-arm - if: github.repository == 'ohcnetwork/care_fe' && github.event_name == 'issues' && github.event.action == 'opened' || github.event.action == 'reopened' - steps: - - name: 'Move issue to "Triage"' - uses: leonsteinhaeuser/project-beta-automations@v2.2.1 - with: - gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - organization: ohcnetwork - project_id: 4 - resource_node_id: ${{ github.event.issue.node_id }} - status_value: "Triage" - issue_closed: - name: issue_closed - runs-on: ubuntu-24.04-arm - if: github.repository == 'ohcnetwork/care_fe' && github.event_name == 'issues' && github.event.action == 'closed' - steps: - - name: 'Moved issue to "Done"' - uses: leonsteinhaeuser/project-beta-automations@v2.2.1 - with: - gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - organization: ohcnetwork - project_id: 4 - resource_node_id: ${{ github.event.issue.node_id }} - status_value: "Done" - issue_assigned: - name: issue_assigned - runs-on: ubuntu-24.04-arm - if: github.repository == 'ohcnetwork/care_fe' && github.event_name == 'issues' && github.event.action == 'assigned' - steps: - - name: 'Move issue to "In Progress"' - uses: leonsteinhaeuser/project-beta-automations@v2.2.1 - with: - gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - organization: ohcnetwork - project_id: 4 - resource_node_id: ${{ github.event.issue.node_id }} - status_value: "In Progress" diff --git a/care.config.ts b/care.config.ts index d99d6fe73cd..9f646dbab0a 100644 --- a/care.config.ts +++ b/care.config.ts @@ -55,6 +55,10 @@ const careConfig = { defaultEncounterType: (env.REACT_DEFAULT_ENCOUNTER_TYPE || "hh") as EncounterClass, + mapFallbackUrlTemplate: + env.REACT_MAPS_FALLBACK_URL_TEMPLATE || + "https://www.openstreetmap.org/?mlat={lat}&mlon={long}&zoom=15", + gmapsApiKey: env.REACT_GMAPS_API_KEY || "AIzaSyDsBAc3y7deI5ZO3NtK5GuzKwtUzQNJNUk", diff --git a/cypress/e2e/patient_spec/patient_creation.cy.ts b/cypress/e2e/patient_spec/patient_creation.cy.ts index dc237fdd1bf..be0b1962115 100644 --- a/cypress/e2e/patient_spec/patient_creation.cy.ts +++ b/cypress/e2e/patient_spec/patient_creation.cy.ts @@ -17,6 +17,7 @@ const patientEncounter = new PatientEncounter(); const ENCOUNTER_TYPE = "Observation"; const ENCOUNTER_STATUS = "In Progress"; const ENCOUNTER_PRIORITY = "ASAP"; +const ORGANIZATION_NAME = "Administration"; describe("Patient Management", () => { const TEST_PHONE = "9495031234"; @@ -100,6 +101,7 @@ describe("Patient Management", () => { ]; beforeEach(() => { + cy.viewport(1920, 1080); cy.loginByApi("doctor"); cy.visit("/"); }); @@ -122,6 +124,7 @@ describe("Patient Management", () => { .selectEncounterType(ENCOUNTER_TYPE) .selectEncounterStatus(ENCOUNTER_STATUS) .selectEncounterPriority(ENCOUNTER_PRIORITY) + .selectOrganization(ORGANIZATION_NAME) .clickSubmitEncounter() .assertEncounterCreationSuccess(); @@ -150,6 +153,7 @@ describe("Patient Management", () => { .selectEncounterType(ENCOUNTER_TYPE) .selectEncounterStatus(ENCOUNTER_STATUS) .selectEncounterPriority(ENCOUNTER_PRIORITY) + .selectOrganization(ORGANIZATION_NAME) .clickSubmitEncounter() .assertEncounterCreationSuccess(); diff --git a/cypress/e2e/patient_spec/patient_details.cy.ts b/cypress/e2e/patient_spec/patient_details.cy.ts index d96baf9bfef..dcbfe35accf 100644 --- a/cypress/e2e/patient_spec/patient_details.cy.ts +++ b/cypress/e2e/patient_spec/patient_details.cy.ts @@ -8,6 +8,7 @@ const patientDetails = new PatientDetails(); describe("Patient Management", () => { beforeEach(() => { + cy.viewport(1920, 1080); cy.loginByApi("devdoctor"); cy.visit("/"); }); diff --git a/cypress/e2e/patient_spec/patient_encounter.cy.ts b/cypress/e2e/patient_spec/patient_encounter.cy.ts index 2569b9567bc..7df0ff4866f 100644 --- a/cypress/e2e/patient_spec/patient_encounter.cy.ts +++ b/cypress/e2e/patient_spec/patient_encounter.cy.ts @@ -6,6 +6,7 @@ const patientEncounter = new PatientEncounter(); describe("Patient Encounter Questionnaire", () => { beforeEach(() => { + cy.viewport(1920, 1080); cy.loginByApi("devnurse"); cy.visit("/"); }); diff --git a/cypress/e2e/users_spec/user_avatar.cy.ts b/cypress/e2e/users_spec/user_avatar.cy.ts new file mode 100644 index 00000000000..830dcb1b40c --- /dev/null +++ b/cypress/e2e/users_spec/user_avatar.cy.ts @@ -0,0 +1,22 @@ +import { UserAvatar } from "@/pageObject/Users/UserAvatar"; + +describe("User Profile Avatar Modification", () => { + const userAvatar = new UserAvatar("teststaff4"); + beforeEach(() => { + cy.loginByApi("teststaff4"); + cy.visit("/"); + }); + it("should modify an avatar", () => { + userAvatar + .navigateToProfile() + .interceptUploadAvatarRequest() + .clickChangeAvatarButton() + .uploadAvatar() + .clickSaveAvatarButton() + .verifyUploadAvatarApiCall() + .interceptDeleteAvatarRequest() + .clickChangeAvatarButton() + .clickDeleteAvatarButton() + .verifyDeleteAvatarApiCall(); + }); +}); diff --git a/cypress/fixtures/avatar.jpg b/cypress/fixtures/avatar.jpg new file mode 100644 index 00000000000..464ca73c65c Binary files /dev/null and b/cypress/fixtures/avatar.jpg differ diff --git a/cypress/fixtures/users.json b/cypress/fixtures/users.json index 1c3799e32ba..db27e9969f7 100644 --- a/cypress/fixtures/users.json +++ b/cypress/fixtures/users.json @@ -22,5 +22,9 @@ "devdoctor": { "username": "developdoctor", "password": "Test@123" + }, + "teststaff4": { + "username": "teststaff4", + "password": "Test@123" } } diff --git a/cypress/pageObject/Patients/PatientVerify.ts b/cypress/pageObject/Patients/PatientVerify.ts index de98d9d8d61..b2af1a32ea9 100644 --- a/cypress/pageObject/Patients/PatientVerify.ts +++ b/cypress/pageObject/Patients/PatientVerify.ts @@ -49,6 +49,11 @@ class PatientVerify { return this; } + selectOrganization(organization: string) { + cy.clickAndSelectOption('[data-cy="facility-organization"]', organization); + return this; + } + clickSubmitEncounter() { cy.clickSubmitButton("Create Encounter"); return this; diff --git a/cypress/pageObject/Users/UserAvatar.ts b/cypress/pageObject/Users/UserAvatar.ts new file mode 100644 index 00000000000..ad8d59ef330 --- /dev/null +++ b/cypress/pageObject/Users/UserAvatar.ts @@ -0,0 +1,59 @@ +export class UserAvatar { + username: string; + constructor(username: string) { + this.username = username; + } + + navigateToProfile() { + cy.visit(`/users/${this.username}`); + return this; + } + + interceptUploadAvatarRequest() { + cy.intercept("POST", `/api/v1/users/${this.username}/profile_picture/`).as( + "uploadAvatar", + ); + return this; + } + + clickChangeAvatarButton() { + cy.verifyAndClickElement('[data-cy="change-avatar"]', "Change Avatar"); + return this; + } + + uploadAvatar() { + cy.get('input[title="changeFile"]').selectFile( + "cypress/fixtures/avatar.jpg", + { force: true }, + ); + return this; + } + + clickSaveAvatarButton() { + cy.verifyAndClickElement('[data-cy="save-cover-image"]', "Save"); + return this; + } + + verifyUploadAvatarApiCall() { + cy.wait("@uploadAvatar").its("response.statusCode").should("eq", 200); + return this; + } + + interceptDeleteAvatarRequest() { + cy.intercept( + "DELETE", + `/api/v1/users/${this.username}/profile_picture/`, + ).as("deleteAvatar"); + return this; + } + + clickDeleteAvatarButton() { + cy.verifyAndClickElement('[data-cy="delete-avatar"]', "Delete"); + return this; + } + + verifyDeleteAvatarApiCall() { + cy.wait("@deleteAvatar").its("response.statusCode").should("eq", 204); + return this; + } +} diff --git a/package-lock.json b/package-lock.json index bc5266174fb..89bcdb6f66d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "care_fe", - "version": "3.2.0", + "version": "3.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "care_fe", - "version": "3.2.0", + "version": "3.4.0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -56,7 +56,7 @@ "i18next-http-backend": "^3.0.1", "i18next-resources-to-backend": "^1.2.1", "input-otp": "^1.4.2", - "jspdf": "^2.5.2", + "jspdf": "^3.0.0", "libphonenumber-js": "^1.11.18", "lucide-react": "^0.475.0", "markdown-it": "^14.1.0", @@ -75,15 +75,17 @@ "react-phone-number-input": "^3.4.11", "react-webcam": "^7.2.0", "recharts": "^2.15.0", - "sonner": "^1.7.2", + "sonner": "^2.0.0", "tailwind-merge": "^3.0.0", "tailwindcss-animate": "^1.0.7", - "use-keyboard-shortcut": "^1.1.6" + "use-keyboard-shortcut": "^1.1.6", + "zod": "^3.23.8" }, "devDependencies": { "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.18.0", "@julr/vite-plugin-validate-env": "^1.1.1", + "@react-scan/vite-plugin-react-scan": "^0.1.3", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", @@ -132,7 +134,7 @@ "unimported": "^1.31.0", "uuid": "^11.0.2", "vite": "^5.4.10", - "vite-plugin-checker": "^0.8.0", + "vite-plugin-checker": "^0.9.0", "vite-plugin-pwa": "^0.21.0", "vite-plugin-static-copy": "^2.0.0", "zod": "^3.23.8" @@ -514,9 +516,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -787,6 +789,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", @@ -1453,6 +1471,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", + "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", @@ -1614,6 +1652,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", + "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", @@ -1790,6 +1848,26 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", @@ -1856,6 +1934,31 @@ "node": ">=6.9.0" } }, + "node_modules/@clack/core": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.5.tgz", + "integrity": "sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.8.2.tgz", + "integrity": "sha512-6b9Ab2UiZwJYA9iMyboYyW9yJvAO9V753ZhS+DHKEjZRKAxPPOb7MXXu84lsPFG+vZt6FRFniZ8rXi+zCIw4yQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@clack/core": "0.3.5", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2077,9 +2180,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", "cpu": [ "ppc64" ], @@ -2094,9 +2197,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", "cpu": [ "arm" ], @@ -2111,9 +2214,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", "cpu": [ "arm64" ], @@ -2128,9 +2231,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", "cpu": [ "x64" ], @@ -2145,9 +2248,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", "cpu": [ "arm64" ], @@ -2162,9 +2265,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", "cpu": [ "x64" ], @@ -2179,9 +2282,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", "cpu": [ "arm64" ], @@ -2196,9 +2299,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", "cpu": [ "x64" ], @@ -2213,9 +2316,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", "cpu": [ "arm" ], @@ -2230,9 +2333,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], @@ -2246,9 +2349,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", "cpu": [ "ia32" ], @@ -2263,9 +2366,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", "cpu": [ "loong64" ], @@ -2280,9 +2383,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", "cpu": [ "mips64el" ], @@ -2297,9 +2400,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", "cpu": [ "ppc64" ], @@ -2314,9 +2417,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", "cpu": [ "riscv64" ], @@ -2331,9 +2434,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", "cpu": [ "s390x" ], @@ -2348,9 +2451,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], @@ -2363,10 +2466,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", "cpu": [ "x64" ], @@ -2381,9 +2501,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", "cpu": [ "arm64" ], @@ -2398,9 +2518,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", "cpu": [ "x64" ], @@ -2415,9 +2535,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", "cpu": [ "x64" ], @@ -2432,9 +2552,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", "cpu": [ "arm64" ], @@ -2449,9 +2569,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", "cpu": [ "ia32" ], @@ -2466,9 +2586,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", "cpu": [ "x64" ], @@ -2512,13 +2632,13 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", - "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", + "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.5", + "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -2551,9 +2671,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz", - "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2564,9 +2684,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", - "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", + "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2625,9 +2745,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.20.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz", - "integrity": "sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==", + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", + "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", "dev": true, "license": "MIT", "engines": { @@ -2635,9 +2755,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", - "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2645,13 +2765,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz", - "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", + "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", + "@eslint/core": "^0.12.0", "levn": "^0.4.1" }, "engines": { @@ -2863,9 +2983,9 @@ "peer": true }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", - "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3095,6 +3215,18 @@ "pnpm": ">=7.0.1" } }, + "node_modules/@pivanov/utils": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@pivanov/utils/-/utils-0.0.1.tgz", + "integrity": "sha512-JQ/pXeG9/Yq3UuwH2Xp4F6bSAIDGzbxT0Vrg/82tMi3Yp+Ps9AYzjSDE+zfvBRqc7J11V6MMonUrWj4+2dYgrg==", + "dev": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3163,6 +3295,36 @@ "validator": "^13.9.0" } }, + "node_modules/@preact/signals": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.3.2.tgz", + "integrity": "sha512-naxcJgUJ6BTOROJ7C3QML7KvwKwCXQJYTc5L/b0eEsdYgPB6SxwoQ1vDGcS0Q7GVjAenVq/tXrybVdFShHYZWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@preact/signals-core": "^1.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": "10.x" + } + }, + "node_modules/@preact/signals-core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz", + "integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", @@ -4347,6 +4509,32 @@ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-scan/vite-plugin-react-scan": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@react-scan/vite-plugin-react-scan/-/vite-plugin-react-scan-0.1.3.tgz", + "integrity": "sha512-cQLvTSePL6T+58u5HON2vBL53C7REPodrK9M7totyyD5+Vv5vTBGjQZC1o2iPSv62VgeUwueYnzhqAdTHlEc6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx": "^7.25.9", + "@babel/preset-typescript": "^7.23.3", + "babel-plugin-add-react-displayname": "^0.0.5", + "cheerio": "^1.0.0" + }, + "peerDependencies": { + "react-scan": "^0.1.0", + "vite": "^2 || ^3 || ^4 || ^5 || ^6" + }, + "peerDependenciesMeta": { + "react-scan": { + "optional": false + }, + "vite": { + "optional": false + } + } + }, "node_modules/@react-stately/utils": { "version": "3.10.5", "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.5.tgz", @@ -5007,9 +5195,9 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.66.5", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.66.5.tgz", - "integrity": "sha512-D9aABj3/aFeNmifsdllh5O3hPyA8gUnZ1jAV8MjODQ7blirfAyGed9NjAnm8rgEdr1wChyjTT738ij3vY0EREQ==", + "version": "5.66.9", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.66.9.tgz", + "integrity": "sha512-NRI02PHJsP5y2gAuWKP+awamTIBFBSKMnO6UVzi03GTclmHHHInH5UzVgzi5tpu4+FmGfsdT7Umqegobtsp23A==", "license": "MIT", "dependencies": { "@tanstack/query-core": "5.66.4" @@ -5023,9 +5211,9 @@ } }, "node_modules/@tanstack/react-query-devtools": { - "version": "5.66.5", - "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.66.5.tgz", - "integrity": "sha512-aj/+IuLdt3fbNweKo2XSK6OMUpOULDUO1MRDUtggRl8W6/EvD7FVvm0ydRrOMvS9KUqC25V88WPYaPj8SEVGXg==", + "version": "5.66.9", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.66.9.tgz", + "integrity": "sha512-70G6AR35he53SYUcUK6EdqNR18zejCv1rM6900gjZP408EAex56YLwVSeijzk9lWeU2J42G9Fjh0i1WngUTsgw==", "license": "MIT", "dependencies": { "@tanstack/query-devtools": "5.65.0" @@ -5035,7 +5223,7 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "peerDependencies": { - "@tanstack/react-query": "^5.66.5", + "@tanstack/react-query": "^5.66.9", "react": "^18 || ^19" } }, @@ -5309,9 +5497,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.4.tgz", - "integrity": "sha512-ywP2X0DYtX3y08eFVx5fNIw7/uIv8hYUKgXoK8oayJlLnKcRfEYCxWMVE1XagUdVtCJlZT1AU4LXEABW+L1Peg==", + "version": "22.13.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", + "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", "devOptional": true, "license": "MIT", "dependencies": { @@ -6581,6 +6769,13 @@ "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", "license": "MIT" }, + "node_modules/babel-plugin-add-react-displayname": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz", + "integrity": "sha512-LY3+Y0XVDYcShHHorshrDbt4KFWL4bSeniCtl4SYZbask+Syngk1uMPCeN9+nSiZo6zX5s0RTq/J9Pnaaf/KHw==", + "dev": true, + "license": "MIT" + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.12", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", @@ -6690,6 +6885,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/bippy": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/bippy/-/bippy-0.2.7.tgz", + "integrity": "sha512-LTCos3SmOJHrag0qF91tLUZMMw6wA+i15ESRBp71pvfNlTMYcxYoJHJ/pvFhd+29Wm5vfgVxBHV7kP5OKUUipg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -6714,6 +6917,13 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "license": "MIT" }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -7064,6 +7274,60 @@ "node": ">= 0.8.0" } }, + "node_modules/cheerio": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^6.19.5", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=18.17" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio/node_modules/undici": { + "version": "6.21.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz", + "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -7487,9 +7751,9 @@ } }, "node_modules/country-flag-icons": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.14.tgz", - "integrity": "sha512-GAFsVzHDu3bdAhbQ1LwBRqk/Ad8+ZzS5zU49P+lRla0KGy/V1V8ywNa1SxBOAmI/lyEOT9dfH3Q++q1lqJlvBA==", + "version": "1.5.18", + "resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.18.tgz", + "integrity": "sha512-z+Uzesi8u8IdkViqqbzzbkf3+a7WJpcET5B7sPwTg7GXqPYpVEgNlZ/FC3l8KO4mEf+mNkmzKLppKTN4PlCJEQ==", "license": "MIT" }, "node_modules/create-require": { @@ -7560,6 +7824,36 @@ "utrie": "^1.0.2" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -7664,9 +7958,9 @@ } }, "node_modules/cypress-split": { - "version": "1.24.13", - "resolved": "https://registry.npmjs.org/cypress-split/-/cypress-split-1.24.13.tgz", - "integrity": "sha512-vu3CHfnXFLUKFWvpEeVo2IQNJe8661ZdtAr9EYySLxaqs1H3I3yNDmQklEv3wF/ZDdQKa0r1crka8Umy2w8BsQ==", + "version": "1.24.14", + "resolved": "https://registry.npmjs.org/cypress-split/-/cypress-split-1.24.14.tgz", + "integrity": "sha512-lc5KuntDKK/n8/XxDh97OeKLWZP6bLbKTiIdoxtsgg2FEXta4hM7mg0xeLPB0IfBRQWKp5g6uyEM1vHAl36f0w==", "dev": true, "license": "MIT", "dependencies": { @@ -7675,7 +7969,7 @@ "console.table": "^0.10.0", "debug": "^4.3.4", "fast-shuffle": "^6.1.0", - "find-cypress-specs": "1.47.7", + "find-cypress-specs": "1.47.9", "globby": "^11.1.0", "humanize-duration": "^3.28.0" }, @@ -8331,16 +8625,75 @@ "csstype": "^3.0.2" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, "node_modules/dompurify": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", - "dev": true, + "devOptional": true, "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/dotenv": { "version": "16.4.7", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", @@ -8425,10 +8778,24 @@ "dev": true, "license": "MIT" }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "node_modules/encoding-sniffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", + "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -8698,9 +9065,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -8711,36 +9078,37 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" } }, "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", "cpu": [ "arm64" ], @@ -8755,9 +9123,9 @@ } }, "node_modules/esbuild/node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", "cpu": [ "x64" ], @@ -8771,6 +9139,23 @@ "node": ">=18" } }, + "node_modules/esbuild/node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -8827,22 +9212,22 @@ } }, "node_modules/eslint": { - "version": "9.20.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz", - "integrity": "sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==", + "version": "9.21.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", + "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.0", - "@eslint/core": "^0.11.0", - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "9.20.0", - "@eslint/plugin-kit": "^0.2.5", + "@eslint/config-array": "^0.19.2", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.0", + "@eslint/js": "9.21.0", + "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", + "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -9061,19 +9446,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/core": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz", - "integrity": "sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/eslint/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -9539,9 +9911,9 @@ } }, "node_modules/find-cypress-specs": { - "version": "1.47.7", - "resolved": "https://registry.npmjs.org/find-cypress-specs/-/find-cypress-specs-1.47.7.tgz", - "integrity": "sha512-l44j22oQRBcgP79Fj9MMMGUQ3T0950sHRB1yOncGdZAqZKjykBLf/sn0u7sGcUf76+pgknsA5n2ehVIHoMqOuA==", + "version": "1.47.9", + "resolved": "https://registry.npmjs.org/find-cypress-specs/-/find-cypress-specs-1.47.9.tgz", + "integrity": "sha512-sB1q4aDq9eqaeCqWdr4wHUk6gpXNfa2HoZDsZxT+MZcC4nTw6kU+t9KpFIHudSRGXsQF/3xpdTGWKmgAgaDtyA==", "dev": true, "license": "MIT", "dependencies": { @@ -9556,7 +9928,7 @@ "require-and-forget": "^1.0.1", "shelljs": "^0.8.5", "spec-change": "^1.11.0", - "tsx": "^4.7.1" + "tsx": "^4.19.3" }, "bin": { "find-cypress-specs": "bin/find.js" @@ -10330,6 +10702,26 @@ "node": ">=8.0.0" } }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -10436,9 +10828,9 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.3.tgz", - "integrity": "sha512-beOOLArattPBc2YZG5IXGJytdYFgUR7cS8Wd6HT4IczIoWKgmTspOQ2yasaGklelVo5seLPmnEKvLHR+E/MdWQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.4.tgz", + "integrity": "sha512-f3frU3pIxD50/Tz20zx9TD9HobKYg47fmAETb117GKGPrhwcSSPJDoCposXlVycVebQ9GQohC3Efbpq7/nnJ5w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" @@ -11472,12 +11864,12 @@ } }, "node_modules/jspdf": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz", - "integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.0.tgz", + "integrity": "sha512-QvuQZvOI8CjfjVgtajdL0ihrDYif1cN5gXiF9lb9Pd9JOpmocvnNyFO9sdiJ/8RA5Bu8zyGOUjJLj5kiku16ug==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.2", + "@babel/runtime": "^7.26.0", "atob": "^2.1.2", "btoa": "^1.2.1", "fflate": "^0.8.1" @@ -11485,17 +11877,10 @@ "optionalDependencies": { "canvg": "^3.0.6", "core-js": "^3.6.0", - "dompurify": "^2.5.4", + "dompurify": "^3.2.4", "html2canvas": "^1.0.0-rc.5" } }, - "node_modules/jspdf/node_modules/dompurify": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.8.tgz", - "integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optional": true - }, "node_modules/jsprim": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", @@ -12754,6 +13139,17 @@ "node": "*" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -12979,6 +13375,19 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nwsapi": { "version": "2.2.16", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", @@ -13313,6 +13722,33 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -13487,6 +13923,56 @@ "node": ">= 6" } }, + "node_modules/playwright": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", + "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "playwright-core": "1.50.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", + "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -13508,9 +13994,9 @@ } }, "node_modules/postcss": { - "version": "8.5.2", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz", - "integrity": "sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -13733,6 +14219,18 @@ "postcss": "^8.2.9" } }, + "node_modules/preact": { + "version": "10.26.2", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.2.tgz", + "integrity": "sha512-0gNmv4qpS9HaN3+40CLBAnKe0ZfyE4ZWo5xKlC1rVrr0ckkEvJvAQqKaHANdFKsGstoxrY4AItZ7kZSGVoVjgg==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", @@ -14259,9 +14757,9 @@ } }, "node_modules/react-i18next": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz", - "integrity": "sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.1.tgz", + "integrity": "sha512-ahGab+IaSgZmNPYXdV1n+OYky95TGpFwnKRflX/16dY04DsYYKHtVLjeny7sBSCREEcoMbAgSkFiGLF5g5Oofw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.0", @@ -14331,15 +14829,15 @@ } }, "node_modules/react-phone-number-input": { - "version": "3.4.11", - "resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.11.tgz", - "integrity": "sha512-ypN9hXwUModpngho9brCHLLD40xzb1DKAZFacbF0J+fFaMVLEJo+zul9sZfSRlKehSjpttT4b1pLMcOWXI228g==", + "version": "3.4.12", + "resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.12.tgz", + "integrity": "sha512-Raob77KdtLGm49iC6nuOX9qy6Mg16idkgC7Y1mHmvG2WBYoauHpzxYNlfmFskQKeiztrJIwPhPzBhjFwjenNCA==", "license": "MIT", "dependencies": { "classnames": "^2.5.1", - "country-flag-icons": "^1.5.11", + "country-flag-icons": "^1.5.17", "input-format": "^0.3.10", - "libphonenumber-js": "^1.11.17", + "libphonenumber-js": "^1.11.20", "prop-types": "^15.8.1" }, "peerDependencies": { @@ -14403,6 +14901,80 @@ } } }, + "node_modules/react-scan": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/react-scan/-/react-scan-0.1.3.tgz", + "integrity": "sha512-mPhceIDUm6KugQPOF6PcQWBxo49/ZX7TnP5+/f/wbz7/36sM1A3ESAIAOXe+Leha30AJPriG1U4nABnEF4N8vQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.26.0", + "@babel/generator": "^7.26.2", + "@babel/types": "^7.26.0", + "@clack/core": "^0.3.5", + "@clack/prompts": "^0.8.2", + "@pivanov/utils": "^0.0.1", + "@preact/signals": "^1.3.1", + "@rollup/pluginutils": "^5.1.3", + "@types/node": "^20.17.9", + "bippy": "0.2.7", + "esbuild": "^0.24.0", + "estree-walker": "^3.0.3", + "kleur": "^4.1.5", + "mri": "^1.2.0", + "playwright": "^1.49.0", + "preact": "^10.25.1", + "tsx": "^4.0.0" + }, + "bin": { + "react-scan": "bin/cli.js" + }, + "optionalDependencies": { + "unplugin": "2.1.0" + }, + "peerDependencies": { + "@remix-run/react": ">=1.0.0", + "next": ">=13.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-router": "^5.0.0 || ^6.0.0 || ^7.0.0", + "react-router-dom": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@remix-run/react": { + "optional": true + }, + "next": { + "optional": true + }, + "react-router": { + "optional": true + }, + "react-router-dom": { + "optional": true + } + } + }, + "node_modules/react-scan/node_modules/@types/node": { + "version": "20.17.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.19.tgz", + "integrity": "sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/react-scan/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/react-smooth": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", @@ -15614,6 +16186,14 @@ "url": "https://github.com/steveukx/git-js?sponsor=1" } }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -15680,9 +16260,9 @@ } }, "node_modules/sonner": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/sonner/-/sonner-1.7.4.tgz", - "integrity": "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.1.tgz", + "integrity": "sha512-FRBphaehZ5tLdLcQ8g2WOIRE+Y7BCfWi5Zyd8bCvBjiW8TxxAyoWZIxS661Yz6TGPqFQ4VLzOF89WEYhfynSFQ==", "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -16594,23 +17174,26 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.2", + "fdir": "^6.4.3", "picomatch": "^4.0.2" }, "engines": { "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", "dev": true, "license": "MIT", "peerDependencies": { @@ -16800,13 +17383,13 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", - "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "version": "4.19.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz", + "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "~0.23.0", + "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -16819,62 +17402,477 @@ "fsevents": "~2.3.3" } }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + "node": ">=18" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "license": "Unlicense" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 0.8.0" + "node": ">=18" } }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/esbuild": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, @@ -17081,6 +18079,19 @@ "node": ">=4" } }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unimported": { "version": "1.31.1", "resolved": "https://registry.npmjs.org/unimported/-/unimported-1.31.1.tgz", @@ -17610,6 +18621,22 @@ "node": ">= 10.0.0" } }, + "node_modules/unplugin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.1.0.tgz", + "integrity": "sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -17749,9 +18776,9 @@ } }, "node_modules/uuid": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", - "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", "dev": true, "funding": [ "https://github.com/sponsors/broofa", @@ -17892,26 +18919,21 @@ } }, "node_modules/vite-plugin-checker": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.8.0.tgz", - "integrity": "sha512-UA5uzOGm97UvZRTdZHiQVYFnd86AVn8EVaD4L3PoVzxH+IZSfaAw14WGFwX9QS23UW3lV/5bVKZn6l0w+q9P0g==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.9.0.tgz", + "integrity": "sha512-gf/zc0KWX8ATEOgnpgAM1I+IbvWkkO80RB+FxlLtC5cabXSesbJmAUw6E+mMDDMGIT+VHAktmxJZpMTt3lSubQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.12.13", - "ansi-escapes": "^4.3.0", - "chalk": "^4.1.1", - "chokidar": "^3.5.1", - "commander": "^8.0.0", - "fast-glob": "^3.2.7", - "fs-extra": "^11.1.0", - "npm-run-path": "^4.0.1", - "strip-ansi": "^6.0.0", - "tiny-invariant": "^1.1.0", - "vscode-languageclient": "^7.0.0", - "vscode-languageserver": "^7.0.0", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-uri": "^3.0.2" + "@babel/code-frame": "^7.26.2", + "chokidar": "^4.0.3", + "npm-run-path": "^6.0.0", + "picocolors": "^1.1.1", + "picomatch": "^4.0.2", + "strip-ansi": "^7.1.0", + "tiny-invariant": "^1.3.3", + "tinyglobby": "^0.2.12", + "vscode-uri": "^3.1.0" }, "engines": { "node": ">=14.16" @@ -17919,14 +18941,14 @@ "peerDependencies": { "@biomejs/biome": ">=1.7", "eslint": ">=7", - "meow": "^9.0.0", + "meow": "^13.2.0", "optionator": "^0.9.1", - "stylelint": ">=13", + "stylelint": ">=16", "typescript": "*", "vite": ">=2.0.0", "vls": "*", "vti": "*", - "vue-tsc": "~2.1.6" + "vue-tsc": "~2.2.2" }, "peerDependenciesMeta": { "@biomejs/biome": { @@ -17958,58 +18980,106 @@ } } }, - "node_modules/vite-plugin-checker/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "node_modules/vite-plugin-checker/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/vite-plugin-checker/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" + "readdirp": "^4.0.1" }, "engines": { - "node": ">=8" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/vite-plugin-checker/node_modules/npm-run-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vite-plugin-checker/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "node_modules/vite-plugin-checker/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", "dev": true, "license": "MIT", "engines": { - "node": ">= 12" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vite-plugin-checker/node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "node_modules/vite-plugin-checker/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "engines": { + "node": ">=12" }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vite-plugin-checker/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=14.14" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/vite-plugin-checker/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/vite-plugin-checker/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/vite-plugin-pwa": { @@ -18512,97 +19582,10 @@ "node": ">=0.10.0" } }, - "node_modules/vscode-jsonrpc": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz", - "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0 || >=10.0.0" - } - }, - "node_modules/vscode-languageclient": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz", - "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimatch": "^3.0.4", - "semver": "^7.3.4", - "vscode-languageserver-protocol": "3.16.0" - }, - "engines": { - "vscode": "^1.52.0" - } - }, - "node_modules/vscode-languageclient/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/vscode-languageclient/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/vscode-languageserver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-7.0.0.tgz", - "integrity": "sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==", - "dev": true, - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.16.0" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz", - "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==", - "dev": true, - "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "6.0.0", - "vscode-languageserver-types": "3.16.0" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz", - "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==", - "dev": true, - "license": "MIT" - }, "node_modules/vscode-uri": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", - "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", "dev": true, "license": "MIT" }, @@ -18648,6 +19631,15 @@ "node": ">=12" } }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", diff --git a/package.json b/package.json index d4d8f582882..5b2047bf801 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "care_fe", - "version": "3.2.0", + "version": "3.4.0", "description": "Care is a Digital Public Good enabling TeleICU & Decentralised Administration of Healthcare Capacity across States.", "private": true, "repository": { @@ -30,6 +30,7 @@ "dev": "npm run supported-browsers && vite", "local": "npm run supported-browsers && vite --mode docker", "preview": "cross-env NODE_ENV=production vite preview", + "preview:scan": "npm run preview & npx react-scan localhost:4000", "build:meta": "node ./scripts/generate-build-version.js", "build:react": "cross-env NODE_ENV=production vite build", "supported-browsers": "node ./scripts/generate-supported-browsers.mjs", @@ -95,7 +96,7 @@ "i18next-http-backend": "^3.0.1", "i18next-resources-to-backend": "^1.2.1", "input-otp": "^1.4.2", - "jspdf": "^2.5.2", + "jspdf": "^3.0.0", "libphonenumber-js": "^1.11.18", "lucide-react": "^0.475.0", "markdown-it": "^14.1.0", @@ -114,7 +115,7 @@ "react-phone-number-input": "^3.4.11", "react-webcam": "^7.2.0", "recharts": "^2.15.0", - "sonner": "^1.7.2", + "sonner": "^2.0.0", "tailwind-merge": "^3.0.0", "tailwindcss-animate": "^1.0.7", "use-keyboard-shortcut": "^1.1.6", @@ -124,6 +125,7 @@ "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.18.0", "@julr/vite-plugin-validate-env": "^1.1.1", + "@react-scan/vite-plugin-react-scan": "^0.1.3", "@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", @@ -172,7 +174,7 @@ "unimported": "^1.31.0", "uuid": "^11.0.2", "vite": "^5.4.10", - "vite-plugin-checker": "^0.8.0", + "vite-plugin-checker": "^0.9.0", "vite-plugin-pwa": "^0.21.0", "vite-plugin-static-copy": "^2.0.0", "zod": "^3.23.8" diff --git a/public/locale/en.json b/public/locale/en.json index 7d7d340c5c9..f091187b0a7 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -282,6 +282,7 @@ "active": "Active", "active_encounters": "Active Encounters", "active_files": "Active Files", + "active_location_cannot_be_in_future": "Active location cannot be in the future", "active_prescriptions": "Active Prescriptions", "add": "Add", "add_another_session": "Add another session", @@ -291,8 +292,11 @@ "add_beds_to_configure_presets": "Add beds to this location to configure presets for them.", "add_consultation": "Add consultation", "add_consultation_update": "Add Consultation Update", + "add_contact_point": "Add Contact Point", "add_department_team": "Add Department/Team", "add_details_of_patient": "Add Details of Patient", + "add_device": "Add Device", + "add_encounter": "Add Encounter", "add_exception": "Add Exception", "add_facility": "Add Facility", "add_files": "Add Files", @@ -301,6 +305,7 @@ "add_location_description": "Create a Location such as Rooms/Beds", "add_new_beds": "Add New Bed(s)", "add_new_facility": "Add New Facility", + "add_new_location": "Add New Location", "add_new_patient": "Add New Patient", "add_new_user": "Add New User", "add_notes": "Add notes", @@ -394,6 +399,7 @@ "archived_reason": "Archived reason", "are_non_editable_fields": "are non-editable fields", "are_you_still_watching": "Are you still watching?", + "are_you_sure": "Are you sure?", "are_you_sure_want_to_delete": "Are you sure you want to delete {{name}}?", "are_you_sure_want_to_delete_this_record": "Are you sure want to delete this record?", "are_you_sure_want_to_remove": "Are you sure you want to remove {{name}} from the patient? This action cannot be undone", @@ -419,6 +425,11 @@ "assigned_facility": "Facility assigned", "assigned_to": "Assigned to", "assigned_volunteer": "Assigned Volunteer", + "associate": "Associate", + "associate_location": "Associate Location", + "associate_location_description": "Select a location to associate with this device", + "associating": "Associating...", + "at_least_one_department_is_required": "At least one department is required", "at_time": "at {{time}}", "atypical_presentation_details": "Atypical presentation details", "audio__allow_permission": "Please allow microphone permission in site settings", @@ -441,6 +452,8 @@ "auto_generated_for_care": "Auto Generated for Care", "autofilled_fields": "Autofilled Fields", "availabilities": "Availabilities", + "availability_status": "Availability Status", + "available": "Available", "available_features": "Available Features", "available_in": "Available in", "available_time_slots": "Available Time Slots", @@ -469,6 +482,7 @@ "bed_type__400": "Isolation Bed", "bed_type__500": "Others", "before": "before", + "begin_clinical_encounter": "Begin a new clinical encounter for {{patientName}}. Select the appropriate encounter type, status, and priority to ensure proper documentation and care delivery.", "beta": "beta", "biologic": "Biologic", "bladder": "Bladder", @@ -511,9 +525,11 @@ "category_description": "Choose the category ", "caution": "Caution", "central_nursing_station": "Central Nursing Station", + "change": "Change", "change_avatar": "Change Avatar", "change_avatar_note": "JPG, GIF or PNG. 1MB max.", "change_file": "Change File", + "change_location": "Change Location", "change_phone_number": "Change Phone Number", "change_status": "Change Status", "chat_on_whatsapp": "Chat on Whatsapp", @@ -576,8 +592,17 @@ "clear_search": "Clear search", "clear_selection": "Clear selection", "clear_skill": "Clear Skill", + "click": "Click", + "click_add_department_team": "Click Add Department/Team to create a new department/team.", + "click_add_main_location": "Click Add Location to add a main location.", + "click_manage_create_users": "Click See Details to create or manage users and departments/teams within the corresponding dept/team.", + "click_manage_create_users_mobile": "Click to create or manage users and departments/teams within the corresponding dept/team.", + "click_manage_sub_locations": "Click See Details to manage sub-locations.", + "click_manage_sub_locations_mobile": "Click to edit and to manage sub-locations.", + "click_on": "Click on", "close": "Close", "close_scanner": "Close Scanner", + "collapse_all": "Collapse All", "collapse_sidebar": "Collapse Sidebar", "combine_files_pdf": "Combine Files To PDF", "comment_added_successfully": "Comment added successfully", @@ -618,6 +643,26 @@ "contact_person_number": "Contact person number", "contact_phone": "Contact Person Number", "contact_phone_description": "Phone number to reach the contact person.", + "contact_point_placeholder__email": "Enter email address", + "contact_point_placeholder__fax": "Enter fax number", + "contact_point_placeholder__other": "Enter contact value", + "contact_point_placeholder__pager": "Enter pager number", + "contact_point_placeholder__phone": "Enter phone number", + "contact_point_placeholder__sms": "Enter SMS number", + "contact_point_placeholder__url": "Enter URL", + "contact_points": "Contact Points", + "contact_system_email": "Email", + "contact_system_fax": "Fax", + "contact_system_other": "Other", + "contact_system_pager": "Pager", + "contact_system_phone": "Phone", + "contact_system_sms": "SMS", + "contact_system_url": "URL", + "contact_use_home": "Home", + "contact_use_mobile": "Mobile", + "contact_use_old": "Old", + "contact_use_temp": "Temporary", + "contact_use_work": "Work", "contact_with_confirmed_carrier": "Contact with confirmed carrier", "contact_with_suspected_carrier": "Contact with suspected carrier", "contact_your_admin_to_add_facilities": "Contact your admin to add facilities", @@ -646,6 +691,7 @@ "create_department_team_description": "Create a new department/team in this facility.", "create_encounter": "Create Encounter", "create_facility": "Create Facility", + "create_location_association": "Create Location Association", "create_new": "Create New", "create_new_asset": "Create New Asset", "create_new_encounter": "Create a new encounter to get started", @@ -655,6 +701,7 @@ "create_position_preset": "Create a new position preset", "create_position_preset_description": "Creates a new position preset in Care from the current position of the camera for the given name", "create_preset_prerequisite": "To create presets for this bed, you'll need to link the camera to the bed first.", + "create_questionnaire": "Create Questionnaire", "create_resource_request": "Create Request", "create_schedule_template": "Create Schedule Template", "create_tag": "Create Tag", @@ -671,6 +718,7 @@ "criticality": "Criticality", "csv_file_in_the_specified_format": "Select a CSV file in the specified format", "current_address": "Current Address", + "current_location_description": "The current location of this device", "current_organizations": "Current Organizations", "current_password": "Current Password", "current_role": "Current Role", @@ -685,6 +733,7 @@ "dashboard": "Dashboard", "date": "Date", "date_and_time": "Date and Time", + "date_and_time_of_death": "Date and Time of Death", "date_declared_positive": "Date of declaring positive", "date_of_admission": "Date of Admission", "date_of_birth": "Date of Birth", @@ -697,12 +746,16 @@ "date_of_return": "Date of Return", "date_of_test": "Date of sample collection for Covid testing", "date_range": "Date Range", + "dates_and_identifiers": "Dates & Identifiers", "day": "Day", - "death_report": "Death Report", + "deceased_disclaimer": "Please provide the date and time of death for record-keeping purposes. This information is handled with utmost sensitivity and respect.", + "deceased_status": "Deceased Status", "delete": "Delete", "delete_account": "Delete account", "delete_account_btn": "Yes, delete this account", "delete_account_note": "Deleting this account will remove all associated data and cannot be undone.", + "delete_device": "Delete Device", + "delete_device_confirmation": "Are you sure you want to delete this device? This action cannot be undone.", "delete_facility": "Delete Facility", "delete_facility_confirmation": "Are you sure you want to delete {{name}}? This action cannot be undone.", "delete_item": "Delete {{name}}", @@ -722,6 +775,17 @@ "details_of_origin_facility": "Details of origin facility", "details_of_patient": "Details of patient", "details_of_shifting_approving_facility": "Details of shifting approving facility", + "device_availability_status_available": "Available", + "device_availability_status_damaged": "Damaged", + "device_availability_status_destroyed": "Destroyed", + "device_availability_status_lost": "Lost", + "device_contact_description": "Contact points associated with this device", + "device_information": "Device Information", + "device_not_found": "Device not found", + "device_status_active": "Active", + "device_status_entered_in_error": "Entered in Error", + "device_status_inactive": "Inactive", + "devices": "Devices", "diagnoses": "Diagnoses", "diagnosis": "Diagnosis", "diagnosis__confirmed": "Confirmed", @@ -801,7 +865,10 @@ "edit_avatar_permission_error": "You do not have permissions to edit the avatar of this user", "edit_caution_note": "A new prescription will be added to the consultation with the edited details and the current prescription will be discontinued.", "edit_cover_photo": "Edit Cover Photo", + "edit_device": "Edit Device", + "edit_device_description": "Edit the details of the device", "edit_facility": "Edit Facility", + "edit_facility_details": "Edit Facility Details", "edit_history": "Edit History", "edit_location": "Edit Location", "edit_location_description": "Edit the Location to make any changes", @@ -888,6 +955,7 @@ "encounter_manage_organization_description": "Add or remove organizations from this encouter", "encounter_marked_as_complete": "Encounter Completed", "encounter_notes__all_discussions": "All Discussions", + "encounter_notes__all_discussions_description": "View and manage encounternotes discussion threads", "encounter_notes__be_first_to_send": "Be the first to send a message", "encounter_notes__choose_template": "Choose a template or enter a custom title", "encounter_notes__create_discussion": "Create a new discussion thread to organize your conversation topics.", @@ -947,21 +1015,31 @@ "end_time": "End Time", "end_time_before_start_error": "End time cannot be before start time", "end_time_future_error": "End time cannot be in the future", + "end_time_required": "End time is required", "ended": "Ended", + "enter_contact_value": "Enter contact value", "enter_department_team_description": "Enter department/team description (optional)", "enter_department_team_name": "Enter department/team name", "enter_dosage_instructions": "Enter Dosage Instructions", "enter_file_name": "Enter File Name", + "enter_identifier": "Enter device identifier", + "enter_lot_number": "Enter lot number", + "enter_manufacturer": "Enter manufacturer name", "enter_message": "Start typing...", "enter_mobile_number": "Enter Mobile Number", "enter_mobile_otp": "Enter OTP sent to the given mobile number", + "enter_model_number": "Enter model number", "enter_otp": "Enter OTP sent to the registered mobile with the respective ID", + "enter_part_number": "Enter part number", "enter_phone_number": "Enter phone number", "enter_phone_number_to_login_register": "Enter phone number to login/register", + "enter_registered_name": "Enter the registered name of the device", + "enter_serial_number": "Enter serial number", "enter_tag_name": "Enter tag name", "enter_tag_slug": "Enter tag slug", "enter_the_file_name": "Enter the file name", "enter_the_verification_code": "Enter the verification code sent to your phone", + "enter_user_friendly_name": "Enter a user friendly name for the device", "enter_valid_age": "Please Enter Valid Age", "enter_valid_dob": "Enter a valid date of birth", "enter_valid_dob_age": "Please enter an age greater than 15 years", @@ -995,10 +1073,14 @@ "exception_created": "Exception created successfully", "exception_deleted": "Exception deleted", "exceptions": "Exceptions", + "expand_all": "Expand All", "expand_sidebar": "Expand Sidebar", "expected_burn_rate": "Expected Burn Rate", + "expiration_date": "Expiration Date", + "expiration_date_must_be_after_manufacture_date": "Expiration date must be after manufacture date", "expired": "Expired", "expired_on": "Expired On", + "expires": "Expires", "expires_on": "Expires On", "export": "Export", "export_live_patients": "Export Live Patients", @@ -1078,6 +1160,8 @@ "filter_by": "Filter By", "filter_by_category": "Filter by category", "filter_by_date": "Filter by Date", + "filter_by_department_or_team_name": "Filter by department or team name", + "filter_by_locations": "Filter by Locations", "filters": "Filters", "first_name": "First Name", "food": "Food", @@ -1139,10 +1223,12 @@ "hospital_identifier": "Hospital Identifier", "hospitalisation_details": "Hospitalization Details", "hospitalization_details": "Hospitalization Details", + "hover_focus_reveal": "Hover or focus to reveal", "hubs": "Hub Facilities", "i_declare": "I hereby declare that:", "icd11_as_recommended": "As per ICD-11 recommended by WHO", "icmr_specimen_referral_form": "ICMR Specimen Referral Form", + "identifier": "Identifier", "immunisation-records": "Immunisation", "in_consultation": "In-Consultation", "in_progress": "In Progress", @@ -1157,6 +1243,7 @@ "information_source_related_person": "Related Person", "information_source_user": "Hospital Staff", "inidcator_event": "Indicator Event", + "initiate_encounter": "Initiate Patient Encounter", "instruction_on_titration": "Instruction on titration", "instructions": "Instructions", "insurance__insurer_id": "Insurer ID", @@ -1212,6 +1299,7 @@ "is_it_upshift": "is it upshift", "is_phone_a_whatsapp_number": "Is the phone number a WhatsApp number?", "is_pregnant": "Is pregnant", + "is_the_patient_deceased": "Is the patient deceased", "is_this_administration_for_a_past_time": "Is this administration for a past time", "is_this_an_emergency": "Is this an Emergency?", "is_this_an_emergency_request": "Is this an emergency request?", @@ -1273,13 +1361,37 @@ "local_ip_address": "Local IP Address", "local_ip_address_example": "e.g. 192.168.0.123", "location": "Location", + "location_associated_successfully": "Location associated successfully", + "location_association_created_successfully": "Location association created successfully", + "location_association_updated_successfully": "Location association updated successfully", "location_beds_empty": "No beds available in this location", "location_created": "Location Created", + "location_description": "Location Description", "location_details": "Location Details", "location_form": "Location Form", + "location_form__area": "Area", + "location_form__bd": "Bed", + "location_form__bu": "Building", + "location_form__ca": "Cabinet", + "location_form__co": "Corridor", + "location_form__ho": "House", + "location_form__jdn": "Jurisdiction", + "location_form__lvl": "Level", + "location_form__rd": "Road", + "location_form__ro": "Room", + "location_form__si": "Site", + "location_form__ve": "Vehicle", + "location_form__vi": "Virtual", + "location_form__wa": "Ward", + "location_form__wi": "Wing", "location_history": "Location History", "location_management": "Location Management", + "location_name": "Location Name", "location_removed_successfully": "Location removed successfully", + "location_status": "Location Status", + "location_status__active": "Active", + "location_status__inactive": "Inactive", + "location_status__unknown": "Unknown", "location_updated": "Location Updated", "location_updated_successfully": "Location updated successfully", "locations": "Locations", @@ -1293,6 +1405,7 @@ "logout": "Log Out", "longitude": "Longitude", "longitude_invalid": "Longitude must be between -180 and 180", + "lot_number": "Lot Number", "low": "Low", "lsg": "Lsg", "make_facility_public": "Make this facility public", @@ -1304,12 +1417,17 @@ "manage_my_schedule": "Manage my schedule", "manage_organizations": "Manage Organizations", "manage_organizations_description": "Add or remove organizations from this questionnaire", + "manage_patient_location_and_transfers": "Manage patient location and transfers", "manage_prescriptions": "Manage Prescriptions", "manage_preset": "Manage preset {{ name }}", "manage_tags": "Manage Tags", "manage_tags_description": "Add or remove tags for this questionnaire", "manage_user": "Manage User", + "manufacture_date": "Manufacture Date", + "manufacture_date_cannot_be_in_future": "Manufacture date cannot be in future", + "manufactured": "Manufactured", "manufacturer": "Manufacturer", + "map": "Map", "map_acronym": "M.A.P.", "mark_active": "Mark Active", "mark_all_as_read": "Mark all as Read", @@ -1365,6 +1483,7 @@ "mobile_otp_send_success": "OTP has been sent to the given mobile number.", "mobile_otp_verify_error": "Failed to verify mobile number. Please try again later.", "mobile_otp_verify_success": "Mobile number has been verified successfully.", + "model_number": "Model Number", "moderate": "Moderate", "modification_caution_note": "No modifications possible once added", "modified": "Modified", @@ -1387,6 +1506,7 @@ "name_of_shifting_approving_facility": "Name of shifting approving facility", "nationality": "Nationality", "nationality_is_required": "Nationality is required", + "navigation": "Navigation", "nearby_facilities": "Nearby Facilities", "network_failure": "Network Failure. Please check your internet connectivity.", "never": "never", @@ -1402,7 +1522,7 @@ "next_sessions": "Next Sessions", "next_week_short": "Next wk", "no": "No", - "no_active_medications": "No active medications", + "no_active_medication_recorded": "No Active Medication Recorded", "no_address_provided": "No address provided", "no_allergies_recorded": "No allergies recorded", "no_appointments": "No appointments found", @@ -1416,15 +1536,17 @@ "no_child_locations_found": "No child locations found", "no_comments_available": "No comments available", "no_consultation_filed": "No consultation filed", - "no_consultation_history": "No consultation history available", "no_consultation_updates": "No consultation updates", "no_country_found": "No country found", "no_data_found": "No data found", "no_departments_teams_found": "No Departments or Teams found", + "no_devices_available": "No devices available", + "no_devices_found": "No devices found", "no_diagnoses_recorded": "No diagnoses recorded", "no_discharge_summaries_found": "No Discharge Summaries found", "no_doctors_found": "No Doctors Found", "no_duplicate_facility": "You should not create duplicate facilities", + "no_encounter_history": "No encounter history available", "no_encounters_found": "No encounters found", "no_facilities": "No Facilities found", "no_facilities_found": "No facilities found", @@ -1435,11 +1557,15 @@ "no_investigation": "No investigation Reports found", "no_investigation_suggestions": "No Investigation Suggestions", "no_linked_facilities": "No Linked Facilities", + "no_location": "No location assigned", + "no_location_description": "This device is not currently assigned to any location", "no_locations_available": "No locations available", "no_locations_found": "No locations found", "no_log_update_delta": "No changes since previous log update", "no_log_updates": "No log updates found", "no_medical_history_available": "No Medical History Available", + "no_medication_recorded": "No Medication Recorded", + "no_medications": "No Medications", "no_medications_found_for_this_encounter": "No medications found for this encounter.", "no_medications_to_administer": "No medications to administer", "no_notices_for_you": "No notices for you.", @@ -1529,6 +1655,7 @@ "ongoing_medications": "Ongoing Medications", "online": "Online", "only_indian_mobile_numbers_supported": "Currently only Indian numbers are supported", + "only_mark_if_applicable": "Only mark if applicable", "onset": "Onset", "op_encounter": "OP Encounter", "op_file_closed": "OP file closed", @@ -1561,6 +1688,7 @@ "page_not_found": "Page Not Found", "pain": "Pain", "pain_chart_description": "Mark region and intensity of pain", + "part_number": "Part Number", "participants": "Participants", "passport_number": "Passport Number", "password": "Password", @@ -1606,6 +1734,7 @@ "patient_face": "Patient Face", "patient_files": "Patient Files", "patient_information": "Patient Information", + "patient_is_deceased": "Patient is deceased", "patient_name": "Patient Name", "patient_name_uhid": "Patient Name/UHID", "patient_no": "OP/IP No", @@ -1657,6 +1786,8 @@ "pincode_district_auto_fill_error": "Failed to auto-fill district information", "pincode_must_be_6_digits": "Pincode must be a 6-digit number", "pincode_state_auto_fill_error": "Failed to auto-fill state and district information", + "planned": "Planned", + "planned_reserved_cannot_be_in_past": "Planned/Reserved cannot be in the past", "play": "Play", "play_audio": "Play Audio", "please_assign_bed_to_patient": "Please assign a bed to this patient", @@ -1745,6 +1876,7 @@ "professional_info_note_view": "View user's professional information", "profile": "Profile", "profile_picture_deleted": "Profile picture deleted", + "properties": "Properties", "proposed": "Proposed", "provisional": "Provisional", "qualification": "Qualification", @@ -1796,6 +1928,7 @@ "register_hospital": "Register Hospital", "register_page_title": "Register As Hospital Administrator", "register_patient": "Register Patient", + "registered_name": "Registered Name", "reject": "Reject", "rejected": "Rejected", "relapse": "Relapse", @@ -1848,6 +1981,7 @@ "rescheduled": "Rescheduled", "rescheduling": "Rescheduling...", "resend_otp": "Resend OTP", + "reserved": "Reserved", "reset": "Reset", "reset_password": "Reset Password", "reset_password_note_self": "Enter your current password, then create and confirm your new password", @@ -1880,6 +2014,7 @@ "resume": "Resume", "retake": "Retake", "retake_recording": "Retake Recording", + "retired": "Retired", "return_to_care": "Return to CARE", "return_to_login": "Return to Login", "return_to_password_reset": "Return to Password Reset", @@ -1905,6 +2040,7 @@ "save": "Save", "save_and_continue": "Save and Continue", "save_investigation": "Save Investigation", + "save_valueset": "Save ValueSet", "saving": "Saving...", "scan_asset_qr": "Scan Asset QR!", "schedule": "Schedule", @@ -1941,7 +2077,7 @@ "search_by_department_team_name": "Search by department/team name", "search_by_emergency_contact_phone_number": "Search by Emergency Contact Phone Number", "search_by_emergency_phone_number": "Search by Emergency Phone Number", - "search_by_name": "Search by Name", + "search_by_name": "Search by name", "search_by_patient_name": "Search by Patient Name", "search_by_patient_no": "Search by Patient Number", "search_by_phone_number": "Search by Phone Number", @@ -1949,6 +2085,7 @@ "search_by_user_name": "Search by user name", "search_by_username": "Search by username", "search_country": "Search country...", + "search_devices": "Search Devices", "search_encounters": "Search Encounters", "search_for_allergies_to_add": "Search for allergies to add", "search_for_diagnoses_to_add": "Search for diagnoses to add", @@ -1960,8 +2097,10 @@ "search_medication": "Search Medication", "search_medications": "Search Medications", "search_medicine": "Search Medicine", + "search_organizations": "Search Organizations", "search_patient_page_text": "Search for existing patients using their phone number or create a new patient record", "search_patients": "Search Patients", + "search_questionnaires": "Search Questionnaires", "search_resource": "Search Resource", "search_tags": "Search tags...", "search_user": "Search User", @@ -1972,12 +2111,16 @@ "see_details": "See Details", "see_note": "See Note", "select": "Select", + "select_a_status": "Select a status", "select_a_value_set": "Select a Value Set", "select_additional_instructions": "Select additional instructions", "select_admit_source": "Select Admit Source", "select_all": "Select All", + "select_availability_status": "Select availability status", "select_category": "Select a category", "select_class": "Select Class", + "select_contact_system": "Select contact type", + "select_contact_use": "Select contact use", "select_date": "Select date", "select_department": "Select Department", "select_diet_preference": "Select diet preference", @@ -2003,6 +2146,7 @@ "select_new_role": "Select New Role", "select_organization": "Select Organization", "select_organization_type": "Select organization type", + "select_organizations": "Select Organizations", "select_patient": "Select Patient", "select_policy": "Select an Insurance Policy", "select_policy_to_add_items": "Select a Policy to Add Items", @@ -2016,8 +2160,10 @@ "select_seven_day_period": "Select a seven day period", "select_site": "Select site", "select_skills": "Select and add some skills", - "select_status": "Select Status", + "select_status": "Select status", "select_sub_department": "Select sub-department", + "select_subject_type": "Select Subject Type", + "select_tags": "Select Tags", "select_time": "Select time", "select_time_slot": "Select time slot", "select_user": "Select user", @@ -2072,10 +2218,13 @@ "show_all_notifications": "Show All", "show_all_slots": "Show all slots", "show_default_presets": "Show Default Presets", + "show_on_map": "Show on Map", "show_patient_presets": "Show Patient Presets", "show_unread_notifications": "Show Unread", "showing_all_appointments": "Showing all appointments", "showing_x_of_y": "Showing {{x}} of {{y}}", + "sidebar": "sidebar", + "sidebar_description": "sidebar provides navigation to different sections", "sign_in": "Sign in", "sign_out": "Sign out", "site": "Site", @@ -2113,6 +2262,7 @@ "start_time_before_authored_error": "Start time cannot be before the medication was prescribed", "start_time_future_error": "Start time cannot be in the future", "start_time_must_be_before_end_time": "Start time must be before end time", + "start_time_required": "Start time is required", "start_typing_to_search": "Start typing to search...", "state": "State", "state_reason_for_archiving": "State reason for archiving {{name}} file?", @@ -2126,6 +2276,7 @@ "stream_uuid": "Stream UUID", "sub_category": "Sub Category", "subject": "Subject", + "subject_type": "Subject Type", "submit": "Submit", "submitting": "Submitting", "subscribe": "Subscribe", @@ -2161,6 +2312,9 @@ "third_party_software_licenses": "Third Party Software Licenses", "this_action_is_irreversible": "This action is irreversible. Once a file is archived it cannot be unarchived.", "this_file_has_been_archived": "This file has been archived and cannot be unarchived.", + "this_will_permanently_remove_the_exception_and_cannot_be_undone": "This will permanently remove the exception and cannot be undone", + "this_will_permanently_remove_the_scheduled_template_and_cannot_be_undone": "This will permanently remove the scheduled template and cannot be undone", + "this_will_permanently_remove_the_session_and_cannot_be_undone": "This will permanently remove the session and cannot be undone", "thread_already_exists": "Thread with this title already exists", "time": "Time", "time_slot": "Time Slot", @@ -2169,6 +2323,7 @@ "titrate_dosage": "Titrate Dosage", "to": "to", "to_be_conducted": "To be conducted", + "to_edit": "to edit", "to_proceed_with_registration": "To proceed with registration, please create a new patient.", "to_view_available_slots_select_resource_and_date": "To view available slots, select a preferred resource and date.", "today": "Today", @@ -2200,6 +2355,7 @@ "type_b_cylinders": "B Type Cylinders", "type_c_cylinders": "C Type Cylinders", "type_d_cylinders": "D Type Cylinders", + "type_of_encounter": "Type of Encounter", "type_patient_age": "Type Patient Age", "type_patient_name": "Type Patient Name", "type_to_search": "Type to search", @@ -2210,6 +2366,7 @@ "unable_to_get_current_position": "Unable to get current position.", "unable_to_get_location: ": "Unable to get location: ", "unassign": "Unassign", + "unavailable": "Unavailable", "unconfirmed": "Unconfirmed", "unique_id": "Unique Id", "unit_a": "Years", @@ -2261,6 +2418,7 @@ "update_available": "Update Available", "update_bed": "Update Bed", "update_department": "Update Department", + "update_device": "Update Device", "update_encounter": "Update Encounter", "update_encounter_details": "Update Encounter Details", "update_existing_facility": "Update the details of the existing facility.", @@ -2299,6 +2457,7 @@ "upload_headings__supporting_info": "Upload Supporting Info", "upload_report": "Upload Report", "uploading": "Uploading", + "use": "Use", "use_address_as_permanent": "Use this address for permanent address", "use_phone_number_for_emergency": "Use this phone number for emergency contact", "user_add_error": "Error while adding User", @@ -2309,6 +2468,7 @@ "user_details": "User Details", "user_details_update_error": "Error while updating user details", "user_details_update_success": "User details updated successfully", + "user_friendly_name": "User Friendly Name", "user_management": "User Management", "user_not_available_for_appointments": "This user is not available for appointments", "user_qualifications": "Qualifications", @@ -2339,6 +2499,7 @@ "valid_otp_found": "Valid OTP found, Navigating to Appointments", "valid_to": "Valid Till", "valid_year_of_birth": "Please enter a valid year of birth (YYYY)", + "value": "Value", "value_set": "Value Set", "valuesets": "Valuesets", "vehicle_preference": "Vehicle preference", @@ -2362,6 +2523,7 @@ "verify_patient_identifier": "Please verify the patient identifier", "verify_patient_identity": "Verify Patient Identity", "verify_using": "Verify Using", + "version": "Version", "video_call": "Video Call", "video_conference_link": "Video Conference Link", "view": "View", @@ -2375,6 +2537,7 @@ "view_consultation_and_log_updates": "View Consultation / Log Updates", "view_dashboard": "View Dashboard", "view_details": "View Details", + "view_encounter": "View Encounter", "view_facility": "View Facility", "view_files": "View Files", "view_patient": "View Patient", diff --git a/public/locale/ml.json b/public/locale/ml.json index 23dfa4fc05f..8ae49d208d8 100644 --- a/public/locale/ml.json +++ b/public/locale/ml.json @@ -317,8 +317,6 @@ "add_attachments": "അറ്റാച്ചുമെൻ്റുകൾ ചേർക്കുക", "add_beds": "കിടക്ക(കൾ) ചേർക്കുക", "add_beds_to_configure_presets": "അവയ്‌ക്കായി പ്രീസെറ്റുകൾ കോൺഫിഗർ ചെയ്യാൻ ഈ ലൊക്കേഷനിലേക്ക് കിടക്കകൾ ചേർക്കുക.", - "add_consultation": "കൂടിയാലോചന ചേർക്കുക", - "add_consultation_update": "കൺസൾട്ടേഷൻ അപ്ഡേറ്റ് ചേർക്കുക", "add_details_of_patient": "രോഗിയുടെ വിശദാംശങ്ങൾ ചേർക്കുക", "add_facility": "സൗകര്യം ചേർക്കുക", "add_files": "ഫയലുകൾ ചേർക്കുക", @@ -678,7 +676,6 @@ "date_of_return": "മടങ്ങിവരുന്ന തീയതി", "date_of_test": "ടെസ്റ്റ് തീയതി", "day": "ദിവസം", - "death_report": "മരണ റിപ്പോർട്ട്", "delete": "ഇല്ലാതാക്കുക", "delete_account": "അക്കൗണ്ട് ഇല്ലാതാക്കുക", "delete_account_btn": "അതെ, ഈ അക്കൗണ്ട് ഇല്ലാതാക്കുക", @@ -1242,7 +1239,6 @@ "no_changes": "മാറ്റങ്ങളൊന്നുമില്ല", "no_changes_made": "മാറ്റങ്ങളൊന്നും വരുത്തിയിട്ടില്ല", "no_consultation_filed": "ഒരു കൺസൾട്ടേഷനും ഫയൽ ചെയ്തിട്ടില്ല", - "no_consultation_history": "കൺസൾട്ടേഷൻ ചരിത്രമൊന്നും ലഭ്യമല്ല", "no_consultation_updates": "കൺസൾട്ടേഷൻ അപ്‌ഡേറ്റുകളൊന്നുമില്ല", "no_data_found": "വിവരങ്ങളൊന്നും കണ്ടെത്തിയില്ല", "no_doctors_found": "ഡോക്ടർമാരെ കണ്ടെത്തിയില്ല", diff --git a/src/App.tsx b/src/App.tsx index 51e33c2209d..7452d7afb23 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,13 +18,23 @@ import AuthUserProvider from "@/Providers/AuthUserProvider"; import HistoryAPIProvider from "@/Providers/HistoryAPIProvider"; import Routers from "@/Routers"; import { handleHttpError } from "@/Utils/request/errorHandler"; +import { HTTPError } from "@/Utils/request/types"; import { PubSubProvider } from "./Utils/pubsubContext"; const queryClient = new QueryClient({ defaultOptions: { queries: { - retry: 2, + retry: (failureCount, error) => { + // Only retry network errors or server errors (502, 503, 504) up to 3 times + if ( + error.message === "Network Error" || + (error instanceof HTTPError && [502, 503, 504].includes(error.status)) + ) { + return failureCount < 3; + } + return false; + }, refetchOnWindowFocus: false, }, }, diff --git a/src/CAREUI/interactive/Zoom.tsx b/src/CAREUI/interactive/Zoom.tsx index d97300d36cb..18a73b9dd40 100644 --- a/src/CAREUI/interactive/Zoom.tsx +++ b/src/CAREUI/interactive/Zoom.tsx @@ -68,7 +68,7 @@ export const ZoomControls = (props: { disabled?: boolean }) => { } return ( -
+
}> + + + ); })} ); diff --git a/src/Providers/HistoryAPIProvider.tsx b/src/Providers/HistoryAPIProvider.tsx index 20077733b01..60fdcf3b3d4 100644 --- a/src/Providers/HistoryAPIProvider.tsx +++ b/src/Providers/HistoryAPIProvider.tsx @@ -2,7 +2,7 @@ import { useLocationChange } from "raviger"; import { ReactNode, createContext, useState } from "react"; export const HistoryContext = createContext([]); -// eslint-disable-next-line @typescript-eslint/no-empty-function + export const ResetHistoryContext = createContext(() => {}); export default function HistoryAPIProvider(props: { children: ReactNode }) { diff --git a/src/Routers/AppRouter.tsx b/src/Routers/AppRouter.tsx index 5461309083a..353e58054f4 100644 --- a/src/Routers/AppRouter.tsx +++ b/src/Routers/AppRouter.tsx @@ -106,24 +106,21 @@ export default function AppRouter() { )}
-
+
{shouldShowSidebar && }
- + care logo
-
+
}> {pages} diff --git a/src/Routers/routes/ConsultationRoutes.tsx b/src/Routers/routes/ConsultationRoutes.tsx index 699964122f3..080b90a0a54 100644 --- a/src/Routers/routes/ConsultationRoutes.tsx +++ b/src/Routers/routes/ConsultationRoutes.tsx @@ -16,33 +16,57 @@ const consultationRoutes: AppRoutes = { /> ), "/facility/:facilityId/patient/:patientId/encounter/:encounterId/treatment_summary": - ({ facilityId, encounterId }) => ( - + ({ facilityId, encounterId, patientId }) => ( + ), - "/facility/:facilityId/encounter/:encounterId/:tab": ({ - facilityId, - encounterId, - tab, - }) => ( - - ), - "/facility/:facilityId/encounter/:encounterId/:tab/:subPage": ({ + "/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire": + ({ facilityId, encounterId, patientId }) => ( + + ), + "/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire/:slug": + ({ facilityId, encounterId, slug, patientId }) => ( + + ), + "/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire_response/:id": + ({ patientId, id }) => ( + + ), + "/facility/:facilityId/patient/:patientId/encounter/:encounterId/:tab": ({ facilityId, + patientId, encounterId, tab, - subPage, }) => ( ), + "/facility/:facilityId/patient/:patientId/encounter/:encounterId/:tab/:subPage": + ({ facilityId, encounterId, patientId, tab, subPage }) => ( + + ), "/facility/:facilityId/patient/:patientId/consultation": ({ facilityId, patientId, @@ -63,27 +87,6 @@ const consultationRoutes: AppRoutes = { subjectType="patient" /> ), - "/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire": - ({ facilityId, encounterId, patientId }) => ( - - ), - "/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire/:slug": - ({ facilityId, encounterId, slug, patientId }) => ( - - ), - "/facility/:facilityId/patient/:patientId/encounter/:encounterId/questionnaire_response/:id": - ({ patientId, id }) => ( - - ), }; export default consultationRoutes; diff --git a/src/Routers/routes/adminRoutes.tsx b/src/Routers/routes/adminRoutes.tsx index abbc7bef952..bbf0aa1e185 100644 --- a/src/Routers/routes/adminRoutes.tsx +++ b/src/Routers/routes/adminRoutes.tsx @@ -1,6 +1,5 @@ import QuestionnaireEditor from "@/components/Questionnaire/QuestionnaireEditor"; import { QuestionnaireList } from "@/components/Questionnaire/QuestionnaireList"; -import { QuestionnaireShow } from "@/components/Questionnaire/show"; import { ValueSetEditor } from "@/components/ValueSet/ValueSetEditor"; import { ValueSetList } from "@/components/ValueSet/ValueSetList"; @@ -9,7 +8,6 @@ import { AppRoutes } from "@/Routers/AppRouter"; const AdminRoutes: AppRoutes = { "/admin/questionnaire": () => , "/admin/questionnaire/create": () => , - "/admin/questionnaire/:id": ({ id }) => , "/admin/questionnaire/:id/edit": ({ id }) => , "/admin/valuesets": () => , "/admin/valuesets/create": () => , diff --git a/src/Utils/utils.ts b/src/Utils/utils.ts index 3198b10bcd3..c17e08e006f 100644 --- a/src/Utils/utils.ts +++ b/src/Utils/utils.ts @@ -1,3 +1,4 @@ +import careConfig from "@careConfig"; import { differenceInMinutes, format } from "date-fns"; import { toPng } from "html-to-image"; @@ -94,6 +95,16 @@ export const isUserOnline = (user: { last_login: DateLike }) => { : false; }; +export const isAndroidDevice = /android/i.test(navigator.userAgent); + +export const getMapUrl = (latitude: string, longitude: string) => { + return isAndroidDevice + ? `geo:${latitude},${longitude}` + : careConfig.mapFallbackUrlTemplate + .replace("{lat}", latitude) + .replace("{long}", longitude); +}; + const getRelativeDateSuffix = (abbreviated: boolean) => { return { day: abbreviated ? "d" : "days", diff --git a/src/common/constants.tsx b/src/common/constants.tsx index 1ce2a011725..c572e130f5b 100644 --- a/src/common/constants.tsx +++ b/src/common/constants.tsx @@ -1,5 +1,16 @@ +import { + Ambulance, + BedDouble, + Building2, + Home, + MonitorSmartphone, + Stethoscope, +} from "lucide-react"; + import { IconName } from "@/CAREUI/icons/CareIcon"; +import { EncounterClass } from "@/types/emr/encounter"; + export const RESULTS_PER_PAGE_LIMIT = 14; /** @@ -112,37 +123,37 @@ export const FACILITY_FEATURE_TYPES: { id: 1, name: "CT Scan", icon: "l-compact-disc", - variant: "green", + variant: "blue", }, { id: 2, name: "Maternity Care", icon: "l-baby-carriage", - variant: "blue", + variant: "pink", }, { id: 3, name: "X-Ray", icon: "l-clipboard-alt", - variant: "amber", + variant: "blue", }, { id: 4, name: "Neonatal Care", icon: "l-baby-carriage", - variant: "teal", + variant: "pink", }, { id: 5, name: "Operation Theater", icon: "l-syringe", - variant: "red", + variant: "orange", }, { id: 6, name: "Blood Bank", icon: "l-medical-drip", - variant: "orange", + variant: "purple", }, { id: 7, @@ -154,17 +165,17 @@ export const FACILITY_FEATURE_TYPES: { id: 8, name: "Inpatient Services", icon: "l-hospital", - variant: "red", + variant: "orange", }, { id: 9, name: "Outpatient Services", icon: "l-hospital", - variant: "red", + variant: "indigo", }, { id: 10, - name: "Intensive Care Units", + name: "Intensive Care Units (ICU)", icon: "l-hospital", variant: "red", }, @@ -172,25 +183,25 @@ export const FACILITY_FEATURE_TYPES: { id: 11, name: "Pharmacy", icon: "l-hospital", - variant: "red", + variant: "indigo", }, { id: 12, name: "Rehabilitation Services", icon: "l-hospital", - variant: "red", + variant: "teal", }, { id: 13, name: "Home Care Services", icon: "l-hospital", - variant: "red", + variant: "teal", }, { id: 14, name: "Psychosocial Support", icon: "l-hospital", - variant: "red", + variant: "purple", }, { id: 15, @@ -202,7 +213,7 @@ export const FACILITY_FEATURE_TYPES: { id: 16, name: "Daycare Programs", icon: "l-hospital", - variant: "red", + variant: "yellow", }, ]; @@ -354,6 +365,14 @@ export const FILE_EXTENSIONS = { PRESENTATION: ["pptx"], DOCUMENT: ["pdf", "docx"], } as const; +export const encounterIcons = { + imp: , + amb: , + obsenc: , + emer: , + vr: , + hh: , +} as const satisfies Record; export const PREVIEWABLE_FILE_EXTENSIONS = [ "html", diff --git a/src/components/Auth/Login.tsx b/src/components/Auth/Login.tsx index dfe4aaac4de..87eb7c10004 100644 --- a/src/components/Auth/Login.tsx +++ b/src/components/Auth/Login.tsx @@ -633,6 +633,7 @@ const Login = (props: LoginProps) => { }} maxLength={5} placeholder="Enter 5-digit OTP" + autoFocus /> {otpValidationError && (

diff --git a/src/components/Common/AvatarEditModal.tsx b/src/components/Common/AvatarEditModal.tsx index 3c278ea80b0..dd4d6284e57 100644 --- a/src/components/Common/AvatarEditModal.tsx +++ b/src/components/Common/AvatarEditModal.tsx @@ -1,3 +1,4 @@ +import DOMPurify from "dompurify"; import React, { ChangeEventHandler, useCallback, @@ -15,6 +16,7 @@ import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, + DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; @@ -26,8 +28,12 @@ interface Props { open: boolean; onOpenChange: (open: boolean) => void; imageUrl?: string; - handleUpload: (file: File, onError: () => void) => Promise; - handleDelete: (onError: () => void) => Promise; + handleUpload: ( + file: File, + onSuccess: () => void, + onError: () => void, + ) => Promise; + handleDelete: (onSuccess: () => void, onError: () => void) => Promise; hint?: React.ReactNode; } @@ -62,8 +68,8 @@ const AvatarEditModal = ({ const [selectedFile, setSelectedFile] = useState(); const [preview, setPreview] = useState(); const [isCameraOpen, setIsCameraOpen] = useState(false); - const webRef = useRef(null); - const [previewImage, setPreviewImage] = useState(null); + const webRef = useRef(null); + const [previewImage, setPreviewImage] = useState(null); const [isCaptureImgBeingUploaded, setIsCaptureImgBeingUploaded] = useState(false); const [constraint, setConstraint] = useState( @@ -81,16 +87,35 @@ const AvatarEditModal = ({ }, []); const captureImage = () => { - setPreviewImage(webRef.current.getScreenshot()); - const canvas = webRef.current.getCanvas(); - canvas?.toBlob((blob: Blob) => { - const myFile = new File([blob], "image.png", { - type: blob.type, - }); - setSelectedFile(myFile); + if (webRef.current) { + setPreviewImage(webRef.current.getScreenshot()); + } + const canvas = webRef.current?.getCanvas(); + canvas?.toBlob((blob) => { + if (blob) { + const myFile = new File([blob], "image.png", { + type: blob.type, + }); + setSelectedFile(myFile); + } else { + toast.error(t("failed_to_capture_image")); + } }); }; - + const stopCamera = useCallback(() => { + try { + if (webRef.current) { + const openCamera = webRef.current?.video?.srcObject as MediaStream; + if (openCamera) { + openCamera.getTracks().forEach((track) => track.stop()); + } + } + } catch { + toast.error("Failed to stop camera"); + } finally { + setIsCameraOpen(false); + } + }, []); const closeModal = () => { setPreview(undefined); setIsProcessing(false); @@ -112,11 +137,12 @@ const AvatarEditModal = ({ setSelectedFile(undefined); return; } - if (!isImageFile(e.target.files[0])) { + const file = e.target.files[0]; + if (!isImageFile(file)) { toast.warning(t("please_upload_an_image_file")); return; } - setSelectedFile(e.target.files[0]); + setSelectedFile(file); }; const uploadAvatar = async () => { @@ -128,24 +154,36 @@ const AvatarEditModal = ({ setIsProcessing(true); setIsCaptureImgBeingUploaded(true); - await handleUpload(selectedFile, () => { - setSelectedFile(undefined); - setPreview(undefined); - setPreviewImage(null); - setIsCaptureImgBeingUploaded(false); - setIsProcessing(false); - }); + await handleUpload( + selectedFile, + () => { + setPreview(undefined); + }, + () => { + setPreview(undefined); + setPreviewImage(null); + setIsCaptureImgBeingUploaded(false); + setIsProcessing(false); + }, + ); } finally { + setPreview(undefined); setIsCaptureImgBeingUploaded(false); setIsProcessing(false); + setSelectedFile(undefined); } }; const deleteAvatar = async () => { setIsProcessing(true); - await handleDelete(() => { - setIsProcessing(false); - }); + await handleDelete( + () => { + setIsProcessing(false); + setPreview(undefined); + setPreviewImage(null); + }, + () => setIsProcessing(false), + ); }; const dragProps = useDragAndDrop(); @@ -187,6 +225,9 @@ const AvatarEditModal = ({ {title} + + {t("edit_avatar")} +

@@ -194,11 +235,15 @@ const AvatarEditModal = ({ <> {preview || imageUrl ? ( <> -
+
cover-photo

@@ -308,6 +353,7 @@ const AvatarEditModal = ({ variant="destructive" onClick={deleteAvatar} disabled={isProcessing} + data-cy="delete-avatar" > {t("delete")} @@ -317,6 +363,7 @@ const AvatarEditModal = ({ variant="outline" onClick={uploadAvatar} disabled={isProcessing || !selectedFile} + data-cy="save-cover-image" > {isProcessing ? ( { setPreviewImage(null); setIsCameraOpen(false); - webRef.current.stopCamera(); + stopCamera(); }} disabled={isProcessing} > diff --git a/src/components/Common/ContactLink.tsx b/src/components/Common/ContactLink.tsx index c8115b42a1f..fc3cf7729e1 100644 --- a/src/components/Common/ContactLink.tsx +++ b/src/components/Common/ContactLink.tsx @@ -7,14 +7,8 @@ type ContactLinkProps = export default function ContactLink(props: ContactLinkProps) { return (

diff --git a/src/components/Common/DebugPreview.tsx b/src/components/Common/DebugPreview.tsx index ef0e794ab4d..25adb85daaf 100644 --- a/src/components/Common/DebugPreview.tsx +++ b/src/components/Common/DebugPreview.tsx @@ -19,7 +19,7 @@ export function DebugPreview({ data, title, className }: DebugPreviewProps) { -
+        
           {JSON.stringify(data, null, 2)}
         
diff --git a/src/components/Common/FilePreviewDialog.tsx b/src/components/Common/FilePreviewDialog.tsx index f5c44865549..7aaabf84dd5 100644 --- a/src/components/Common/FilePreviewDialog.tsx +++ b/src/components/Common/FilePreviewDialog.tsx @@ -13,6 +13,8 @@ import { import { useTranslation } from "react-i18next"; import useKeyboardShortcut from "use-keyboard-shortcut"; +import { cn } from "@/lib/utils"; + import CareIcon, { IconName } from "@/CAREUI/icons/CareIcon"; import { Button } from "@/components/ui/button"; @@ -27,7 +29,6 @@ import CircularProgress from "@/components/Common/CircularProgress"; import { FileUploadModel } from "@/components/Patient/models"; const PDFViewer = lazy(() => import("@/components/Common/PDFViewer")); - export const zoom_values = [ "scale-25", "scale-50", @@ -38,7 +39,6 @@ export const zoom_values = [ "scale-175", "scale-200", ]; - export interface StateInterface { open: boolean; isImage: boolean; @@ -51,7 +51,6 @@ export interface StateInterface { id?: string; associating_id?: string; } - type FilePreviewProps = { title?: ReactNode; description?: ReactNode; @@ -68,7 +67,6 @@ type FilePreviewProps = { loadFile?: (file: FileUploadModel, associating_id: string) => void; currentIndex: number; }; - const previewExtensions = [ ".html", ".htm", @@ -81,7 +79,6 @@ const previewExtensions = [ ".gif", ".webp", ]; - const FilePreviewDialog = (props: FilePreviewProps) => { const { show, @@ -95,18 +92,15 @@ const FilePreviewDialog = (props: FilePreviewProps) => { currentIndex, } = props; const { t } = useTranslation(); - const [page, setPage] = useState(1); const [numPages, setNumPages] = useState(1); const [index, setIndex] = useState(currentIndex); const [scale, setScale] = useState(1.0); - useEffect(() => { if (uploadedFiles && show) { setIndex(currentIndex); } }, [uploadedFiles, show, currentIndex]); - const handleZoomIn = () => { const checkFull = file_state.zoom === zoom_values.length; setFileState({ @@ -115,7 +109,6 @@ const FilePreviewDialog = (props: FilePreviewProps) => { }); setScale((prevScale) => Math.min(prevScale + 0.25, 2)); }; - const handleZoomOut = () => { const checkFull = file_state.zoom === 1; setFileState({ @@ -124,6 +117,29 @@ const FilePreviewDialog = (props: FilePreviewProps) => { }); setScale((prevScale) => Math.max(prevScale - 0.25, 0.5)); }; + const handleRotate = (angle: number) => { + setFileState((prev: any) => { + const newRotation = (prev.rotation + angle + 360) % 360; + return { + ...prev, + rotation: newRotation, + }; + }); + }; + + function getRotationClass(rotation: number) { + const normalizedRotation = rotation % 360; + switch (normalizedRotation) { + case 90: + return "rotate-90"; + case 180: + return "rotate-180"; + case 270: + return "-rotate-90"; + default: + return ""; + } + } const fileName = file_state?.name ? file_state.name + "." + file_state.extension @@ -138,12 +154,11 @@ const FilePreviewDialog = (props: FilePreviewProps) => { !loadFile || newIndex < 0 || newIndex >= uploadedFiles.length - ) + ) { return; - + } const nextFile = uploadedFiles[newIndex]; if (!nextFile?.id) return; - const associating_id = nextFile.associating_id || ""; loadFile(nextFile, associating_id); setIndex(newIndex); @@ -157,24 +172,8 @@ const FilePreviewDialog = (props: FilePreviewProps) => { onClose?.(); }; - const handleRotate = (rotation: number) => { - setFileState((prev: any) => ({ - ...prev, - rotation: prev.rotation + rotation, - })); - }; - - function getRotationClass(rotation: number) { - let normalizedRotation = ((rotation % 360) + 360) % 360; - if (normalizedRotation > 180) { - normalizedRotation -= 360; - } - return normalizedRotation === -90 - ? "-rotate-90" - : `rotate-${normalizedRotation}`; - } - useKeyboardShortcut(["ArrowLeft"], () => index > 0 && handleNext(index - 1)); + useKeyboardShortcut( ["ArrowRight"], () => index < (uploadedFiles?.length || 0) - 1 && handleNext(index + 1), @@ -188,7 +187,6 @@ const FilePreviewDialog = (props: FilePreviewProps) => { {t("file_preview")} - {fileUrl ? ( <>
@@ -251,7 +249,7 @@ const FilePreviewDialog = (props: FilePreviewProps) => { )} -
+
{file_state.isImage ? ( { sandbox="" title={t("source_file")} src={fileUrl} - className="h-[75vh] w-full" + className="h-[50vh] md:h-[75vh] w-full" /> ) : (
@@ -289,7 +287,6 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
)}
- {uploadedFiles && uploadedFiles.length > 1 && ( )}
-
-
+
+
{file_state.isImage && ( <> {[ @@ -344,7 +341,10 @@ const FilePreviewDialog = (props: FilePreviewProps) => { variant="ghost" key={index} onClick={button[2] as () => void} - className="z-50 rounded bg-white/60 px-4 py-2 text-black backdrop-blur transition hover:bg-white/70" + className={cn( + "z-50 rounded bg-white/60 px-4 py-2 text-black backdrop-blur transition hover:bg-white/70", + index > 2 ? "max-md:col-span-3" : "max-md:col-span-2", + )} disabled={button[3] as boolean} > {button[1] && ( @@ -387,7 +387,10 @@ const FilePreviewDialog = (props: FilePreviewProps) => { variant="ghost" key={index} onClick={button[2] as () => void} - className="z-50 rounded bg-white/60 px-4 py-2 text-black backdrop-blur transition hover:bg-white/70" + className={cn( + "z-50 rounded bg-white/60 px-4 py-2 text-black backdrop-blur transition hover:bg-white/70", + index > 2 ? "max-md:col-span-3" : "max-md:col-span-2", + )} disabled={button[3] as boolean} > {button[1] && ( @@ -405,7 +408,7 @@ const FilePreviewDialog = (props: FilePreviewProps) => {
) : ( -
+
)} @@ -413,5 +416,4 @@ const FilePreviewDialog = (props: FilePreviewProps) => { ); }; - export default FilePreviewDialog; diff --git a/src/components/Common/Page.tsx b/src/components/Common/Page.tsx index b9079c5089e..a4a2ba48a3e 100644 --- a/src/components/Common/Page.tsx +++ b/src/components/Common/Page.tsx @@ -9,7 +9,6 @@ interface PageProps extends PageTitleProps { options?: React.ReactNode | React.ReactNode[]; changePageMetadata?: boolean; className?: string; - noImplicitPadding?: boolean; ref?: RefObject; /** * If true, the sidebar will be collapsed when mounted, and restored to original state when unmounted. @@ -31,14 +30,8 @@ export default function Page(props: PageProps) { // }; // }, [props.collapseSidebar]); - let padding = ""; - if (!props.noImplicitPadding) { - if (props.componentRight) padding = "py-0 md:px-6"; - else padding = "px-6 py-0"; - } - return ( -
+
; +interface GenericTableProps { + headers: HeaderRow[]; + rows: TableRowType[] | undefined; +} + +export default function PrintTable({ headers, rows }: GenericTableProps) { + return ( +
+ + + + {headers.map(({ key, width }, index) => ( + + {t(key)} + + ))} + + + + {!!rows && + rows.map((row, index) => ( + + {headers.map(({ key }) => ( + + {row[key] || "-"} + + ))} + + ))} + +
+
+ ); +} diff --git a/src/components/Common/SearchByMultipleFields.tsx b/src/components/Common/SearchByMultipleFields.tsx index 242266ae23e..7cd3550b3ba 100644 --- a/src/components/Common/SearchByMultipleFields.tsx +++ b/src/components/Common/SearchByMultipleFields.tsx @@ -47,6 +47,7 @@ interface SearchByMultipleFieldsProps { clearSearch?: { value: boolean; params?: string[] }; enableOptionButtons?: boolean; onFieldChange?: (options: SearchOption) => void; + autoFocus?: boolean; } const KeyboardShortcutHint = ({ open }: { open: boolean }) => { @@ -90,6 +91,7 @@ const SearchByMultipleFields: React.FC = ({ clearSearch, onFieldChange, enableOptionButtons = true, + autoFocus = false, }) => { const { t } = useTranslation(); const [selectedOptionIndex, setSelectedOptionIndex] = @@ -175,12 +177,6 @@ const SearchByMultipleFields: React.FC = ({ return () => document.removeEventListener("keydown", handleKeyDown); }, [focusedIndex, open, handleOptionChange, options]); - useEffect(() => { - if (inputRef.current) { - inputRef.current.focus(); - } - }, [selectedOptionIndex]); - useEffect(() => { if (selectedOption.value !== searchValue) { onSearch(selectedOption.key, searchValue); @@ -224,6 +220,12 @@ const SearchByMultipleFields: React.FC = ({ } }, [selectedOption, searchValue, t, inputClassName, open]); + useEffect(() => { + if (autoFocus) { + inputRef.current?.focus(); + } + }, [autoFocus, open, selectedOptionIndex]); + return (
-

+

{formatName(selected)}

diff --git a/src/components/Encounter/CreateEncounterForm.tsx b/src/components/Encounter/CreateEncounterForm.tsx index 488cbc585fd..32d7d600fd6 100644 --- a/src/components/Encounter/CreateEncounterForm.tsx +++ b/src/components/Encounter/CreateEncounterForm.tsx @@ -1,6 +1,7 @@ import careConfig from "@careConfig"; import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { t } from "i18next"; import { Ambulance, BedDouble, @@ -12,9 +13,12 @@ import { import { navigate } from "raviger"; import { useState } from "react"; import { useForm } from "react-hook-form"; +import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import * as z from "zod"; +import { cn } from "@/lib/utils"; + import { Button } from "@/components/ui/button"; import { Form, @@ -74,7 +78,9 @@ const encounterFormSchema = z.object({ "use_as_directed", "urgent", ] as const), - organizations: z.array(z.string()), + organizations: z.array(z.string()).min(1, { + message: t("at_least_one_department_is_required"), + }), }); const encounterClasses = [ @@ -135,6 +141,7 @@ export default function CreateEncounterForm({ }: Props) { const [isOpen, setIsOpen] = useState(false); const queryClient = useQueryClient(); + const { t } = useTranslation(); const form = useForm>({ resolver: zodResolver(encounterFormSchema), @@ -154,13 +161,9 @@ export default function CreateEncounterForm({ form.reset(); queryClient.invalidateQueries({ queryKey: ["encounters", patientId] }); onSuccess?.(); - navigate(`/facility/${facilityId}/encounter/${data.id}/updates`); - }, - onError: (error) => { - const errorData = error.cause as { errors: { msg: string[] } }; - errorData.errors.msg.forEach((er) => { - toast.error(er); - }); + navigate( + `/facility/${facilityId}/patient/${patientId}/encounter/${data.id}/updates`, + ); }, }); @@ -178,7 +181,15 @@ export default function CreateEncounterForm({ } return ( - + { + setIsOpen(open); + if (!open) { + form.reset(); + } + }} + > {trigger || ( )} - Initiate Patient Encounter + {t("initiate_encounter")} - Begin a new clinical encounter for {patientName}. Select the - appropriate encounter type, status, and priority to ensure proper - documentation and care delivery. + {t("begin_clinical_encounter", { patientName })}
@@ -209,7 +218,9 @@ export default function CreateEncounterForm({ name="encounter_class" render={({ field }) => ( - Type of Encounter + + {t("type_of_encounter")} +
{encounterClasses.map( ({ value, label, icon: Icon, description }) => ( @@ -217,16 +228,18 @@ export default function CreateEncounterForm({ key={value} type="button" data-cy={`encounter-type-${value}`} - className="h-24 w-full justify-start text-lg" - variant={ - field.value === value ? "default" : "outline" - } + className={cn( + "h-24 w-full justify-start text-lg", + field.value === value && + "ring-2 ring-primary text-primary", + )} + variant="outline" onClick={() => field.onChange(value)} >
{label}
-
+
{description}
@@ -245,7 +258,7 @@ export default function CreateEncounterForm({ name="status" render={({ field }) => ( - Status + {t("status")} { + handleLocationUpdate({ + ...location, + status: val, + end_datetime: + val === "active" ? undefined : location.end_datetime, + }); + }} + > + + + + + {t("active")} + {t("planned")} + {t("reserved")} + {t("completed")} + + + +
+
+ + {stringifyNestedObject(location.location, " < ")} + +
+ {(location.status === "active" || + location.status === "planned" || + location.status === "reserved") && ( +
+ + + handleLocationUpdate({ + ...location, + start_datetime: e.target.value, + }) + } + className="h-9 w-auto" + /> +
+ )} + {location.status !== "active" && ( +
+ + + handleLocationUpdate({ + ...location, + end_datetime: e.target.value, + }) + } + className="h-9" + /> +
+ )} +
+
+ ); + + // Get locations by their original display status + const activeLocation = locations.find( + (loc) => loc.displayStatus === "active", + ); + const plannedLocations = locations.filter( + (loc) => loc.displayStatus === "planned", + ); + const reservedLocations = locations.filter( + (loc) => loc.displayStatus === "reserved", + ); + + return ( + + {trigger} + + + + {t("update_location")} + +

+ {t("manage_patient_location_and_transfers")} +

+
+ +
+ {/* Active Location */} + {activeLocation && renderLocation(activeLocation)} + + {/* Reserved Locations */} + {reservedLocations.map((location) => renderLocation(location))} + + {/* Planned Locations */} + {plannedLocations.map((location) => renderLocation(location))} + +
+
+
+ +
+
+ setSelectedLocation(location)} + value={selectedLocation} + /> + {selectedLocation && ( +
+
+ + +
+ {(newLocation.status === "active" || + newLocation.status === "planned" || + newLocation.status === "reserved") && ( +
+ + + setNewLocation((prev) => ({ + ...prev, + start_datetime: e.target.value, + })) + } + className="h-9" + /> +
+ )} + {newLocation.status !== "active" && ( +
+ + + setNewLocation((prev) => ({ + ...prev, + end_datetime: e.target.value, + })) + } + className="h-9" + /> +
+ )} + +
+ )} +
+
+ {history.map((item, index) => ( +
+ +
+ ))} +
+ + + + ); +} diff --git a/src/components/Medicine/MedicationAdministration/AdministrationTab.tsx b/src/components/Medicine/MedicationAdministration/AdministrationTab.tsx index 4a0bc9d63ac..cb53325fd11 100644 --- a/src/components/Medicine/MedicationAdministration/AdministrationTab.tsx +++ b/src/components/Medicine/MedicationAdministration/AdministrationTab.tsx @@ -1,14 +1,15 @@ "use client"; -import { useMutation, useQuery } from "@tanstack/react-query"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { format, formatDistanceToNow } from "date-fns"; import { t } from "i18next"; -import React, { useState } from "react"; +import React, { useCallback, useMemo, useState } from "react"; import CareIcon from "@/CAREUI/icons/CareIcon"; import { Button } from "@/components/ui/button"; -import { Card } from "@/components/ui/card"; +import { Card, CardContent } from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; import { Popover, PopoverContent, @@ -257,15 +258,30 @@ const MedicationRow: React.FC = ({ return (
onEditAdministration(medication, admin)} > -
+
+
+
+ {admin.note && ( + + )} +
+
+
+ {new Date( admin.occurrence_period_start, ).toLocaleTimeString("en-US", { @@ -273,11 +289,11 @@ const MedicationRow: React.FC = ({ minute: "2-digit", hour12: true, })} -
-
- {admin.occurrence_period_end && ( - <> - {"- "} + + {admin.occurrence_period_end && ( + <> + {"-"} + {new Date( admin.occurrence_period_end, ).toLocaleTimeString("en-US", { @@ -285,19 +301,10 @@ const MedicationRow: React.FC = ({ minute: "2-digit", hour12: true, })} - - )} -
+ + + )}
- {admin.note && ( - - )}
); })} @@ -361,7 +368,7 @@ export const AdministrationTab: React.FC = ({ Math.floor(currentDate.getHours() / 6), ); // Calculate visible slots based on end slot - const visibleSlots = React.useMemo(() => { + const visibleSlots = useMemo(() => { const slots = []; let currentIndex = endSlotIndex; let currentDate = new Date(endSlotDate); @@ -382,8 +389,10 @@ export const AdministrationTab: React.FC = ({ return slots; }, [endSlotDate, endSlotIndex]); + const queryClient = useQueryClient(); + // Queries - const { data: activeMedications, refetch: refetchActive } = useQuery({ + const { data: activeMedications } = useQuery({ queryKey: ["medication_requests_active", patientId], queryFn: query(medicationRequestApi.list, { pathParams: { patientId }, @@ -396,7 +405,7 @@ export const AdministrationTab: React.FC = ({ enabled: !!patientId, }); - const { data: stoppedMedications, refetch: refetchStopped } = useQuery({ + const { data: stoppedMedications } = useQuery({ queryKey: ["medication_requests_stopped", patientId], queryFn: query(medicationRequestApi.list, { pathParams: { patientId }, @@ -409,7 +418,7 @@ export const AdministrationTab: React.FC = ({ enabled: !!patientId, }); - const { data: administrations, refetch: refetchAdministrations } = useQuery({ + const { data: administrations } = useQuery({ queryKey: ["medication_administrations", patientId, visibleSlots], queryFn: query(medicationAdministrationApi.list, { pathParams: { patientId }, @@ -438,7 +447,7 @@ export const AdministrationTab: React.FC = ({ }); // Get last administered date and last administered by for each medication - const lastAdministeredDetails = React.useMemo(() => { + const lastAdministeredDetails = useMemo(() => { return administrations?.results?.reduce<{ dates: Record; performers: Record; @@ -473,7 +482,7 @@ export const AdministrationTab: React.FC = ({ }; // Calculate if we can go back further based on the earliest slot and authored date - const canGoBack = React.useMemo(() => { + const canGoBack = useMemo(() => { const medications = showStopped ? [ ...(activeMedications?.results || []), @@ -500,7 +509,7 @@ export const AdministrationTab: React.FC = ({ useState(null); // Calculate last modified date - const lastModifiedDate = React.useMemo(() => { + const lastModifiedDate = useMemo(() => { if (!administrations?.results?.length) return null; const sortedAdmins = [...administrations.results].sort( @@ -518,13 +527,17 @@ export const AdministrationTab: React.FC = ({ pathParams: { patientId }, }), onSuccess: () => { - refetchActive(); - refetchStopped(); + queryClient.invalidateQueries({ + queryKey: ["medication_requests_active"], + }); + queryClient.invalidateQueries({ + queryKey: ["medication_requests_stopped"], + }); }, }); // Handlers - const handlePreviousSlot = React.useCallback(() => { + const handlePreviousSlot = useCallback(() => { if (!canGoBack) return; const newEndSlotIndex = endSlotIndex - 1; @@ -538,7 +551,7 @@ export const AdministrationTab: React.FC = ({ } }, [endSlotDate, endSlotIndex, canGoBack]); - const handleNextSlot = React.useCallback(() => { + const handleNextSlot = useCallback(() => { const newEndSlotIndex = endSlotIndex + 1; if (newEndSlotIndex > 3) { setEndSlotIndex(0); @@ -550,7 +563,7 @@ export const AdministrationTab: React.FC = ({ } }, [endSlotDate, endSlotIndex]); - const handleAdminister = React.useCallback( + const handleAdminister = useCallback( (medication: MedicationRequestRead) => { setAdministrationRequest( createMedicationAdministrationRequest(medication, encounterId), @@ -561,7 +574,7 @@ export const AdministrationTab: React.FC = ({ [encounterId], ); - const handleEditAdministration = React.useCallback( + const handleEditAdministration = useCallback( (medication: MedicationRequestRead, admin: MedicationAdministration) => { setAdministrationRequest({ id: admin.id, @@ -580,7 +593,7 @@ export const AdministrationTab: React.FC = ({ [], ); - const handleDiscontinue = React.useCallback( + const handleDiscontinue = useCallback( (medication: MedicationRequestRead) => { discontinueMedication({ datapoints: [ @@ -602,14 +615,16 @@ export const AdministrationTab: React.FC = ({ ] : activeMedications?.results || []; - const filteredMedications = medications.filter( - (med: MedicationRequestRead) => { - if (!searchQuery.trim()) return true; - const searchTerm = searchQuery.toLowerCase().trim(); - const medicationName = med.medication?.display?.toLowerCase() || ""; - return medicationName.includes(searchTerm); - }, - ); + const filteredMedications = !searchQuery.trim() + ? medications + : [ + ...(activeMedications?.results || []), + ...(stoppedMedications?.results || []), + ].filter((med: MedicationRequestRead) => + med.medication?.display + ?.toLowerCase() + .includes(searchQuery.toLowerCase().trim()), + ); let content; if (!activeMedications || !stoppedMedications) { @@ -618,10 +633,13 @@ export const AdministrationTab: React.FC = ({
); - } else if (!medications?.length) { + } else if ( + !activeMedications?.results?.length && + !stoppedMedications?.results?.length + ) { content = ( ); @@ -629,124 +647,134 @@ export const AdministrationTab: React.FC = ({ content = ; } else { content = ( - - -
- {/* Top row without vertical borders */} -
-
-
- {lastModifiedDate && ( -
- {t("last_modified")}{" "} - {formatDistanceToNow(lastModifiedDate)} {t("ago")} -
- )} + <> + {!filteredMedications.length && ( + +

+ {t("no_active_medication_recorded")} +

+
+ )} + + +
+ {/* Top row without vertical borders */} +
+
+
+ {lastModifiedDate && ( +
+ {t("last_modified")}{" "} + {formatDistanceToNow(lastModifiedDate)} {t("ago")} +
+ )} +
+
+ +
-
+ {visibleSlots.map((slot) => ( + + ))} +
- {visibleSlots.map((slot) => ( - - ))} -
- -
-
- {/* Main content with borders */} -
- {/* Headers */} -
- {t("medicine")}: -
- {visibleSlots.map((slot, i) => ( -
- {i === endSlotIndex && - slot.date.getTime() === currentDate.getTime() && ( -
-
-
- )} - {slot.label} + {/* Main content with borders */} +
+ {/* Headers */} +
+ {t("medicine")}:
- ))} -
- - {/* Medication rows */} - {filteredMedications?.map((medication) => ( - - ))} + {visibleSlots.map((slot, i) => ( +
+ {i === endSlotIndex && + slot.date.getTime() === currentDate.getTime() && ( +
+
+
+ )} + {slot.label} +
+ ))} +
+ + {/* Medication rows */} + {filteredMedications?.map((medication) => ( + + ))} +
-
- {stoppedMedications?.results?.length > 0 && ( -
setShowStopped(!showStopped)} - > - - - {showStopped ? t("hide") : t("show")}{" "} - {`${stoppedMedications?.results?.length} ${t("stopped")}`}{" "} - {t("prescriptions")} - -
- )} - - - + {stoppedMedications?.results?.length > 0 && !searchQuery.trim() && ( +
setShowStopped(!showStopped)} + > + + + {showStopped ? t("hide") : t("show")}{" "} + {`${stoppedMedications?.results?.length} ${t("stopped")}`}{" "} + {t("prescriptions")} + +
+ )} + + + + ); } return (
-
+
- setSearchQuery(e.target.value)} @@ -766,8 +794,9 @@ export const AdministrationTab: React.FC = ({