diff --git a/.cursorrules b/.cursorrules index 2eed3afe459..94ebea1bd57 100644 --- a/.cursorrules +++ b/.cursorrules @@ -1,23 +1,35 @@ -Care is a React Typescript Project, built with Vite and styled with TailwindCSS. +You are an expert in TypeScript, React, Shadcn UI, Tailwind. -Care uses a Plugin Architecture. Apps are installed in /apps. +Key Principles -Care uses a custom useQuery hook to fetch data from the API. APIs are defined in the api.tsx file +- Write concise, technical TypeScript code with accurate examples. +- Use functional and declarative programming patterns; avoid classes. +- Prefer iteration and modularization over code duplication. +- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError). -Here's an example of how to use the useQuery hook to fetch data from the API: +Naming Conventions -``` -useQuery from "@/common/hooks/useQuery"; -const { data, loading, error } = useQuery(routes.getFacilityUsers, { - facility_id: "1", -}); +- Use lowercase with dashes for directories (e.g., components/auth-wizard). +- Favor named exports for components. -request from "@/common/utils/request"; -const { res } = await request(routes.partialUpdateAsset, { - pathParams: { external_id: assetId }, - body: data, -}); -``` +TypeScript Usage +- Use TypeScript for all code; prefer interfaces over types. +- Avoid enums; use maps instead. +- Use functional components with TypeScript interfaces. +Syntax and Formatting +- Use the "function" keyword for pure functions. +- Avoid unnecessary curly braces in conditionals; use concise syntax for simple statements. +- Use declarative JSX. + +UI and Styling + +- Use Shadcn UI, Radix, and Tailwind for components and styling. +- Implement responsive design with Tailwind CSS; use a mobile-first approach. + +General Guidelines + +- Care uses a custom useQuery hook to fetch data from the API. (Docs @ /Utils/request/useQuery) +- APIs are defined in the api.tsx file. diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 40e5259b1c6..517bcf98d88 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node { "name": "care_fe", - "image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye", + "image": "mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm", "features": { "ghcr.io/devcontainers/features/docker-outside-of-docker:1": { "moby": true, diff --git a/.env b/.env index b5db3d0088f..77e4641b8b2 100644 --- a/.env +++ b/.env @@ -14,4 +14,4 @@ ESLINT_NO_DEV_ERRORS=true CARE_CDN_URL="https://egov-s3-facility-10bedicu.s3.amazonaws.com https://egov-s3-patient-data-10bedicu.s3.amazonaws.com http://localhost:4566" REACT_ALLOWED_LOCALES="en,hi,ta,ml,mr,kn" -REACT_ENABLED_APPS="" +REACT_ENABLED_APPS="" \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..2125666142e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/.github/workflows/auto-testing-label.yml b/.github/workflows/auto-testing-label.yml index 6c6fc1002a0..98cfd46dab3 100644 --- a/.github/workflows/auto-testing-label.yml +++ b/.github/workflows/auto-testing-label.yml @@ -38,7 +38,7 @@ jobs: } if (isChangesRequired) { - await github.issues.createComment({ + await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: pr.number, diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml index 1104d7f480d..3abf95cd4b0 100644 --- a/.github/workflows/cypress.yaml +++ b/.github/workflows/cypress.yaml @@ -18,6 +18,9 @@ jobs: containers: [1, 2, 3, 4] env: REACT_CARE_API_URL: http://localhost:9000 + REACT_ENABLED_APPS: "ohcnetwork/care_hcx_fe@main,ohcnetwork/care_abdm_fe@main" + REACT_ENABLE_HCX: true + REACT_ENABLE_ABDM: true steps: - name: Checkout 📥 uses: actions/checkout@v3 @@ -114,7 +117,6 @@ jobs: group: "UI-Chrome" env: CYPRESS_SPLIT_TESTS: "true" - CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_OPTIONS: --max_old_space_size=4096 COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}} @@ -131,7 +133,7 @@ jobs: - name: Upload cypress videos 📹 uses: actions/upload-artifact@v3 - if: steps.pr_origin.outputs.is_forked == 'true' + if: ${{ failure() && steps.pr_origin.outputs.is_forked == 'true' }} with: name: cypress-videos - path: cypress/videos \ No newline at end of file + path: cypress/videos diff --git a/.github/workflows/notify-non-core-qn.yml b/.github/workflows/notify-non-core-qn.yml new file mode 100644 index 00000000000..07533c320c5 --- /dev/null +++ b/.github/workflows/notify-non-core-qn.yml @@ -0,0 +1,88 @@ +name: Notify Core Team on Non-Core Questions + +on: + issue_comment: + types: [created] + +permissions: + issues: write + pull-requests: write + +jobs: + notify_core_team: + runs-on: ubuntu-latest + env: + ALLOWED_USERNAMES: ${{ vars.ALLOWED_USERNAMES || '' }} + QUESTION_KEYWORDS: ${{ vars.QUESTION_KEYWORDS || '' }} + QUESTION_LABELS: ${{ vars.QUESTION_LABELS || '' }} + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK || '' }} + + steps: + - name: Check and Notify + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const isOrgMember = (commenter, allowedUsers) => + allowedUsers.split(',').map(u => u.trim()).includes(commenter); + + const containsQuestionKeywords = (text, keywords) => + keywords.split(',').map(k => k.trim()).some(keyword => + text.toLowerCase().includes(keyword.toLowerCase()) + ); + + const addLabelsToIssue = async (github, context, labelsString) => { + const labels = labelsString.split(',').map(label => label.trim()).filter(Boolean); + if (labels.length > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.issue.number, + labels: labels + }); + } + }; + + const sendSlackNotification = async (webhook, commentUrl) => { + const payload = { commentUrl }; + const response = await fetch(webhook, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + if (!response.ok) { + throw new Error(`Slack notification failed with status: ${response.status}`); + } + }; + + const isBot = async (github, commenter) => { + try { + const { data: user } = await github.rest.users.getByUsername({ username: commenter }); + return user.type === 'Bot'; + } catch { + return false; + } + }; + + const commenter = context.payload.comment.user.login; + const allowedUsers = process.env.ALLOWED_USERNAMES; + const keywords = process.env.QUESTION_KEYWORDS; + const labels = process.env.QUESTION_LABELS; + const webhook = process.env.SLACK_WEBHOOK; + + if (await isBot(github, commenter)) return; + + if (allowedUsers && !isOrgMember(commenter, allowedUsers)) { + const commentBody = context.payload.comment.body.trim(); + const filteredCommentBody = commentBody.split('\n').filter(line => !line.startsWith('>')).join('\n'); + + if (keywords && containsQuestionKeywords(filteredCommentBody, keywords)) { + if (labels) { + await addLabelsToIssue(github, context, labels); + } + if (webhook) { + const commentUrl = context.payload.comment.html_url; + await sendSlackNotification(webhook, commentUrl); + } + } + } diff --git a/.github/workflows/thank-you.yml b/.github/workflows/thank-you.yml index 192f71d1a64..b91642dd24f 100644 --- a/.github/workflows/thank-you.yml +++ b/.github/workflows/thank-you.yml @@ -18,26 +18,20 @@ jobs: uses: actions/github-script@v6.3.3 with: script: | - const thankyouNote = 'Your efforts have helped advance digital healthcare and TeleICU systems. :rocket: Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! :raised_hands:' + const thankyouNote = 'Your efforts have helped advance digital healthcare and TeleICU systems. :rocket: Thank you for taking the time out to make CARE better. We hope you continue to innovate and contribute; your impact is immense! :raised_hands:'; const options = { issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, - } + }; - const result = await github.rest.issues.get({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - }) - - const { assignees, user } = result.data + const { data : { assignees, user } } = await github.rest.issues.get(options); - const assignees_tagged = assignees.map((user) => '@' + user.login).join(' ') - const owner_tagged = '@' + user.login + const taggedUsers = [...new Set( + assignees.map(u => "@"+u.login).concat("@"+user.login) + )].join(" ") - if (assignees.length == 0) { - await github.rest.issues.createComment({ ...options, body: `${owner_tagged} ${thankyouNote}` }) - } else { - await github.rest.issues.createComment({ ...options, body: `${assignees_tagged} ${owner_tagged} ${thankyouNote}` }) - } + await github.rest.issues.createComment({ + ...options, + body: `${taggedUsers} ${thankyouNote}` + }); diff --git a/.gitignore b/.gitignore index 000a965c44a..3ae96d927fb 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,4 @@ cypress/fixtures/token.json # Care Apps /apps/* src/pluginMap.ts +/apps_backup/* \ No newline at end of file diff --git a/.husky/_/husky.sh b/.husky/_/husky.sh deleted file mode 100644 index cec959a6b9d..00000000000 --- a/.husky/_/husky.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env sh -if [ -z "$husky_skip_init" ]; then - debug () { - if [ "$HUSKY_DEBUG" = "1" ]; then - echo "husky (debug) - $1" - fi - } - - readonly hook_name="$(basename -- "$0")" - debug "starting $hook_name..." - - if [ "$HUSKY" = "0" ]; then - debug "HUSKY env variable is set to 0, skipping hook" - exit 0 - fi - - if [ -f ~/.huskyrc ]; then - debug "sourcing ~/.huskyrc" - . ~/.huskyrc - fi - - readonly husky_skip_init=1 - export husky_skip_init - sh -e "$0" "$@" - exitCode="$?" - - if [ $exitCode != 0 ]; then - echo "husky - $hook_name hook exited with code $exitCode (error)" - fi - - if [ $exitCode = 127 ]; then - echo "husky - command not found in PATH=$PATH" - fi - - exit $exitCode -fi diff --git a/.husky/pre-commit b/.husky/pre-commit index 36af219892f..2312dc587f6 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - npx lint-staged diff --git a/.node-version b/.node-version index 85aee5a534c..92f279e3e66 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -v20 \ No newline at end of file +v22 \ No newline at end of file diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 2edeafb09db..00000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 4ab5ed7dbc0..bf9997b55e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ #build-stage -FROM --platform=$BUILDPLATFORM node:20-buster-slim as build-stage +FROM --platform=$BUILDPLATFORM node:22-bookworm-slim as build-stage WORKDIR /app @@ -7,9 +7,6 @@ ENV NODE_OPTIONS="--max-old-space-size=4096" RUN apt-get update && apt-get install -y git -RUN if [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then apt-get install -y python3-dev make g++; fi - - COPY package.json package-lock.json ./ RUN npm install diff --git a/crowdin.yml b/crowdin.yml index 0ab1a042711..fdcb6bcd32d 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -1,5 +1,6 @@ files: - - source: /src/Locale/en/*.json - translation: /src/Locale/%two_letters_code%/%original_file_name% + - source: /public/locale/{{lang}}.json + translation: /public/locale/%two_letters_code%/%original_file_name% bundles: - 2 + diff --git a/cypress.config.ts b/cypress.config.ts index b6e8fadd462..4da5d989a88 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,7 +1,10 @@ import { defineConfig } from "cypress"; import cypressSplit from "cypress-split"; +import * as dotenv from "dotenv"; import fs from "fs"; +dotenv.config(); + export default defineConfig({ projectId: "wf7d2m", defaultCommandTimeout: 10000, @@ -32,7 +35,7 @@ export default defineConfig({ requestTimeout: 15000, }, env: { - API_URL: process.env.REACT_CARE_API_URL ?? "http://localhost:9000", + API_URL: process.env.REACT_CARE_API_URL, ENABLE_HCX: process.env.REACT_ENABLE_HCX ?? false, }, }); diff --git a/cypress/e2e/assets_spec/AssetHomepage.cy.ts b/cypress/e2e/assets_spec/AssetHomepage.cy.ts index bda4abdfae3..e19f885db72 100644 --- a/cypress/e2e/assets_spec/AssetHomepage.cy.ts +++ b/cypress/e2e/assets_spec/AssetHomepage.cy.ts @@ -1,112 +1,129 @@ -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; -import { AssetQRScanPage } from "../../pageobject/Asset/AssetQRScan"; -import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; -import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; -import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import LoginPage from "../../pageobject/Login/LoginPage"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; +import { pageNavigation } from "pageobject/utils/paginationHelpers"; import { v4 as uuidv4 } from "uuid"; -describe("Asset Tab", () => { - const assetSearchPage = new AssetSearchPage(); - const assetQRScanPage = new AssetQRScanPage(); - const assetPagination = new AssetPagination(); - const assetFilters = new AssetFilters(); - const assetPage = new AssetPage(); - const loginPage = new LoginPage(); - const assetName = "Dummy Camera 10"; - const qrCode = uuidv4(); - const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); - - before(() => { - loginPage.loginAsDistrictAdmin(); - cy.saveLocalStorage(); - }); - - beforeEach(() => { - cy.restoreLocalStorage(); - cy.clearLocalStorage(/filters--.+/); - cy.awaitUrl("/assets"); - }); - - // search for a element +import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; +import { AssetHome } from "../../pageobject/Asset/AssetHome"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { nonAdminRoles } from "../../pageobject/utils/userConfig"; - it("Search Asset Name/QR_ID/Serial_number", () => { - assetSearchPage.typeSearchKeyword(assetName); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetName); - assetSearchPage.clickAssetByName(assetName); - assetSearchPage.clickUpdateButton(); - assetSearchPage.clearAndTypeQRCode(qrCode); - assetSearchPage.clearAndTypeSerialNumber(serialNumber); - assetSearchPage.clickAssetSubmitButton(); - assetSearchPage.visitAssetsPage(); - assetSearchPage.typeSearchKeyword(qrCode); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetListContains(assetName); - assetSearchPage.verifyBadgeContent(qrCode); - assetSearchPage.typeSearchKeyword(serialNumber); - assetSearchPage.verifyAssetListContains(assetName); - assetSearchPage.verifyBadgeContent(serialNumber); - }); +const rolesToTest: Array<"districtAdmin" | (typeof nonAdminRoles)[number]> = [ + "districtAdmin", + ...nonAdminRoles, +]; - // scan a asset qr code +rolesToTest.forEach((role) => { + describe(`Asset Tab Tests for Role: ${role}`, () => { + const assetHome = new AssetHome(); + const assetFilters = new AssetFilters(); + const loginPage = new LoginPage(); + const assetName = "Dummy Camera 10"; + const assetStatus = "ACTIVE"; + const assetClass = "ONVIF"; + const assetLocation = "Camera Loc"; + const facilityName = "Dummy Facility 40"; + const newImportAssetName = "New Test Asset"; + const qrCode = uuidv4(); + const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); - it("Scan Asset QR", () => { - assetQRScanPage.scanAssetQR(); - }); + before(() => { + loginPage.loginByRole(role); + cy.saveLocalStorage(); + }); - // filter the asset and verify the badges are there + beforeEach(() => { + cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + cy.awaitUrl("/assets"); + }); - it("Filter Asset", () => { - assetFilters.filterAssets( - "Dummy Facility 40", - "ACTIVE", - "ONVIF Camera", - "Camera Loc", - ); - assetFilters.clickadvancefilter(); - assetFilters.clickslideoverbackbutton(); // to verify the back button doesn't clear applied filters - assetFilters.assertFacilityText("Dummy Facility 40"); - assetFilters.assertAssetClassText("ONVIF"); - assetFilters.assertStatusText("ACTIVE"); - assetFilters.assertLocationText("Camera Loc"); - assetFilters.clickadvancefilter(); - assetFilters.clearFilters(); - }); + it("Search Asset Name/QR_ID/Serial_number", () => { + assetHome.typeAssetSearch(assetName); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetName, + true, + ); + assetHome.clickAssetByName(assetName); + assetHome.clickAssetDetailsUpdateButton(); + assetHome.clearAndTypeQRCode(qrCode); + assetHome.clearAndTypeSerialNumber(serialNumber); + assetHome.clickAssetUpdateSubmitButton(); + assetHome.navigateToAssetsPage(); + assetHome.typeAssetSearch(qrCode); + assetHome.verifyAssetListContains(assetName); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + qrCode, + true, + ); + assetHome.typeAssetSearch(serialNumber); + assetHome.verifyAssetListContains(assetName); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + serialNumber, + true, + ); + }); - // Verify the pagination in the page + it("Scan Asset QR", () => { + assetHome.scanAssetQR(); + }); - it("Next/Previous Page", () => { - assetPagination.navigateToNextPage(); - assetPagination.verifyNextUrl(); - assetPagination.navigateToPreviousPage(); - assetPagination.verifyPreviousUrl(); - }); + it("Advance Filter Asset", () => { + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.typeFacilityName(facilityName); + assetFilters.filterAssets(assetStatus, assetClass, assetLocation); + advanceFilters.applySelectedFilter(); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.clickslideoverbackbutton(); // to verify the back button doesn't clear applied filters + advanceFilters.verifyFilterBadgePresence("Facility", facilityName, true); + advanceFilters.verifyFilterBadgePresence("Asset Class", assetClass, true); + advanceFilters.verifyFilterBadgePresence("Status", assetStatus, true); + advanceFilters.verifyFilterBadgePresence("Location", assetLocation, true); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.clickClearAdvanceFilters(); + }); - it("Import new asset", () => { - assetPage.selectassetimportbutton(); - assetPage.selectImportOption(); - assetPage.selectImportFacility("Dummy Facility 40"); - assetPage.importAssetFile(); - assetPage.selectImportLocation("Camera Loc"); - assetPage.clickImportAsset(); - }); + it("Next/Previous Page", () => { + pageNavigation.navigateToNextPage(); + pageNavigation.verifyCurrentPageNumber(2); + pageNavigation.navigateToPreviousPage(); + pageNavigation.verifyCurrentPageNumber(1); + }); - it("verify imported asset", () => { - assetSearchPage.typeSearchKeyword("New Test Asset"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset"); - }); + it("Import new asset and verify its presence", () => { + if (role === "districtAdmin") { + assetHome.selectAssetImportButton("click"); + assetHome.selectImportOption(); + assetHome.selectImportFacility(facilityName); + assetHome.importAssetFile(); + assetHome.selectImportLocation(assetLocation); + assetHome.clickImportAsset(); + cy.verifyNotification("Assets imported successfully"); + cy.closeNotification(); + assetHome.navigateToAssetsPage(); + assetHome.typeAssetSearch(newImportAssetName); + assetHome.verifyAssetIsPresent(newImportAssetName); + } else { + assetHome.selectAssetImportButton("verifyNotExist"); + } + }); - it("Export asset", () => { - assetPage.selectassetimportbutton(); - cy.wait(2000); - assetPage.selectJsonExportButton(); - assetPage.selectassetimportbutton(); - assetPage.selectCsvExportButton(); - }); + it("Export the list of assets in CSV & Json", () => { + if (role === "districtAdmin") { + assetHome.selectAssetImportButton("click"); + cy.wait(2000); + assetHome.selectJsonExportButton(); + assetHome.selectAssetImportButton("click"); + assetHome.selectCsvExportButton(); + } else { + assetHome.selectAssetImportButton("verifyNotExist"); + } + }); - afterEach(() => { - cy.saveLocalStorage(); + afterEach(() => { + cy.saveLocalStorage(); + }); }); }); diff --git a/cypress/e2e/assets_spec/AssetsCreation.cy.ts b/cypress/e2e/assets_spec/AssetsCreation.cy.ts index 16a4fd050fb..820ac4231a9 100644 --- a/cypress/e2e/assets_spec/AssetsCreation.cy.ts +++ b/cypress/e2e/assets_spec/AssetsCreation.cy.ts @@ -1,17 +1,18 @@ -import { AssetPage } from "../../pageobject/Asset/AssetCreation"; import { v4 as uuidv4 } from "uuid"; + +import { AssetPage } from "../../pageobject/Asset/AssetCreation"; +import { AssetHome } from "../../pageobject/Asset/AssetHome"; import LoginPage from "../../pageobject/Login/LoginPage"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; describe("Asset", () => { const assetPage = new AssetPage(); - const assetSearchPage = new AssetSearchPage(); + const assetHome = new AssetHome(); const loginPage = new LoginPage(); const phone_number = "9999999999"; const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -42,21 +43,21 @@ describe("Asset", () => { const qr_id_1 = uuidv4(); - assetPage.enterAssetDetails( - "New Test Asset 1", - "Test Description", - "Working", - qr_id_1, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!", - ); + assetPage.enterAssetDetails({ + name: "New Test Asset 1", + description: "Test Description", + workingStatus: "Working", + qrId: qr_id_1, + manufacturer: "Manufacturer's Name", + warranty: "2025-12-25", + supportName: "Customer Support's Name", + supportPhone: phone_number, + supportEmail: "email@support.com", + vendorName: "Vendor's Name", + serialNumber: serialNumber, + lastServicedOn: "25122021", + notes: "Test note for asset creation!", + }); assetPage.clickCreateAddMore(); assetPage.verifySuccessNotification("Asset created successfully"); @@ -65,30 +66,29 @@ describe("Asset", () => { assetPage.selectLocation("Camera Loc"); assetPage.selectAssetClass("ONVIF Camera"); - assetPage.enterAssetDetails( - "New Test Asset 2", - "Test Description", - "Working", - qr_id_2, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!", - ); + assetPage.enterAssetDetails({ + name: "New Test Asset 2", + description: "Test Description", + workingStatus: "Working", + qrId: qr_id_2, + manufacturer: "Manufacturer's Name", + warranty: "2025-12-25", + supportName: "Customer Support's Name", + supportPhone: phone_number, + supportEmail: "email@support.com", + vendorName: "Vendor's Name", + serialNumber: serialNumber, + lastServicedOn: "25122021", + notes: "Test note for asset creation!", + }); assetPage.interceptAssetCreation(); assetPage.clickCreateAsset(); assetPage.verifyAssetCreation(); assetPage.verifySuccessNotification("Asset created successfully"); - assetSearchPage.typeSearchKeyword("New Test Asset 2"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset 2"); + assetHome.typeAssetSearch("New Test Asset 2"); + assetHome.verifyAssetIsPresent("New Test Asset 2"); }); it("Edit an Asset", () => { @@ -113,9 +113,8 @@ describe("Asset", () => { }); it("Verify Editted Asset", () => { - assetSearchPage.typeSearchKeyword("New Test Asset Edited"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset Edited"); + assetHome.typeAssetSearch("New Test Asset Edited"); + assetHome.verifyAssetIsPresent("New Test Asset Edited"); }); it("Configure an asset", () => { @@ -140,26 +139,26 @@ describe("Asset", () => { const qr_id_1 = uuidv4(); - assetPage.enterAssetDetails( - "New Test Asset Vital", - "Test Description", - "Working", - qr_id_1, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!", - ); + assetPage.enterAssetDetails({ + name: "New Test Asset Vital", + description: "Test Description", + workingStatus: "Working", + qrId: qr_id_1, + manufacturer: "Manufacturer's Name", + warranty: "2025-12-25", + supportName: "Customer Support's Name", + supportPhone: phone_number, + supportEmail: "email@support.com", + vendorName: "Vendor's Name", + serialNumber: serialNumber, + lastServicedOn: "25122021", + notes: "Test note for asset creation!", + }); + assetPage.interceptAssetCreation(); assetPage.clickCreateAsset(); assetPage.verifyAssetCreation(); - assetSearchPage.typeSearchKeyword("New Test Asset Vital"); - assetSearchPage.pressEnter(); + assetHome.typeAssetSearch("New Test Asset Vital"); assetPage.openCreatedAsset(); assetPage.configureVitalAsset("Host name", "192.168.1.20"); assetPage.clickConfigureVital(); diff --git a/cypress/e2e/assets_spec/AssetsManage.cy.ts b/cypress/e2e/assets_spec/AssetsManage.cy.ts index 756d3b261a6..32dc5791bd3 100644 --- a/cypress/e2e/assets_spec/AssetsManage.cy.ts +++ b/cypress/e2e/assets_spec/AssetsManage.cy.ts @@ -1,8 +1,10 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import LoginPage from "../../pageobject/Login/LoginPage"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import { AssetHome } from "../../pageobject/Asset/AssetHome"; import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; +import LoginPage from "../../pageobject/Login/LoginPage"; function addDaysToDate(numberOfDays: number) { const inputDate = new Date(); @@ -14,15 +16,15 @@ describe("Asset", () => { const assetPage = new AssetPage(); const loginPage = new LoginPage(); const facilityPage = new FacilityPage(); - const assetSearchPage = new AssetSearchPage(); - const assetFilters = new AssetFilters(); + const assetHome = new AssetHome(); + const facilityHome = new FacilityHome(); const fillFacilityName = "Dummy Facility 40"; const assetname = "Dummy Camera"; const locationName = "Dummy Location 1"; const initiallocationName = "Camera Location"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -33,10 +35,13 @@ describe("Asset", () => { }); it("Verify Asset Warranty Expiry Label", () => { - assetSearchPage.typeSearchKeyword(assetname); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetname); - assetSearchPage.clickAssetByName(assetname); + assetHome.typeAssetSearch(assetname); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetname, + true, + ); + assetHome.clickAssetByName(assetname); assetPage.clickupdatedetailbutton(); assetPage.scrollintoWarrantyDetails(); assetPage.enterWarrantyExpiryDate(addDaysToDate(100)); // greater than 3 months @@ -60,10 +65,13 @@ describe("Asset", () => { }); it("Create & Edit a service history and verify reflection", () => { - assetSearchPage.typeSearchKeyword(assetname); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetname); - assetSearchPage.clickAssetByName(assetname); + assetHome.typeAssetSearch(assetname); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetname, + true, + ); + assetHome.clickAssetByName(assetname); assetPage.clickupdatedetailbutton(); assetPage.scrollintonotes(); assetPage.enterAssetNotes("Dummy Notes"); @@ -82,10 +90,13 @@ describe("Asset", () => { }); it("Create a asset transaction and verify history", () => { - assetSearchPage.typeSearchKeyword(assetname); - assetSearchPage.pressEnter(); - assetSearchPage.verifyBadgeContent(assetname); - assetSearchPage.clickAssetByName(assetname); + assetHome.typeAssetSearch(assetname); + advanceFilters.verifyFilterBadgePresence( + "Name/Serial No./QR ID", + assetname, + true, + ); + assetHome.clickAssetByName(assetname); assetPage.clickupdatedetailbutton(); assetPage.clickassetlocation(locationName); assetPage.clickUpdateAsset(); @@ -94,10 +105,13 @@ describe("Asset", () => { }); it("Verify Facility Asset Page Redirection", () => { - cy.visit("/facility"); - assetSearchPage.typeSearchKeyword(fillFacilityName); - assetSearchPage.pressEnter(); - facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(fillFacilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + fillFacilityName, + true, + ); facilityPage.visitAlreadyCreatedFacility(); facilityPage.clickManageFacilityDropdown(); facilityPage.clickCreateAssetFacilityOption(); @@ -106,7 +120,11 @@ describe("Asset", () => { facilityPage.clickManageFacilityDropdown(); facilityPage.clickviewAssetFacilityOption(); facilityPage.verifyfacilityviewassetredirection(); - assetFilters.assertFacilityText(fillFacilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility", + fillFacilityName, + true, + ); facilityPage.verifyassetfacilitybackredirection(); }); diff --git a/cypress/e2e/auth_spec/ForgotPassword.cy.ts b/cypress/e2e/auth_spec/ForgotPassword.cy.ts deleted file mode 100644 index c1b1db7ecad..00000000000 --- a/cypress/e2e/auth_spec/ForgotPassword.cy.ts +++ /dev/null @@ -1,17 +0,0 @@ -describe("Forgot Password", () => { - beforeEach(() => { - cy.awaitUrl("/", true); - cy.get("button").contains("Forgot password?").click().wait(100); - }); - - it("Send Password Reset Link", () => { - cy.get("input[id='forgot_username']").type("dummy_user_1"); - cy.contains("Send Reset Link").click().wait(1000); - cy.contains("Password Reset Email Sent").should("exist"); - }); - - it("Go to Login page", () => { - cy.get("button").contains("Back to login").click(); - cy.url().should("contain", "/"); - }); -}); diff --git a/cypress/e2e/auth_spec/auth.cy.ts b/cypress/e2e/auth_spec/auth.cy.ts deleted file mode 100644 index b2bd7b634c0..00000000000 --- a/cypress/e2e/auth_spec/auth.cy.ts +++ /dev/null @@ -1,23 +0,0 @@ -describe("Authorisation/Authentication", () => { - beforeEach(() => { - cy.awaitUrl("/", true); - }); - - it("Try login as admin with correct password", () => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); - cy.awaitUrl("/facility"); - cy.get("#user-profile-name").click(); - cy.get("#sign-out-button").contains("Sign Out").click(); - cy.url().should("include", "/"); - }); - - it("Try login as admin with incorrect password", () => { - cy.log("Logging in the user: devdistrictadmin:Coronasafe@123"); - - cy.awaitUrl("/", true); - cy.get("input[id='username']").type("devdistrictadmin"); - cy.get("input[id='password']").type("coronasafe@123"); - cy.get("button").contains("Login").click(); - cy.contains("No active account").should("exist"); - }); -}); diff --git a/cypress/e2e/facility_spec/FacilityCreation.cy.ts b/cypress/e2e/facility_spec/FacilityCreation.cy.ts index 4961ae4a4cb..78ce17d8b9e 100644 --- a/cypress/e2e/facility_spec/FacilityCreation.cy.ts +++ b/cypress/e2e/facility_spec/FacilityCreation.cy.ts @@ -1,8 +1,10 @@ +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import LoginPage from "../../pageobject/Login/LoginPage"; import FacilityHome from "../../pageobject/Facility/FacilityHome"; +import LoginPage from "../../pageobject/Login/LoginPage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; -import { UserCreationPage } from "../../pageobject/Users/UserCreation"; +import { nonAdminRoles } from "../../pageobject/utils/userConfig"; describe("Facility Creation", () => { let facilityUrl1: string; @@ -10,7 +12,6 @@ describe("Facility Creation", () => { const loginPage = new LoginPage(); const facilityHome = new FacilityHome(); const manageUserPage = new ManageUserPage(); - const userCreationPage = new UserCreationPage(); const facilityFeature = [ "CT Scan", "X-Ray", @@ -57,9 +58,10 @@ describe("Facility Creation", () => { "This field is required", ]; const triageErrorMessage = ["This field is required"]; + const facilityType = "Primary Health Centres"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -71,15 +73,19 @@ describe("Facility Creation", () => { it("Verify Facility Triage Function", () => { // mandatory field error throw - manageUserPage.typeFacilitySearch(facilityName2); - facilityPage.verifyFacilityBadgeContent(facilityName2); - manageUserPage.assertFacilityInCard(facilityName2); + facilityHome.typeFacilitySearch(facilityName2); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName2, + true, + ); + facilityHome.assertFacilityInCard(facilityName2); facilityHome.verifyURLContains(facilityName2); facilityPage.visitAlreadyCreatedFacility(); facilityPage.scrollToFacilityTriage(); facilityPage.clickAddFacilityTriage(); manageUserPage.clickSubmit(); - userCreationPage.verifyErrorMessages(triageErrorMessage); + cy.verifyErrorMessages(triageErrorMessage); // create a entry and verify reflection facilityPage.fillEntryDate(triageDate); facilityPage.fillTriageEntryFields( @@ -115,9 +121,9 @@ describe("Facility Creation", () => { // create facility with multiple capacity and verify form error message for facility form facilityPage.visitCreateFacilityPage(); facilityPage.submitForm(); - userCreationPage.verifyErrorMessages(facilityErrorMessage); + cy.verifyErrorMessages(facilityErrorMessage); facilityPage.fillFacilityName(facilityName); - facilityPage.clickUpdateFacilityType("Primary Health Centres"); + facilityPage.selectFacilityType(facilityType); facilityPage.clickfacilityfeatureoption(); facilityFeature.forEach((featureText) => { cy.get("[role='option']").contains(featureText).click(); @@ -206,7 +212,7 @@ describe("Facility Creation", () => { it("Create a new facility with single bed and doctor capacity", () => { facilityPage.visitCreateFacilityPage(); facilityPage.fillFacilityName(facilityName); - facilityPage.clickUpdateFacilityType("Primary Health Centres"); + facilityPage.selectFacilityType(facilityType); facilityPage.fillPincode("682001"); facilityPage.selectStateOnPincode("Kerala"); facilityPage.selectDistrictOnPincode("Ernakulam"); @@ -236,17 +242,21 @@ describe("Facility Creation", () => { .contains(facilityNumber) .should("be.visible"); // verify the facility homepage - cy.visit("/facility"); - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.verifyURLContains(facilityName); }); it("Create a new facility with no bed and doctor capacity", () => { facilityPage.visitCreateFacilityPage(); facilityPage.fillFacilityName(facilityName); - facilityPage.clickUpdateFacilityType("Primary Health Centres"); + facilityPage.selectFacilityType(facilityType); facilityPage.fillPincode("682001"); facilityPage.selectStateOnPincode("Kerala"); facilityPage.selectDistrictOnPincode("Ernakulam"); @@ -258,12 +268,12 @@ describe("Facility Creation", () => { // add no bed capacity and verify form error message facilityPage.isVisibleselectBedType(); facilityPage.saveAndExitBedCapacityForm(); - userCreationPage.verifyErrorMessages(bedErrorMessage); + cy.verifyErrorMessages(bedErrorMessage); facilityPage.clickcancelbutton(); // add no doctor capacity and verify form error message facilityPage.isVisibleAreaOfSpecialization(); facilityPage.clickdoctorcapacityaddmore(); - userCreationPage.verifyErrorMessages(doctorErrorMessage); + cy.verifyErrorMessages(doctorErrorMessage); facilityPage.clickcancelbutton(); cy.url().then((newUrl) => { facilityUrl1 = newUrl; @@ -285,7 +295,7 @@ describe("Facility Creation", () => { facilityPage.visitUpdateFacilityPage(facilityUrl1); facilityPage.clickManageFacilityDropdown(); facilityPage.clickUpdateFacilityOption(); - facilityPage.clickUpdateFacilityType("Primary Health Centres"); + facilityPage.selectFacilityType(facilityType); facilityPage.fillAddress(facilityUpdateAddress); facilityPage.fillOxygenCapacity(oxygenCapacity); facilityPage.fillExpectedOxygenRequirement(oxygenExpected); @@ -316,6 +326,34 @@ describe("Facility Creation", () => { ); }); + it("Should display error when district admin tries to create facility in a different district", () => { + facilityPage.visitCreateFacilityPage(); + facilityPage.fillFacilityName(facilityName); + facilityPage.selectFacilityType(facilityType); + facilityPage.fillPincode("682001"); + facilityPage.selectStateOnPincode("Kerala"); + facilityPage.selectDistrictOnPincode("Kottayam"); + facilityPage.selectLocalBody("Arpookara"); + facilityPage.selectWard("5"); + facilityPage.fillAddress(facilityAddress); + facilityPage.fillPhoneNumber(facilityNumber); + facilityPage.submitForm(); + facilityPage.verifyErrorNotification( + "You do not have permission to perform this action.", + ); + }); + + it("Access Restriction for Non-Admin Users to facility creation page", () => { + nonAdminRoles.forEach((role) => { + loginPage.loginByRole(role); + cy.visit("/facility/create"); + facilityPage.verifyErrorNotification( + "You don't have permission to perform this action. Contact the admin", + ); + cy.clearCookies(); + }); + }); + afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/facility_spec/FacilityHomepage.cy.ts b/cypress/e2e/facility_spec/FacilityHomepage.cy.ts index e6caf645f7a..6f01baac714 100644 --- a/cypress/e2e/facility_spec/FacilityHomepage.cy.ts +++ b/cypress/e2e/facility_spec/FacilityHomepage.cy.ts @@ -1,19 +1,19 @@ // FacilityCreation +import { pageNavigation } from "pageobject/utils/paginationHelpers"; -import LoginPage from "../../pageobject/Login/LoginPage"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import FacilityHome from "../../pageobject/Facility/FacilityHome"; +import FacilityNotify from "../../pageobject/Facility/FacilityNotify"; +import LoginPage from "../../pageobject/Login/LoginPage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; -import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import { UserPage } from "../../pageobject/Users/UserSearch"; -import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; +import { advanceFilters } from "../../pageobject/utils/advanceFilterHelpers"; describe("Facility Homepage Function", () => { const loginPage = new LoginPage(); const facilityHome = new FacilityHome(); + const facilityNotify = new FacilityNotify(); const facilityPage = new FacilityPage(); const manageUserPage = new ManageUserPage(); - const userPage = new UserPage(); - const assetPagination = new AssetPagination(); const facilitiesAlias = "downloadFacilitiesCSV"; const doctorsAlias = "downloadDoctorsCSV"; const triagesAlias = "downloadTriagesCSV"; @@ -23,28 +23,32 @@ describe("Facility Homepage Function", () => { const district = "Ernakulam"; const localBody = "Aikaranad"; const facilityType = "Private Hospital"; + const notificationErrorMsg = "Message cannot be empty"; + const notificationMessage = "Test Notification"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); beforeEach(() => { cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); cy.awaitUrl("/facility"); }); it("Verify the Facility card button redirection", () => { // view cns button - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.clickViewCnsButton(); facilityHome.verifyCnsUrl(); facilityHome.navigateBack(); - // view notify button - facilityHome.clickFacilityNotifyButton(); - facilityHome.verifyAndCloseNotifyModal(); // view facility button facilityHome.clickViewFacilityDetails(); facilityPage.getFacilityName().should("be.visible"); @@ -60,34 +64,43 @@ describe("Facility Homepage Function", () => { }); it("Verify the functionality of advance filter", () => { - userPage.clickAdvancedFilters(); - facilityPage.selectState(stateName); - facilityPage.selectDistrict(district); - facilityPage.selectLocalBody(localBody); - facilityPage.clickUpdateFacilityType(facilityType); - userPage.applyFilter(); - facilityPage.verifyStateBadgeContent(stateName); - facilityPage.verifyDistrictBadgeContent(district); - facilityPage.verifyLocalBodyBadgeContent(localBody); - facilityPage.verifyFacilityTypeBadgeContent(facilityType); - manageUserPage.assertFacilityInCard(facilityName); - userPage.clearFilters(); - userPage.verifyDataTestIdNotVisible("State"); - userPage.verifyDataTestIdNotVisible("District"); - userPage.verifyDataTestIdNotVisible("Facility type"); - userPage.verifyDataTestIdNotVisible("Local Body"); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.selectState(stateName); + advanceFilters.selectDistrict(district); + advanceFilters.selectLocalBody(localBody); + advanceFilters.selectFacilityType(facilityType); + advanceFilters.applySelectedFilter(); + advanceFilters.verifyFilterBadgePresence("State", stateName, true); + advanceFilters.verifyFilterBadgePresence("District", district, true); + advanceFilters.verifyFilterBadgePresence( + "Facility type", + facilityType, + true, + ); + advanceFilters.verifyFilterBadgePresence("Local Body", localBody, true); + facilityHome.assertFacilityInCard(facilityName); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.clickClearAdvanceFilters(); + advanceFilters.verifyFilterBadgePresence("State", "", false); + advanceFilters.verifyFilterBadgePresence("District", "", false); + advanceFilters.verifyFilterBadgePresence("Facility type", "", false); + advanceFilters.verifyFilterBadgePresence("Local Body", "", false); }); it("Search a facility in homepage and pagination", () => { // pagination of the facility page - assetPagination.navigateToNextPage(); - assetPagination.verifyNextUrl(); - assetPagination.navigateToPreviousPage(); - assetPagination.verifyPreviousUrl(); + pageNavigation.navigateToNextPage(); + pageNavigation.verifyCurrentPageNumber(2); + pageNavigation.navigateToPreviousPage(); + pageNavigation.verifyCurrentPageNumber(1); // search for a facility - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.verifyURLContains(facilityName); }); @@ -115,15 +128,19 @@ describe("Facility Homepage Function", () => { }); it("Verify Facility Detail page redirection to CNS and Live Minitoring ", () => { - userPage.clickAdvancedFilters(); - facilityPage.selectState(stateName); - facilityPage.selectDistrict(district); - facilityPage.selectLocalBody(localBody); - userPage.applyFilter(); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.selectState(stateName); + advanceFilters.selectDistrict(district); + advanceFilters.selectLocalBody(localBody); + advanceFilters.applySelectedFilter(); // go to cns page in the facility details page - manageUserPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); - manageUserPage.assertFacilityInCard(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); facilityHome.clickViewFacilityDetails(); facilityHome.clickFacilityCnsButton(); facilityHome.verifyCnsUrl(); @@ -135,6 +152,55 @@ describe("Facility Homepage Function", () => { facilityHome.verifyLiveMonitorUrl(); }); + it("Verify Notice Board Functionality", () => { + // search facility and verify it's loaded or not + facilityHome.interceptFacilitySearchReq(); + facilityHome.typeFacilitySearch(facilityName); + facilityHome.verifyFacilitySearchReq(); + // verify facility name and card reflection + facilityNotify.verifyUrlContains("Dummy+Facility+40"); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); + facilityHome.assertFacilityInCard(facilityName); + // send notification to a facility + facilityHome.clickFacilityNotifyButton(); + facilityNotify.verifyFacilityName(facilityName); + facilityNotify.fillNotifyText(notificationMessage); + facilityNotify.interceptPostNotificationReq(); + cy.clickSubmitButton("Notify"); + facilityNotify.verifyPostNotificationReq(); + cy.verifyNotification("Facility Notified"); + cy.closeNotification(); + cy.wait(2000); + // Verify the frontend error on empty message + facilityHome.clickFacilityNotifyButton(); + facilityNotify.verifyFacilityName(facilityName); + cy.clickSubmitButton("Notify"); + facilityNotify.verifyErrorMessage(notificationErrorMsg); + // close pop-up and verify + cy.clickCancelButton("Cancel"); + // signout as district admin and login as a Nurse + loginPage.ensureLoggedIn(); + loginPage.clickSignOutBtn(); + loginPage.loginManuallyAsNurse(); + // Verify Notice Board Reflection + facilityNotify.interceptGetNotificationReq("MESSAGE"); + facilityNotify.visitNoticeBoard(); + facilityNotify.verifyGetNotificationReq(); + facilityNotify.verifyFacilityNoticeBoardMessage(notificationMessage); + facilityNotify.interceptGetNotificationReq(); + // Verify Sidebar Notification Reflection + facilityNotify.openNotificationSlide(); + facilityNotify.verifyGetNotificationReq(); + cy.verifyContentPresence("#notification-slide-msg", [notificationMessage]); + facilityNotify.closeNotificationSlide(); + loginPage.ensureLoggedIn(); + loginPage.clickSignOutBtn(); + }); + afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/facility_spec/FacilityInventory.cy.ts b/cypress/e2e/facility_spec/FacilityInventory.cy.ts index cdada75ee06..b3f77479763 100644 --- a/cypress/e2e/facility_spec/FacilityInventory.cy.ts +++ b/cypress/e2e/facility_spec/FacilityInventory.cy.ts @@ -1,6 +1,6 @@ import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import LoginPage from "../../pageobject/Login/LoginPage"; import FacilityHome from "../../pageobject/Facility/FacilityHome"; +import LoginPage from "../../pageobject/Login/LoginPage"; describe("Inventory Management Section", () => { const facilityPage = new FacilityPage(); @@ -9,7 +9,7 @@ describe("Inventory Management Section", () => { const inventoryName = "PPE"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/facility_spec/FacilityLocation.cy.ts b/cypress/e2e/facility_spec/FacilityLocation.cy.ts index d29ee95e873..1ae61e5ecb0 100644 --- a/cypress/e2e/facility_spec/FacilityLocation.cy.ts +++ b/cypress/e2e/facility_spec/FacilityLocation.cy.ts @@ -1,18 +1,19 @@ +import { AssetHome } from "pageobject/Asset/AssetHome"; +import LoginPage from "pageobject/Login/LoginPage"; +import { generatePhoneNumber } from "pageobject/utils/constants"; +import { pageNavigation } from "pageobject/utils/paginationHelpers"; +import { v4 as uuidv4 } from "uuid"; + import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import { UserCreationPage } from "../../pageobject/Users/UserCreation"; -import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import FacilityLocation from "../../pageobject/Facility/FacilityLocation"; -import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; import FacilityHome from "../../pageobject/Facility/FacilityHome"; -import { v4 as uuidv4 } from "uuid"; +import FacilityLocation from "../../pageobject/Facility/FacilityLocation"; describe("Location Management Section", () => { const assetPage = new AssetPage(); - const userCreationPage = new UserCreationPage(); - const facilityPage = new FacilityPage(); const facilityLocation = new FacilityLocation(); - const assetPagination = new AssetPagination(); const facilityHome = new FacilityHome(); + const assetHome = new AssetHome(); + const loginPage = new LoginPage(); const EXPECTED_LOCATION_ERROR_MESSAGES = [ "Name is required", @@ -22,30 +23,21 @@ describe("Location Management Section", () => { "Please enter a name", "Please select a bed type", ]; - const locationName = "Test-location"; - const locationNameTwo = "Test-location-2"; const locationDescription = "Test Description"; const locationType = "WARD"; const locationMiddleware = "dev_middleware.coronasafe.live"; - const locationModifiedName = "Test Modified location"; const locationModifiedDescription = "Test Modified Description"; const locationModifiedType = "ICU"; const locationModifiedMiddleware = "dev-middleware.coronasafe.live"; - const bedName = "Test-Bed"; const bedDescrption = "test description"; const bedType = "ICU"; const bedStatus = "Vacant"; - const bedModifiedName = "test modified bed"; const bedModifiedDescrption = "test modified description"; const bedModifiedType = "Isolation"; - const numberOfBeds = 10; - const numberOfModifiedBeds = 25; - const qr_id_1 = uuidv4(); - const phone_number = "9999999999"; - const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); + const phone_number = generatePhoneNumber(); before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -54,229 +46,226 @@ describe("Location Management Section", () => { cy.restoreLocalStorage(); cy.clearLocalStorage(/filters--.+/); cy.awaitUrl("/"); - facilityLocation.loadLocationManagementPage("Dummy Shifting Center"); }); - it("Add a Bed to facility location along with duplication and deleting a bed", () => { - // mandatory field verification in bed creation - cy.get("body").then(($body) => { - if ($body.find("#manage-bed-button:visible").length) { - // If the '#manage-bed-button' is visible - facilityLocation.clickManageBedButton(); - } else { - // If the '#manage-bed-button' is not visible - facilityLocation.clickAddNewLocationButton(); - facilityPage.fillFacilityName(locationName); - facilityLocation.selectLocationType(locationType); - assetPage.clickassetupdatebutton(); - facilityLocation.clickNotification(); - facilityLocation.clickManageBedButton(); - } + it("Delete location with linked assets", () => { + const locationName = `ICU-${uuidv4().substring(0, 2)}`; + const facilityName = "Dummy Facility 13"; + const assetName = "Test Asset linked to location"; + // Select a new facility + facilityLocation.navigateToFacilityLocationManagement(facilityName); + // Create a new location + facilityLocation.clickAddNewLocationButton(); + facilityLocation.fillLocationDetails( + locationName, + undefined, + locationType, + undefined, + ); + facilityLocation.clickAddLocationButton(); + facilityLocation.verifyAddLocationSuccessfulMesssage(); + // create asset and link it to location + assetHome.navigateToAssetsPage(); + assetPage.createAsset(); + assetPage.selectFacility(facilityName); + assetPage.selectLocation(locationName); + assetPage.enterAssetDetails({ + name: assetName, + workingStatus: "Working", + supportPhone: phone_number, }); - facilityLocation.clickAddBedButton(); - assetPage.clickassetupdatebutton(); - userCreationPage.verifyErrorMessages(EXPECTED_BED_ERROR_MESSAGES); - // create a new single bed and verify - facilityLocation.enterBedName(bedName); - facilityLocation.enterBedDescription(bedDescrption); - facilityLocation.selectBedType(bedType); - assetPage.clickassetupdatebutton(); - // Verify the bed creation - facilityLocation.verifyBedNameBadge(bedName); - facilityLocation.verifyBedBadge(bedType); - facilityLocation.verifyBedBadge(bedStatus); - // Try to create duplication bed and verify the error - facilityLocation.clickAddBedButton(); - facilityLocation.enterBedName(bedName); - facilityLocation.selectBedType(bedType); assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification( - "Name - Bed with same name already exists in location", + cy.verifyNotification("Asset created successfully"); + cy.closeNotification(); + // Select a new facility + facilityHome.navigateToFacilityHomepage(); + facilityLocation.navigateToFacilityLocationManagement(facilityName); + facilityLocation.clickDeleteLocation(locationName); + cy.clickSubmitButton("Confirm"); + cy.verifyNotification("Cannot delete a Location with associated Assets"); + cy.closeNotification(); + + // delete asset + facilityLocation.clickManageAssets(); + assetPage.openCreatedAsset(); + assetPage.deleteAsset(); + cy.verifyNotification("Asset deleted successfully"); + cy.closeNotification(); + + // delete location + facilityHome.navigateToFacilityHomepage(); + facilityLocation.navigateToFacilityLocationManagement(facilityName); + facilityLocation.clickDeleteLocation(locationName); + cy.clickSubmitButton("Confirm"); + cy.verifyNotification(`Location ${locationName} deleted successfully`); + cy.closeNotification(); + }); + + it("Delete location with linked beds", () => { + const locationName = `ICU-${uuidv4().substring(0, 2)}`; + const facilityName = "Dummy Facility 12"; + const bedName = `Bed-${uuidv4().substring(0, 2)}`; + // Select a new facility + facilityLocation.navigateToFacilityLocationManagement(facilityName); + // Create a new location with a bed + facilityLocation.clickAddNewLocationButton(); + facilityLocation.fillLocationDetails( + locationName, + undefined, + locationType, + undefined, ); - facilityHome.verifyAndCloseNotifyModal(); - // edit the created bed - facilityLocation.clickEditBedButton(); - facilityLocation.enterBedName(bedModifiedName); - facilityLocation.enterBedDescription(bedModifiedDescrption); - facilityLocation.selectBedType(bedModifiedType); - assetPage.clickassetupdatebutton(); - // verify the modification - facilityLocation.verifyBedNameBadge(bedModifiedName); - facilityLocation.verifyBedBadge(bedModifiedType); - facilityLocation.verifyBedBadge(bedStatus); - facilityLocation.closeNotification(); + facilityLocation.clickAddLocationButton(); + facilityLocation.verifyAddLocationSuccessfulMesssage(); + // Create a new bed to the location + facilityLocation.clickManageBedButton(locationName); + facilityLocation.clickAddBedButton(); + facilityLocation.fillBedForm(bedName, undefined, bedType, undefined); + facilityLocation.clickSubmitBedsButton(); + facilityLocation.verifyAddSingleBedSuccessfulMesssage(); + // Now try to delete the location with bed in it + facilityLocation.fetchAndNavigateToLocationPage(); + facilityLocation.clickDeleteLocation(locationName); + cy.clickSubmitButton("Confirm"); + cy.verifyNotification("Cannot delete a Location with associated Beds"); + cy.closeNotification(); + + // delete bed + facilityLocation.clickManageBedPopup(); + facilityLocation.deleteBedWithName(bedName); + cy.clickSubmitButton("Delete"); + cy.verifyNotification("Bed deleted successfully"); + cy.closeNotification(); + + // delete location + facilityLocation.fetchAndNavigateToLocationPage(); + facilityLocation.clickDeleteLocation(locationName); + cy.clickSubmitButton("Confirm"); + cy.verifyNotification(`Location ${locationName} deleted successfully`); + cy.closeNotification(); }); it("Adds Location to a facility and modify it", () => { + const locationName = `ICU-${uuidv4().substring(0, 2)}`; + const locationModifiedName = `ICU-${uuidv4().substring(0, 2)}}`; + const facilityName = "Dummy Facility 11"; + // Select a new facility + facilityLocation.navigateToFacilityLocationManagement(facilityName); // add a new location form mandatory error facilityLocation.clickAddNewLocationButton(); - assetPage.clickassetupdatebutton(); - userCreationPage.verifyErrorMessages(EXPECTED_LOCATION_ERROR_MESSAGES); + facilityLocation.clickAddLocationButton(); + cy.verifyErrorMessages(EXPECTED_LOCATION_ERROR_MESSAGES); // create a new location - facilityPage.fillFacilityName(locationNameTwo); - facilityLocation.fillDescription(locationDescription); - facilityLocation.selectLocationType(locationType); - facilityLocation.fillMiddlewareAddress(locationMiddleware); - assetPage.clickassetupdatebutton(); - facilityLocation.clickNotification(); + facilityLocation.fillLocationDetails( + locationName, + locationDescription, + locationType, + locationMiddleware, + ); + facilityLocation.clickAddLocationButton(); + facilityLocation.verifyAddLocationSuccessfulMesssage(); // verify the reflection - facilityLocation.verifyLocationName(locationNameTwo); + facilityLocation.verifyLocationName(locationName); facilityLocation.verifyLocationType(locationType); facilityLocation.verifyLocationDescription(locationDescription); facilityLocation.verifyLocationMiddleware(locationMiddleware); - // modify the existing data + // verify the duplicate location error message + facilityLocation.clickAddNewLocationButton(); + facilityLocation.fillLocationDetails( + locationName, + undefined, + locationType, + undefined, + ); + facilityLocation.clickAddLocationButton(); + cy.verifyNotification( + "Name - Asset location with this name and facility already exists.", + ); + cy.closeNotification(); + facilityLocation.closeAddLocationForm(); facilityLocation.clickEditLocationButton(); - facilityPage.fillFacilityName(locationModifiedName); - facilityLocation.fillDescription(locationModifiedDescription); - facilityLocation.selectLocationType(locationModifiedType); - facilityLocation.fillMiddlewareAddress(locationModifiedMiddleware); - assetPage.clickassetupdatebutton(); + facilityLocation.fillLocationDetails( + locationModifiedName, + locationModifiedDescription, + locationModifiedType, + locationModifiedMiddleware, + ); + facilityLocation.clickUpdateLocationButton(); + facilityLocation.verifyEditLocationSuccessfulMessage(); // verify the reflection facilityLocation.verifyLocationName(locationModifiedName); facilityLocation.verifyLocationType(locationModifiedType); facilityLocation.verifyLocationDescription(locationModifiedDescription); facilityLocation.verifyLocationMiddleware(locationModifiedMiddleware); - facilityLocation.closeNotification(); }); - it("Multiple Bed to a facility location and delete a bed", () => { - // create multiple bed and verify - facilityLocation.clickManageBedButton(); + it("Add single & Multiple Bed to facility location along with duplication and deleting a bed", () => { + const locationName = `ICU-${uuidv4().substring(0, 2)}`; + const facilityName = "Dummy Request Fulfilment Center"; + const bedName = `Bed-${uuidv4().substring(0, 2)}`; + const duplicateBedName = `Duplicate-${uuidv4().substring(0, 2)}`; + const multipleBedName = `Multi-${uuidv4().substring(0, 2)}}`; + const numberOfBeds = 25; + // Select a new facility + facilityLocation.navigateToFacilityLocationManagement(facilityName); + // Create a new location and Bed into it + facilityLocation.clickAddNewLocationButton(); + facilityLocation.fillLocationDetails( + locationName, + undefined, + locationType, + undefined, + ); + facilityLocation.clickAddLocationButton(); + facilityLocation.verifyAddLocationSuccessfulMesssage(); + // Verify the error message of beds creation form + facilityLocation.clickManageBedButton(locationName); facilityLocation.clickAddBedButton(); - facilityLocation.enterBedName(bedName); - facilityLocation.enterBedDescription(bedDescrption); - facilityLocation.selectBedType(bedType); - facilityLocation.setMultipleBeds(numberOfBeds); - assetPage.clickassetupdatebutton(); - facilityLocation.clickNotification(); - // verify the bed creation + facilityLocation.clickSubmitBedsButton(); + cy.verifyErrorMessages(EXPECTED_BED_ERROR_MESSAGES); + // Add a new bed to the location + facilityLocation.fillBedForm(bedName, bedDescrption, bedType, undefined); + facilityLocation.clickSubmitBedsButton(); + facilityLocation.verifyAddSingleBedSuccessfulMesssage(); + // Verify the bed creation + facilityLocation.verifyBedNameBadge(bedName); facilityLocation.verifyBedBadge(bedType); facilityLocation.verifyBedBadge(bedStatus); - facilityLocation.verifyIndividualBedName(bedName, numberOfBeds); - // delete a bed and verify it - facilityLocation.deleteFirstBed(); - facilityLocation.deleteBedRequest(); - assetPage.clickassetupdatebutton(); - facilityLocation.deleteBedRequest(); - facilityLocation.closeNotification(); - }); - - it("Add Multiple Bed to a facility location and verify pagination", () => { - // bed creation - facilityLocation.clickManageBedButton(); + // Try to create duplication bed and verify the error facilityLocation.clickAddBedButton(); - facilityLocation.enterBedName(bedModifiedName); - facilityLocation.enterBedDescription(bedModifiedDescrption); - facilityLocation.selectBedType(bedModifiedType); - facilityLocation.setMultipleBeds(numberOfModifiedBeds); - assetPage.clickassetupdatebutton(); - // pagination - assetPagination.navigateToNextPage(); - assetPagination.navigateToPreviousPage(); - facilityLocation.closeNotification(); - }); - - it("Delete location", () => { - facilityLocation.clickAddNewLocationButton(); - facilityLocation.enterLocationName("Test Location"); - facilityLocation.selectLocationType("OTHER"); - assetPage.clickassetupdatebutton(); - facilityLocation.deleteLocation("Test Location"); - assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification( - "Location Test Location deleted successfully", + facilityLocation.fillBedForm(bedName, undefined, bedType, undefined); + facilityLocation.clickSubmitBedsButton(); + cy.verifyNotification( + "Name - Bed with same name already exists in location", ); - facilityLocation.closeNotification(); - }); - - it("Delete location with linked beds", () => { - facilityLocation.clickAddNewLocationButton(); - facilityLocation.enterLocationName("Test Location with Beds"); - facilityLocation.selectLocationType("OTHER"); - cy.submitButton("Add Location"); - cy.verifyNotification("Location created successfully"); cy.closeNotification(); - facilityLocation.clickManageBedButton(); - facilityLocation.clickAddBedButton(); - facilityLocation.enterBedName("Bed 1"); - facilityLocation.selectBedType("Regular"); - cy.submitButton("Add Bed(s)"); - cy.verifyNotification("1 Bed created successfully"); - cy.closeNotification(); - facilityLocation.loadLocationManagementPage("Dummy Shifting Center"); - facilityLocation.deleteLocation("Test Location with Beds"); - assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification( - "Cannot delete a Location with associated Beds", - ); - facilityLocation.closeNotification(); - - // delete bed - facilityLocation.clickManageBeds(); - facilityLocation.deleteFirstBed(); - assetPage.clickassetupdatebutton(); - facilityLocation.closeNotification(); - - // delete location - facilityLocation.loadLocationManagementPage("Dummy Shifting Center"); - facilityLocation.deleteLocation("Test Location with Beds"); - assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification( - "Location Test Location with Beds deleted successfully", - ); - facilityLocation.closeNotification(); - }); - - it("Delete location with linked assets", () => { - facilityLocation.clickAddNewLocationButton(); - facilityLocation.enterLocationName("Test Location with linked Assets"); - facilityLocation.selectLocationType("OTHER"); - assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification("Location created successfully"); - facilityLocation.closeNotification(); - // create asset and link it to location - cy.awaitUrl("/assets"); - assetPage.createAsset(); - assetPage.selectFacility("Dummy Shifting Center"); - assetPage.selectLocation("Test Location with linked Assets"); - assetPage.enterAssetDetails( - "Test Asset linked to Facility", - "Test Description", - "Working", - qr_id_1, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!", + facilityLocation.closeAddLocationForm(); + // edit the newly created existing bed + facilityLocation.clickEditBedButton(bedName); + facilityLocation.fillBedForm( + duplicateBedName, + bedModifiedDescrption, + bedModifiedType, + undefined, ); - assetPage.clickassetupdatebutton(); - facilityLocation.loadLocationManagementPage("Dummy Shifting Center"); - facilityLocation.deleteLocation("Test Location with linked Assets"); - assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification( - "Cannot delete a Location with associated Assets", - ); - facilityLocation.closeNotification(); - - // delete asset - facilityLocation.clickManageAssets(); - assetPage.openCreatedAsset(); - assetPage.deleteAsset(); - facilityLocation.closeNotification(); - - // delete location - facilityLocation.loadLocationManagementPage("Dummy Shifting Center"); - facilityLocation.deleteLocation("Test Location with linked Assets"); - assetPage.clickassetupdatebutton(); - facilityLocation.verifyNotification( - "Location Test Location with linked Assets deleted successfully", + facilityLocation.clickUpdateBedButton(); + facilityLocation.verifyEditBedSuccessfulMessage(); + // verify the modification + facilityLocation.verifyBedNameBadge(duplicateBedName); + facilityLocation.verifyBedBadge(bedModifiedType); + facilityLocation.verifyBedBadge(bedStatus); + // Create Multiple Bed + facilityLocation.clickAddBedButton(); + facilityLocation.fillBedForm( + multipleBedName, + bedDescrption, + bedType, + numberOfBeds, ); - facilityLocation.closeNotification(); + facilityLocation.clickSubmitBedsButton(); + // Verify Pagination in the page + pageNavigation.navigateToNextPage(); + pageNavigation.navigateToPreviousPage(); }); afterEach(() => { diff --git a/cypress/e2e/facility_spec/FacilityManage.cy.ts b/cypress/e2e/facility_spec/FacilityManage.cy.ts index 1f0d2b66108..9f1523768c1 100644 --- a/cypress/e2e/facility_spec/FacilityManage.cy.ts +++ b/cypress/e2e/facility_spec/FacilityManage.cy.ts @@ -1,12 +1,15 @@ -import LoginPage from "../../pageobject/Login/LoginPage"; -import FacilityManage from "../../pageobject/Facility/FacilityManage"; +import FacilityHome from "pageobject/Facility/FacilityHome"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import { v4 as uuidv4 } from "uuid"; +import FacilityManage from "../../pageobject/Facility/FacilityManage"; +import LoginPage from "../../pageobject/Login/LoginPage"; describe("Facility Manage Functions", () => { const loginPage = new LoginPage(); const facilityManage = new FacilityManage(); const facilityPage = new FacilityPage(); + const facilityHome = new FacilityHome(); const facilityName = "Dummy Facility 40"; const facilityMiddlewareUpdateButton = "Update"; const facilityMiddleware = "dev-middleware.coronasafe.live"; @@ -17,7 +20,7 @@ describe("Facility Manage Functions", () => { const facilityHfridToastNotificationText = /Health Facility config updated successfully|Health ID registration failed/; const facilityHfrId = "IN180000018"; - const facilityUpdatedHfrId = uuidv4(); + const facilityUpdatedHfrId = "IN180000020"; const doctorCapacity = "5"; const doctorModifiedCapacity = "7"; const totalCapacity = "100"; @@ -26,7 +29,7 @@ describe("Facility Manage Functions", () => { const currentUpdatedOccupied = "100"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -35,8 +38,12 @@ describe("Facility Manage Functions", () => { cy.restoreLocalStorage(); cy.clearLocalStorage(/filters--.+/); cy.awaitUrl("/"); - facilityPage.typeFacilitySearch(facilityName); - facilityPage.verifyFacilityBadgeContent(facilityName); + facilityHome.typeFacilitySearch(facilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + facilityName, + true, + ); facilityPage.visitAlreadyCreatedFacility(); }); diff --git a/cypress/e2e/hcx_spec/HcxClaims.cy.ts b/cypress/e2e/hcx_spec/HcxClaims.cy.ts new file mode 100644 index 00000000000..ccaa628febb --- /dev/null +++ b/cypress/e2e/hcx_spec/HcxClaims.cy.ts @@ -0,0 +1,99 @@ +import { HcxClaims } from "pageobject/Hcx/HcxClaims"; +import { PatientConsultationPage } from "pageobject/Patient/PatientConsultation"; +import PatientInsurance from "pageobject/Patient/PatientInsurance"; + +import LoginPage from "../../pageobject/Login/LoginPage"; +import { PatientPage } from "../../pageobject/Patient/PatientCreation"; + +describe("HCX Claims configuration and approval workflow", () => { + const loginPage = new LoginPage(); + const patientPage = new PatientPage(); + const patientConsultationPage = new PatientConsultationPage(); + const patientInsurance = new PatientInsurance(); + const hcxClaims = new HcxClaims(); + const hcxPatientName = "Dummy Patient Thirteen"; + const firstInsuranceIdentifier = "insurance-details-0"; + const patientMemberId = "001"; + const patientPolicyId = "100"; + const patientInsurerName = "Demo Payor"; + + before(() => { + loginPage.loginByRole("districtAdmin"); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + cy.awaitUrl("/patients"); + }); + + it("Verify the HCX Workflow for a patient with mocked eligibility", () => { + // Modify the insurance for a facility + patientPage.visitPatient(hcxPatientName); + patientConsultationPage.clickPatientDetails(); + patientPage.clickPatientUpdateDetails(); + patientInsurance.clickAddInsruanceDetails(); + patientInsurance.typePatientInsuranceDetail( + firstInsuranceIdentifier, + "subscriber_id", + patientMemberId, + ); + patientInsurance.typePatientInsuranceDetail( + firstInsuranceIdentifier, + "policy_id", + patientPolicyId, + ); + patientInsurance.selectPatientInsurerName( + firstInsuranceIdentifier, + patientInsurerName, + ); + cy.clickSubmitButton("Save Details"); + cy.verifyNotification("Patient updated successfully"); + cy.closeNotification(); + // Navigate to Consultation View and capture dynamic consultation ID + let consultationId: string; + patientConsultationPage.clickViewConsultationButton(); + cy.url().then((url) => { + const urlRegex = + /facility\/([^/]+)\/patient\/([^/]+)\/consultation\/([^/]+)/; + const match = url.match(urlRegex); + if (match) { + consultationId = match[3]; + } + }); + // Intercept and mock the eligibility check response using captured consultationId + cy.intercept("POST", "/api/hcx/check_eligibility", (req) => { + req.reply({ + statusCode: 200, + body: { + api_call_id: "bfa228f0-cdfa-4426-bebe-26e996079dbb", + correlation_id: "86ae030c-1b33-4e52-a6f1-7a74a48111eb", + timestamp: Date.now(), + consultation: consultationId, + policy: patientPolicyId, + outcome: "Complete", + limit: 1, + }, + }); + }).as("checkEligibility"); + // Raise a HCX Pre-auth + patientConsultationPage.clickManagePatientButton(); + patientConsultationPage.clickClaimsButton(); + cy.verifyAndClickElement("#edit-insurance-policy", "Edit Insurance Policy"); + cy.clickCancelButton(); + hcxClaims.selectEligiblePolicy(patientInsurerName); + hcxClaims.verifyPolicyEligibility(); + cy.verifyNotification("Checking Policy Eligibility"); + cy.closeNotification(); + // Confirm that the eligibility check displays as successful + cy.wait("@checkEligibility").then((interception) => { + const response = interception.response.body; + expect(response.outcome).to.equal("Complete"); + }); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/homepage_spec/UserLogin.cy.ts b/cypress/e2e/homepage_spec/UserLogin.cy.ts new file mode 100644 index 00000000000..ab00bd80ff1 --- /dev/null +++ b/cypress/e2e/homepage_spec/UserLogin.cy.ts @@ -0,0 +1,48 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); +const userName = "dummy_user_1"; +const forgotPasswordHeading = "Forgot password?"; + +describe("User login workflow with correct and incorrect passwords", () => { + beforeEach(() => { + cy.awaitUrl("/", true); + }); + + it("Log in as admin with correct password", () => { + loginPage.loginManuallyAsDistrictAdmin(); + loginPage.interceptFacilityReq(); + loginPage.verifyFacilityReq(); + loginPage.ensureLoggedIn(); + loginPage.clickSignOutBtn(); + loginPage.verifyLoginPageUrl(); + }); + + it("Display an error when logging in as admin with incorrect password", () => { + loginPage.interceptLoginReq(); + loginPage.loginManuallyAsDistrictAdmin(false); + loginPage.verifyLoginReq(); + cy.verifyNotification("No active account found with the given credentials"); + cy.closeNotification(); + }); +}); + +describe("Reset user's password using email", () => { + beforeEach(() => { + cy.awaitUrl("/", true); + }); + + it("Send a password reset link and navigate back to the login page", () => { + loginPage.clickForgotPasswordButton(forgotPasswordHeading); + loginPage.verifyForgotPasswordHeading([forgotPasswordHeading]); + loginPage.fillUserNameInForgotPasswordForm(userName); + loginPage.interceptResetLinkReq(); + loginPage.clickSendResetLinkBtn(); + loginPage.verifyResetLinkReq(); + cy.verifyNotification("Password Reset Email Sent"); + cy.closeNotification(); + loginPage.clickBackButton(); + loginPage.verifyLoginPageUrl(); + loginPage.verifyLoginButtonPresence(); + }); +}); diff --git a/cypress/e2e/auth_spec/redirect.cy.ts b/cypress/e2e/homepage_spec/redirect.cy.ts similarity index 100% rename from cypress/e2e/auth_spec/redirect.cy.ts rename to cypress/e2e/homepage_spec/redirect.cy.ts diff --git a/cypress/e2e/patient_spec/PatientBedManagement.cy.ts b/cypress/e2e/patient_spec/PatientBedManagement.cy.ts index 84ef2f4800e..fbc31ff9698 100644 --- a/cypress/e2e/patient_spec/PatientBedManagement.cy.ts +++ b/cypress/e2e/patient_spec/PatientBedManagement.cy.ts @@ -1,7 +1,7 @@ import LoginPage from "../../pageobject/Login/LoginPage"; +import { PatientConsultationPage } from "../../pageobject/Patient/PatientConsultation"; import { PatientPage } from "../../pageobject/Patient/PatientCreation"; import PatientLogupdate from "../../pageobject/Patient/PatientLogupdate"; -import { PatientConsultationPage } from "../../pageobject/Patient/PatientConsultation"; describe("Patient swtich bed functionality", () => { const loginPage = new LoginPage(); @@ -11,11 +11,11 @@ describe("Patient swtich bed functionality", () => { const switchBedOne = "Dummy Bed 4"; const switchBedTwo = "Dummy Bed 1"; const switchBedThree = "Dummy Bed 7"; - const switchPatientOne = "Dummy Patient 6"; - const switchPatientTwo = "Dummy Patient 7"; + const switchPatientOne = "Dummy Patient Six"; + const switchPatientTwo = "Dummy Patient Seven"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts b/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts index ee38b24d746..4191d63b3e2 100644 --- a/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts +++ b/cypress/e2e/patient_spec/PatientConsultationCreation.cy.ts @@ -1,12 +1,12 @@ import LoginPage from "../../pageobject/Login/LoginPage"; -import { PatientPage } from "../../pageobject/Patient/PatientCreation"; import { PatientConsultationPage } from "../../pageobject/Patient/PatientConsultation"; -import PatientPredefined from "../../pageobject/Patient/PatientPredefined"; -import ShiftCreation from "../../pageobject/Shift/ShiftCreation"; -import PatientInvestigation from "../../pageobject/Patient/PatientInvestigation"; -import PatientTreatmentPlan from "../../pageobject/Patient/PatientTreatmentPlan"; +import { PatientPage } from "../../pageobject/Patient/PatientCreation"; import PatientDeathReport from "../../pageobject/Patient/PatientDeathReport"; +import PatientInvestigation from "../../pageobject/Patient/PatientInvestigation"; +import PatientPredefined from "../../pageobject/Patient/PatientPredefined"; import PatientPrescription from "../../pageobject/Patient/PatientPrescription"; +import PatientTreatmentPlan from "../../pageobject/Patient/PatientTreatmentPlan"; +import ShiftCreation from "../../pageobject/Shift/ShiftCreation"; describe("Patient Consultation in multiple combination", () => { const patientConsultationPage = new PatientConsultationPage(); @@ -38,7 +38,7 @@ describe("Patient Consultation in multiple combination", () => { const patientIpNumber = `${Math.floor(Math.random() * 90 + 10)}/${Math.floor(Math.random() * 9000 + 1000)}`; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -91,11 +91,11 @@ describe("Patient Consultation in multiple combination", () => { patientTreatmentPlan.typePatientGeneralInstruction(generalInstruction); patientTreatmentPlan.typeSpecialInstruction(specialInstruction); patientTreatmentPlan.fillTreatingPhysican(doctorName); - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); // the above submit should fail as IP number is missing patientConsultationPage.typePatientNumber(patientIpNumber); patientConsultationPage.selectBed("Dummy Bed 6"); - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); cy.verifyNotification("Consultation created successfully"); // Below code for the prescription module only present while creating a new consultation patientPrescription.clickAddPrescription(); @@ -104,7 +104,7 @@ describe("Patient Consultation in multiple combination", () => { patientPrescription.selectMedicine(medicineOne); patientPrescription.enterDosage("3"); patientPrescription.selectDosageFrequency("Twice daily"); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.wait(2000); cy.verifyNotification("Medicine prescribed"); patientPrescription.clickReturnToDashboard(); @@ -189,7 +189,7 @@ describe("Patient Consultation in multiple combination", () => { "#encounter_date", "220220241230", ); - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); cy.verifyNotification( "Create Diagnoses - Atleast one diagnosis is required", ); @@ -198,7 +198,7 @@ describe("Patient Consultation in multiple combination", () => { diagnosis4, "add-icd11-diagnosis-as-confirmed", ); - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); cy.verifyNotification("Consultation created successfully"); // verify the data and death report patientConsultationPage.verifyTextInConsultation( @@ -215,7 +215,7 @@ describe("Patient Consultation in multiple combination", () => { "#cause_of_death", "Cause of Death", ); - cy.submitButton("Preview"); + cy.clickSubmitButton("Preview"); cy.preventPrint(); patientDeathReport.clickPrintDeathReport(); cy.get("@verifyPrevent").should("be.called"); @@ -261,7 +261,7 @@ describe("Patient Consultation in multiple combination", () => { // add telemedicine patientTreatmentPlan.clickTelemedicineCheckbox(); patientTreatmentPlan.assignTelemedicineDoctor(doctorName); - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); cy.verifyNotification("Consultation created successfully"); // verify the data reflection - patientConsultationPage.verifyTextInConsultation( @@ -312,7 +312,7 @@ describe("Patient Consultation in multiple combination", () => { patientTreatmentPlan.typePatientGeneralInstruction(generalInstruction); // no review after and no action patientTreatmentPlan.fillTreatingPhysican(doctorName); - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); cy.verifyNotification("Patient discharged successfully"); // verify the Discharge Reason, Diagnosis, treatment physican patientConsultationPage.verifyTextInConsultation( @@ -364,18 +364,18 @@ describe("Patient Consultation in multiple combination", () => { patientTreatmentPlan.typePatientGeneralInstruction(generalInstruction); patientTreatmentPlan.fillTreatingPhysican(doctorName); // no review after and no action - cy.submitButton("Create Consultation"); + cy.clickSubmitButton("Create Consultation"); // Create a shifting request cy.closeNotification(); shiftCreation.typeCurrentFacilityPerson("Current Facility Person"); shiftCreation.typeCurrentFacilityPhone("9999999999"); shiftCreation.typeShiftReason("reason for shift"); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Shift request created successfully"); }); it("Edit created consultation to existing patient", () => { - patientPage.visitPatient("Dummy Patient 13"); + patientPage.visitPatient("Dummy Patient Thirteen"); patientConsultationPage.clickEditConsultationButton(); patientConsultationPage.typePatientIllnessHistory("editted"); patientConsultationPage.selectPatientDiagnosis( @@ -386,7 +386,7 @@ describe("Patient Consultation in multiple combination", () => { cy.get("#condition-verification-status-menu").click(); cy.get("#add-icd11-diagnosis-as-entered-in-error").click(); }); - cy.submitButton("Update Consultation"); + cy.clickSubmitButton("Update Consultation"); cy.verifyNotification("Consultation updated successfully"); cy.get("#diagnoses-view").should("not.contain.text", diagnosis5); patientConsultationPage.verifyTextInConsultation( diff --git a/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts b/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts index e2403fd56bd..b7ef6936804 100644 --- a/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts +++ b/cypress/e2e/patient_spec/PatientConsultationDischarge.cy.ts @@ -20,7 +20,7 @@ describe("Patient Discharge based on multiple reason", () => { const doctorName = "Custom Doctor"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -31,11 +31,11 @@ describe("Patient Discharge based on multiple reason", () => { }); it("Discharge a LAMA patient in the consultation", () => { - patientPage.visitPatient("Dummy Patient 12"); + patientPage.visitPatient("Discharge Patient One"); patientDischarge.clickDischarge(); patientDischarge.selectDischargeReason(patientDischargeReason4); - cy.submitButton("Confirm Discharge"); - cy.submitButton("Acknowledge & Submit"); + cy.clickSubmitButton("Confirm Discharge"); + cy.clickSubmitButton("Acknowledge & Submit"); cy.verifyNotification("Patient Discharged Successfully"); cy.closeNotification(); // Verify the consultation dashboard reflection @@ -47,13 +47,13 @@ describe("Patient Discharge based on multiple reason", () => { }); it("Discharge a expired patient in the consultation", () => { - patientPage.visitPatient("Dummy Patient 13"); + patientPage.visitPatient("Discharge Patient Two"); patientDischarge.clickDischarge(); patientDischarge.selectDischargeReason(patientDischargeReason3); patientDischarge.typeDischargeNote(patientDeathCause); patientDischarge.typeDoctorName(doctorName); - cy.submitButton("Confirm Discharge"); - cy.submitButton("Acknowledge & Submit"); + cy.clickSubmitButton("Confirm Discharge"); + cy.clickSubmitButton("Acknowledge & Submit"); cy.verifyNotification("Patient Discharged Successfully"); cy.closeNotification(); // Verify the consultation dashboard reflection @@ -67,7 +67,7 @@ describe("Patient Discharge based on multiple reason", () => { }); it("Discharge patient with referred reason to a facility", () => { - patientPage.visitPatient("Dummy Patient 16"); + patientPage.visitPatient("Discharge Patient Three"); patientDischarge.clickDischarge(); patientDischarge.selectDischargeReason(patientDischargeReason2); patientDischarge.typeDischargeNote(patientDischargeAdvice); @@ -77,8 +77,8 @@ describe("Patient Discharge based on multiple reason", () => { // select a non-registered facility and perform the discharge patientDischarge.typeReferringFacility(referringFreetextFacility); cy.wait(2000); - cy.submitButton("Confirm Discharge"); - cy.submitButton("Acknowledge & Submit"); + cy.clickSubmitButton("Confirm Discharge"); + cy.clickSubmitButton("Acknowledge & Submit"); cy.wait(2000); cy.verifyNotification("Patient Discharged Successfully"); cy.closeNotification(); @@ -93,7 +93,7 @@ describe("Patient Discharge based on multiple reason", () => { }); it("Discharge a recovered patient with all relevant fields", () => { - patientPage.visitPatient("Dummy Patient 15"); + patientPage.visitPatient("Discharge Patient Four"); patientDischarge.clickDischarge(); patientDischarge.selectDischargeReason(patientDischargeReason1); patientDischarge.typeDischargeNote(patientDischargeAdvice); @@ -104,13 +104,13 @@ describe("Patient Discharge based on multiple reason", () => { patientPrescription.selectMedicine(patientMedicine); patientPrescription.enterDosage("4"); patientPrescription.selectDosageFrequency("Twice daily"); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.wait(2000); cy.closeNotification(); // submit the discharge pop-up - cy.submitButton("Confirm Discharge"); - cy.submitButton("Acknowledge & Submit"); + cy.clickSubmitButton("Confirm Discharge"); + cy.clickSubmitButton("Acknowledge & Submit"); cy.wait(2000); cy.verifyNotification("Patient Discharged Successfully"); cy.closeNotification(); diff --git a/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts b/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts index 9197cac2d90..9dd43da4e13 100644 --- a/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts +++ b/cypress/e2e/patient_spec/PatientDoctorConnect.cy.ts @@ -1,4 +1,5 @@ import { DoctorConnect } from "pageobject/Patient/PatientDoctorConnect"; + import LoginPage from "../../pageobject/Login/LoginPage"; import { PatientPage } from "../../pageobject/Patient/PatientCreation"; @@ -6,13 +7,13 @@ describe("Patient Doctor Connect in consultation page", () => { const loginPage = new LoginPage(); const patientPage = new PatientPage(); const doctorconnect = new DoctorConnect(); - const patientName = "Dummy Patient 11"; + const patientName = "Dummy Patient Eleven"; const doctorUser = "Dev Doctor"; const nurseUser = "Dev Staff"; - const teleIcuUser = "Dev Doctor Two"; + const teleIcuUser = "Tester Doctor"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts b/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts index e35d3eb8961..4fe19329af1 100644 --- a/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts +++ b/cypress/e2e/patient_spec/PatientDoctorNotes.cy.ts @@ -6,7 +6,7 @@ describe("Patient Discussion notes in the consultation page", () => { const loginPage = new LoginPage(); const patientPage = new PatientPage(); const patientDoctorNotes = new PatientDoctorNotes(); - const patientName = "Dummy Patient 4"; + const patientName = "Dummy Patient Four"; const patientNurseNote = "Test nurse Notes"; const patientNurseReplyNote = "Test nurse reply Notes"; const discussionNotesSubscribeWarning = @@ -14,7 +14,7 @@ describe("Patient Discussion notes in the consultation page", () => { const discussionNotesSuccessMessage = "Note added successfully"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/patient_spec/PatientFileUpload.ts b/cypress/e2e/patient_spec/PatientFileUpload.cy.ts similarity index 92% rename from cypress/e2e/patient_spec/PatientFileUpload.ts rename to cypress/e2e/patient_spec/PatientFileUpload.cy.ts index cc94943fd6f..ebf85d2cfad 100644 --- a/cypress/e2e/patient_spec/PatientFileUpload.ts +++ b/cypress/e2e/patient_spec/PatientFileUpload.cy.ts @@ -1,6 +1,7 @@ import LoginPage from "../../pageobject/Login/LoginPage"; import { PatientPage } from "../../pageobject/Patient/PatientCreation"; import { PatientFileUpload } from "../../pageobject/Patient/PatientFileupload"; + const loginPage = new LoginPage(); const patientPage = new PatientPage(); const patientFileUpload = new PatientFileUpload(); @@ -13,11 +14,11 @@ function runTests( const cypressAudioName = "cypress audio"; const cypressFileName = "cypress name"; const newFileName = "cypress modified name"; - const patientNameOne = "Dummy Patient 3"; - const patientNameTwo = "Dummy Patient 4"; - const patientNameThree = "Dummy Patient 5"; + const patientNameOne = "Dummy Patient Three"; + const patientNameTwo = "Dummy Patient Four"; + const patientNameThree = "Dummy Patient Five"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -62,7 +63,7 @@ function runTests( it("User-level Based Permission for File Modification", () => { // Login as Nurse 1 - loginPage.login("dummynurse1", "Coronasafe@123"); + loginPage.loginByRole("nurse"); cy.reload(); // Visit the patient details page patientPage.visitPatient(patientNameThree); @@ -84,13 +85,13 @@ function runTests( cy.closeNotification(); patientFileUpload.verifyUploadFilePresence(newFileName); // Login as Nurse 2 - loginPage.login("dummynurse2", "Coronasafe@123"); + loginPage.loginByRole("nurse2"); cy.reload(); // Verify the file edit option is not available patientFileUpload.verifyUploadFilePresence(newFileName); patientFileUpload.verifyFileRenameOption(false); // Login as District Admin - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.reload(); // Verify the file edit option is available patientFileUpload.verifyUploadFilePresence(newFileName); diff --git a/cypress/e2e/patient_spec/PatientHomepage.cy.ts b/cypress/e2e/patient_spec/PatientHomepage.cy.ts index 32d869b8f50..a120e282a2d 100644 --- a/cypress/e2e/patient_spec/PatientHomepage.cy.ts +++ b/cypress/e2e/patient_spec/PatientHomepage.cy.ts @@ -1,3 +1,6 @@ +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; +import { pageNavigation } from "pageobject/utils/paginationHelpers"; + import LoginPage from "../../pageobject/Login/LoginPage"; import PatientHome from "../../pageobject/Patient/PatientHome"; @@ -24,7 +27,7 @@ describe("Patient Homepage present functionalities", () => { const patientToDateBadge = "2023-12-07"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -35,7 +38,7 @@ describe("Patient Homepage present functionalities", () => { }); it("Date based advance filters applied in the patient tab", () => { - patientHome.clickPatientAdvanceFilters(); + advanceFilters.clickAdvancedFiltersButton(); patientHome.typePatientCreatedBeforeDate(patientFromDate); patientHome.typePatientCreatedAfterDate(patientToDate); patientHome.typePatientModifiedBeforeDate(patientFromDate); @@ -43,7 +46,6 @@ describe("Patient Homepage present functionalities", () => { patientHome.typePatientAdmitedBeforeDate(patientFromDate); patientHome.typePatientAdmitedAfterDate(patientToDate); patientHome.clickPatientFilterApply(); - patientHome.verifyTotalPatientCount("1"); // verify the badge and clear the count patientHome.verifyPatientCreatedBeforeDate(patientToDateBadge); patientHome.verifyPatientCreatedAfterDate(patientFromDateBadge); @@ -56,7 +58,7 @@ describe("Patient Homepage present functionalities", () => { }); it("Facility Geography based advance filters applied in the patient tab", () => { - patientHome.clickPatientAdvanceFilters(); + advanceFilters.clickAdvancedFiltersButton(); patientHome.typeFacilityName(facilityName); patientHome.selectFacilityType(facilityType); patientHome.typeFacilityLsgBody(facilityLsgBody); @@ -74,7 +76,7 @@ describe("Patient Homepage present functionalities", () => { it("Patient diagnosis based advance filters applied in the patient tab", () => { // Patient Filtering based on icd-11 data - patientHome.clickPatientAdvanceFilters(); + advanceFilters.clickAdvancedFiltersButton(); patientHome.selectAnyIcdDiagnosis(patientIcdDiagnosis, patientIcdDiagnosis); patientHome.selectConfirmedIcdDiagnosis( patientIcdDiagnosis, @@ -104,7 +106,7 @@ describe("Patient Homepage present functionalities", () => { cy.clearAllFilters(); patientHome.verifyTotalPatientCount("1"); // Apply Any and confirmed diagonsis to verify patient count 17 - patientHome.clickPatientAdvanceFilters(); + advanceFilters.clickAdvancedFiltersButton(); patientHome.selectAnyIcdDiagnosis(patientIcdDiagnosis, patientIcdDiagnosis); patientHome.selectConfirmedIcdDiagnosis( patientIcdDiagnosis, @@ -116,7 +118,7 @@ describe("Patient Homepage present functionalities", () => { it("Patient Details based advance filters applied in the patient tab", () => { // Patient Filtering based on patient details - patientHome.clickPatientAdvanceFilters(); + advanceFilters.clickAdvancedFiltersButton(); patientHome.selectPatientGenderfilter(patientGender); patientHome.selectPatientCategoryfilter(patientCategory); patientHome.typePatientMinimumAgeFilter(patientMinimumAge); @@ -128,7 +130,6 @@ describe("Patient Homepage present functionalities", () => { patientHome.selectPatientMedicoFilter(patientMedicoStatus); patientHome.clickPatientFilterApply(); cy.get("a[data-cy='patient']").should("contain.text", "Dummy Patient"); - patientHome.verifyTotalPatientCount("1"); // Verify the presence of badges patientHome.verifyGenderBadgeContent(patientGender); patientHome.verifyCategoryBadgeContent(patientCategory); @@ -156,22 +157,23 @@ describe("Patient Homepage present functionalities", () => { patientHome.verifyPatientExportRequest(); }); - it("Verify the functionality of the patient tab pagination", () => { + it("Test Pagination on Patient List Page", () => { let firstPatientPageOne: string; cy.get('[data-cy="patient"]') .first() .invoke("text") .then((patientOne: string) => { firstPatientPageOne = patientOne.trim(); - patientHome.clickNextPage(); - patientHome.verifySecondPageUrl(); + pageNavigation.navigateToNextPage(); + cy.wait(2000); + pageNavigation.verifyCurrentPageNumber(2); cy.get('[data-cy="patient"]') .first() .invoke("text") .then((patientTwo: string) => { const firstPatientPageTwo = patientTwo.trim(); expect(firstPatientPageOne).not.to.eq(firstPatientPageTwo); - patientHome.clickPreviousPage(); + pageNavigation.navigateToPreviousPage(); }); }); }); diff --git a/cypress/e2e/patient_spec/PatientInvestigation.cy.ts b/cypress/e2e/patient_spec/PatientInvestigation.cy.ts new file mode 100644 index 00000000000..27d68aa257f --- /dev/null +++ b/cypress/e2e/patient_spec/PatientInvestigation.cy.ts @@ -0,0 +1,40 @@ +import { PatientPage } from "pageobject/Patient/PatientCreation"; +import PatientInvestigation from "pageobject/Patient/PatientInvestigation"; + +import LoginPage from "../../pageobject/Login/LoginPage"; + +describe("Patient Investigation Creation from Patient consultation page", () => { + const loginPage = new LoginPage(); + const patientPage = new PatientPage(); + const patientInvestigation = new PatientInvestigation(); + const patientName = "Dummy Patient Thirteen"; + + before(() => { + loginPage.loginByRole("districtAdmin"); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + cy.awaitUrl("/patients"); + }); + + it("Create a investigation for a patient and verify its reflection", () => { + patientPage.visitPatient(patientName); + patientInvestigation.clickInvestigationTab(); + patientInvestigation.clickLogLabResults(); + patientInvestigation.selectInvestigationOption([ + "Haematology", + "Urine Test", + ]); + cy.clickSubmitButton("Save Investigation"); + cy.verifyNotification("Please Enter at least one value"); + cy.closeNotification(); + // Temporary workflow for investigation since we dont have dummy data and moving away from existing module + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts b/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts index b32990872e2..ec5aef250dc 100644 --- a/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts +++ b/cypress/e2e/patient_spec/PatientLogUpdate.cy.ts @@ -1,8 +1,8 @@ import LoginPage from "../../pageobject/Login/LoginPage"; import { PatientConsultationPage } from "../../pageobject/Patient/PatientConsultation"; import { PatientPage } from "../../pageobject/Patient/PatientCreation"; -import PatientLogupdate from "../../pageobject/Patient/PatientLogupdate"; import PatientInvestigation from "../../pageobject/Patient/PatientInvestigation"; +import PatientLogupdate from "../../pageobject/Patient/PatientLogupdate"; import PatientPrescription from "../../pageobject/Patient/PatientPrescription"; describe("Patient Log Update in Normal, Critical and TeleIcu", () => { @@ -32,16 +32,16 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { const patientInsulinDosage = "56"; const patientFluidBalance = "500"; const patientNetBalance = "1000"; - const patientOne = "Dummy Patient 9"; + const patientOne = "Dummy Patient Nine"; const bedOne = "Dummy Bed 5"; - const patientTwo = "Dummy Patient 10"; + const patientTwo = "Dummy Patient Ten"; const bedTwo = "Dummy Bed 2"; - const patientThree = "Dummy Patient 8"; + const patientThree = "Dummy Patient Eight"; const bedThree = "Dummy Bed 3"; - const domicilaryPatient = "Dummy Patient 11"; + const domicilaryPatient = "Dummy Patient Eleven"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -55,7 +55,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientPage.visitPatient(domicilaryPatient); patientConsultationPage.clickEditConsultationButton(); patientConsultationPage.selectPatientSuggestion("Domiciliary Care"); - cy.submitButton("Update Consultation"); + cy.clickSubmitButton("Update Consultation"); cy.verifyNotification("Consultation updated successfully"); cy.closeNotification(); patientLogupdate.clickLogupdate(); @@ -74,7 +74,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.selectRhythm(patientRhythmType); patientLogupdate.typeRhythm(patientRhythm); cy.get("#consciousness_level-option-RESPONDS_TO_PAIN").click(); - cy.submitButton("Save"); + cy.clickSubmitButton("Save"); cy.verifyNotification("Tele-medicine Log created successfully"); }); @@ -108,11 +108,11 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientPrescription.selectMedicine("DOLO"); patientPrescription.enterDosage("4"); patientPrescription.selectDosageFrequency("Twice daily"); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); // Submit the doctors log update - cy.submitButton("Save and Continue"); + cy.clickSubmitButton("Save and Continue"); cy.wait(2000); cy.verifyNotification("Progress Note created successfully"); cy.closeNotification(); @@ -120,19 +120,19 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.selectCriticalCareSection("Neurological Monitoring"); cy.get("#consciousness_level-option-RESPONDS_TO_PAIN").click(); cy.get("#left_pupil_light_reaction-option-FIXED").click(); - cy.submitButton("Update Details"); + cy.clickSubmitButton("Update Details"); cy.verifyNotification( "Neurological Monitoring details succesfully updated.", ); cy.closeNotification(); // Final Submission of the form - cy.submitButton("Complete"); + cy.clickSubmitButton("Complete"); cy.verifyNotification("Progress Note Log Update filed successfully"); cy.closeNotification(); // Verify the data reflection - cy.contains("button", "Daily Rounds").click(); + cy.contains("button", "Log Updates").click(); patientLogupdate.clickLogUpdateViewDetails( - "#dailyround-entry", + "#logupdate-entry", patientCategory, ); cy.verifyContentPresence("#consultation-preview", [ @@ -143,7 +143,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.clickUpdateDetail(); patientLogupdate.typeSystolic(patientModifiedSystolic); patientLogupdate.typeDiastolic(patientModifiedDiastolic); - cy.submitButton("Continue"); + cy.clickSubmitButton("Continue"); cy.verifyNotification("Progress Note updated successfully"); }); @@ -156,7 +156,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.clickLogupdate(); patientLogupdate.selectRoundType("Detailed Update"); patientLogupdate.selectPatientCategory(patientCategory); - cy.submitButton("Save and Continue"); + cy.clickSubmitButton("Save and Continue"); cy.verifyNotification("Detailed Update created successfully"); cy.closeNotification(); // Select two Section - First One is Respiratory Support @@ -166,7 +166,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.selectOxygenSupport(); patientLogupdate.typeOxygenFlowRate(patientOxygenFlowRate); patientLogupdate.typeVentilatorSpo2(patientSpo2); - cy.submitButton("Update Details"); + cy.clickSubmitButton("Update Details"); cy.verifyNotification("Respiratory Support details succesfully updated."); cy.closeNotification(); // Second Section will be Blood Sugar @@ -174,15 +174,15 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.typeBloodSugar(patientBloodSugar); patientLogupdate.typeInsulinDosage(patientInsulinDosage); cy.get("#insulin_intake_frequency-option-BD").click(); - cy.submitButton("Update Details"); + cy.clickSubmitButton("Update Details"); cy.verifyNotification("Blood Sugar details succesfully updated."); // Submit the form and verify the details - cy.submitButton("Complete"); + cy.clickSubmitButton("Complete"); cy.verifyNotification("Detailed Log Update filed successfully"); cy.closeNotification(); - cy.contains("button", "Daily Rounds").click(); + cy.contains("button", "Log Updates").click(); patientLogupdate.clickLogUpdateViewDetails( - "#dailyround-entry", + "#logupdate-entry", patientCategory, ); cy.verifyContentPresence("#respiratory-support", [ @@ -195,24 +195,24 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { ]); // Go back and edit the data on a third section patientLogupdate.clickGoBackConsultation(); - cy.contains("button", "Daily Rounds").click(); + cy.contains("button", "Log Updates").click(); patientLogupdate.clickLogUpdateUpdateLog( - "#dailyround-entry", + "#logupdate-entry", patientCategory, ); patientLogupdate.selectCriticalCareSection("Dialysis"); patientLogupdate.typeFluidBalance(patientFluidBalance); patientLogupdate.typeNetBalance(patientNetBalance); - cy.submitButton("Update Details"); + cy.clickSubmitButton("Update Details"); cy.verifyNotification("Dialysis details succesfully updated."); cy.closeNotification(); - cy.submitButton("Complete"); + cy.clickSubmitButton("Complete"); cy.verifyNotification("Detailed Log Update filed successfully"); cy.closeNotification(); //Reverify the editted and newly added data - cy.contains("button", "Daily Rounds").click(); + cy.contains("button", "Log Updates").click(); patientLogupdate.clickLogUpdateViewDetails( - "#dailyround-entry", + "#logupdate-entry", patientCategory, ); cy.verifyContentPresence("#respiratory-support", [ @@ -251,7 +251,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.selectRhythm(patientRhythmType); patientLogupdate.typeRhythm(patientRhythm); cy.get("#consciousness_level-option-RESPONDS_TO_PAIN").click(); - cy.submitButton("Save"); + cy.clickSubmitButton("Save"); cy.wait(2000); cy.verifyNotification("Brief Update created successfully"); // Verify the card content @@ -263,7 +263,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientPage.visitPatient(domicilaryPatient); patientConsultationPage.clickEditConsultationButton(); patientConsultationPage.selectPatientSuggestion("Domiciliary Care"); - cy.submitButton("Update Consultation"); + cy.clickSubmitButton("Update Consultation"); cy.verifyNotification("Consultation updated successfully"); cy.closeNotification(); patientLogupdate.clickLogupdate(); @@ -281,13 +281,13 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.selectRhythm(patientRhythmType); patientLogupdate.typeRhythm(patientRhythm); cy.get("#consciousness_level-option-RESPONDS_TO_PAIN").click(); - cy.submitButton("Save"); + cy.clickSubmitButton("Save"); cy.verifyNotification("Brief Update created successfully"); cy.closeNotification(); // edit the card and verify the data. - cy.contains("button", "Daily Rounds").click(); + cy.contains("button", "Log Updates").click(); patientLogupdate.clickLogUpdateViewDetails( - "#dailyround-entry", + "#logupdate-entry", patientCategory, ); cy.verifyContentPresence("#consultation-preview", [ @@ -307,11 +307,11 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.typeSystolic(patientModifiedSystolic); patientLogupdate.clearIntoElementById("#diastolic"); patientLogupdate.typeDiastolic(patientModifiedDiastolic); - cy.submitButton("Continue"); + cy.clickSubmitButton("Continue"); cy.verifyNotification("Brief Update updated successfully"); - cy.contains("button", "Daily Rounds").click(); + cy.contains("button", "Log Updates").click(); patientLogupdate.clickLogUpdateViewDetails( - "#dailyround-entry", + "#logupdate-entry", patientCategory, ); cy.verifyContentPresence("#consultation-preview", [ @@ -324,7 +324,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientPage.visitPatient(domicilaryPatient); patientConsultationPage.clickEditConsultationButton(); patientConsultationPage.selectPatientSuggestion("Domiciliary Care"); - cy.submitButton("Update Consultation"); + cy.clickSubmitButton("Update Consultation"); cy.verifyNotification("Consultation updated successfully"); cy.closeNotification(); patientLogupdate.clickLogupdate(); @@ -336,7 +336,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.typeTemperature(patientTemperature); patientLogupdate.typeRespiratory(patientRespiratory); cy.get("#consciousness_level-option-RESPONDS_TO_PAIN").click(); - cy.submitButton("Save"); + cy.clickSubmitButton("Save"); cy.verifyNotification("Brief Update created successfully"); cy.closeNotification(); cy.verifyContentPresence("#consultation-buttons", ["9"]); @@ -346,7 +346,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => { patientLogupdate.typeSystolic(patientSystolic); patientLogupdate.typeDiastolic(patientDiastolic); patientLogupdate.typePulse(patientPulse); - cy.submitButton("Save"); + cy.clickSubmitButton("Save"); cy.verifyNotification("Brief Update created successfully"); cy.closeNotification(); cy.verifyContentPresence("#consultation-buttons", ["-"]); diff --git a/cypress/e2e/patient_spec/PatientPrescription.cy.ts b/cypress/e2e/patient_spec/PatientPrescription.cy.ts index f5febc85fdc..61f8067eea0 100644 --- a/cypress/e2e/patient_spec/PatientPrescription.cy.ts +++ b/cypress/e2e/patient_spec/PatientPrescription.cy.ts @@ -1,6 +1,6 @@ -import PatientPrescription from "../../pageobject/Patient/PatientPrescription"; import LoginPage from "../../pageobject/Login/LoginPage"; import { PatientPage } from "../../pageobject/Patient/PatientCreation"; +import PatientPrescription from "../../pageobject/Patient/PatientPrescription"; const patientPrescription = new PatientPrescription(); const loginPage = new LoginPage(); @@ -15,7 +15,7 @@ const medicineIndicator = "Test Indicator"; describe("Patient Medicine Administration", () => { before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -26,7 +26,7 @@ describe("Patient Medicine Administration", () => { }); it("Add a new medicine | Verify the Edit and Discontinue Medicine workflow |", () => { - patientPage.visitPatient("Dummy Patient 9"); + patientPage.visitPatient("Dummy Patient Nine"); patientPrescription.visitMedicineTab(); patientPrescription.visitEditPrescription(); // Add a normal Medicine to the patient @@ -36,7 +36,7 @@ describe("Patient Medicine Administration", () => { patientPrescription.selectMedicine(medicineNameOne); patientPrescription.enterDosage(medicineBaseDosage); patientPrescription.selectDosageFrequency(medicineFrequency); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); // Edit the existing medicine & Verify they are properly moved to discontinue position @@ -44,16 +44,16 @@ describe("Patient Medicine Administration", () => { patientPrescription.visitMedicineTab(); cy.verifyAndClickElement("#0", medicineNameOne); cy.verifyContentPresence("#submit", ["Discontinue"]); // To verify the pop-up is open - cy.submitButton("Edit"); + cy.clickSubmitButton("Edit"); patientPrescription.enterDosage(medicineTargetDosage); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Prescription edited successfully"); cy.closeNotification(); // Discontinue a medicine & Verify the notification cy.verifyAndClickElement("#0", medicineNameOne); - cy.submitButton("Discontinue"); + cy.clickSubmitButton("Discontinue"); patientPrescription.enterDiscontinueReason("Medicine is been discontinued"); - cy.submitButton("Confirm Discontinue"); + cy.clickSubmitButton("Confirm Discontinue"); cy.verifyNotification("Prescription discontinued"); cy.closeNotification(); // verify the discontinue medicine view @@ -63,7 +63,7 @@ describe("Patient Medicine Administration", () => { }); it("Add a PRN Prescription medicine | Group Administrate it |", () => { - patientPage.visitPatient("Dummy Patient 6"); + patientPage.visitPatient("Dummy Patient Six"); patientPrescription.visitMedicineTab(); patientPrescription.visitEditPrescription(); // Add First Medicine @@ -73,7 +73,7 @@ describe("Patient Medicine Administration", () => { patientPrescription.selectMedicine(medicineNameOne); patientPrescription.enterDosage(medicineBaseDosage); patientPrescription.enterIndicator(medicineIndicator); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); // Add Second Medicine @@ -83,7 +83,7 @@ describe("Patient Medicine Administration", () => { patientPrescription.selectMedicine(medicineNameTwo); patientPrescription.enterDosage(medicineBaseDosage); patientPrescription.enterIndicator(medicineIndicator); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); patientPrescription.clickReturnToDashboard(); @@ -97,7 +97,7 @@ describe("Patient Medicine Administration", () => { }); it("Add a new titrated medicine for a patient | Individual Administeration |", () => { - patientPage.visitPatient("Dummy Patient 5"); + patientPage.visitPatient("Dummy Patient Five"); patientPrescription.visitMedicineTab(); patientPrescription.visitEditPrescription(); patientPrescription.clickAddPrescription(); @@ -108,7 +108,7 @@ describe("Patient Medicine Administration", () => { patientPrescription.enterDosage(medicineBaseDosage); patientPrescription.enterTargetDosage(medicineTargetDosage); patientPrescription.selectDosageFrequency(medicineFrequency); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); // Administer the medicine in edit form @@ -116,7 +116,7 @@ describe("Patient Medicine Administration", () => { cy.wait(2000); patientPrescription.enterAdministerDosage(medicineBaseDosage); patientPrescription.enterAdministerNotes(medicineAdministerNote); - cy.submitButton("Administer Medicine"); + cy.clickSubmitButton("Administer Medicine"); cy.verifyNotification("Medicine(s) administered"); cy.closeNotification(); // Verify the Reflection on the Medicine @@ -129,14 +129,14 @@ describe("Patient Medicine Administration", () => { // Go to medicine tab and administer it again patientPrescription.visitMedicineTab(); cy.verifyAndClickElement("#0", medicineNameOne); - cy.submitButton("Administer"); + cy.clickSubmitButton("Administer"); patientPrescription.enterAdministerDosage(medicineBaseDosage); - cy.submitButton("Administer Medicine"); + cy.clickSubmitButton("Administer Medicine"); cy.verifyNotification("Medicine(s) administered"); }); it("Add a new medicine for a patient and verify the duplicate medicine validation", () => { - patientPage.visitPatient("Dummy Patient 4"); + patientPage.visitPatient("Dummy Patient Four"); patientPrescription.visitMedicineTab(); patientPrescription.visitEditPrescription(); patientPrescription.clickAddPrescription(); @@ -145,7 +145,7 @@ describe("Patient Medicine Administration", () => { patientPrescription.selectMedicine(medicineNameOne); patientPrescription.enterDosage(medicineBaseDosage); patientPrescription.selectDosageFrequency(medicineFrequency); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification("Medicine prescribed"); cy.closeNotification(); // verify the duplicate medicine error message @@ -155,7 +155,7 @@ describe("Patient Medicine Administration", () => { patientPrescription.selectMedicine(medicineNameOne); patientPrescription.enterDosage(medicineBaseDosage); patientPrescription.selectDosageFrequency(medicineFrequency); - cy.submitButton("Submit"); + cy.clickSubmitButton("Submit"); cy.verifyNotification( "Medicine - This medicine is already prescribed to this patient. Please discontinue the existing prescription to prescribe again.", ); diff --git a/cypress/e2e/patient_spec/PatientRegistration.cy.ts b/cypress/e2e/patient_spec/PatientRegistration.cy.ts index d774a90ceb8..a7c869401cd 100644 --- a/cypress/e2e/patient_spec/PatientRegistration.cy.ts +++ b/cypress/e2e/patient_spec/PatientRegistration.cy.ts @@ -1,13 +1,12 @@ +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; import { PatientPage } from "../../pageobject/Patient/PatientCreation"; -import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import { generatePhoneNumber } from "../../pageobject/utils/constants"; -import PatientTransfer from "../../pageobject/Patient/PatientTransfer"; import PatientInsurance from "../../pageobject/Patient/PatientInsurance"; import PatientMedicalHistory from "../../pageobject/Patient/PatientMedicalHistory"; +import PatientTransfer from "../../pageobject/Patient/PatientTransfer"; +import { generatePhoneNumber } from "../../pageobject/utils/constants"; const yearOfBirth = "2001"; -const isHCXEnabled = Cypress.env("ENABLE_HCX"); const calculateAge = () => { const currentYear = new Date().getFullYear(); @@ -41,10 +40,12 @@ describe("Patient Creation with consultation", () => { const patientDateOfBirth = "01012001"; const patientMenstruationStartDate = getRelativeDateString(-10); const patientDateOfDelivery = getRelativeDateString(-20); - const patientOneName = "Patient With No Consultation"; + const patientOneName = "Great Napolean 14"; const patientOneGender = "Male"; const patientOneUpdatedGender = "Female"; - const patientOneAddress = "Test Patient Address"; + const patientOneAddress = `149/J, 3rd Block, + Aluva + Ernakulam, Kerala - 682001`; const patientOnePincode = "682001"; const patientOneState = "Kerala"; const patientOneDistrict = "Ernakulam"; @@ -58,20 +59,18 @@ describe("Patient Creation with consultation", () => { const patientOneFirstInsuranceId = "insurance-details-0"; const patientOneFirstSubscriberId = "member id 01"; const patientOneFirstPolicyId = "policy name 01"; - const patientOneFirstInsurerId = "insurer id 01"; - const patientOneFirstInsurerName = "insurer name 01"; + const patientOneFirstInsurerName = "Demo Payor"; const patientOneSecondInsuranceId = "insurance-details-1"; const patientOneSecondSubscriberId = "member id 02"; const patientOneSecondPolicyId = "policy name 02"; - const patientOneSecondInsurerId = "insurer id 02"; - const patientOneSecondInsurerName = "insurer name 02"; + const patientOneSecondInsurerName = "Care Payor"; const patientTransferPhoneNumber = "9849511866"; const patientTransferFacility = "Dummy Shifting Center"; - const patientTransferName = "Dummy Patient 10"; + const patientTransferName = "Dummy Patient Twelve"; const patientOccupation = "Student"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -133,6 +132,7 @@ describe("Patient Creation with consultation", () => { "Middle Class", "Family member", ); + patientMedicalHistory.verifyPatientMedicalDetails( patientOnePresentHealth, patientOneOngoingMedication, @@ -178,21 +178,10 @@ describe("Patient Creation with consultation", () => { "policy_id", patientOneFirstPolicyId, ); - if (isHCXEnabled) { - patientInsurance.selectInsurer("test"); - } else { - patientInsurance.typePatientInsuranceDetail( - patientOneFirstInsuranceId, - "insurer_id", - patientOneFirstInsurerId, - ); - patientInsurance.typePatientInsuranceDetail( - patientOneFirstInsuranceId, - "insurer_name", - patientOneFirstInsurerName, - ); - } - + patientInsurance.selectPatientInsurerName( + patientOneFirstInsuranceId, + patientOneFirstInsurerName, + ); patientInsurance.clickAddInsruanceDetails(); patientInsurance.typePatientInsuranceDetail( patientOneSecondInsuranceId, @@ -204,21 +193,10 @@ describe("Patient Creation with consultation", () => { "policy_id", patientOneSecondPolicyId, ); - if (isHCXEnabled) { - patientInsurance.selectInsurer("Care"); - } else { - patientInsurance.typePatientInsuranceDetail( - patientOneSecondInsuranceId, - "insurer_id", - patientOneSecondInsurerId, - ); - patientInsurance.typePatientInsuranceDetail( - patientOneSecondInsuranceId, - "insurer_name", - patientOneSecondInsurerName, - ); - } - + patientInsurance.selectPatientInsurerName( + patientOneSecondInsuranceId, + patientOneSecondInsurerName, + ); patientPage.clickUpdatePatient(); cy.wait(3000); patientPage.verifyPatientUpdated(); @@ -239,24 +217,18 @@ describe("Patient Creation with consultation", () => { patientMedicalHistory.verifyNoSymptosPresent("Diabetes"); // verify insurance details and dedicatd page cy.get("[data-testid=patient-details]") - .contains("member id") + .contains("Member ID") .scrollIntoView(); cy.wait(2000); - patientInsurance.clickPatientInsuranceViewDetail(); - cy.wait(3000); patientInsurance.verifyPatientPolicyDetails( patientOneFirstSubscriberId, patientOneFirstPolicyId, - patientOneFirstInsurerId, patientOneFirstInsurerName, - isHCXEnabled, ); patientInsurance.verifyPatientPolicyDetails( patientOneSecondSubscriberId, patientOneSecondPolicyId, - patientOneSecondInsurerId, patientOneSecondInsurerName, - isHCXEnabled, ); }); @@ -272,7 +244,7 @@ describe("Patient Creation with consultation", () => { patientTransfer.clickTransferPatientYOB(yearOfBirth); patientTransfer.clickTransferSubmitButton(); cy.verifyNotification( - "Patient Dummy Patient 10 (Male) transferred successfully", + `Patient ${patientTransferName} (Male) transferred successfully`, ); patientTransfer.clickConsultationCancelButton(); // allow the transfer button of a patient diff --git a/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts b/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts index aafc03680ee..33e11b4987a 100644 --- a/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts +++ b/cypress/e2e/resource_spec/ResourcesAdvanceFilters.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Resource filter", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts b/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts index 8dc526a68c3..23077a71ed8 100644 --- a/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts +++ b/cypress/e2e/resource_spec/ResourcesHomepage.cy.ts @@ -1,16 +1,19 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; + +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; import ResourcePage from "../../pageobject/Resource/ResourcePage"; -import FacilityPage from "../../pageobject/Facility/FacilityCreation"; describe("Resource Page", () => { let createdResource: string; const loginPage = new LoginPage(); const resourcePage = new ResourcePage(); const facilityPage = new FacilityPage(); + const facilityHome = new FacilityHome(); const phone_number = "9999999999"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -39,8 +42,8 @@ describe("Resource Page", () => { }); it("Create a resource request", () => { - cy.visit("/facility"); - cy.get("#search").click().type("dummy facility 40"); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch("dummy facility 40"); cy.intercept("GET", "**/api/v1/facility/**").as("loadFacilities"); cy.get("#facility-details").click(); cy.wait("@loadFacilities").its("response.statusCode").should("eq", 200); diff --git a/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts b/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts index ad2e57b7433..562eb22a75e 100644 --- a/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts +++ b/cypress/e2e/sample_test_spec/SampleTestAdvanceFilters.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Sample Filter", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts b/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts index 98d69ccff41..491da5ee7ad 100644 --- a/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts +++ b/cypress/e2e/sample_test_spec/SampleTestHomepage.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Sample List", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts b/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts new file mode 100644 index 00000000000..a4b26d328e5 --- /dev/null +++ b/cypress/e2e/sample_test_spec/SampleTestRequest.cy.ts @@ -0,0 +1,88 @@ +import LoginPage from "pageobject/Login/LoginPage"; +import { PatientConsultationPage } from "pageobject/Patient/PatientConsultation"; +import { PatientPage } from "pageobject/Patient/PatientCreation"; +import { SampleTestPage } from "pageobject/Sample/SampleTestCreate"; + +describe("Sample Test", () => { + const sampleTestPage = new SampleTestPage(); + const patientPage = new PatientPage(); + const loginPage = new LoginPage(); + const patientConsultationPage = new PatientConsultationPage(); + const patientName = "Dummy Patient Eleven"; + const sampleTestType = "BA/ETA"; + const icmrCategory = "Cat 0"; + const icmrLabel = "Test Icmr Label"; + const doctorName = "Dr John Doe"; + const atypicalDetails = "Patient showing unusual symptoms"; + const diagnosis = "Suspected respiratory infection"; + const etiologyIdentified = "Bacterial infection suspected"; + const differentialDiagnosis = "Possibly a viral infection"; + const fastTrackReason = + "The patient has a high risk of complications and requires immediate testing."; + const sampleTestStatus = "Request Submitted"; + const expectedSampleTestType = "ba/eta"; + const sampleTestResult = "Awaiting"; + + before(() => { + loginPage.loginByRole("districtAdmin"); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.clearLocalStorage(/filters--.+/); + }); + + it("should request a new sample test", () => { + // Ensure patient list API is loaded before proceeding + cy.awaitUrl("/patients"); + patientPage.visitPatient(patientName); + patientConsultationPage.interceptPatientDetailsAPI(); + patientConsultationPage.clickPatientDetails(); + patientConsultationPage.verifyPatientDetailsResponse(); + // Visit SampleRequest Page + sampleTestPage.visitSampleRequestPage(); + // Fill Sample Test Request Form + sampleTestPage.selectSampleType(sampleTestType); + sampleTestPage.selectIcmrCategory(icmrCategory); + sampleTestPage.fillIcmrLabel(icmrLabel); + sampleTestPage.fillFastTrackReason(fastTrackReason); + sampleTestPage.fillDoctorName(doctorName); + sampleTestPage.fillAtypicalPresentation(atypicalDetails); + sampleTestPage.fillDiagnosis(diagnosis); + sampleTestPage.fillEtiology(etiologyIdentified); + sampleTestPage.fillDiffDiagnosis(differentialDiagnosis); + sampleTestPage.checkHasSari(); + sampleTestPage.checkHasAri(); + sampleTestPage.checkIsUnusualCourse(); + sampleTestPage.interceptSampleTestReq(); + // Submit the form and verify notification + cy.clickSubmitButton("Confirm your request to send sample for testing"); + sampleTestPage.verifySampleTestReq(); + cy.verifyNotification("Sample test created successfully"); + // Check the updated request history + sampleTestPage.checkRequestHistory( + sampleTestStatus, + expectedSampleTestType, + fastTrackReason, + sampleTestResult, + ); + // Checking Reflection on Sample Page + cy.awaitUrl("/sample"); + sampleTestPage.interceptGetSampleTestReq(); + sampleTestPage.searchPatientSample(patientName); + sampleTestPage.verifyGetSampleTestReq(); + sampleTestPage.verifyPatientName(patientName); + sampleTestPage.interceptGetSampleTestReq(); + sampleTestPage.clickOnSampleDetailsBtn(); + sampleTestPage.verifyGetSampleTestReq(); + sampleTestPage.verifyPatientTestDetails( + patientName, + fastTrackReason, + doctorName, + diagnosis, + differentialDiagnosis, + etiologyIdentified, + ); + }); +}); diff --git a/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts b/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts index bb536a1865c..1a773350b2d 100644 --- a/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts +++ b/cypress/e2e/shifting_spec/ShiftingAdvanceFilters.cy.ts @@ -1,10 +1,14 @@ +import LoginPage from "pageobject/Login/LoginPage"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import ShiftingPage from "../../pageobject/Shift/ShiftFilters"; describe("Shifting section filter", () => { const shiftingPage = new ShiftingPage(); + const loginPage = new LoginPage(); before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -12,7 +16,7 @@ describe("Shifting section filter", () => { cy.restoreLocalStorage(); cy.clearLocalStorage(/filters--.+/); cy.awaitUrl("/shifting"); - shiftingPage.advancedFilterButton().click(); + advanceFilters.clickAdvancedFiltersButton(); }); it("filter by facility", () => { diff --git a/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts b/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts index a0a637f97f1..a94de68591d 100644 --- a/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts +++ b/cypress/e2e/shifting_spec/ShiftingHomepage.cy.ts @@ -1,6 +1,10 @@ +import LoginPage from "pageobject/Login/LoginPage"; + +const loginPage = new LoginPage(); + describe("Shifting Page", () => { before(() => { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); diff --git a/cypress/e2e/users_spec/UsersCreation.cy.ts b/cypress/e2e/users_spec/UsersCreation.cy.ts index 683a2131b2f..947d5b6ce87 100644 --- a/cypress/e2e/users_spec/UsersCreation.cy.ts +++ b/cypress/e2e/users_spec/UsersCreation.cy.ts @@ -1,23 +1,29 @@ -import LoginPage from "../../pageobject/Login/LoginPage"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; +import FacilityHome from "pageobject/Facility/FacilityHome"; +import ManageUserPage from "pageobject/Users/ManageUserPage"; +import UserProfilePage from "pageobject/Users/UserProfilePage"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import FacilityPage from "../../pageobject/Facility/FacilityCreation"; -import { UserPage } from "../../pageobject/Users/UserSearch"; +import LoginPage from "../../pageobject/Login/LoginPage"; import { UserCreationPage } from "../../pageobject/Users/UserCreation"; +import { UserPage } from "../../pageobject/Users/UserSearch"; import { - generatePhoneNumber, generateEmergencyPhoneNumber, + generatePhoneNumber, } from "../../pageobject/utils/constants"; describe("User Creation", () => { const userPage = new UserPage(); const loginPage = new LoginPage(); + const userProfilePage = new UserProfilePage(); + const manageUserPage = new ManageUserPage(); const userCreationPage = new UserCreationPage(); const facilityPage = new FacilityPage(); - const assetSearchPage = new AssetSearchPage(); - const phone_number = generatePhoneNumber(); - const emergency_phone_number = generateEmergencyPhoneNumber(); + const facilityHome = new FacilityHome(); + const phoneNumber = generatePhoneNumber(); + const emergencyPhoneNumber = generateEmergencyPhoneNumber(); const fillFacilityName = "Dummy Facility 40"; - const makeid = (length: number) => { + const makeId = (length: number) => { let result = ""; const characters = "abcdefghijklmnopqrstuvwxyz0123456789"; const charactersLength = characters.length; @@ -26,8 +32,8 @@ describe("User Creation", () => { } return result; }; - const username = makeid(8); - const alreadylinkedusersviews = [ + const username = makeId(8); + const alreadyLinkedUsersViews = [ "devdoctor", "devstaff2", "devdistrictadmin", @@ -53,9 +59,28 @@ describe("User Creation", () => { "This field is required", "Please enter valid phone number", ]; + const userName = "devdistrictadmin"; + const firstName = "District Editted"; + const lastName = "Cypress"; + const gender = "Male"; + const email = "test@test.com"; + const password = "Test@123"; + const qualification = "MBBS"; + const experience = "2"; + const regNo = "123456789"; + const newUserFirstName = "cypress test"; + const newUserLastName = "staff user"; + const state = "Kerala"; + const district = "Ernakulam"; + const role = "Doctor"; + const homeFacility = "Dummy Shifting Center"; + const weeklyWorkingHrs = "14"; + const dob = "01011998"; + const formattedDob = "01/01/1998"; + const newUserDob = "25081999"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -66,135 +91,107 @@ describe("User Creation", () => { }); it("Update the existing user profile and verify its reflection", () => { - userCreationPage.clickElementById("user-profile-name"); - userCreationPage.clickElementById("profile-button"); - userCreationPage.verifyElementContainsText( - "username-profile-details", - "devdistrictadmin", - ); - userCreationPage.clickElementById("edit-cancel-profile-button"); - userCreationPage.typeIntoElementByIdPostClear( - "firstName", - "District Editted", - ); - userCreationPage.typeIntoElementByIdPostClear("lastName", "Cypress"); - userCreationPage.selectDropdownOption("gender", "Male"); - userCreationPage.typeIntoElementByIdPostClear("phoneNumber", phone_number); - userCreationPage.typeIntoElementByIdPostClear( - "altPhoneNumber", - emergency_phone_number, - ); - userCreationPage.typeIntoElementByIdPostClear("email", "test@test.com"); - userCreationPage.typeIntoElementByIdPostClear("weekly_working_hours", "14"); - userCreationPage.typeIntoElementByIdPostClearDob( - "date_of_birth", - "01011998", - ); - userCreationPage.clickElementById("submit"); - userCreationPage.verifyElementContainsText( - "contactno-profile-details", - "+91" + phone_number, - ); - userCreationPage.verifyElementContainsText( - "whatsapp-profile-details", - "+91" + emergency_phone_number, - ); - userCreationPage.verifyElementContainsText( - "firstname-profile-details", - "District Editted", - ); - userCreationPage.verifyElementContainsText( - "lastname-profile-details", - "Cypress", - ); - userCreationPage.verifyElementContainsText( - "date_of_birth-profile-details", - "01/01/1998", - ); - userCreationPage.verifyElementContainsText( - "emailid-profile-details", - "test@test.com", - ); - userCreationPage.verifyElementContainsText( - "gender-profile-details", - "Male", - ); - userCreationPage.verifyElementContainsText( - "averageworkinghour-profile-details", - "14", - ); + manageUserPage.navigateToProfile(); + cy.verifyContentPresence("#username-profile-details", [userName]); + userProfilePage.clickEditProfileButton(); + userCreationPage.clearFirstName(); + userCreationPage.typeFirstName(firstName); + userCreationPage.clearLastName(); + userCreationPage.typeLastName(lastName); + userProfilePage.selectGender(gender); + userProfilePage.clearPhoneNumber(); + userProfilePage.typePhoneNumber(phoneNumber); + userProfilePage.clearAltPhoneNumber(); + userProfilePage.typeWhatsappNumber(emergencyPhoneNumber); + userProfilePage.clearEmail(); + userProfilePage.typeEmail(email); + userProfilePage.clearWorkingHours(); + userProfilePage.typeWorkingHours(weeklyWorkingHrs); + userProfilePage.typeDateOfBirth(dob); + cy.intercept("PATCH", "/api/v1/users/*").as("updateUser"); + userProfilePage.clickUpdateButton(); + cy.wait("@updateUser").its("response.statusCode").should("eq", 200); + cy.verifyContentPresence("#contactno-profile-details", [ + "+91" + phoneNumber, + ]); + cy.verifyContentPresence("#whatsapp-profile-details", [ + "+91" + emergencyPhoneNumber, + ]); + cy.verifyContentPresence("#firstname-profile-details", [firstName]); + cy.verifyContentPresence("#lastname-profile-details", [lastName]); + cy.verifyContentPresence("#date_of_birth-profile-details", [formattedDob]); + cy.verifyContentPresence("#emailid-profile-details", [email]); + cy.verifyContentPresence("#gender-profile-details", [gender]); + cy.verifyContentPresence("#averageworkinghour-profile-details", [ + weeklyWorkingHrs, + ]); }); it("Update the existing user profile Form Mandatory File Error", () => { - userCreationPage.clickElementById("user-profile-name"); - userCreationPage.clickElementById("profile-button"); - userCreationPage.clickElementById("edit-cancel-profile-button"); - userCreationPage.clearIntoElementById("firstName"); - userCreationPage.clearIntoElementById("lastName"); - userCreationPage.clearIntoElementById("phoneNumber"); - userCreationPage.clearIntoElementById("altPhoneNumber"); - userCreationPage.clearIntoElementById("weekly_working_hours"); - userCreationPage.clickElementById("submit"); - userCreationPage.verifyErrorMessages(EXPECTED_PROFILE_ERROR_MESSAGES); + manageUserPage.navigateToProfile(); + userProfilePage.clickEditProfileButton(); + userCreationPage.clearFirstName(); + userCreationPage.clearLastName(); + userProfilePage.clearPhoneNumber(); + userProfilePage.clearAltPhoneNumber(); + userProfilePage.clearWorkingHours(); + userProfilePage.clickUpdateButton(); + cy.verifyErrorMessages(EXPECTED_PROFILE_ERROR_MESSAGES); }); it("create new user and verify reflection", () => { - userCreationPage.clickElementById("addUserButton"); - userCreationPage.selectFacility("Dummy Shifting Center"); - userCreationPage.typeIntoElementById("username", username); - userCreationPage.typeIntoElementById("password", "Test@123"); - userCreationPage.selectHomeFacility("Dummy Shifting Center"); - userCreationPage.typeIntoElementById("phone_number", phone_number); - userCreationPage.setInputDate("date_of_birth", "25081999"); - userCreationPage.selectDropdownOption("user_type", "Doctor"); - userCreationPage.typeIntoElementById("c_password", "Test@123"); - userCreationPage.typeIntoElementById("qualification", "MBBS"); - userCreationPage.typeIntoElementById("doctor_experience_commenced_on", "2"); - userCreationPage.typeIntoElementById( - "doctor_medical_council_registration", - "123456789", - ); - userCreationPage.typeIntoElementById("first_name", "cypress test"); - userCreationPage.typeIntoElementById("last_name", "staff user"); - userCreationPage.typeIntoElementById("email", "test@test.com"); - userCreationPage.selectDropdownOption("gender", "Male"); - userCreationPage.selectDropdownOption("state", "Kerala"); - userCreationPage.selectDropdownOption("district", "Ernakulam"); - userCreationPage.clickElementById("submit"); - userCreationPage.verifyNotification("User added successfully"); + userCreationPage.clickAddUserButton(); + userCreationPage.selectFacility(homeFacility); + userCreationPage.typeUserName(username); + userCreationPage.typePassword(password); + userCreationPage.typeConfirmPassword(password); + userCreationPage.selectHomeFacility(homeFacility); + userPage.typeInPhoneNumber(phoneNumber); + userProfilePage.typeDateOfBirth(newUserDob); + userCreationPage.selectUserType(role); + userProfilePage.typeQualification(qualification); + userProfilePage.typeDoctorYoE(experience); + userProfilePage.typeMedicalCouncilRegistration(regNo); + userPage.typeInFirstName(newUserFirstName); + userPage.typeInLastName(newUserLastName); + userProfilePage.typeEmail(email); + userCreationPage.selectGender(gender); + userCreationPage.selectState(state); + userCreationPage.selectDistrict(district); + cy.intercept("POST", "/api/v1/users/add_user/").as("createUser"); + userCreationPage.clickSaveUserButton(); + cy.wait("@createUser").its("response.statusCode").should("eq", 201); + cy.verifyNotification("User added successfully"); userPage.typeInSearchInput(username); userPage.checkUsernameText(username); - userCreationPage.verifyElementContainsText("name", "cypress test"); - userCreationPage.verifyElementContainsText("role", "Doctor"); - userCreationPage.verifyElementContainsText("district", "Ernakulam"); - userCreationPage.verifyElementContainsText( - "home_facility", - "Dummy Shifting Center", - ); - userCreationPage.verifyElementContainsText("qualification", "MBBS"); - userCreationPage.verifyElementContainsText("doctor-experience", "2"); - userCreationPage.verifyElementContainsText( - "medical-council-registration", - "123456789", - ); + cy.verifyContentPresence("#name", [newUserFirstName]); + cy.verifyContentPresence("#role", [role]); + cy.verifyContentPresence("#district", [district]); + cy.verifyContentPresence("#home_facility", [homeFacility]); + cy.verifyContentPresence("#qualification", [qualification]); + cy.verifyContentPresence("#doctor-experience", [experience]); + cy.verifyContentPresence("#medical-council-registration", [regNo]); }); it("create new user form throwing mandatory field error", () => { - userCreationPage.clickElementById("addUserButton"); - userCreationPage.clickElementById("submit"); - cy.wait(2000); - userCreationPage.verifyErrorMessages(EXPECTED_ERROR_MESSAGES); + userCreationPage.clickAddUserButton(); + userCreationPage.clickSaveUserButton(); + cy.get(".error-text", { timeout: 10000 }).should("be.visible"); + cy.verifyErrorMessages(EXPECTED_ERROR_MESSAGES); }); it("view user redirection from facility page", () => { - cy.visit("/facility"); - assetSearchPage.typeSearchKeyword(fillFacilityName); - assetSearchPage.pressEnter(); - facilityPage.verifyFacilityBadgeContent(fillFacilityName); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(fillFacilityName); + advanceFilters.verifyFilterBadgePresence( + "Facility/District Name", + fillFacilityName, + true, + ); facilityPage.visitAlreadyCreatedFacility(); facilityPage.clickManageFacilityDropdown(); facilityPage.clickViewUsersOption(); - userPage.verifyMultipleBadgesWithSameId(alreadylinkedusersviews); + userPage.verifyMultipleBadgesWithSameId(alreadyLinkedUsersViews); }); afterEach(() => { diff --git a/cypress/e2e/users_spec/UsersHomepage.cy.ts b/cypress/e2e/users_spec/UsersHomepage.cy.ts index 0dd03c74304..8d86482645b 100644 --- a/cypress/e2e/users_spec/UsersHomepage.cy.ts +++ b/cypress/e2e/users_spec/UsersHomepage.cy.ts @@ -1,3 +1,6 @@ +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; +import { pageNavigation } from "pageobject/utils/paginationHelpers"; + import LoginPage from "../../pageobject/Login/LoginPage"; import { UserPage } from "../../pageobject/Users/UserSearch"; @@ -14,10 +17,10 @@ describe("User Homepage", () => { const altPhoneNumber = "8878825662"; const homeFacility = "Dummy Facility 40"; const nurseUserName = "dummynurse1"; - const doctorUserName = "devdoctor1"; + const doctorUserName = "dev-doctor2"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -28,7 +31,7 @@ describe("User Homepage", () => { }); it("User advance filter functionality", () => { - userPage.clickAdvancedFilters(); + advanceFilters.clickAdvancedFiltersButton(); userPage.typeInFirstName(firstName); userPage.typeInLastName(lastName); userPage.selectRole(role); @@ -37,32 +40,31 @@ describe("User Homepage", () => { userPage.typeInPhoneNumber(phoneNumber); userPage.typeInAltPhoneNumber(altPhoneNumber); userPage.selectHomeFacility(homeFacility); - userPage.applyFilter(); + advanceFilters.applySelectedFilter(); userPage.checkUsernameText(nurseUserName); // Verify the badges related to the data - userPage.verifyDataTestIdText("First Name", `First Name: ${firstName}`); - userPage.verifyDataTestIdText("Last Name", `Last Name: ${lastName}`); - userPage.verifyDataTestIdText( - "Phone Number", - `Phone Number: +91${phoneNumber}`, - ); - userPage.verifyDataTestIdText( + advanceFilters.verifyFilterBadgePresence("First Name", firstName, true); + advanceFilters.verifyFilterBadgePresence("Last Name", lastName, true); + advanceFilters.verifyFilterBadgePresence("Phone Number", phoneNumber, true); + advanceFilters.verifyFilterBadgePresence( "WhatsApp no.", - `WhatsApp no.: +91${altPhoneNumber}`, + altPhoneNumber, + true, ); - userPage.verifyDataTestIdText("Role", `Role: ${role}`); - userPage.verifyDataTestIdText( + advanceFilters.verifyFilterBadgePresence("Role", role, true); + advanceFilters.verifyFilterBadgePresence( "Home Facility", - `Home Facility: ${homeFacility}`, + homeFacility, + true, ); - userPage.clearFilters(); - userPage.verifyDataTestIdNotVisible("First Name"); - userPage.verifyDataTestIdNotVisible("Last Name"); - userPage.verifyDataTestIdNotVisible("Phone Number"); - userPage.verifyDataTestIdNotVisible("WhatsApp no."); - userPage.verifyDataTestIdNotVisible("Role"); - userPage.verifyDataTestIdNotVisible("Home Facility"); - userPage.verifyDataTestIdNotVisible("District"); + advanceFilters.clickAdvancedFiltersButton(); + advanceFilters.clickClearAdvanceFilters(); + advanceFilters.verifyFilterBadgePresence("First Name", "", false); + advanceFilters.verifyFilterBadgePresence("Last Name", "", false); + advanceFilters.verifyFilterBadgePresence("Phone Number", "", false); + advanceFilters.verifyFilterBadgePresence("WhatsApp no.", "", false); + advanceFilters.verifyFilterBadgePresence("Role", "", false); + advanceFilters.verifyFilterBadgePresence("Home Facility", "", false); }); it("Search by username", () => { @@ -81,10 +83,10 @@ describe("User Homepage", () => { }); it("Next/Previous Page Navigation", () => { - userPage.navigateToNextPage(); - userPage.verifyCurrentPageNumber(2); - userPage.navigateToPreviousPage(); - userPage.verifyCurrentPageNumber(1); + pageNavigation.navigateToNextPage(); + pageNavigation.verifyCurrentPageNumber(2); + pageNavigation.navigateToPreviousPage(); + pageNavigation.verifyCurrentPageNumber(1); }); afterEach(() => { diff --git a/cypress/e2e/users_spec/UsersManage.cy.ts b/cypress/e2e/users_spec/UsersManage.cy.ts index 98c2d564f6d..41557e87756 100644 --- a/cypress/e2e/users_spec/UsersManage.cy.ts +++ b/cypress/e2e/users_spec/UsersManage.cy.ts @@ -1,17 +1,21 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; + import LoginPage from "../../pageobject/Login/LoginPage"; -import { UserPage } from "../../pageobject/Users/UserSearch"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; -import { UserCreationPage } from "../../pageobject/Users/UserCreation"; +import { UserPage } from "../../pageobject/Users/UserSearch"; describe("Manage User", () => { const loginPage = new LoginPage(); const userPage = new UserPage(); const manageUserPage = new ManageUserPage(); - const usernametolinkfacilitydoc1 = "dummydoctor4"; - const usernametolinkfacilitydoc2 = "dummydoctor5"; - const usernametolinkfacilitydoc3 = "dummydoctor6"; - const usernametolinkskill = "devdoctor"; - const userCreationPage = new UserCreationPage(); + const facilityHome = new FacilityHome(); + const usernameToLinkFacilitydoc1 = "dummydoctor4"; + const usernameToLinkFacilitydoc2 = "dummydoctor5"; + const usernameToLinkFacilitydoc3 = "dummydoctor6"; + const usernameToLinkSkill = "devdoctor"; + const firstNameUserSkill = "Dev"; + const lastNameUserSkill = "Doctor"; const usernameforworkinghour = "devdistrictadmin"; const usernamerealname = "Dummy Doctor"; const facilitytolinkusername = "Dummy Shifting Center"; @@ -20,7 +24,7 @@ describe("Manage User", () => { const linkedskill = "General Medicine"; before(() => { - loginPage.loginAsDistrictAdmin(); + loginPage.loginByRole("districtAdmin"); cy.saveLocalStorage(); }); @@ -44,33 +48,31 @@ describe("Manage User", () => { manageUserPage.clickCloseSlideOver(); cy.wait(5000); manageUserPage.navigateToProfile(); - userCreationPage.verifyElementContainsText( - "username-profile-details", + cy.verifyContentPresence("#username-profile-details", [ usernameforworkinghour, - ); + ]); manageUserPage.assertSkillInAlreadyLinkedSkills(linkedskill); }); it("linking skills for a doctor users and verify its reflection in doctor connect", () => { // select a doctor user and link and unlink same skill twice and verify the badge is only shown once in doctor connect - userPage.typeInSearchInput(usernametolinkskill); - userPage.checkUsernameText(usernametolinkskill); + advanceFilters.clickAdvancedFiltersButton(); + userPage.typeInFirstName(firstNameUserSkill); + userPage.typeInLastName(lastNameUserSkill); + userPage.selectHomeFacility(facilitytolinkskill); + advanceFilters.applySelectedFilter(); + userPage.checkUsernameText(usernameToLinkSkill); manageUserPage.clicklinkedskillbutton(); manageUserPage.selectSkillFromDropdown(linkedskill); manageUserPage.clickAddSkillButton(); - manageUserPage.clickCloseSlideOver(); - cy.wait(5000); // temporary hack to fix the failure - manageUserPage.clicklinkedskillbutton(); + cy.verifyNotification("Skill added successfully"); + cy.closeNotification(); manageUserPage.assertSkillInAddedUserSkills(linkedskill); - manageUserPage.clickUnlinkSkill(); - manageUserPage.clickSubmit(); - manageUserPage.selectSkillFromDropdown(linkedskill); - manageUserPage.clickAddSkillButton(); manageUserPage.clickCloseSlideOver(); // verifying the doctor connect - manageUserPage.navigateToFacility(); - manageUserPage.typeFacilitySearch(facilitytolinkskill); - manageUserPage.assertFacilityInCard(facilitytolinkskill); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilitytolinkskill); + facilityHome.assertFacilityInCard(facilitytolinkskill); manageUserPage.clickFacilityPatients(); manageUserPage.clickDoctorConnectButton(); manageUserPage.assertSkillIndoctorconnect(linkedskill); @@ -94,8 +96,8 @@ describe("Manage User", () => { it("linking and unlinking facility for multiple users, and confirm reflection in user cards and doctor connect", () => { // verify the user doesn't have any home facility - userPage.typeInSearchInput(usernametolinkfacilitydoc1); - userPage.checkUsernameText(usernametolinkfacilitydoc1); + userPage.typeInSearchInput(usernameToLinkFacilitydoc1); + userPage.checkUsernameText(usernameToLinkFacilitydoc1); manageUserPage.assertHomeFacility("No Home Facility"); // Link a new facility and ensure it is under linked facility - doctor username (1) manageUserPage.clickFacilitiesTab(); @@ -107,8 +109,8 @@ describe("Manage User", () => { manageUserPage.clickCloseSlideOver(); // Link a new facility and ensure it is under home facility - doctor username (2) userPage.clearSearchInput(); - userPage.typeInSearchInput(usernametolinkfacilitydoc2); - userPage.checkUsernameText(usernametolinkfacilitydoc2); + userPage.typeInSearchInput(usernameToLinkFacilitydoc2); + userPage.checkUsernameText(usernameToLinkFacilitydoc2); manageUserPage.clickFacilitiesTab(); manageUserPage.selectFacilityFromDropdown(facilitytolinkusername); manageUserPage.clickLinkFacility(); @@ -118,13 +120,13 @@ describe("Manage User", () => { manageUserPage.clickCloseSlideOver(); // verify the home facility doctor id have reflection in user card userPage.clearSearchInput(); - userPage.typeInSearchInput(usernametolinkfacilitydoc2); - userPage.checkUsernameText(usernametolinkfacilitydoc2); + userPage.typeInSearchInput(usernameToLinkFacilitydoc2); + userPage.checkUsernameText(usernameToLinkFacilitydoc2); manageUserPage.assertHomeFacility(facilitytolinkusername); // Link a new facility and unlink the facility from the doctor username (3) userPage.clearSearchInput(); - userPage.typeInSearchInput(usernametolinkfacilitydoc3); - userPage.checkUsernameText(usernametolinkfacilitydoc3); + userPage.typeInSearchInput(usernameToLinkFacilitydoc3); + userPage.checkUsernameText(usernameToLinkFacilitydoc3); manageUserPage.clickFacilitiesTab(); manageUserPage.selectFacilityFromDropdown(facilitytolinkusername); manageUserPage.clickLinkFacility(); @@ -134,9 +136,9 @@ describe("Manage User", () => { manageUserPage.clickCloseSlideOver(); // Go to particular facility doctor connect and all user-id are reflected based on there access // Path will be facility page to patient page then doctor connect button - manageUserPage.navigateToFacility(); - manageUserPage.typeFacilitySearch(facilitytolinkusername); - manageUserPage.assertFacilityInCard(facilitytolinkusername); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilitytolinkusername); + facilityHome.assertFacilityInCard(facilitytolinkusername); manageUserPage.clickFacilityPatients(); manageUserPage.clickDoctorConnectButton(); manageUserPage.assertDoctorConnectVisibility(usernamerealname); diff --git a/cypress/e2e/users_spec/UsersProfile.cy.ts b/cypress/e2e/users_spec/UsersProfile.cy.ts index 3073cebe7ce..551fba4c0f1 100644 --- a/cypress/e2e/users_spec/UsersProfile.cy.ts +++ b/cypress/e2e/users_spec/UsersProfile.cy.ts @@ -1,11 +1,14 @@ +import FacilityHome from "pageobject/Facility/FacilityHome"; + import LoginPage from "../../pageobject/Login/LoginPage"; -import UserProfilePage from "../../pageobject/Users/UserProfilePage"; import ManageUserPage from "../../pageobject/Users/ManageUserPage"; +import UserProfilePage from "../../pageobject/Users/UserProfilePage"; describe("Manage User Profile", () => { const loginPage = new LoginPage(); const userProfilePage = new UserProfilePage(); const manageUserPage = new ManageUserPage(); + const facilityHome = new FacilityHome(); const date_of_birth = "01011999"; const gender = "Male"; @@ -19,7 +22,7 @@ describe("Manage User Profile", () => { const facilitySearch = "Dummy Facility 40"; before(() => { - loginPage.loginAsDevDoctor(); + loginPage.loginByRole("devDoctor"); cy.saveLocalStorage(); }); @@ -32,25 +35,22 @@ describe("Manage User Profile", () => { it("Set Dob, Gender, Email, Phone and Working Hours for a user and verify its reflection in user profile", () => { userProfilePage.clickEditProfileButton(); - userProfilePage.typedate_of_birth(date_of_birth); + userProfilePage.typeDateOfBirth(date_of_birth); userProfilePage.selectGender(gender); userProfilePage.typeEmail(email); - userProfilePage.typePhone(phone); - userProfilePage.typeWhatsApp(phone); + userProfilePage.typePhoneNumber(phone); + userProfilePage.typeWhatsappNumber(phone); userProfilePage.typeWorkingHours(workinghours); userProfilePage.typeQualification(qualification); userProfilePage.typeDoctorYoE(doctorYoE); userProfilePage.typeMedicalCouncilRegistration(medicalCouncilRegistration); - userProfilePage.clickUpdateButton(); - cy.verifyNotification("Details updated successfully"); - - userProfilePage.assertdate_of_birth("01/01/1999"); + userProfilePage.assertDateOfBirth("01/01/1999"); userProfilePage.assertGender(gender); userProfilePage.assertEmail(email); - userProfilePage.assertPhone(phone); - userProfilePage.assertWhatsApp(phone); + userProfilePage.assertPhoneNumber(phone); + userProfilePage.assertAltPhoneNumber(phone); userProfilePage.assertWorkingHours(workinghours); }); @@ -68,9 +68,9 @@ describe("Manage User Profile", () => { userProfilePage.clickUpdateButton(); userProfilePage.assertVideoConnectLink("https://www.test.com"); // Go to particular facility doctor connect and verify the video connect link is present - manageUserPage.navigateToFacility(); - manageUserPage.typeFacilitySearch(facilitySearch); - manageUserPage.assertFacilityInCard(facilitySearch); + facilityHome.navigateToFacilityHomepage(); + facilityHome.typeFacilitySearch(facilitySearch); + facilityHome.assertFacilityInCard(facilitySearch); manageUserPage.clickFacilityPatients(); manageUserPage.clickDoctorConnectButton(); manageUserPage.assertVideoConnectLink("Dev Doctor", "https://www.test.com"); diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index ec631768154..7a37f65dff7 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -31,39 +31,68 @@ export class AssetPage { }); } - enterAssetDetails( - name: string, - description: string, - workingStatus: string, - qrId: string, - manufacturer: string, - warranty: string, - supportName: string, - supportPhone: string, - supportEmail: string, - vendorName: string, - serialNumber: string, - lastServicedOn: string, - notes: string, - ) { - cy.get("[data-testid=asset-name-input] input").type(name); - cy.get("[data-testid=asset-description-input] textarea").type(description); - cy.get("[data-testid=asset-working-status-input] li") - .contains(workingStatus) - .click(); - cy.get("[data-testid=asset-qr-id-input] input").type(qrId); - cy.get("[data-testid=asset-manufacturer-input] input").type(manufacturer); - cy.get("[data-testid=asset-warranty-input] input").type(warranty); - cy.get("[data-testid=asset-support-name-input] input").type(supportName); - cy.get("#customer-support-phone-div").type(supportPhone); - cy.get("[data-testid=asset-support-email-input] input").type(supportEmail); - cy.get("[data-testid=asset-vendor-name-input] input").type(vendorName); - cy.get("[data-testid=asset-serial-number-input] input").type(serialNumber); - cy.clickAndTypeDate( - "[data-testid=asset-last-serviced-on-input]", - lastServicedOn, - ); - cy.get("[data-testid=asset-notes-input] textarea").type(notes); + enterAssetDetails({ + name, + description, + workingStatus, + qrId, + manufacturer, + warranty, + supportName, + supportPhone, + supportEmail, + vendorName, + serialNumber, + lastServicedOn, + notes, + }: { + name?: string; + description?: string; + workingStatus?: string; + qrId?: string; + manufacturer?: string; + warranty?: string; + supportName?: string; + supportPhone?: string; + supportEmail?: string; + vendorName?: string; + serialNumber?: string; + lastServicedOn?: string; + notes?: string; + }) { + if (name) cy.get("[data-testid=asset-name-input] input").type(name); + if (description) + cy.get("[data-testid=asset-description-input] textarea").type( + description, + ); + if (workingStatus) + cy.get("[data-testid=asset-working-status-input] li") + .contains(workingStatus) + .click(); + if (qrId) cy.get("[data-testid=asset-qr-id-input] input").type(qrId); + if (manufacturer) + cy.get("[data-testid=asset-manufacturer-input] input").type(manufacturer); + if (warranty) + cy.get("[data-testid=asset-warranty-input] input").type(warranty); + if (supportName) + cy.get("[data-testid=asset-support-name-input] input").type(supportName); + if (supportPhone) cy.get("#customer-support-phone-div").type(supportPhone); + if (supportEmail) + cy.get("[data-testid=asset-support-email-input] input").type( + supportEmail, + ); + if (vendorName) + cy.get("[data-testid=asset-vendor-name-input] input").type(vendorName); + if (serialNumber) + cy.get("[data-testid=asset-serial-number-input] input").type( + serialNumber, + ); + if (lastServicedOn) + cy.clickAndTypeDate( + "[data-testid=asset-last-serviced-on-input]", + lastServicedOn, + ); + if (notes) cy.get("[data-testid=asset-notes-input] textarea").type(notes); } interceptAssetCreation() { @@ -208,51 +237,6 @@ export class AssetPage { ); } - selectImportFacility(facilityName: string) { - cy.get("input[name='facilities']") - .type(facilityName) - .then(() => { - cy.get("[role='option']").contains(facilityName).click(); - }); - } - - selectassetimportbutton() { - cy.get("[data-testid=import-asset-button]").click(); - } - - selectJsonExportButton() { - cy.intercept("GET", "**/api/v1/asset/?**json=true**").as("getJsonexport"); - cy.get("#export-json-option").click(); - cy.wait("@getJsonexport").its("response.statusCode").should("eq", 200); - } - - selectCsvExportButton() { - cy.intercept("GET", "**/api/v1/asset/?**csv=true**").as("getCsvexport"); - cy.get("#export-csv-option").click(); - cy.wait("@getCsvexport").its("response.statusCode").should("eq", 200); - } - - selectImportOption() { - cy.get(".import-assets-button").click(); - } - - importAssetFile() { - cy.get("[data-testid=import-file]") - .selectFile("cypress/fixtures/sample-asset.xlsx", { force: true }) - .wait(100); - } - - selectImportLocation(locationName: string) { - cy.get("[data-testid=select-import-location]").click(); - cy.get("li[role=option]").contains(locationName).click(); - } - - clickImportAsset() { - cy.intercept("POST", "**/api/v1/asset/").as("importAsset"); - cy.get("#submit").contains("Import").click(); - cy.wait("@importAsset").its("response.statusCode").should("eq", 201); - } - clickupdatedetailbutton() { cy.get("[data-testid=asset-update-button]").click(); } diff --git a/cypress/pageobject/Asset/AssetFilters.ts b/cypress/pageobject/Asset/AssetFilters.ts index 5a942b22f47..b562841a598 100644 --- a/cypress/pageobject/Asset/AssetFilters.ts +++ b/cypress/pageobject/Asset/AssetFilters.ts @@ -1,71 +1,7 @@ export class AssetFilters { - filterAssets( - facilityName: string, - assetStatus: string, - assetClass: string, - assetLocation: string, - ) { - cy.contains("Advanced Filters").click(); - cy.get("input[name='Facilities']") - .click() - .type(facilityName) - .then(() => { - cy.get("[role='option']").contains(facilityName).click(); - }); - cy.get("#asset-status") - .click() - .then(() => { - cy.get("[role='option']").contains(assetStatus).click(); - }); - cy.get("#asset-class") - .click() - .then(() => { - cy.get("[role='option']").contains(assetClass).click(); - }); - cy.get("#Facilities-location") - .click() - .type(assetLocation) - .then(() => { - cy.get("[role='option']").contains(assetLocation).click(); - }); - cy.contains("Apply").click(); - } - clearFilters() { - cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets"); - cy.get("#clear-filter").click(); - cy.wait("@clearAssets").its("response.statusCode").should("eq", 200); - cy.location("pathname").should("match", /\/assets$/); - cy.url().then((url) => { - const queryParams = new URL(url).searchParams; - let allEmpty = true; - const blacklistedKeys = ["page", "limit", "offset"]; - - queryParams.forEach((value, key) => { - if (value !== "" && !blacklistedKeys.includes(key)) { - allEmpty = false; - } - }); - - expect(allEmpty).to.be.true; - }); - } - clickadvancefilter() { - cy.get("#advanced-filter").click(); - } - clickslideoverbackbutton() { - cy.get("#close-slide-over").click(); - } - // Assertions - assertFacilityText(text: string) { - cy.get("[data-testid=Facility]").should("contain", text); - } - assertAssetClassText(text: string) { - cy.get("[data-testid='Asset Class']").should("contain", text); - } - assertStatusText(text: string) { - cy.get("[data-testid=Status]").should("contain", text); - } - assertLocationText(text: string) { - cy.get("[data-testid=Location]").should("contain", text); + filterAssets(assetStatus: string, assetClass: string, assetLocation: string) { + cy.clickAndSelectOption("#asset-status", assetStatus); + cy.clickAndSelectOption("#asset-class", assetClass); + cy.typeAndSelectOption("#Facilities-location", assetLocation); } } diff --git a/cypress/pageobject/Asset/AssetHome.ts b/cypress/pageobject/Asset/AssetHome.ts new file mode 100644 index 00000000000..e127b785100 --- /dev/null +++ b/cypress/pageobject/Asset/AssetHome.ts @@ -0,0 +1,112 @@ +export class AssetHome { + clickAssetByName(assetName: string) { + cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets"); + cy.get("[data-testid='created-asset-list']").contains(assetName).click(); + cy.wait("@clearAssets").its("response.statusCode").should("eq", 200); + } + + typeAssetSearch(name: string) { + cy.get("#asset-search").click().type(name); + } + + verifyAssetIsPresent(assetName: string) { + cy.get("[data-testid=created-asset-list]") + .first() + .should("contain", assetName); + } + + clickAssetDetailsUpdateButton() { + cy.verifyAndClickElement("[data-testid='asset-update-button']", "Update"); + } + + clearAndTypeQRCode(qrCode: string) { + cy.get("#qr_code_id").clear(); + cy.get("#qr_code_id").click().type(qrCode); + } + + clearAndTypeSerialNumber(serialNumber: string) { + cy.get("#serial-number").clear(); + cy.get("#serial-number").click().type(serialNumber); + } + + clickAssetSubmitButton() { + cy.intercept("GET", "**/api/v1/asset/**").as("getAssets"); + cy.get("#submit").click(); + cy.wait("@getAssets").its("response.statusCode").should("eq", 200); + } + + clickAssetUpdateSubmitButton() { + cy.intercept("GET", "**/api/v1/asset/**").as("getAssets"); + cy.clickSubmitButton("Update"); + cy.wait("@getAssets").its("response.statusCode").should("eq", 200); + } + + navigateToAssetsPage() { + cy.visit("/assets"); + } + + verifyAssetListContains(dummyCameraText: string) { + cy.get("[data-testid='created-asset-list']").should( + "contain", + dummyCameraText, + ); + } + + scanAssetQR() { + cy.contains("Scan Asset QR").click().wait(1000); + cy.get("video").should("exist"); + cy.get("button").contains("Close Scanner").should("exist").click(); + } + + selectImportFacility(facilityName: string) { + cy.get("input[name='facilities']") + .type(facilityName) + .then(() => { + cy.get("[role='option']").contains(facilityName).click(); + }); + } + + selectAssetImportButton(action: "click" | "verifyNotExist"): void { + const selector = "[data-testid=import-asset-button]"; + if (action === "click") { + cy.get(selector).click(); + } else if (action === "verifyNotExist") { + cy.get(selector).should("not.exist"); + } + } + + selectJsonExportButton() { + cy.intercept("GET", "**/api/v1/asset/?**json=true**").as("getJsonexport"); + cy.get("#export-json-option").click(); + cy.wait("@getJsonexport").its("response.statusCode").should("eq", 200); + } + + selectCsvExportButton() { + cy.intercept("GET", "**/api/v1/asset/?**csv=true**").as("getCsvexport"); + cy.get("#export-csv-option").click(); + cy.wait("@getCsvexport").its("response.statusCode").should("eq", 200); + } + + selectImportOption() { + cy.get(".import-assets-button").click(); + } + + importAssetFile() { + cy.get("[data-testid=import-file]") + .selectFile("cypress/fixtures/sample-asset.xlsx", { force: true }) + .wait(100); + } + + selectImportLocation(locationName: string) { + cy.clickAndSelectOption( + "[data-testid=select-import-location]", + locationName, + ); + } + + clickImportAsset() { + cy.intercept("POST", "**/api/v1/asset/").as("importAsset"); + cy.clickSubmitButton("Import"); + cy.wait("@importAsset").its("response.statusCode").should("eq", 201); + } +} diff --git a/cypress/pageobject/Asset/AssetPagination.ts b/cypress/pageobject/Asset/AssetPagination.ts deleted file mode 100644 index f2a4103b065..00000000000 --- a/cypress/pageobject/Asset/AssetPagination.ts +++ /dev/null @@ -1,19 +0,0 @@ -export class AssetPagination { - navigateToNextPage() { - // only works for desktop mode - cy.get("button#next-pages").click(); - } - - verifyNextUrl() { - cy.url().should("include", "page=2"); - } - - navigateToPreviousPage() { - // only works for desktop mode - cy.get("button#prev-pages").click(); - } - - verifyPreviousUrl() { - cy.url().should("include", "page=1"); - } -} diff --git a/cypress/pageobject/Asset/AssetQRScan.ts b/cypress/pageobject/Asset/AssetQRScan.ts deleted file mode 100644 index a88f378f02f..00000000000 --- a/cypress/pageobject/Asset/AssetQRScan.ts +++ /dev/null @@ -1,7 +0,0 @@ -export class AssetQRScanPage { - scanAssetQR() { - cy.contains("Scan Asset QR").click().wait(1000); - cy.get("video").should("exist"); - cy.get("button").contains("Close Scanner").should("exist").click(); - } -} diff --git a/cypress/pageobject/Asset/AssetSearch.ts b/cypress/pageobject/Asset/AssetSearch.ts deleted file mode 100644 index 653c7bdd89c..00000000000 --- a/cypress/pageobject/Asset/AssetSearch.ts +++ /dev/null @@ -1,60 +0,0 @@ -export class AssetSearchPage { - typeSearchKeyword(keyword: string) { - cy.get("#search").click().clear(); - cy.get("#search").click().type(keyword); - } - - pressEnter() { - cy.get("[name='search']").type("{enter}"); - } - - clickAssetByName(assetName: string) { - cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets"); - cy.get("[data-testid='created-asset-list']").contains(assetName).click(); - cy.wait("@clearAssets").its("response.statusCode").should("eq", 200); - } - - verifyBadgeContent(expectedText: string) { - cy.get("[data-testid='Name/Serial No./QR ID']").should( - "contain", - expectedText, - ); - } - - verifyAssetIsPresent(assetName: string) { - cy.get("[data-testid=created-asset-list]") - .first() - .should("contain", assetName); - } - - clickUpdateButton() { - cy.get("[data-testid='asset-update-button']").contains("Update").click(); - } - - clearAndTypeQRCode(qrCode: string) { - cy.get("#qr_code_id").clear(); - cy.get("#qr_code_id").click().type(qrCode); - } - - clearAndTypeSerialNumber(serialNumber: string) { - cy.get("#serial-number").clear(); - cy.get("#serial-number").click().type(serialNumber); - } - - clickAssetSubmitButton() { - cy.intercept("GET", "**/api/v1/asset/**").as("getAssets"); - cy.get("#submit").click(); - cy.wait("@getAssets").its("response.statusCode").should("eq", 200); - } - - visitAssetsPage() { - cy.visit("/assets"); - } - - verifyAssetListContains(dummyCameraText: string) { - cy.get("[data-testid='created-asset-list']").should( - "contain", - dummyCameraText, - ); - } -} diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index a48ffe0856b..4c064956fcc 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -1,4 +1,4 @@ -// FacilityPage.ts +import { advanceFilters } from "pageobject/utils/advanceFilterHelpers"; class FacilityPage { visitCreateFacilityPage() { @@ -9,9 +9,12 @@ class FacilityPage { .should("eq", 200); } - typeFacilitySearch(facilityName: string) { - cy.get("#search").click().clear(); - cy.get("#search").click().type(facilityName); + selectFacilityType(facility: string) { + advanceFilters.selectFacilityType(facility); + } + + selectLocalBody(localBody: string) { + advanceFilters.selectLocalBody(localBody); } visitUpdateFacilityPage(url: string) { @@ -21,14 +24,6 @@ class FacilityPage { cy.get("#manage-facility-dropdown button").should("be.visible"); } - clickUpdateFacilityType(facilityType: string) { - cy.get("#facility_type") - .click() - .then(() => { - cy.get("[role='option']").contains(facilityType).click(); - }); - } - fillFacilityName(name: string) { cy.get("#name").click().clear().click().type(name); } @@ -37,21 +32,6 @@ class FacilityPage { cy.get("#pincode").click().type(pincode); } - selectState(state: string) { - cy.get("div#state button").click(); - cy.get("[role='option']").contains(state).click(); - } - - selectDistrict(district: string) { - cy.get("div#district button").click(); - cy.get("[role='option']").contains(district).click(); - } - - selectLocalBody(localBody: string) { - cy.get("div#local_body button").click(); - cy.get("[role='option']").contains(localBody).click(); - } - selectWard(ward: string) { cy.get("div#ward button").click(); cy.get("[role='option']").contains(ward).click(); @@ -291,7 +271,7 @@ class FacilityPage { } confirmDeleteFacility() { - cy.submitButton("Delete"); + cy.clickSubmitButton("Delete"); } selectLocation(location: string) { @@ -317,6 +297,10 @@ class FacilityPage { cy.verifyNotification(message); } + verifyErrorNotification(message: string) { + cy.verifyNotification(message); + } + visitAlreadyCreatedFacility() { cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); cy.get("[id='facility-details']").first().click(); @@ -324,29 +308,6 @@ class FacilityPage { cy.get("h1.text-3xl.font-bold", { timeout: 10000 }).should("be.visible"); } - verifyFacilityBadgeContent(expectedText: string) { - cy.get("[data-testid='Facility/District Name']").should( - "contain", - expectedText, - ); - } - - verifyStateBadgeContent(expectedText: string) { - cy.get("[data-testid='State']").should("contain", expectedText); - } - - verifyDistrictBadgeContent(expectedText: string) { - cy.get("[data-testid='District']").should("contain", expectedText); - } - - verifyLocalBodyBadgeContent(expectedText: string) { - cy.get("[data-testid='Local Body']").should("contain", expectedText); - } - - verifyFacilityTypeBadgeContent(expectedText: string) { - cy.get("[data-testid='Facility type']").should("contain", expectedText); - } - verifyfacilitycreateassetredirection() { cy.url().should("include", "/assets/new"); } diff --git a/cypress/pageobject/Facility/FacilityHome.ts b/cypress/pageobject/Facility/FacilityHome.ts index dea7de0e7b6..fe8585b48be 100644 --- a/cypress/pageobject/Facility/FacilityHome.ts +++ b/cypress/pageobject/Facility/FacilityHome.ts @@ -1,7 +1,6 @@ class FacilityHome { // Selectors exportButton = "#export-button"; - searchButton = "#search"; menuItem = "[role='menuitem']"; // Operations @@ -10,8 +9,24 @@ class FacilityHome { cy.get(this.exportButton).click(); } - clickSearchButton() { - cy.get(this.searchButton).click(); + navigateToFacilityHomepage() { + cy.visit("/facility"); + } + + assertFacilityInCard(facilityName: string) { + cy.get("#facility-name-card").should("contain", facilityName); + } + + interceptFacilitySearchReq() { + cy.intercept("GET", "**/api/v1/facility/**").as("searchFacility"); + } + + verifyFacilitySearchReq() { + cy.wait("@searchFacility").its("response.statusCode").should("eq", 200); + } + + typeFacilitySearch(facilityName: string) { + cy.get("#facility-search").click().clear().type(facilityName); } clickMenuItem(itemName: string) { @@ -35,7 +50,8 @@ class FacilityHome { } clickFacilityNotifyButton() { - cy.get("#facility-notify").first().click(); + cy.get("#facility-notify", { timeout: 10000 }).should("be.visible"); + cy.get("#facility-notify").focus().click(); } clickLiveMonitorButton() { @@ -75,11 +91,6 @@ class FacilityHome { cy.get('[data-test-id="occupancy-badge"]').should("be.visible"); } - verifyAndCloseNotifyModal() { - cy.get("#cancel").should("be.visible"); - cy.get("#cancel").click(); - } - navigateBack() { cy.go(-1); } diff --git a/cypress/pageobject/Facility/FacilityLocation.ts b/cypress/pageobject/Facility/FacilityLocation.ts index 31bc30290f7..9cb23f9fba0 100644 --- a/cypress/pageobject/Facility/FacilityLocation.ts +++ b/cypress/pageobject/Facility/FacilityLocation.ts @@ -1,37 +1,81 @@ -class FacilityLocation { - loadLocationManagementPage(name: string) { - cy.awaitUrl("/"); - cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); - cy.get("[id='facility-name-card']").contains(name).click(); - cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); - cy.get("h1.text-3xl.font-bold", { timeout: 10000 }).should("be.visible"); - cy.get("#manage-facility-dropdown button").should("be.visible"); - cy.get("[id='manage-facility-dropdown']").scrollIntoView().click(); - cy.get("[id=location-management]").click(); - } +import FacilityPage from "./FacilityCreation"; +import FacilityHome from "./FacilityHome"; - closeNotification() { - cy.get(".pnotify") - .should("exist") - .each(($div) => { - cy.wrap($div).click(); - }); +const facilityHome = new FacilityHome(); +const facilityPage = new FacilityPage(); + +class FacilityLocation { + navigateToFacilityLocationManagement(facilityName: string) { + facilityHome.typeFacilitySearch(facilityName); + facilityHome.assertFacilityInCard(facilityName); + facilityHome.clickViewFacilityDetails(); + facilityPage.clickManageFacilityDropdown(); + this.clickFacilityLocationManagement(); + } + + fillLocationDetails( + name?: string, + description?: string, + type?: string, + middleware?: string, + ) { + if (name) this.typeLocationName(name); + if (description) this.fillDescription(description); + if (type) this.selectLocationType(type); + if (middleware) this.fillMiddlewareAddress(middleware); + } + + fetchAndNavigateToLocationPage() { + cy.url().then((currentUrl) => { + const baseUrl = currentUrl.split("/location/")[0]; + const locationUrl = `${baseUrl}/location/`; + cy.visit(locationUrl); + }); + } + + fillBedForm( + bedName?: string, + bedDescription?: string, + bedType?: string, + numberOfBeds?: number, + ) { + if (bedName) this.enterBedName(bedName); + if (bedDescription) { + this.enterBedDescription(bedDescription); + } + if (bedType) this.selectBedType(bedType); + if (numberOfBeds && numberOfBeds > 1) { + this.setMultipleBeds(numberOfBeds); + } } clickAddNewLocationButton() { cy.get("#add-new-location").click(); } + typeLocationName(locationName: string) { + cy.get("#location-name").type(locationName); + } + clickFacilityLocationManagement() { cy.get("[id=location-management]").click(); } + clickAddLocationButton() { + cy.clickSubmitButton("Add Location"); + } + clickEditLocationButton() { cy.get("#edit-location-button").click(); } - clickEditBedButton() { - cy.get("#edit-bed-button").click(); + clickEditBedButton(cardText: string) { + cy.get("#bed-cards") + .contains(cardText) + .parents("#bed-cards") + .within(() => { + cy.get("#edit-bed-button").click(); + }); } fillDescription(description: string) { @@ -42,13 +86,8 @@ class FacilityLocation { cy.get("div").contains(name).click(); } - enterLocationName(name: string) { - cy.get("input[id=name]").type(name); - } - selectLocationType(type: string) { - cy.get("#location-type").click(); - cy.get("li[role=option]").contains(type).click(); + cy.clickAndSelectOption("#location-type", type); } fillMiddlewareAddress(address: string) { @@ -63,10 +102,6 @@ class FacilityLocation { cy.get("#location-type").contains(type); } - verifyNotification(message: string) { - cy.get(".pnotify-container").should("contain", message).and("be.visible"); - } - verifyLocationDescription(description: string) { cy.get("#view-location-description").contains(description); } @@ -75,16 +110,49 @@ class FacilityLocation { cy.get("#view-location-middleware").contains(middleware); } - clickManageBedButton() { - cy.get("#manage-bed-button").first().click(); + clickManageBedButton(cardText: string) { + cy.get("#location-cards") + .contains(cardText) + .parents("#location-cards") + .within(() => { + cy.get("#manage-bed-button").click(); + }); + } + + clickManageBedPopup() { + cy.get("#manage-beds").click(); } clickAddBedButton() { - cy.get("#add-new-bed").click(); + cy.verifyAndClickElement("#add-new-bed", "Add New Bed(s)"); + } + + clickSubmitBedsButton() { + cy.clickSubmitButton("Add Bed(s)"); + } + + closeAddLocationForm() { + cy.clickCancelButton("Cancel"); + } + + verifyAddLocationSuccessfulMesssage() { + cy.verifyNotification("Location created successfully"); + cy.closeNotification(); } - clickNotification() { - cy.get(".pnotify-container").click(); + verifyEditBedSuccessfulMessage() { + cy.verifyNotification("Bed updated successfully"); + cy.closeNotification(); + } + + verifyEditLocationSuccessfulMessage() { + cy.verifyNotification("Location updated successfully"); + cy.closeNotification(); + } + + verifyAddSingleBedSuccessfulMesssage() { + cy.verifyNotification("1 Bed created successfully"); + cy.closeNotification(); } enterBedName(name: string) { @@ -95,6 +163,14 @@ class FacilityLocation { cy.get("#bed-description").clear().click().type(description); } + clickUpdateBedButton() { + cy.clickSubmitButton("Update Bed"); + } + + clickUpdateLocationButton() { + cy.clickSubmitButton("Update Location"); + } + selectBedType(type: string) { cy.get("#bed-type").click(); cy.get("li[role=option]").contains(type).click(); @@ -136,16 +212,22 @@ class FacilityLocation { cy.get("#manage-assets").click(); } - deleteLocation(name: string) { - cy.contains("div", name) - .should("exist") - .then(($div) => { - $div.parents("div").eq(2).find("button#delete-location-button").click(); + clickDeleteLocation(cardText: string) { + cy.get("#location-cards") + .contains(cardText) + .parents("#location-cards") + .within(() => { + cy.verifyAndClickElement("#delete-location-button", "Delete"); }); } - deleteFirstBed() { - cy.get("#delete-bed-button").first().click(); + deleteBedWithName(text: string) { + cy.get("#bed-cards") + .contains(text) + .parents("#bed-cards") + .within(() => { + cy.get("#delete-bed-button").click(); + }); } deleteBedRequest() { diff --git a/cypress/pageobject/Facility/FacilityNotify.ts b/cypress/pageobject/Facility/FacilityNotify.ts new file mode 100644 index 00000000000..08c44b32e84 --- /dev/null +++ b/cypress/pageobject/Facility/FacilityNotify.ts @@ -0,0 +1,58 @@ +export default class FacilityNotify { + verifyFacilityName(facilityName: string) { + cy.verifyContentPresence("#notify-facility-name", [facilityName]); + } + + verifyErrorMessage(errorMessage: string) { + cy.verifyContentPresence(".error-text", [errorMessage]); + } + + fillNotifyText(message: string) { + cy.get("#NotifyModalMessageInput").scrollIntoView(); + cy.get("#NotifyModalMessageInput").click().type(message); + } + + verifyFacilityNoticeBoardMessage(message: string) { + cy.get("#notification-message", { timeout: 10000 }).should("be.visible"); + cy.verifyContentPresence("#notification-message", [message]); + } + + openNotificationSlide() { + cy.get("#notification-slide-btn").should("be.visible").click(); + } + + closeNotificationSlide() { + cy.get("#close-slide-over").should("be.visible").click(); + } + + visitNoticeBoard() { + cy.get("a[href='/notice_board']").should("be.visible").click(); + } + + visitNotificationSideBar() { + cy.get("#notification-slide-btn").should("be.visible").click(); + } + + verifyUrlContains(substring: string) { + cy.url().should("include", substring); + } + + interceptPostNotificationReq() { + cy.intercept("POST", "**/api/v1/notification/notify").as("notifyFacility"); + } + + verifyPostNotificationReq() { + cy.wait("@notifyFacility").its("response.statusCode").should("eq", 204); + } + + interceptGetNotificationReq(event: string = "") { + cy.intercept( + "GET", + `**/api/v1/notification/?offset=0&event=${event}&*=SYSTEM`, + ).as("getNotifications"); + } + + verifyGetNotificationReq() { + cy.wait("@getNotifications").its("response.statusCode").should("eq", 200); + } +} diff --git a/cypress/pageobject/Hcx/HcxClaims.ts b/cypress/pageobject/Hcx/HcxClaims.ts new file mode 100644 index 00000000000..b93862e6d13 --- /dev/null +++ b/cypress/pageobject/Hcx/HcxClaims.ts @@ -0,0 +1,12 @@ +export class HcxClaims { + selectEligiblePolicy(policy: string) { + cy.get("#select-insurance-policy", { timeout: 10000 }) + .should("be.visible") + .and("not.be.disabled"); + cy.clickAndSelectOption("#select-insurance-policy", policy); + } + + verifyPolicyEligibility() { + cy.verifyAndClickElement("#check-eligibility", "Check Eligibility"); + } +} diff --git a/cypress/pageobject/Login/LoginPage.ts b/cypress/pageobject/Login/LoginPage.ts index cd5230a7772..481c6ec3045 100644 --- a/cypress/pageobject/Login/LoginPage.ts +++ b/cypress/pageobject/Login/LoginPage.ts @@ -1,32 +1,28 @@ -// LoginPage.ts +import { users } from "../utils/userConfig"; class LoginPage { - loginAsDistrictAdmin(): void { - cy.loginByApi("devdistrictadmin", "Coronasafe@123"); + loginByRole(role: keyof typeof users): void { + const user = users[role]; + if (!user) { + throw new Error(`Role "${role}" is not defined in userConfig`); + } + cy.loginByApi(user.username, user.password); } - loginAsDevDoctor(): void { - cy.loginByApi("devdoctor", "Coronasafe@123"); - } - - loginAsStaff(): void { - cy.loginByApi("staffdev", "Coronasafe@123"); - } - - loginManuallyAsDistrictAdmin(): void { + loginManuallyAsDistrictAdmin(isCorrectCredentials: boolean = true): void { cy.get("input[id='username']").type("devdistrictadmin"); - cy.get("input[id='password']").type("Coronasafe@123"); - cy.get("button").contains("Login").click(); + if (isCorrectCredentials) { + cy.get("input[id='password']").type("Coronasafe@123"); + } else { + cy.get("input[id='password']").type("Corona"); + } + cy.clickSubmitButton("Login"); } loginManuallyAsNurse(): void { cy.get("input[id='username']").click().type("dummynurse1"); cy.get("input[id='password']").click().type("Coronasafe@123"); - cy.get("button").contains("Login").click(); - } - - login(username: string, password: string): void { - cy.loginByApi(username, password); + cy.clickSubmitButton("Login"); } ensureLoggedIn(): void { @@ -34,6 +30,62 @@ class LoginPage { cy.get("#sign-out-button").scrollIntoView(); cy.get("#sign-out-button").contains("Sign Out").should("exist"); } + + clickSignOutBtn(): void { + cy.verifyAndClickElement("#sign-out-button", "Sign Out"); + } + + fillUserNameInForgotPasswordForm(userName: string): void { + cy.get("#forgot_username").type(userName); + } + + clickSendResetLinkBtn(): void { + cy.verifyAndClickElement("#send-reset-link-btn", "Send Reset Link"); + } + + verifyLoginPageUrl(): void { + cy.url().should("include", "/"); + } + + clickBackButton(): void { + cy.verifyAndClickElement("#back-to-login-btn", "Back to login"); + } + + clickForgotPasswordButton(text: string): void { + cy.verifyAndClickElement("#forgot-pass-btn", text); + } + + interceptFacilityReq(): void { + cy.intercept("GET", "**/api/v1/facility/**").as("getFacilities"); + } + + verifyFacilityReq(): void { + cy.wait("@getFacilities").its("response.statusCode").should("eq", 200); + } + + interceptLoginReq(): void { + cy.intercept("POST", "**/api/v1/auth/login").as("userLogin"); + } + + verifyLoginReq(): void { + cy.wait("@userLogin").its("response.statusCode").should("eq", 401); + } + + interceptResetLinkReq(): void { + cy.intercept("POST", "**/api/v1/password_reset").as("resetLink"); + } + + verifyResetLinkReq(): void { + cy.wait("@resetLink").its("response.statusCode").should("eq", 200); + } + + verifyLoginButtonPresence(): void { + cy.verifyContentPresence("#login-button", ["Login"]); + } + + verifyForgotPasswordHeading(text: string[]): void { + cy.verifyContentPresence("#forgot-password-heading", text); + } } export default LoginPage; diff --git a/cypress/pageobject/Patient/PatientConsultation.ts b/cypress/pageobject/Patient/PatientConsultation.ts index e0b51b9265e..edd8ae135a4 100644 --- a/cypress/pageobject/Patient/PatientConsultation.ts +++ b/cypress/pageobject/Patient/PatientConsultation.ts @@ -13,6 +13,7 @@ export class PatientConsultationPage { selectSymptomsDate(date: string) { cy.clickAndTypeDate("#symptoms_onset_date", date); } + clickAddSymptom() { cy.get("#add-symptom").click(); } @@ -111,4 +112,31 @@ export class PatientConsultationPage { ); cy.wait(3000); } + + interceptPatientDetailsAPI(): void { + cy.intercept("GET", "**/api/v1/patient/**").as("patientDetails"); + } + + verifyPatientDetailsResponse(): void { + cy.wait("@patientDetails").its("response.statusCode").should("eq", 200); + } + + clickViewConsultationButton() { + cy.get("a").contains("Encounters").click(); + cy.verifyAndClickElement( + "#view_consultation_and_log_updates", + "View Updates", + ); + } + + clickManagePatientButton() { + cy.verifyAndClickElement("#show-more", "Manage Patient"); + } + + clickClaimsButton() { + cy.get("#log-update").scrollIntoView(); + cy.intercept(/\/api\/hcx\/policy\/\?.*/).as("policyStatus"); + cy.get("#consultation-buttons").contains("Claims").click(); + cy.wait("@policyStatus").its("response.statusCode").should("eq", 200); + } } diff --git a/cypress/pageobject/Patient/PatientCreation.ts b/cypress/pageobject/Patient/PatientCreation.ts index 41b3c02977d..febf31b33b5 100644 --- a/cypress/pageobject/Patient/PatientCreation.ts +++ b/cypress/pageobject/Patient/PatientCreation.ts @@ -11,7 +11,8 @@ export class PatientPage { } visitPatient(patientName: string) { - cy.get("#name").click().type(patientName); + cy.get('[data-test-id="patient-search__name"]').click(); + cy.get("#patient-search").click().type(patientName); // Type the patient name cy.intercept("GET", "**/api/v1/consultation/**").as("getPatient"); cy.get("#patient-name-list").contains(patientName).click(); cy.wait(2000); @@ -23,7 +24,7 @@ export class PatientPage { selectFacility(facilityName: string) { cy.typeAndSelectOption("input[name='facilities']", facilityName); - cy.submitButton("Select"); + cy.clickSubmitButton("Select"); } interceptCreatePatientAPI() { @@ -57,7 +58,7 @@ export class PatientPage { typePatientAge(age: string) { cy.clickAndSelectOption("#patientAge", "Age"); - cy.submitButton("Confirm"); + cy.clickSubmitButton("Confirm"); cy.get("#age").clear().type(age); } @@ -66,7 +67,8 @@ export class PatientPage { } typePatientNameList(patientName: string) { - cy.get("#name").click().type(patientName); + cy.get('[data-test-id="patient-search__name"]').click(); + cy.get("#patient-search").click().type(patientName); } typePatientAddress(address: string) { @@ -181,7 +183,7 @@ export class PatientPage { expect($dashboard).to.contain(patientName); expect($dashboard).to.contain(phoneNumber); expect($dashboard).to.contain(emergencyPhoneNumber); - expect($dashboard).to.contain(yearOfBirth); + //expect($dashboard).to.contain(yearOfBirth); //Commented out because new proposed UI does not have DOB. Can change later. expect($dashboard).to.contain(bloodGroup); expect($dashboard).to.contain(occupation); socioeconomicStatus && expect($dashboard).to.contain(socioeconomicStatus); @@ -220,6 +222,10 @@ export class PatientPage { cy.visit(patient_url + "/update"); } + clickPatientUpdateDetails() { + cy.verifyAndClickElement("#update-patient-details", "Edit Profile"); + } + interceptFacilities() { cy.intercept("GET", "**/facility/*/patient/**").as("getFacilities"); } diff --git a/cypress/pageobject/Patient/PatientFileupload.ts b/cypress/pageobject/Patient/PatientFileupload.ts index 0616a19729c..c70170a744d 100644 --- a/cypress/pageobject/Patient/PatientFileupload.ts +++ b/cypress/pageobject/Patient/PatientFileupload.ts @@ -20,7 +20,9 @@ export class PatientFileUpload { recordAudio() { cy.get("#record-audio").click(); - cy.wait(5000); + cy.wait(2000); + cy.get("#start-recording").click(); + cy.wait(2000); cy.get("#stop-recording").click(); cy.wait(1000); cy.get("#save-recording").click(); @@ -58,7 +60,7 @@ export class PatientFileUpload { clickSaveArchiveFile() { cy.intercept("PATCH", "**/api/v1/files/**").as("saveArchiveFile"); - cy.submitButton("Proceed"); + cy.clickSubmitButton("Proceed"); cy.wait("@saveArchiveFile").its("response.statusCode").should("eq", 200); } @@ -89,7 +91,7 @@ export class PatientFileUpload { clickSaveFileName() { cy.intercept("PATCH", "**/api/v1/files/**").as("saveFileName"); - cy.submitButton("Proceed"); + cy.clickSubmitButton("Proceed"); cy.wait("@saveFileName").its("response.statusCode").should("eq", 200); } } diff --git a/cypress/pageobject/Patient/PatientHome.ts b/cypress/pageobject/Patient/PatientHome.ts index a69a96c3f77..36cad15f0e5 100644 --- a/cypress/pageobject/Patient/PatientHome.ts +++ b/cypress/pageobject/Patient/PatientHome.ts @@ -1,16 +1,4 @@ class PatientHome { - clickNextPage() { - cy.get("#next-pages").click(); - } - - verifySecondPageUrl() { - cy.url().should("include", "/patients?page=2"); - } - - clickPreviousPage() { - cy.get("#prev-pages").click(); - } - clickPatientExport() { cy.get("#patient-export").click(); } @@ -60,10 +48,6 @@ class PatientHome { ); } - clickPatientAdvanceFilters() { - cy.get("#advanced-filter").click(); - } - selectPatientGenderfilter(gender: string) { cy.clickAndSelectOption("#gender-advancefilter", gender); } diff --git a/cypress/pageobject/Patient/PatientInsurance.ts b/cypress/pageobject/Patient/PatientInsurance.ts index 1b91d27b629..79d6e3b7510 100644 --- a/cypress/pageobject/Patient/PatientInsurance.ts +++ b/cypress/pageobject/Patient/PatientInsurance.ts @@ -9,32 +9,10 @@ class PatientInsurance { }); } - selectInsurer(insurer: string) { - cy.intercept("GET", "**/api/v1/hcx/payors/**", { - statusCode: 200, - body: [ - { - name: "test payor 2", - code: "testpayor2.swasthmock@swasth-hcx-staging", - }, - { - name: "Care Payor", - code: "khavinshankar.gmail@swasth-hcx-staging", - }, - { - name: "Alliance", - code: "hcxdemo.yopmail@swasth-hcx-staging", - }, - ], - }).as("getInsurer"); - cy.get("[name='insurer']") - .last() - .click() - .type(insurer) - .then(() => { - cy.wait("@getInsurer"); - cy.get("[role='option']").contains(insurer).click(); - }); + selectPatientInsurerName(containerId: string, value: string) { + cy.get(`#${containerId}`).within(() => { + cy.typeAndSelectOption("#insurer", value); + }); } clickPatientInsuranceViewDetail() { @@ -49,18 +27,13 @@ class PatientInsurance { verifyPatientPolicyDetails( subscriberId: string, policyId: string, - insurerId: string, insurerName: string, - isHcxEnabled: string, ) { cy.get("[data-testid=patient-details]").then(($dashboard) => { cy.url().should("include", "/facility/"); expect($dashboard).to.contain(subscriberId); expect($dashboard).to.contain(policyId); - if (!isHcxEnabled) { - expect($dashboard).to.contain(insurerId); - expect($dashboard).to.contain(insurerName); - } + expect($dashboard).to.contain(insurerName); }); } } diff --git a/cypress/pageobject/Patient/PatientInvestigation.ts b/cypress/pageobject/Patient/PatientInvestigation.ts index 8f73cf908bc..a9f8f38435a 100644 --- a/cypress/pageobject/Patient/PatientInvestigation.ts +++ b/cypress/pageobject/Patient/PatientInvestigation.ts @@ -1,11 +1,9 @@ class PatientInvestigation { clickAddInvestigation() { - cy.get("#investigation").scrollIntoView(); cy.verifyAndClickElement("#investigation", "Add Investigation"); } clickInvestigationTab() { - cy.get("#consultation_tab_nav").scrollIntoView(); cy.verifyAndClickElement("#consultation_tab_nav", "Investigations"); } @@ -19,6 +17,14 @@ class PatientInvestigation { cy.get("#investigation-checkbox").click(); } + selectInvestigationOption(options: string[]) { + cy.clickAndMultiSelectOption("#investigations", options); + } + + clickLogLabResults() { + cy.verifyAndClickElement("#log-lab-results", "Log Lab Results"); + } + selectInvestigationFrequency(frequency: string) { cy.get("#investigation-frequency").click(); cy.contains("button", frequency).should("be.visible").click(); diff --git a/cypress/pageobject/Patient/PatientLogupdate.ts b/cypress/pageobject/Patient/PatientLogupdate.ts index d7b49fde05e..45c1924e1a3 100644 --- a/cypress/pageobject/Patient/PatientLogupdate.ts +++ b/cypress/pageobject/Patient/PatientLogupdate.ts @@ -51,7 +51,7 @@ class PatientLogupdate { } typePulse(pulse: string) { - cy.typeAndSelectOption("#pulse", pulse); + cy.get("#pulse").click().type(pulse); } typeTemperature(temperature: string) { @@ -59,11 +59,11 @@ class PatientLogupdate { } typeRespiratory(respiratory: string) { - cy.typeAndSelectOption("#resp", respiratory); + cy.get("#resp").click().type(respiratory); } typeSpo2(spo: string) { - cy.typeAndSelectOption("#ventilator_spo2", spo); + cy.get("#ventilator_spo2").click().type(spo); } selectRhythm(rhythm: string) { @@ -89,7 +89,7 @@ class PatientLogupdate { } clickUpdateDetail() { - cy.verifyAndClickElement("#consultation-preview", "Update Details"); + cy.verifyAndClickElement("#consultation-preview", "Update Log"); cy.wait(3000); } diff --git a/cypress/pageobject/Patient/PatientMedicalHistory.ts b/cypress/pageobject/Patient/PatientMedicalHistory.ts index 93fdd1b38b3..bf2296b4471 100644 --- a/cypress/pageobject/Patient/PatientMedicalHistory.ts +++ b/cypress/pageobject/Patient/PatientMedicalHistory.ts @@ -33,7 +33,9 @@ class PatientMedicalHistory { patientSymptoms6: string, patientSymptoms7: string, ) { - cy.get("[data-testid=patient-details]").then(($dashboard) => { + cy.get("a").contains("Health Profile").click(); + cy.wait(2000); + cy.get("[data-test-id=patient-health-profile]").then(($dashboard) => { cy.url().should("include", "/facility/"); expect($dashboard).to.contain(patientPresentHealth); expect($dashboard).to.contain(patientOngoingMedication); diff --git a/cypress/pageobject/Patient/PatientPredefined.ts b/cypress/pageobject/Patient/PatientPredefined.ts index f0a005ec97b..445fbaf9b31 100644 --- a/cypress/pageobject/Patient/PatientPredefined.ts +++ b/cypress/pageobject/Patient/PatientPredefined.ts @@ -1,11 +1,10 @@ // PatientPredefined.js - -import { PatientPage } from "../../pageobject/Patient/PatientCreation"; import FacilityPage from "../../pageobject/Facility/FacilityCreation"; +import { PatientPage } from "../../pageobject/Patient/PatientCreation"; import PatientMedicalHistory from "../../pageobject/Patient/PatientMedicalHistory"; import { - generatePhoneNumber, generateEmergencyPhoneNumber, + generatePhoneNumber, } from "../utils/constants"; class PatientPredefined { @@ -20,7 +19,9 @@ class PatientPredefined { patientPage.typePatientDateOfBirth("01012001"); patientPage.typePatientName("Patient With Predefined Data"); patientPage.selectPatientGender("Male"); - patientPage.typePatientAddress("Test Patient Address"); + patientPage.typePatientAddress( + "149/J, 3rd Block, Aluva, Ernakulam - 682001", + ); facilityPage.fillPincode("682001"); facilityPage.selectStateOnPincode("Kerala"); facilityPage.selectDistrictOnPincode("Ernakulam"); diff --git a/cypress/pageobject/Sample/SampleTestCreate.ts b/cypress/pageobject/Sample/SampleTestCreate.ts new file mode 100644 index 00000000000..445d08732c3 --- /dev/null +++ b/cypress/pageobject/Sample/SampleTestCreate.ts @@ -0,0 +1,116 @@ +export class SampleTestPage { + visitSampleRequestPage(): void { + cy.get("a").contains("Service Request").click(); + cy.verifyAndClickElement("#sample-request-btn", "Request Sample Test"); + cy.url().should("include", "/sample-test"); + } + + selectSampleType(option: string): void { + cy.clickAndSelectOption("#sample-type", option); + } + + selectIcmrCategory(option: string): void { + cy.clickAndSelectOption("#icmr-category", option); + } + + fillIcmrLabel(label: string): void { + cy.get("#icmr-label").should("be.visible").type(label); + } + + fillFastTrackReason(value: string): void { + cy.get("#is_fast_track").should("be.visible").check(); + cy.get("#fast_track").should("be.visible").type(value); + } + + fillDoctorName(value: string): void { + cy.get("#doctor_name").should("be.visible").type(value); + } + + fillAtypicalPresentation(value: string): void { + cy.get("#is_atypical_presentation").should("be.visible").check(); + cy.get("#atypical_presentation").should("be.visible").type(value); + } + + fillDiagnosis(value: string): void { + cy.get("#diagnosis").should("be.visible").type(value); + } + + fillEtiology(value: string): void { + cy.get("#etiology_identified").should("be.visible").type(value); + } + + fillDiffDiagnosis(value: string): void { + cy.get("#diff_diagnosis").should("be.visible").type(value); + } + + checkHasSari(): void { + cy.get("#has_sari").should("be.visible").check(); + } + + checkHasAri(): void { + cy.get("#has_ari").should("be.visible").check(); + } + + checkIsUnusualCourse(): void { + cy.get("#is_unusual_course").should("be.visible").check(); + } + + checkRequestHistory( + sampleTestStatus: string, + sampleTestType: string, + fastTrack: string, + sampleTestResult: string, + ): void { + cy.get("a").contains("Service Request").click(); + cy.verifyContentPresence("#sample-test-status", [sampleTestStatus]); + cy.verifyContentPresence("#sample-test-type", [sampleTestType]); + cy.verifyContentPresence("#sample-test-fast-track", [fastTrack]); + cy.verifyContentPresence("#sample-test-result", [sampleTestResult]); + } + + searchPatientSample(patientName: string): void { + cy.get("#search_patient_name").should("be.visible").type(patientName); + } + + verifyPatientName(patientName: string): void { + cy.verifyContentPresence("#sample-test-patient-name", [patientName]); + } + + clickOnSampleDetailsBtn(): void { + cy.get("#sample-details-btn").should("be.visible").first().click(); + } + + verifyPatientTestDetails( + patientName: string, + fastTrackReason: string, + doctorName: string, + diagnosis: string, + differentialDiagnosis: string, + etiologyIdentified: string, + ): void { + cy.verifyContentPresence("#patient_name", [patientName]); + cy.verifyContentPresence("#fast_track_reason", [fastTrackReason]); + cy.verifyContentPresence("#doctor_name", [doctorName]); + cy.verifyContentPresence("#diagnosis", [diagnosis]); + cy.verifyContentPresence("#diff_diagnosis", [differentialDiagnosis]); + cy.verifyContentPresence("#etiology_identified", [etiologyIdentified]); + } + + interceptSampleTestReq(): void { + cy.intercept("POST", "**/api/v1/patient/*/test_sample/").as( + "sampleDetails", + ); + } + + verifySampleTestReq(): void { + cy.wait("@sampleDetails").its("response.statusCode").should("eq", 201); + } + + interceptGetSampleTestReq(): void { + cy.intercept("GET", "**/api/v1/test_sample/**").as("getSampleTestReq"); + } + + verifyGetSampleTestReq(): void { + cy.wait("@getSampleTestReq").its("response.statusCode").should("eq", 200); + } +} diff --git a/cypress/pageobject/Shift/ShiftFilters.ts b/cypress/pageobject/Shift/ShiftFilters.ts index fe20b97bd9f..d191436c0e9 100644 --- a/cypress/pageobject/Shift/ShiftFilters.ts +++ b/cypress/pageobject/Shift/ShiftFilters.ts @@ -1,8 +1,4 @@ class ShiftingPage { - advancedFilterButton() { - return cy.get("#advanced-filter"); - } - originFacilityInput() { return cy.get("input[name='origin_facility']"); } diff --git a/cypress/pageobject/Users/ManageUserPage.ts b/cypress/pageobject/Users/ManageUserPage.ts index 470862693a8..01871acd97d 100644 --- a/cypress/pageobject/Users/ManageUserPage.ts +++ b/cypress/pageobject/Users/ManageUserPage.ts @@ -90,19 +90,6 @@ export class ManageUserPage { ); } - navigateToFacility() { - cy.visit("/facility"); - } - - typeFacilitySearch(facilityName: string) { - cy.get("#search").click().clear(); - cy.get("#search").click().type(facilityName); - } - - assertFacilityInCard(facilityName: string) { - cy.get("#facility-name-card").should("contain", facilityName); - } - clickFacilityPatients() { cy.get("#facility-patients").should("be.visible"); cy.get("#facility-patients").click(); diff --git a/cypress/pageobject/Users/UserCreation.ts b/cypress/pageobject/Users/UserCreation.ts index 906c07e797a..d8d386402b7 100644 --- a/cypress/pageobject/Users/UserCreation.ts +++ b/cypress/pageobject/Users/UserCreation.ts @@ -1,79 +1,51 @@ // UserCreation.ts export class UserCreationPage { - clickElementById(elementId: string) { - cy.get("#" + elementId).click(); + clickAddUserButton() { + cy.verifyAndClickElement("#addUserButton", "Add New User"); } - - typeIntoElementById(elementId: string, value: string) { - cy.get("#" + elementId) - .click() - .type(value); + typeUserName(username: string) { + cy.get("#username").click().type(username); } - - typeIntoElementByIdPostClear(elementId: string, value: string) { - cy.get("#" + elementId) - .click() - .clear() - .click() - .type(value); + typeFirstName(firstName: string) { + cy.get("#firstName").click().type(firstName); } - typeIntoElementByIdPostClearDob(elementId: string, value: string) { - cy.clickAndTypeDate("#" + elementId, value); + typeLastName(lastName: string) { + cy.get("#lastName").click().type(lastName); } - clearIntoElementById(elementId: string) { - cy.get("#" + elementId) - .click() - .clear(); + typePassword(password: string) { + cy.get("#password").click().type(password); } - - typeIntoInputByName(inputName: string, value: string) { - cy.get("input[name='" + inputName + "']") - .click() - .type(value); + typeConfirmPassword(password: string) { + cy.get("#c_password").click().type(password); } - - selectOptionContainingText(text: string) { - cy.get("[role='option']").contains(text).click(); + clearFirstName() { + cy.get("#firstName").click().clear(); } - - verifyNotification(message: string) { - cy.verifyNotification(message); + clearLastName() { + cy.get("#lastName").click().clear(); } - - selectFacility(name: string) { - this.typeIntoInputByName("facilities", name); - this.selectOptionContainingText(name); - cy.get("input[name='facilities'] + button") - .find("#dropdown-toggle") - .click(); + selectUserType(role: string) { + cy.clickAndSelectOption("#user_type", role); } - selectHomeFacility(name: string) { - this.clickElementById("home_facility"); - this.selectOptionContainingText(name); + cy.clickAndSelectOption("#home_facility", name); } - setInputDate(dateElementId: string, dateValue: string) { - cy.clickAndTypeDate("#" + dateElementId, dateValue); + selectGender(gender: string) { + cy.clickAndSelectOption("#gender", gender); } - - selectDropdownOption(dropdownId: string, optionText: string) { - this.clickElementById(dropdownId); - this.selectOptionContainingText(optionText); + selectState(state: string) { + cy.clickAndSelectOption("#state", state); + } + selectDistrict(district: string) { + cy.clickAndSelectOption("#district", district); } - verifyElementContainsText(elementId: string, expectedText: string) { - cy.get("#" + elementId).should("contain.text", expectedText); + selectFacility(name: string) { + cy.typeAndSelectOption("input[name='facilities']", name); } - verifyErrorMessages(errorMessages: string[]) { - cy.get(".error-text").then(($errors) => { - const displayedErrorMessages = $errors - .map((_, el) => Cypress.$(el).text()) - .get(); - errorMessages.forEach((errorMessage) => { - expect(displayedErrorMessages).to.include(errorMessage); - }); - }); + clickSaveUserButton() { + cy.clickSubmitButton("Save User"); } } diff --git a/cypress/pageobject/Users/UserProfilePage.ts b/cypress/pageobject/Users/UserProfilePage.ts index 3744c5a5d82..882be0b7b9b 100644 --- a/cypress/pageobject/Users/UserProfilePage.ts +++ b/cypress/pageobject/Users/UserProfilePage.ts @@ -12,11 +12,24 @@ export default class UserProfilePage { } clickUpdateButton() { - cy.get("#submit").click(); + cy.clickSubmitButton("Update"); } - typedate_of_birth(date_of_birth: string) { - cy.clickAndTypeDate("#date_of_birth", date_of_birth); + typeDateOfBirth(dob: string) { + cy.clickAndTypeDate("#date_of_birth", dob); + } + + clearPhoneNumber() { + cy.get("#phoneNumber").click().clear(); + } + clearAltPhoneNumber() { + cy.get("#altPhoneNumber").click().clear(); + } + clearWorkingHours() { + cy.get("#weekly_working_hours").click().clear(); + } + clearEmail() { + cy.get("#email").click().clear(); } selectGender(gender: string) { @@ -28,16 +41,16 @@ export default class UserProfilePage { cy.get("#email").click().clear().type(email); } - typePhone(phone: string) { + typePhoneNumber(phone: string) { cy.get("#phoneNumber").click().clear().type(phone); } - typeWhatsApp(phone: string) { + typeWhatsappNumber(phone: string) { cy.get("#altPhoneNumber").click().clear().type(phone); } - typeWorkingHours(workinghours: string) { - cy.get("#weekly_working_hours").click().clear().type(workinghours); + typeWorkingHours(workingHours: string) { + cy.get("#weekly_working_hours").click().clear().type(workingHours); } typeQualification = (qualification: string) => { @@ -55,11 +68,8 @@ export default class UserProfilePage { .type(medicalCouncilRegistration); }; - assertdate_of_birth(date_of_birth: string) { - cy.get("#date_of_birth-profile-details").should( - "contain.text", - date_of_birth, - ); + assertDateOfBirth(dob: string) { + cy.get("#date_of_birth-profile-details").should("contain.text", dob); } assertGender(gender: string) { @@ -70,18 +80,18 @@ export default class UserProfilePage { cy.get("#emailid-profile-details").should("contain.text", email); } - assertPhone(phone: string) { + assertPhoneNumber(phone: string) { cy.get("#contactno-profile-details").should("contain.text", phone); } - assertWhatsApp(phone: string) { + assertAltPhoneNumber(phone: string) { cy.get("#whatsapp-profile-details").should("contain.text", phone); } - assertWorkingHours(workinghours: string) { + assertWorkingHours(workingHours: string) { cy.get("#averageworkinghour-profile-details").should( "contain.text", - workinghours, + workingHours, ); } } diff --git a/cypress/pageobject/Users/UserSearch.ts b/cypress/pageobject/Users/UserSearch.ts index 1292395fce3..9d996abd83f 100644 --- a/cypress/pageobject/Users/UserSearch.ts +++ b/cypress/pageobject/Users/UserSearch.ts @@ -35,10 +35,6 @@ export class UserPage { cy.get(this.removeIcon).click(); } - clickAdvancedFilters() { - cy.get("#advanced-filter").contains("Advanced Filters").click(); - } - typeInFirstName(firstName: string) { cy.get("#first_name").click().type(firstName); } @@ -72,35 +68,6 @@ export class UserPage { cy.typeAndSelectOption("input[name='home_facility']", facility); } - applyFilter() { - cy.get("#apply-filter").click(); - } - - verifyDataTestIdText(testId: string, text: string) { - cy.get(`[data-testid="${testId}"]`).contains(text).should("be.visible"); - } - - clearFilters() { - this.clickAdvancedFilters(); - cy.get("#clear-filter").contains("Clear").click(); - } - - verifyDataTestIdNotVisible(testId: string) { - cy.get(`[data-testid="${testId}"]`).should("not.be.visible"); - } - - navigateToNextPage() { - cy.get("button#next-pages").click(); - } - - navigateToPreviousPage() { - cy.get("button#prev-pages").click(); - } - - verifyCurrentPageNumber(pageNumber: number) { - cy.url().should("include", `page=${pageNumber}`); - } - verifyMultipleBadgesWithSameId(alreadylinkedusersviews: string[]) { cy.get("#user-view-name").then(($elements) => { const userViews = $elements diff --git a/cypress/pageobject/utils/advanceFilterHelpers.ts b/cypress/pageobject/utils/advanceFilterHelpers.ts new file mode 100644 index 00000000000..22925fc2c23 --- /dev/null +++ b/cypress/pageobject/utils/advanceFilterHelpers.ts @@ -0,0 +1,50 @@ +export const advanceFilters = { + clickAdvancedFiltersButton() { + cy.verifyAndClickElement("#advanced-filter", "Advanced Filters"); + }, + + selectState(state: string) { + cy.clickAndSelectOption("#state", state); + }, + + selectDistrict(district: string) { + cy.clickAndSelectOption("#district", district); + }, + + selectLocalBody(localBody: string) { + cy.clickAndSelectOption("#local_body", localBody); + }, + + applySelectedFilter() { + cy.verifyAndClickElement("#apply-filter", "Apply"); + }, + + selectFacilityType(facilityType: string) { + cy.clickAndSelectOption("#facility_type", facilityType); + }, + + typeFacilityName(facilityName: string) { + cy.typeAndSelectOption("input[name='Facilities']", facilityName); + }, + + clickslideoverbackbutton() { + cy.get("#close-slide-over").click(); + }, + + clickClearAdvanceFilters() { + cy.verifyAndClickElement("#clear-filter", "Clear"); + }, + + verifyFilterBadgePresence( + badgeTestId: string, + text: string, + visible: boolean = true, + ) { + const badgeElement = cy.get(`[data-testid="${badgeTestId}"]`); + if (visible) { + badgeElement.contains(text).should("be.visible"); + } else { + badgeElement.should("not.be.visible"); + } + }, +}; diff --git a/cypress/pageobject/utils/constants.ts b/cypress/pageobject/utils/constants.ts index 08411e84b6a..053d0561ce8 100644 --- a/cypress/pageobject/utils/constants.ts +++ b/cypress/pageobject/utils/constants.ts @@ -1,7 +1,10 @@ -export function generatePhoneNumber() { - return "9" + Math.floor(100000000 + Math.random() * 900000000).toString(); +export function generatePhoneNumber(): string { + const array = new Uint32Array(1); + window.crypto.getRandomValues(array); + const randomNum = (array[0] % 900000000) + 100000000; + return "9" + randomNum.toString(); } -export function generateEmergencyPhoneNumber() { - return "9" + Math.floor(100000000 + Math.random() * 900000000).toString(); +export function generateEmergencyPhoneNumber(): string { + return generatePhoneNumber(); } diff --git a/cypress/pageobject/utils/paginationHelpers.ts b/cypress/pageobject/utils/paginationHelpers.ts new file mode 100644 index 00000000000..edbabec5523 --- /dev/null +++ b/cypress/pageobject/utils/paginationHelpers.ts @@ -0,0 +1,13 @@ +export const pageNavigation = { + navigateToNextPage() { + cy.get("button#next-pages").click(); + }, + + verifyCurrentPageNumber(pageNumber: number) { + cy.url().should("include", `page=${pageNumber}`); + }, + + navigateToPreviousPage() { + cy.get("button#prev-pages").click(); + }, +}; diff --git a/cypress/pageobject/utils/userConfig.ts b/cypress/pageobject/utils/userConfig.ts new file mode 100644 index 00000000000..270fbfba10a --- /dev/null +++ b/cypress/pageobject/utils/userConfig.ts @@ -0,0 +1,8 @@ +export const users = { + districtAdmin: { username: "devdistrictadmin", password: "Coronasafe@123" }, + devDoctor: { username: "devdoctor", password: "Coronasafe@123" }, + nurse: { username: "dummynurse1", password: "Coronasafe@123" }, + nurse2: { username: "dummynurse2", password: "Coronasafe@123" }, +}; + +export const nonAdminRoles = ["devDoctor", "nurse"] as const; diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 9af5f97e5d4..0268beebc42 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -121,11 +121,16 @@ Cypress.Commands.add("clearAllFilters", () => { return cy.get("#clear-all-filters").click(); }); -Cypress.Commands.add("submitButton", (buttonText = "Submit") => { +Cypress.Commands.add("clickSubmitButton", (buttonText = "Submit") => { cy.get("button[type='submit']").contains(buttonText).scrollIntoView(); cy.get("button[type='submit']").contains(buttonText).click(); }); +Cypress.Commands.add("clickCancelButton", (buttonText = "Cancel") => { + cy.get("#cancel").contains(buttonText).scrollIntoView(); + cy.get("#cancel").contains(buttonText).click(); +}); + Cypress.Commands.add( "typeAndSelectOption", (element: string, referance: string) => { @@ -224,3 +229,15 @@ Cypress.Commands.add("verifyContentPresence", (selector, texts) => { }); }); }); + +Cypress.Commands.add("verifyErrorMessages", (errorMessages: string[]) => { + const selector = ".error-text"; // Static selector + cy.get(selector).then(($errors) => { + const displayedErrorMessages = $errors + .map((_, el) => Cypress.$(el).text()) + .get(); + errorMessages.forEach((errorMessage) => { + expect(displayedErrorMessages).to.include(errorMessage); + }); + }); +}); diff --git a/cypress/support/index.ts b/cypress/support/index.ts index b2895871872..831ee71a5bc 100644 --- a/cypress/support/index.ts +++ b/cypress/support/index.ts @@ -14,7 +14,8 @@ declare global { ): Chainable; getAttached(selector: string): Chainable; clearAllFilters(): Chainable; - submitButton(buttonText?: string): Chainable; + clickSubmitButton(buttonText?: string): Chainable; + clickCancelButton(buttonText?: string): Chainable; typeAndSelectOption( element: string, referance: string, @@ -44,6 +45,7 @@ declare global { selector: string, texts: string[], ): Chainable; + verifyErrorMessages(errorMessages: string[]): Chainable; } } } diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json index 114000b60f0..3fbb7b08f69 100644 --- a/cypress/tsconfig.json +++ b/cypress/tsconfig.json @@ -2,9 +2,18 @@ "compilerOptions": { "baseUrl": "./", "target": "es5", - "lib": ["es5", "dom", "es2015", "es2016", "es2017", "es2018", "es2019", "es2020"], + "lib": [ + "es5", + "dom", + "es2015", + "es2016", + "es2017", + "es2018", + "es2019", + "es2020" + ], "typeRoots": ["./support"], "resolveJsonModule": true }, - "include": ["**/*.cy.ts", "support/commands.ts","**/*.ts"], -} \ No newline at end of file + "include": ["**/*.cy.ts", "support/commands.ts", "**/*.ts"] +} diff --git a/package-lock.json b/package-lock.json index e46a726b69c..dfa66181bd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,123 +12,111 @@ "apps/*" ], "dependencies": { - "@fontsource/figtree": "^5.1.0", - "@googlemaps/react-wrapper": "^1.1.35", + "@fontsource/figtree": "^5.1.1", + "@googlemaps/react-wrapper": "^1.1.42", "@googlemaps/typescript-guards": "^2.0.3", - "@headlessui/react": "^2.1.2", + "@headlessui/react": "^2.2.0", "@hello-pangea/dnd": "^17.0.0", "@pnotify/core": "^5.2.0", "@pnotify/mobile": "^5.2.0", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-popover": "^1.1.2", + "@radix-ui/react-scroll-area": "^1.2.0", + "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-tooltip": "^1.1.3", - "@sentry/browser": "^8.33.0", + "@radix-ui/react-tooltip": "^1.1.4", + "@sentry/browser": "^8.42.0", "@yudiel/react-qr-scanner": "^2.0.8", "bowser": "^2.11.0", "browser-image-compression": "^2.0.2", - "browserslist": "^4.24.0", + "browserslist": "^4.24.2", "browserslist-useragent-regexp": "^4.1.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "cmdk": "^1.0.0", "cross-env": "^7.0.3", - "cypress": "^13.14.2", - "dayjs": "^1.11.11", + "cypress": "^13.16.1", + "dayjs": "^1.11.13", "echarts": "^5.5.1", "echarts-for-react": "^3.0.2", "events": "^3.3.0", "hi-profiles": "^1.1.0", - "i18next": "^23.11.4", - "i18next-browser-languagedetector": "^7.2.1", + "i18next": "^23.16.4", + "i18next-browser-languagedetector": "^8.0.0", "i18next-http-backend": "^2.6.2", "lodash-es": "^4.17.21", - "postcss-loader": "^7.3.3", - "qrcode.react": "^3.1.0", + "postcss-loader": "^8.1.1", + "qrcode.react": "^4.1.0", "raviger": "^4.1.2", "react": "18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "18.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^15.0.2", + "react-i18next": "^15.1.1", "react-infinite-scroll-component": "^6.1.0", - "react-pdf": "^9.1.0", + "react-pdf": "^9.1.1", "react-webcam": "^7.2.0", - "tailwind-merge": "^2.5.2", + "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "use-keyboard-shortcut": "^1.1.6", "xlsx": "^0.18.5" }, "devDependencies": { + "@julr/vite-plugin-validate-env": "^1.1.1", "@tailwindcss/container-queries": "^0.1.1", - "@tailwindcss/forms": "^0.5.7", - "@tailwindcss/typography": "^0.5.13", + "@tailwindcss/forms": "^0.5.9", + "@tailwindcss/typography": "^0.5.15", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/dompurify": "^3.0.5", "@types/events": "^3.0.3", - "@types/google.maps": "^3.55.8", + "@types/google.maps": "^3.58.1", "@types/jsdom": "^21.1.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.7.4", - "@types/qrcode.react": "^1.0.5", - "@types/react": "^18.3.11", + "@types/node": "^22.9.0", + "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-csv": "^1.1.10", - "@types/react-dom": "^18.3.0", + "@types/react-dom": "^18.3.1", "@types/react-google-recaptcha": "^2.1.9", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.18.0", - "@vitejs/plugin-react-swc": "^3.6.0", - "autoprefixer": "^10.4.19", - "cypress-localstorage-commands": "^2.2.5", - "cypress-split": "^1.23.2", + "@vitejs/plugin-react-swc": "^3.7.1", + "autoprefixer": "^10.4.20", + "cypress-localstorage-commands": "^2.2.6", + "cypress-split": "^1.24.5", "dompurify": "^3.1.7", "dotenv": "^16.4.5", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-i18next": "^6.0.9", + "eslint-plugin-i18next": "^6.1.0", "eslint-plugin-mdx": "^3.1.5", "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-react": "^7.35.0", - "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^5.0.0", "glob": "^11.0.0", - "husky": "^8.0.3", + "husky": "^9.1.7", "jsdom": "^25.0.1", - "lint-staged": "^13.2.3", + "lint-staged": "^15.2.10", "local-cypress": "^1.2.6", - "marked": "^14.1.3", - "postcss": "^8.4.38", + "marked": "^14.1.4", + "postcss": "^8.4.47", "prettier": "^3.3.3", - "prettier-plugin-tailwindcss": "^0.6.5", - "snyk": "^1.1291.0", - "tailwindcss": "^3.4.3", - "typescript": "^5.4.5", - "uuid": "^10.0.0", - "vite": "^5.2.11", - "vite-plugin-checker": "^0.6.4", - "vite-plugin-pwa": "^0.20.0", - "vite-plugin-static-copy": "^1.0.6" + "prettier-plugin-tailwindcss": "^0.6.8", + "snyk": "^1.1294.0", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3", + "uuid": "^11.0.2", + "vite": "^5.4.10", + "vite-plugin-checker": "^0.8.0", + "vite-plugin-pwa": "^0.20.5", + "vite-plugin-static-copy": "^2.0.0", + "zod": "^3.23.8" }, "engines": { - "node": ">=20.12.0" - } - }, - "apps/care_livekit_fe": { - "name": "care-livekit", - "version": "0.0.1", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@livekit/components-react": "^2.6.2", - "@livekit/components-styles": "^1.1.3", - "livekit-client": "^2.5.5" - }, - "devDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependencies": { - "react": "18.3.1", - "react-dom": "18.3.1" + "node": ">=22.11.0" } }, "node_modules/@actions/core": { @@ -196,6 +184,16 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@babel/code-frame": { "version": "7.25.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", @@ -1955,9 +1953,9 @@ } }, "node_modules/@cypress/request": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.5.tgz", - "integrity": "sha512-v+XHd9XmWbufxF1/bTaVm2yhbxY+TB4YtWRqF2zaXBlDNMkls34KiATz0AVDLavL3iB6bQk9/7n3oY1EoLSWGA==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", + "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==", "license": "Apache-2.0", "dependencies": { "aws-sign2": "~0.7.0", @@ -1975,7 +1973,7 @@ "performance-now": "^2.1.0", "qs": "6.13.0", "safe-buffer": "^5.1.2", - "tough-cookie": "^4.1.3", + "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", "uuid": "^8.3.2" }, @@ -2465,7 +2463,6 @@ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -2490,7 +2487,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2502,7 +2498,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2516,7 +2511,6 @@ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } @@ -2615,9 +2609,9 @@ "license": "Apache-2.0" }, "node_modules/@headlessui/react": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.1.10.tgz", - "integrity": "sha512-6mLa2fjMDAFQi+/R10B+zU3edsUk/MDtENB2zHho0lqKU1uzhAfJLUduWds4nCo8wbl3vULtC5rJfZAQ1yqIng==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.0.tgz", + "integrity": "sha512-RzCEg+LXsuI7mHiSomsu/gBJSjpupm6A1qIZ5sWjd7JhARNlMiSA4kKfJpCKwU9tE+zMRterhhrP74PvfJrpXQ==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.16", @@ -2629,8 +2623,8 @@ "node": ">=10" }, "peerDependencies": { - "react": "^18", - "react-dom": "^18" + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" } }, "node_modules/@hello-pangea/dnd": { @@ -2659,7 +2653,6 @@ "deprecated": "Use @eslint/config-array instead", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", @@ -2675,7 +2668,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2687,7 +2679,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2701,7 +2692,6 @@ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=12.22" }, @@ -2716,8 +2706,7 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", "dev": true, - "license": "BSD-3-Clause", - "peer": true + "license": "BSD-3-Clause" }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -2822,6 +2811,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -2844,6 +2834,33 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@julr/vite-plugin-validate-env": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@julr/vite-plugin-validate-env/-/vite-plugin-validate-env-1.1.1.tgz", + "integrity": "sha512-MiAvuLrolS6xkzG/B4ofOCFUzmOEnC32pvD5fn9g6b3SK4nVruGZp5PU/WG+F+hw9fhsw0ES13L7GVzAeDJaYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@poppinss/cliui": "^6.3.0", + "@poppinss/validator-lite": "^1.0.3", + "unconfig": "^0.3.11" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Julien-R44" + }, + "peerDependencies": { + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0", + "zod": "^3.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", @@ -2930,22 +2947,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@npmcli/config/node_modules/ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@npmcli/config/node_modules/ini": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", @@ -3290,163 +3291,347 @@ "@pnotify/core": "^5.2.0" } }, - "node_modules/@radix-ui/primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", - "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==", - "license": "MIT" - }, - "node_modules/@radix-ui/react-arrow": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", - "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "node_modules/@poppinss/cliui": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@poppinss/cliui/-/cliui-6.4.1.tgz", + "integrity": "sha512-tdV3QpAfrPFRLPOh98F8QxWBvwYF3ziWGGtpVqfZtFNTFkC7nQnVQlUW55UtQ7rkeMmFohxfDI+2JNWScGJ1jQ==", + "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.0" + "@poppinss/colors": "^4.1.3", + "cli-boxes": "^3.0.0", + "cli-table3": "^0.6.4", + "cli-truncate": "^4.0.0", + "log-update": "^6.0.0", + "pretty-hrtime": "^1.0.3", + "string-width": "^7.1.0", + "supports-color": "^9.4.0", + "terminal-size": "^4.0.0", + "wordwrap": "^1.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "engines": { + "node": ">=18.16.0" } }, - "node_modules/@radix-ui/react-collection": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", - "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", + "node_modules/@poppinss/cliui/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-slot": "1.1.0" + "environment": "^1.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", - "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "node_modules/@poppinss/cliui/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", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", - "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "node_modules/@poppinss/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=12" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@radix-ui/react-context": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", - "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "node_modules/@poppinss/cliui/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "dependencies": { + "restore-cursor": "^5.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@radix-ui/react-direction": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", - "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "node_modules/@poppinss/cliui/node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", - "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", + "node_modules/@poppinss/cliui/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@poppinss/cliui/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@poppinss/cliui/node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-escape-keydown": "1.1.0" + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz", - "integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==", + "node_modules/@poppinss/cliui/node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-menu": "2.1.2", - "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-controllable-state": "1.1.0" + "get-east-asian-width": "^1.0.0" }, - "peerDependencies": { + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@poppinss/cliui/node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/@poppinss/cliui/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@poppinss/cliui/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@poppinss/cliui/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@poppinss/cliui/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/@poppinss/cliui/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@poppinss/cliui/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", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@poppinss/cliui/node_modules/supports-color": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", + "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/@poppinss/cliui/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@poppinss/colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@poppinss/colors/-/colors-4.1.3.tgz", + "integrity": "sha512-A0FjJ6x14donWDN3bHAFFjJaPWTwM2PgWT834+bPKVK6Xukf25CscoRqCPYI939a8yuJFX9PYWWnVbUVI0E2Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^4.1.5" + }, + "engines": { + "node": ">=18.16.0" + } + }, + "node_modules/@poppinss/validator-lite": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@poppinss/validator-lite/-/validator-lite-1.0.3.tgz", + "integrity": "sha512-u4dmT7PDHwNtxY3q1jHVp/u+hMEEcBlkzd37QwwM4tVt/0mLlEDttSfPQ+TT7sqPG4VEtWKwVSlMInwPUYyJpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "validator": "^13.9.0" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.0.tgz", + "integrity": "sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", @@ -3461,30 +3646,16 @@ } } }, - "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", - "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", - "license": "MIT", - "peerDependencies": { - "@types/react": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@radix-ui/react-focus-scope": { + "node_modules/@radix-ui/react-collection": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", - "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", + "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-use-callback-ref": "1.1.0" + "@radix-ui/react-slot": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -3501,23 +3672,26 @@ } } }, - "node_modules/@radix-ui/react-icons": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz", - "integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==", + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", "license": "MIT", "peerDependencies": { - "react": "^16.x || ^17.x || ^18.x" + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@radix-ui/react-id": { + "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", - "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", "license": "MIT", - "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.0" - }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" @@ -3528,28 +3702,38 @@ } } }, - "node_modules/@radix-ui/react-menu": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz", - "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==", + "node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.2.tgz", + "integrity": "sha512-Yj4dZtqa2o+kG61fzB0H2qUvmwBA2oyQroGLyNtBj1beo1khoQ3q1a2AO8rrQYjd8256CO9+N8L9tvsS+bnIyA==", "dependencies": { "@radix-ui/primitive": "1.1.0", - "@radix-ui/react-collection": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", "@radix-ui/react-context": "1.1.1", - "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-dismissable-layer": "1.1.1", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.0", "@radix-ui/react-id": "1.1.0", - "@radix-ui/react-popper": "1.2.0", "@radix-ui/react-portal": "1.1.2", "@radix-ui/react-presence": "1.1.1", "@radix-ui/react-primitive": "2.0.0", - "@radix-ui/react-roving-focus": "1.1.0", "@radix-ui/react-slot": "1.1.0", - "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", "aria-hidden": "^1.1.1", "react-remove-scroll": "2.6.0" }, @@ -3568,22 +3752,32 @@ } } }, - "node_modules/@radix-ui/react-popper": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", - "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz", + "integrity": "sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ==", "license": "MIT", "dependencies": { - "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/primitive": "1.1.0", "@radix-ui/react-compose-refs": "1.1.0", - "@radix-ui/react-context": "1.1.0", "@radix-ui/react-primitive": "2.0.0", "@radix-ui/react-use-callback-ref": "1.1.0", - "@radix-ui/react-use-layout-effect": "1.1.0", - "@radix-ui/react-use-rect": "1.1.0", - "@radix-ui/react-use-size": "1.1.0", - "@radix-ui/rect": "1.1.0" + "@radix-ui/react-use-escape-keydown": "1.1.0" }, "peerDependencies": { "@types/react": "*", @@ -3600,7 +3794,233 @@ } } }, - "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz", + "integrity": "sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-menu": "2.1.2", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", + "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-icons": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", + "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", + "license": "MIT", + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.0.tgz", + "integrity": "sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.2.tgz", + "integrity": "sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-collection": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-roving-focus": "1.1.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.2.tgz", + "integrity": "sha512-u2HRUyWW+lOiA2g0Le0tMmT55FGOEWHwPFt1EPfbLly7uXQExFo5duNKqG2DzmFXIdqOeNd+TpE8baHWJCyP9w==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.1", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.2", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.6.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", @@ -3732,6 +4152,36 @@ } } }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.0.tgz", + "integrity": "sha512-q2jMBdsJ9zB7QG6ngQNzNwlvxLQqONyL58QbEGwuyRZZb/ARQwk3uQVbCF7GvQVOtV6EU/pDxAw3zRzJZI3rpQ==", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.1", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", @@ -3785,9 +4235,9 @@ } }, "node_modules/@radix-ui/react-tooltip": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.3.tgz", - "integrity": "sha512-Z4w1FIS0BqVFI2c1jZvb/uDVJijJjJ2ZMuPV81oVgTZ7g3BZxobplnMVvXtFWgtozdvYJ+MFWtwkM5S2HnAong==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.4.tgz", + "integrity": "sha512-QpObUH/ZlpaO4YgHSaYzrLO2VuO+ZBFFgGzjMUPwtiYnAzzNNDPJeEGRrT7qNOrWm/Jr08M1vlp+vTHtnSQ0Uw==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.0", @@ -4346,58 +4796,50 @@ ] }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.34.0.tgz", - "integrity": "sha512-4AcYOzPzD1tL5eSRQ/GpKv5enquZf4dMVUez99/Bh3va8qiJrNP55AcM7UzZ7WZLTqKygIYruJTU5Zu2SpEAPQ==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.42.0.tgz", + "integrity": "sha512-xzgRI0wglKYsPrna574w1t38aftuvo44gjOKFvPNGPnYfiW9y4m+64kUz3JFbtanvOrKPcaITpdYiB4DeJXEbA==", "license": "MIT", "dependencies": { - "@sentry/core": "8.34.0", - "@sentry/types": "8.34.0", - "@sentry/utils": "8.34.0" + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/feedback": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.34.0.tgz", - "integrity": "sha512-aYSM2KPUs0FLPxxbJCFSwCYG70VMzlT04xepD1Y/tTlPPOja/02tSv2tyOdZbv8Uw7xslZs3/8Lhj74oYcTBxw==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.42.0.tgz", + "integrity": "sha512-dkIw5Wdukwzngg5gNJ0QcK48LyJaMAnBspqTqZ3ItR01STi6Z+6+/Bt5XgmrvDgRD+FNBinflc5zMmfdFXXhvw==", "license": "MIT", "dependencies": { - "@sentry/core": "8.34.0", - "@sentry/types": "8.34.0", - "@sentry/utils": "8.34.0" + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.34.0.tgz", - "integrity": "sha512-EoMh9NYljNewZK1quY23YILgtNdGgrkzJ9TPsj6jXUG0LZ0Q7N7eFWd0xOEDBvFxrmI3cSXF1i4d1sBb+eyKRw==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.42.0.tgz", + "integrity": "sha512-oNcJEBlDfXnRFYC5Mxj5fairyZHNqlnU4g8kPuztB9G5zlsyLgWfPxzcn1ixVQunth2/WZRklDi4o1ZfyHww7w==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.34.0", - "@sentry/core": "8.34.0", - "@sentry/types": "8.34.0", - "@sentry/utils": "8.34.0" + "@sentry-internal/browser-utils": "8.42.0", + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.34.0.tgz", - "integrity": "sha512-x8KhZcCDpbKHqFOykYXiamX6x0LRxv6N1OJHoH+XCrMtiDBZr4Yo30d/MaS6rjmKGMtSRij30v+Uq+YWIgxUrg==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.42.0.tgz", + "integrity": "sha512-XrPErqVhPsPh/oFLVKvz7Wb+Fi2J1zCPLeZCxWqFuPWI2agRyLVu0KvqJyzSpSrRAEJC/XFzuSVILlYlXXSfgA==", "license": "MIT", "dependencies": { - "@sentry-internal/replay": "8.34.0", - "@sentry/core": "8.34.0", - "@sentry/types": "8.34.0", - "@sentry/utils": "8.34.0" + "@sentry-internal/replay": "8.42.0", + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" @@ -4456,32 +4898,26 @@ } }, "node_modules/@sentry/browser": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.34.0.tgz", - "integrity": "sha512-3HHG2NXxzHq1lVmDy2uRjYjGNf9NsJsTPlOC70vbQdOb+S49EdH/XMPy+J3ruIoyv6Cu0LwvA6bMOM6rHZOgNQ==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.42.0.tgz", + "integrity": "sha512-lStrEk609KJHwXfDrOgoYVVoFFExixHywxSExk7ZDtwj2YPv6r6Y1gogvgr7dAZj7jWzadHkxZ33l9EOSJBfug==", "license": "MIT", "dependencies": { - "@sentry-internal/browser-utils": "8.34.0", - "@sentry-internal/feedback": "8.34.0", - "@sentry-internal/replay": "8.34.0", - "@sentry-internal/replay-canvas": "8.34.0", - "@sentry/core": "8.34.0", - "@sentry/types": "8.34.0", - "@sentry/utils": "8.34.0" + "@sentry-internal/browser-utils": "8.42.0", + "@sentry-internal/feedback": "8.42.0", + "@sentry-internal/replay": "8.42.0", + "@sentry-internal/replay-canvas": "8.42.0", + "@sentry/core": "8.42.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry/core": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.34.0.tgz", - "integrity": "sha512-adrXCTK/zsg5pJ67lgtZqdqHvyx6etMjQW3P82NgWdj83c8fb+zH+K79Z47pD4zQjX0ou2Ws5nwwi4wJbz4bfA==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.42.0.tgz", + "integrity": "sha512-ac6O3pgoIbU6rpwz6LlwW0wp3/GAHuSI0C5IsTgIY6baN8rOBnlAtG6KrHDDkGmUQ2srxkDJu9n1O6Td3cBCqw==", "license": "MIT", - "dependencies": { - "@sentry/types": "8.34.0", - "@sentry/utils": "8.34.0" - }, "engines": { "node": ">=14.18" } @@ -4593,27 +5029,6 @@ "node": ">=8" } }, - "node_modules/@sentry/types": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-8.34.0.tgz", - "integrity": "sha512-zLRc60CzohGCo6zNsNeQ9JF3SiEeRE4aDCP9fDDdIVCOKovS+mn1rtSip0qd0Vp2fidOu0+2yY0ALCz1A3PJSQ==", - "license": "MIT", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry/utils": { - "version": "8.34.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-8.34.0.tgz", - "integrity": "sha512-W1KoRlFUjprlh3t86DZPFxLfM6mzjRzshVfMY7vRlJFymBelJsnJ3A1lPeBZM9nCraOSiw6GtOWu6k5BAkiGIg==", - "license": "MIT", - "dependencies": { - "@sentry/types": "8.34.0" - }, - "engines": { - "node": ">=14.18" - } - }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", @@ -5146,6 +5561,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "devOptional": true, "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -5196,6 +5612,7 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/@types/lodash": { @@ -5240,12 +5657,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.7.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.6.tgz", - "integrity": "sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==", + "version": "22.9.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", + "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", + "devOptional": true, "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/prop-types": { @@ -5255,20 +5673,10 @@ "devOptional": true, "license": "MIT" }, - "node_modules/@types/qrcode.react": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/qrcode.react/-/qrcode.react-1.0.5.tgz", - "integrity": "sha512-BghPtnlwvrvq8QkGa1H25YnN+5OIgCKFuQruncGWLGJYOzeSKiix/4+B9BtfKF2wf5ja8yfyWYA3OXju995G8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, "node_modules/@types/react": { - "version": "18.3.11", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", - "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", "devOptional": true, "license": "MIT", "dependencies": { @@ -5585,8 +5993,7 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.7.1", @@ -5667,6 +6074,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", @@ -5678,6 +6086,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { @@ -5685,6 +6094,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { @@ -5692,6 +6102,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { @@ -5699,6 +6110,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", @@ -5711,6 +6123,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { @@ -5718,6 +6131,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", @@ -5731,6 +6145,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" @@ -5741,6 +6156,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "license": "Apache-2.0", + "optional": true, "peer": true, "dependencies": { "@xtuc/long": "4.2.2" @@ -5751,6 +6167,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { @@ -5758,6 +6175,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", @@ -5775,6 +6193,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", @@ -5789,6 +6208,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", @@ -5802,6 +6222,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", @@ -5817,6 +6238,7 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", @@ -5828,6 +6250,7 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "license": "BSD-3-Clause", + "optional": true, "peer": true }, "node_modules/@xtuc/long": { @@ -5835,6 +6258,7 @@ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "license": "Apache-2.0", + "optional": true, "peer": true }, "node_modules/@yudiel/react-qr-scanner": { @@ -5862,6 +6286,7 @@ "version": "8.13.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "devOptional": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -5875,6 +6300,7 @@ "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "license": "MIT", + "optional": true, "peer": true, "peerDependencies": { "acorn": "^8" @@ -5942,8 +6368,8 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5960,6 +6386,7 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "license": "MIT", + "optional": true, "peer": true, "peerDependencies": { "ajv": "^6.9.1" @@ -6576,9 +7003,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", - "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "funding": [ { "type": "opencollective", @@ -6595,10 +7022,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001663", - "electron-to-chromium": "^1.5.28", + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.0" + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -6671,6 +7098,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "devOptional": true, "license": "MIT" }, "node_modules/cachedir": { @@ -6917,116 +7345,490 @@ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "license": "MIT", + "optional": true, "peer": true, "engines": { "node": ">=6.0" } }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } - ], - "license": "MIT", - "engines": { - "node": ">=8" + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "2.0.0" + }, + "funding": { + "url": "https://joebell.co.uk" + } + }, + "node_modules/class-variance-authority/node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "license": "MIT", + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cmdk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.0.0.tgz", + "integrity": "sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==", + "dependencies": { + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/cmdk/node_modules/@radix-ui/primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.0.1.tgz", + "integrity": "sha512-yQ8oGX2GVsEYMWGxcovu1uGWPCxV5BFfeeYxqPmuAzUyLT9qmaMXSAhXpb0WrspIeqYzdJpkh2vHModJPgRIaw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-compose-refs": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.1.tgz", + "integrity": "sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.0.1.tgz", + "integrity": "sha512-ebbrdFoYTcuZ0v4wG5tedGnp9tzcV8awzsxYph7gXUyvnNLuTIcCk1q17JEbnVhXAKG9oX3KtchwiMIAYp9NLg==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz", + "integrity": "sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz", + "integrity": "sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1", + "@radix-ui/react-use-escape-keydown": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-focus-guards": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", + "integrity": "sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==", + "dependencies": { + "@babel/runtime": "^7.13.10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-focus-scope": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz", + "integrity": "sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-callback-ref": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", + "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-portal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.4.tgz", + "integrity": "sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-presence": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.0.1.tgz", + "integrity": "sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-use-layout-effect": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-primitive": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.3.tgz", + "integrity": "sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/cmdk/node_modules/@radix-ui/react-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.2.tgz", + "integrity": "sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-compose-refs": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/class-variance-authority": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", - "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", - "license": "Apache-2.0", + "node_modules/cmdk/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", + "integrity": "sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ==", "dependencies": { - "clsx": "2.0.0" + "@babel/runtime": "^7.13.10" }, - "funding": { - "url": "https://joebell.co.uk" - } - }, - "node_modules/class-variance-authority/node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "license": "MIT", - "engines": { - "node": ">=6" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "license": "MIT", + "node_modules/cmdk/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz", + "integrity": "sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==", "dependencies": { - "restore-cursor": "^3.1.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "license": "MIT", + "node_modules/cmdk/node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz", + "integrity": "sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==", "dependencies": { - "string-width": "^4.2.0" + "@babel/runtime": "^7.13.10", + "@radix-ui/react-use-callback-ref": "1.0.1" }, - "engines": { - "node": "10.* || >= 12.*" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "license": "MIT", + "node_modules/cmdk/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.1.tgz", + "integrity": "sha512-v/5RegiJWYdoCvMnITBkNNx6bCj20fiaJnWtRkU18yITptraXjffz5Qbn05uOiQnOvi+dbkznkoaMltz1GnszQ==", "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" + "@babel/runtime": "^7.13.10" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.8" + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", + "node_modules/cmdk/node_modules/react-remove-scroll": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", + "integrity": "sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.3", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, "node_modules/codepage": { @@ -7192,15 +7994,15 @@ "license": "MIT" }, "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "license": "MIT", "dependencies": { + "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" + "parse-json": "^5.2.0" }, "engines": { "node": ">=14" @@ -7322,13 +8124,13 @@ "license": "MIT" }, "node_modules/cypress": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.15.0.tgz", - "integrity": "sha512-53aO7PwOfi604qzOkCSzNlWquCynLlKE/rmmpSPcziRH6LNfaDUAklQT6WJIsD8ywxlIy+uVZsnTMCCQVd2kTw==", + "version": "13.16.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.1.tgz", + "integrity": "sha512-17FtCaz0cx7ssWYKXzGB0Vub8xHwpVPr+iPt2fHhLMDhVAPVrplD+rTQsZUsfb19LVBn5iwkEUFjQ1yVVJXsLA==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@cypress/request": "^3.0.4", + "@cypress/request": "^3.0.6", "@cypress/xvfb": "^1.2.4", "@types/sinonjs__fake-timers": "8.1.1", "@types/sizzle": "^2.3.2", @@ -7339,6 +8141,7 @@ "cachedir": "^2.3.0", "chalk": "^4.1.0", "check-more-types": "^2.24.0", + "ci-info": "^4.0.0", "cli-cursor": "^3.1.0", "cli-table3": "~0.6.1", "commander": "^6.2.1", @@ -7353,7 +8156,6 @@ "figures": "^3.2.0", "fs-extra": "^9.1.0", "getos": "^3.2.1", - "is-ci": "^3.0.1", "is-installed-globally": "~0.4.0", "lazy-ass": "^1.6.0", "listr2": "^3.8.3", @@ -7368,6 +8170,7 @@ "semver": "^7.5.3", "supports-color": "^8.1.1", "tmp": "~0.2.3", + "tree-kill": "1.2.2", "untildify": "^4.0.0", "yauzl": "^2.10.0" }, @@ -7392,9 +8195,9 @@ } }, "node_modules/cypress-split": { - "version": "1.24.4", - "resolved": "https://registry.npmjs.org/cypress-split/-/cypress-split-1.24.4.tgz", - "integrity": "sha512-sKBFQB659Ss5B08GSESeMKXBEpPD2wKNGQR1HYbKT98rnM1x5E+MugzcicqEdsK4T2Ng0feuuZQkz8XniOA18A==", + "version": "1.24.5", + "resolved": "https://registry.npmjs.org/cypress-split/-/cypress-split-1.24.5.tgz", + "integrity": "sha512-7c58IyRtT79wSffrJ78pbKtvhYsjhF6OD5Jhe/32mJ6ue9YFocHIy8D2LM5imM6UcDri6pPMROLMlIyxPElfIg==", "dev": true, "license": "MIT", "dependencies": { @@ -7635,8 +8438,7 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", @@ -7696,6 +8498,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7968,7 +8777,6 @@ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "esutils": "^2.0.2" }, @@ -8095,6 +8903,7 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "devOptional": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -8130,6 +8939,28 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/err-code": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", @@ -8280,6 +9111,7 @@ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/es-object-atoms": { @@ -8436,7 +9268,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -8622,9 +9453,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.1.tgz", - "integrity": "sha512-xwTnwDqzbDRA8uJ7BMxPs/EXRB3i8ZfnOIp8BsxEQkT0nHPp+WWceqGgo6rKb9ctNi8GJLDT4Go5HAWELa/WMg==", + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", "dev": true, "license": "MIT", "dependencies": { @@ -8633,7 +9464,7 @@ "array.prototype.flatmap": "^1.3.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", + "es-iterator-helpers": "^1.1.0", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", @@ -8655,16 +9486,16 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz", + "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "node_modules/eslint-plugin-react/node_modules/brace-expansion": { @@ -8720,7 +9551,6 @@ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -8751,7 +9581,6 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -8763,7 +9592,6 @@ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -8809,7 +9637,6 @@ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", - "peer": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -8821,8 +9648,8 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "devOptional": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -8834,6 +9661,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -9019,6 +9847,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "devOptional": true, "license": "MIT" }, "node_modules/fast-levenshtein": { @@ -9026,8 +9855,7 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/fast-shuffle": { "version": "6.1.0", @@ -9094,7 +9922,6 @@ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -9268,7 +10095,6 @@ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -9286,7 +10112,6 @@ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", @@ -9301,8 +10126,7 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true, - "license": "ISC", - "peer": true + "license": "ISC" }, "node_modules/for-each": { "version": "0.3.3", @@ -9541,6 +10365,19 @@ "node": ">=18" } }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", @@ -9681,6 +10518,7 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "license": "BSD-2-Clause", + "optional": true, "peer": true }, "node_modules/glob/node_modules/minimatch": { @@ -9738,7 +10576,6 @@ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -10051,25 +10888,25 @@ "license": "Unlicense" }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { - "husky": "lib/bin.js" + "husky": "bin.js" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" } }, "node_modules/i18next": { - "version": "23.16.0", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.0.tgz", - "integrity": "sha512-Ni3CG6c14teOogY19YNRl+kYaE/Rb59khy0VyHVn4uOZ97E2E/Yziyi6r3C3s9+wacjdLZiq/LLYyx+Cgd+FCw==", + "version": "23.16.4", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.4.tgz", + "integrity": "sha512-9NIYBVy9cs4wIqzurf7nLXPyf3R78xYbxExVqHLK9od3038rjpyOEzW+XB130kZ1N4PZ9inTtJ471CRJ4Ituyg==", "funding": [ { "type": "individual", @@ -10090,9 +10927,9 @@ } }, "node_modules/i18next-browser-languagedetector": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.1.tgz", - "integrity": "sha512-h/pM34bcH6tbz8WgGXcmWauNpQupCGr25XPp9cZwZInR9XHSjIFDYp1SIok7zSPsTOMxdvuLyu86V+g2Kycnfw==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.0.tgz", + "integrity": "sha512-zhXdJXTTCoG39QsrOCiOabnWj2jecouOqbchu3EfhtSHxIB5Uugnm9JaizenOy39h7ne3+fLikIjeW88+rgszw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" @@ -10197,7 +11034,6 @@ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.8.19" } @@ -10410,18 +11246,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "license": "MIT", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -10974,6 +11798,7 @@ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@types/node": "*", @@ -11085,19 +11910,6 @@ "node": ">= 14" } }, - "node_modules/jsdom/node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/jsdom/node_modules/tr46": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", @@ -11153,8 +11965,7 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -11172,16 +11983,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "license": "MIT", - "peer": true + "devOptional": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", @@ -11261,7 +12071,6 @@ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "json-buffer": "3.0.1" } @@ -11301,7 +12110,6 @@ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -11336,44 +12144,44 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz", - "integrity": "sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ==", + "version": "15.2.10", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz", + "integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "5.3.0", - "commander": "11.0.0", - "debug": "4.3.4", - "execa": "7.2.0", - "lilconfig": "2.1.0", - "listr2": "6.6.1", - "micromatch": "4.0.5", - "pidtree": "0.6.0", - "string-argv": "0.3.2", - "yaml": "2.3.1" + "chalk": "~5.3.0", + "commander": "~12.1.0", + "debug": "~4.3.6", + "execa": "~8.0.1", + "lilconfig": "~3.1.2", + "listr2": "~8.2.4", + "micromatch": "~4.0.8", + "pidtree": "~0.6.0", + "string-argv": "~0.3.2", + "yaml": "~2.5.0" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=18.12.0" }, "funding": { "url": "https://opencollective.com/lint-staged" } }, "node_modules/lint-staged/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^1.0.2" + "environment": "^1.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11419,118 +12227,100 @@ } }, "node_modules/lint-staged/node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/commander": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", - "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/lint-staged/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=18" } }, "node_modules/lint-staged/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true, "license": "MIT" }, "node_modules/lint-staged/node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "license": "MIT", "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", - "signal-exit": "^3.0.7", + "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, "node_modules/lint-staged/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lint-staged/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=14.18.0" + "node": ">=16.17.0" } }, "node_modules/lint-staged/node_modules/is-fullwidth-code-point": { @@ -11559,64 +12349,88 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, "node_modules/lint-staged/node_modules/listr2": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", - "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, "license": "MIT", "dependencies": { - "cli-truncate": "^3.1.0", + "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", - "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/lint-staged/node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" + "engines": { + "node": ">=18" }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", + "node_modules/lint-staged/node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-escapes": "^5.0.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" + "get-east-asian-width": "^1.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "node_modules/lint-staged/node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, "license": "MIT", "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, "engines": { - "node": ">=8.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/lint-staged/node_modules/mimic-fn": { @@ -11632,13 +12446,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, "node_modules/lint-staged/node_modules/npm-run-path": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", @@ -11685,48 +12492,51 @@ } }, "node_modules/lint-staged/node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/lint-staged/node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/lint-staged/node_modules/slice-ansi": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", @@ -11745,18 +12555,18 @@ } }, "node_modules/lint-staged/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11791,17 +12601,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lint-staged/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "node_modules/lint-staged/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/listr2": { @@ -11868,6 +12683,7 @@ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "license": "MIT", + "optional": true, "peer": true, "engines": { "node": ">=6.11.5" @@ -11925,7 +12741,6 @@ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -11959,8 +12774,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/lodash.isplainobject": { "version": "4.0.6", @@ -12149,9 +12963,9 @@ } }, "node_modules/marked": { - "version": "14.1.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", - "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.4.tgz", + "integrity": "sha512-vkVZ8ONmUdPnjCKc5uTRvmkRbx4EAi2OkTOXmfTDhZz3OFqMNBM1oTTWwTr4HY4uAEojhzPf+Fy8F1DWa3Sndg==", "dev": true, "license": "MIT", "bin": { @@ -13698,6 +14512,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", @@ -13957,6 +14784,7 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "license": "MIT", + "optional": true, "peer": true }, "node_modules/node-fetch": { @@ -14294,7 +15122,6 @@ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -14319,7 +15146,6 @@ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -14336,7 +15162,6 @@ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -14436,7 +15261,6 @@ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -14497,6 +15321,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14758,25 +15583,34 @@ } }, "node_modules/postcss-loader": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", - "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", "license": "MIT", "dependencies": { - "cosmiconfig": "^8.3.5", + "cosmiconfig": "^9.0.0", "jiti": "^1.20.0", "semver": "^7.5.4" }, "engines": { - "node": ">= 14.15.0" + "node": ">= 18.12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "postcss": "^7.0.0 || ^8.0.1", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/postcss-nested": { @@ -14901,7 +15735,6 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 0.8.0" } @@ -15026,6 +15859,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/proc-log": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", @@ -15083,12 +15926,6 @@ "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", "license": "MIT" }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "license": "MIT" - }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -15103,15 +15940,16 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/qrcode.react": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.2.0.tgz", - "integrity": "sha512-YietHHltOHA4+l5na1srdaMx4sVSOjV9tamHs+mwiLWAMr6QVACRUw1Neax5CptFILcNoITctJY0Ipyn5enQ8g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-4.1.0.tgz", + "integrity": "sha512-uqXVIIVD/IPgWLYxbOczCNAQw80XCM/LulYDADF+g2xDsPj5OoRwSWtIS4jGyp295wyjKstfG1qIv/I2/rNWpQ==", "license": "ISC", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" @@ -15132,12 +15970,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -15186,6 +16018,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "devOptional": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" @@ -15268,9 +16101,9 @@ } }, "node_modules/react-i18next": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.0.3.tgz", - "integrity": "sha512-BlO1P+oLKjjIxDBQ0GkAIMacgjfMbnvops+3Y5nZXF7UJ99v4KCWr0Na1azJXC8AMiNWp4kgUcFCJM7U9ZsUDg==", + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.1.1.tgz", + "integrity": "sha512-R/Vg9wIli2P3FfeI8o1eNJUJue5LWpFsQePCHdQDmX0Co3zkr6kdT8gAseb/yGeWbNz1Txc4bKDQuZYsC0kQfw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.25.0", @@ -15959,12 +16792,6 @@ "node": ">=10.13.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" - }, "node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -16336,6 +17163,7 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -16408,6 +17236,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" @@ -16643,9 +17472,9 @@ "license": "MIT" }, "node_modules/snyk": { - "version": "1.1293.1", - "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.1293.1.tgz", - "integrity": "sha512-CnbNrsEUMGfajfJ5/03BIgx1ixWKr9Kk+9xDw6sZqKy4K5K01DkyUp/V+WjbCfjr0li9+aE7u70s276KEOuiNA==", + "version": "1.1294.0", + "resolved": "https://registry.npmjs.org/snyk/-/snyk-1.1294.0.tgz", + "integrity": "sha512-4RBj3Lfccz5+6L2Kw9bt7icF+ex3antwt9PkSl2oEulI7mgqvc8VUFLnezg8c6PY60IPM9DrSSmNjXBac10I3Q==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -16664,6 +17493,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -16682,6 +17512,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", @@ -17057,7 +17888,6 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=8" }, @@ -17237,9 +18067,9 @@ "license": "MIT" }, "node_modules/tailwind-merge": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", - "integrity": "sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", "license": "MIT", "funding": { "type": "github", @@ -17326,6 +18156,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" @@ -17408,10 +18239,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/terminal-size": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/terminal-size/-/terminal-size-4.0.0.tgz", + "integrity": "sha512-rcdty1xZ2/BkWa4ANjWRp4JGpda2quksXIHgn5TMjNBPZfwzJIgR68DKfSYiTL+CZWowDX/sbOo5ME/FRURvYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/terser": { "version": "5.36.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "devOptional": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -17431,6 +18276,7 @@ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", @@ -17465,6 +18311,7 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "devOptional": true, "license": "MIT" }, "node_modules/text-table": { @@ -17472,8 +18319,7 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/thenify": { "version": "3.3.1", @@ -17572,7 +18418,6 @@ "version": "6.1.58", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.58.tgz", "integrity": "sha512-MQJrJhjHOYGYb8DobR6Y4AdDbd4TYkyQ+KBDVc5ODzs1cbrvPpfN1IemYi9jfipJ/vR1YWvrDli0hg1y19VRoA==", - "dev": true, "license": "MIT", "dependencies": { "tldts-core": "^6.1.58" @@ -17585,7 +18430,6 @@ "version": "6.1.58", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.58.tgz", "integrity": "sha512-dR936xmhBm7AeqHIhCWwK765gZ7dFyL+IqLSFAjJbFlUXGMLCb8i2PzlzaOuWBuplBTaBYseSb565nk/ZEM0Bg==", - "dev": true, "license": "MIT" }, "node_modules/tmp": { @@ -17626,27 +18470,15 @@ "license": "MIT" }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", "license": "BSD-3-Clause", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^6.1.32" }, "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "license": "MIT", - "engines": { - "node": ">= 4.0.0" + "node": ">=16" } }, "node_modules/tr46": { @@ -17655,6 +18487,15 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/trough": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", @@ -17760,7 +18601,6 @@ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -17774,7 +18614,6 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "license": "(MIT OR CC0-1.0)", - "peer": true, "engines": { "node": ">=10" }, @@ -17909,6 +18748,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unconfig": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-0.3.13.tgz", + "integrity": "sha512-N9Ph5NC4+sqtcOjPfHrRcHekBCadCXWTBzp2VYYbySOHW0PfD9XLCeXshTXjkPYwLrBr9AtSeU0CZmkYECJhng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/utils": "^0.7.7", + "defu": "^6.1.4", + "jiti": "^1.21.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/undici": { "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", @@ -17926,6 +18780,7 @@ "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "devOptional": true, "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -18320,22 +19175,12 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "devOptional": true, "license": "BSD-2-Clause", - "peer": true, "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/use-callback-ref": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", @@ -18414,9 +19259,9 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.2.tgz", + "integrity": "sha512-14FfcOJmqdjbBPdDjFQyk/SdT4NySW4eM0zcG+HqbHP5jzuH56xO3J1DGhgs/cEMCfwYi3HQI1gnTO62iaG+tQ==", "dev": true, "funding": [ "https://github.com/sponsors/broofa", @@ -18424,7 +19269,7 @@ ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/uvu": { @@ -18473,6 +19318,16 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -18664,9 +19519,9 @@ } }, "node_modules/vite": { - "version": "5.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz", - "integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==", + "version": "5.4.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", + "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", "dev": true, "license": "MIT", "dependencies": { @@ -18724,9 +19579,9 @@ } }, "node_modules/vite-plugin-checker": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/vite-plugin-checker/-/vite-plugin-checker-0.6.4.tgz", - "integrity": "sha512-2zKHH5oxr+ye43nReRbC2fny1nyARwhxdm0uNYp/ERy4YvU9iZpNOsueoi/luXw5gnpqRSvjcEPxXbS153O2wA==", + "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==", "dev": true, "license": "MIT", "dependencies": { @@ -18738,7 +19593,6 @@ "fast-glob": "^3.2.7", "fs-extra": "^11.1.0", "npm-run-path": "^4.0.1", - "semver": "^7.5.0", "strip-ansi": "^6.0.0", "tiny-invariant": "^1.1.0", "vscode-languageclient": "^7.0.0", @@ -18750,6 +19604,7 @@ "node": ">=14.16" }, "peerDependencies": { + "@biomejs/biome": ">=1.7", "eslint": ">=7", "meow": "^9.0.0", "optionator": "^0.9.1", @@ -18758,9 +19613,12 @@ "vite": ">=2.0.0", "vls": "*", "vti": "*", - "vue-tsc": ">=1.3.9" + "vue-tsc": "~2.1.6" }, "peerDependenciesMeta": { + "@biomejs/biome": { + "optional": true + }, "eslint": { "optional": true }, @@ -18857,9 +19715,9 @@ } }, "node_modules/vite-plugin-static-copy": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-1.0.6.tgz", - "integrity": "sha512-3uSvsMwDVFZRitqoWHj0t4137Kz7UynnJeq1EZlRW7e25h2068fyIZX4ORCCOAkfp1FklGxJNVJBkBOD+PZIew==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-2.0.0.tgz", + "integrity": "sha512-b/quFjTUa/RY9t3geIyeeT2GtWEoRI0GawYFFjys5iMLGgVP638NTGu0RoMjwmi8MoZZ3BQw4OQvb1GpVcXZDA==", "dev": true, "license": "MIT", "dependencies": { @@ -19457,6 +20315,7 @@ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", @@ -19487,6 +20346,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.95.0.tgz", "integrity": "sha512-2t3XstrKULz41MNMBF+cJ97TyHdyQ8HCt//pqErqDvNjU9YQBnZxIHa11VXsi7F3mb5/aO2tuDxdeTPdU7xu9Q==", "license": "MIT", + "optional": true, "peer": true, "dependencies": { "@types/estree": "^1.0.5", @@ -19534,6 +20394,7 @@ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "license": "MIT", + "optional": true, "peer": true, "engines": { "node": ">=10.13.0" @@ -19544,6 +20405,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "license": "BSD-2-Clause", + "optional": true, "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -19558,6 +20420,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "license": "BSD-2-Clause", + "optional": true, "peer": true, "engines": { "node": ">=4.0" @@ -19741,11 +20604,17 @@ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, "node_modules/workbox-background-sync": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.1.0.tgz", @@ -20350,11 +21219,14 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "dev": true, "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -20375,7 +21247,6 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10" }, @@ -20383,6 +21254,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zrender": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.6.0.tgz", diff --git a/package.json b/package.json index a84fdb9ac13..e07e45edaeb 100644 --- a/package.json +++ b/package.json @@ -44,108 +44,115 @@ "cypress:run": "cross-env NODE_ENV=development cypress run", "cypress:run:gui": "cross-env NODE_ENV=development cypress run --headed", "cypress:install": "cross-env NODE_ENV=development cypress install", - "prepare": "husky install", + "prepare": "husky", "lint": "eslint ./src", "lint-fix": "eslint ./src --fix", - "format": "prettier ./src --write", + "format": "prettier ./src ./cypress --write", "sort-locales": "node ./scripts/sort-locales.js" }, "dependencies": { - "@fontsource/figtree": "^5.1.0", - "@googlemaps/react-wrapper": "^1.1.35", + "@fontsource/figtree": "^5.1.1", + "@googlemaps/react-wrapper": "^1.1.42", "@googlemaps/typescript-guards": "^2.0.3", - "@headlessui/react": "^2.1.2", + "@headlessui/react": "^2.2.0", "@hello-pangea/dnd": "^17.0.0", "@pnotify/core": "^5.2.0", "@pnotify/mobile": "^5.2.0", + "@radix-ui/react-dialog": "^1.1.2", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-popover": "^1.1.2", + "@radix-ui/react-scroll-area": "^1.2.0", + "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-toast": "^1.2.2", - "@radix-ui/react-tooltip": "^1.1.3", - "@sentry/browser": "^8.33.0", + "@radix-ui/react-tooltip": "^1.1.4", + "@sentry/browser": "^8.42.0", "@yudiel/react-qr-scanner": "^2.0.8", "bowser": "^2.11.0", "browser-image-compression": "^2.0.2", - "browserslist": "^4.24.0", + "browserslist": "^4.24.2", "browserslist-useragent-regexp": "^4.1.3", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "cmdk": "^1.0.0", "cross-env": "^7.0.3", - "cypress": "^13.14.2", - "dayjs": "^1.11.11", + "cypress": "^13.16.1", + "dayjs": "^1.11.13", "echarts": "^5.5.1", "echarts-for-react": "^3.0.2", "events": "^3.3.0", "hi-profiles": "^1.1.0", - "i18next": "^23.11.4", - "i18next-browser-languagedetector": "^7.2.1", + "i18next": "^23.16.4", + "i18next-browser-languagedetector": "^8.0.0", "i18next-http-backend": "^2.6.2", "lodash-es": "^4.17.21", - "postcss-loader": "^7.3.3", - "qrcode.react": "^3.1.0", + "postcss-loader": "^8.1.1", + "qrcode.react": "^4.1.0", "raviger": "^4.1.2", "react": "18.3.1", "react-copy-to-clipboard": "^5.1.0", "react-dom": "18.3.1", "react-google-recaptcha": "^3.1.0", - "react-i18next": "^15.0.2", + "react-i18next": "^15.1.1", "react-infinite-scroll-component": "^6.1.0", - "react-pdf": "^9.1.0", + "react-pdf": "^9.1.1", "react-webcam": "^7.2.0", - "tailwind-merge": "^2.5.2", + "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", "use-keyboard-shortcut": "^1.1.6", "xlsx": "^0.18.5" }, "devDependencies": { + "@julr/vite-plugin-validate-env": "^1.1.1", "@tailwindcss/container-queries": "^0.1.1", - "@tailwindcss/forms": "^0.5.7", - "@tailwindcss/typography": "^0.5.13", + "@tailwindcss/forms": "^0.5.9", + "@tailwindcss/typography": "^0.5.15", "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/dompurify": "^3.0.5", "@types/events": "^3.0.3", - "@types/google.maps": "^3.55.8", + "@types/google.maps": "^3.58.1", "@types/jsdom": "^21.1.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.7.4", - "@types/qrcode.react": "^1.0.5", - "@types/react": "^18.3.11", + "@types/node": "^22.9.0", + "@types/react": "^18.3.12", "@types/react-copy-to-clipboard": "^5.0.7", "@types/react-csv": "^1.1.10", - "@types/react-dom": "^18.3.0", + "@types/react-dom": "^18.3.1", "@types/react-google-recaptcha": "^2.1.9", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.18.0", - "@vitejs/plugin-react-swc": "^3.6.0", - "autoprefixer": "^10.4.19", - "cypress-localstorage-commands": "^2.2.5", - "cypress-split": "^1.23.2", + "@vitejs/plugin-react-swc": "^3.7.1", + "autoprefixer": "^10.4.20", + "cypress-localstorage-commands": "^2.2.6", + "cypress-split": "^1.24.5", "dompurify": "^3.1.7", "dotenv": "^16.4.5", + "eslint": "^8.57.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-i18next": "^6.0.9", + "eslint-plugin-i18next": "^6.1.0", "eslint-plugin-mdx": "^3.1.5", "eslint-plugin-prettier": "^5.2.1", - "eslint-plugin-react": "^7.35.0", - "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react-hooks": "^5.0.0", "glob": "^11.0.0", - "husky": "^8.0.3", + "husky": "^9.1.7", "jsdom": "^25.0.1", - "lint-staged": "^13.2.3", + "lint-staged": "^15.2.10", "local-cypress": "^1.2.6", - "marked": "^14.1.3", - "postcss": "^8.4.38", + "marked": "^14.1.4", + "postcss": "^8.4.47", "prettier": "^3.3.3", - "prettier-plugin-tailwindcss": "^0.6.5", - "snyk": "^1.1291.0", - "tailwindcss": "^3.4.3", - "typescript": "^5.4.5", - "uuid": "^10.0.0", - "vite": "^5.2.11", - "vite-plugin-checker": "^0.6.4", - "vite-plugin-pwa": "^0.20.0", - "vite-plugin-static-copy": "^1.0.6" + "prettier-plugin-tailwindcss": "^0.6.8", + "snyk": "^1.1294.0", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3", + "uuid": "^11.0.2", + "vite": "^5.4.10", + "vite-plugin-checker": "^0.8.0", + "vite-plugin-pwa": "^0.20.5", + "vite-plugin-static-copy": "^2.0.0", + "zod": "^3.23.8" }, "browserslist": { "production": [ @@ -161,16 +168,16 @@ }, "lint-staged": { "*.{ts,tsx,js,jsx}": [ - "prettier --write --ignore-unknown --plugin prettier-plugin-tailwindcss", + "prettier --write --ignore-unknown --plugin prettier-plugin-tailwindcss --plugin @trivago/prettier-plugin-sort-imports", "eslint --fix", "git update-index --again" ], - "src/Locale/*.json": [ + "public/locale/*.json": [ "npm run sort-locales" ] }, "engines": { - "node": ">=20.12.0" + "node": ">=22.11.0" }, - "packageManager": "npm@10.5.0" + "packageManager": "npm@10.9.0" } diff --git a/plugins/treeShakeCareIcons.ts b/plugins/treeShakeCareIcons.ts index 131889c0f44..3ce077f5d5f 100644 --- a/plugins/treeShakeCareIcons.ts +++ b/plugins/treeShakeCareIcons.ts @@ -1,7 +1,7 @@ -import { Plugin } from "vite"; import * as fs from "fs"; -import * as path from "path"; import { globSync } from "glob"; +import * as path from "path"; +import { Plugin } from "vite"; /** * Interface defining options for the treeShakeUniconPathsPlugin. @@ -48,7 +48,7 @@ export function treeShakeCareIcons( } // Finds all used icon names within the project's source files (`.tsx` or `.res` extensions). function getAllUsedIconNames() { - const files = globSync(path.resolve(rootDir, "src/**/*.{tsx,res}")); + const files = globSync(path.resolve(rootDir, "{apps,src}/**/*.{tsx,res}")); const usedIconsArray: string[] = []; files.forEach((file) => { diff --git a/public/locale/en.json b/public/locale/en.json index b6ccb84de08..f86d78fa3aa 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -5,6 +5,7 @@ "APPETITE__NO_TASTE_FOR_FOOD": "No taste for food", "APPETITE__REDUCED": "Reduced", "APPETITE__SATISFACTORY": "Satisfactory", + "APPROVED": "Approved", "AUTOMATED": "Automated", "BED_WITH_OXYGEN_SUPPORT": "Bed with Oxygen Support", "BLADDER_DRAINAGE__CONDOM_CATHETER": "Condom Catheter", @@ -133,9 +134,14 @@ "ORAL_ISSUE__NO_ISSUE": "No issues", "ORAL_ISSUE__ODYNOPHAGIA": "Odynophagia", "OXYGEN_MODALITY__HIGH_FLOW_NASAL_CANNULA": "High Flow Nasal Cannula", + "OXYGEN_MODALITY__HIGH_FLOW_NASAL_CANNULA_short": "HFNC", "OXYGEN_MODALITY__NASAL_PRONGS": "Nasal Prongs", + "OXYGEN_MODALITY__NASAL_PRONGS_short": "NP", "OXYGEN_MODALITY__NON_REBREATHING_MASK": "Non Rebreathing Mask", + "OXYGEN_MODALITY__NON_REBREATHING_MASK_short": "NRM", "OXYGEN_MODALITY__SIMPLE_FACE_MASK": "Simple Face Mask", + "OXYGEN_MODALITY__SIMPLE_FACE_MASK_short": "SFM", + "PENDING": "Pending", "PRESCRIPTION_FREQUENCY_BD": "Twice daily", "PRESCRIPTION_FREQUENCY_HS": "Night only", "PRESCRIPTION_FREQUENCY_OD": "Once daily", @@ -199,19 +205,31 @@ "SORT_OPTIONS__name": "Patient name A-Z", "SORT_OPTIONS__review_time": "Oldest review date first", "SORT_OPTIONS__taken_at": "Oldest taken date first", + "SPO2_LEVEL_MILD_HYPOXEMIA": "Mild Hypoxemia", + "SPO2_LEVEL_MODERATE_HYPOXEMIA": "Moderate Hypoxemia", + "SPO2_LEVEL_NORMAL": "Normal", + "SPO2_LEVEL_SEVERE_HYPOXEMIA": "Severe Hypoxemia", "Submit": "Submit", "TELEMEDICINE": "Telemedicine", + "TRANSPORTATION TO BE ARRANGED": "Transportation", "URINATION_FREQUENCY__DECREASED": "Decreased", "URINATION_FREQUENCY__INCREASED": "Increased", "URINATION_FREQUENCY__NORMAL": "Normal", "VENTILATOR": "Detailed Update", "VENTILATOR_MODE__CMV": "Control Mechanical Ventilation (CMV)", + "VENTILATOR_MODE__CMV_short": "CMV", "VENTILATOR_MODE__PCV": "Pressure Control Ventilation (PCV)", + "VENTILATOR_MODE__PCV_short": "PCV", "VENTILATOR_MODE__PC_SIMV": "Pressure Controlled SIMV (PC-SIMV)", + "VENTILATOR_MODE__PC_SIMV_short": "PC-SIMV", "VENTILATOR_MODE__PSV": "C-PAP / Pressure Support Ventilation (PSV)", + "VENTILATOR_MODE__PSV_short": "C-PAP/PSV", "VENTILATOR_MODE__SIMV": "Synchronised Intermittent Mandatory Ventilation (SIMV)", + "VENTILATOR_MODE__SIMV_short": "SIMV", "VENTILATOR_MODE__VCV": "Volume Control Ventilation (VCV)", + "VENTILATOR_MODE__VCV_short": "VCV", "VENTILATOR_MODE__VC_SIMV": "Volume Controlled SIMV (VC-SIMV)", + "VENTILATOR_MODE__VC_SIMV_short": "VC-SIMV", "View Facility": "View Facility", "aadhaar_number": "Aadhaar Number", "aadhaar_number_will_not_be_stored": "Aadhaar number will not be stored by CARE", @@ -245,14 +263,18 @@ "abha_link_options__link_with_demographics__title": "Link with Demographics", "abha_link_options__link_with_otp__description": "Link Existing ABHA Number Using Mobile or Aadhaar OTP", "abha_link_options__link_with_otp__title": "Link with OTP", + "abha_link_options__link_with_qr__description": "Link Existing ABHA Number by Scanning the ABHA QR", "abha_link_options__link_with_qr__title": "Link with ABHA QR", "abha_number": "ABHA Number", "abha_number_exists": "ABHA Number already exists", "abha_number_exists_description": "There is an ABHA Number already linked with the given Aadhaar Number, Do you want to create a new ABHA Address?", "abha_number_linked_successfully": "ABHA Number has been linked successfully.", "abha_profile": "ABHA Profile", + "accept": "Accept", + "accept_all": "Accept All", "access_level": "Access Level", "action_irreversible": "This action is irreversible", + "actions": "Actions", "active": "Active", "active_prescriptions": "Active Prescriptions", "add": "Add", @@ -260,7 +282,10 @@ "add_attachments": "Add Attachments", "add_beds": "Add Bed(s)", "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_details_of_patient": "Add Details of Patient", + "add_insurance_details": "Add Insurance Details", "add_location": "Add Location", "add_new_beds": "Add New Bed(s)", "add_new_user": "Add New User", @@ -280,11 +305,14 @@ "administered_on": "Administered on", "administration_dosage_range_error": "Dosage should be between start and target dosage", "administration_notes": "Administration Notes", + "admitted": "Admitted", + "admitted_on": "Admitted On", "advanced_filters": "Advanced Filters", "age": "Age", "all_changes_have_been_saved": "All changes have been saved", "all_details": "All Details", "allergies": "Allergies", + "allow_transfer": "Allow Transfer", "allowed_formats_are": "Allowed formats are", "already_a_member": "Already a member?", "ambulance_driver_name": "Name of ambulance driver", @@ -295,6 +323,7 @@ "any_id_description": "Currently we support: Aadhaar Number / Mobile Number", "any_other_comments": "Any other comments", "apply": "Apply", + "approve": "Approve", "approved_by_district_covid_control_room": "Approved by District COVID Control Room", "approving_facility": "Name of Approving Facility", "archive": "Archive", @@ -303,6 +332,7 @@ "are_you_still_watching": "Are you still watching?", "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?", + "ari": "ARI - Acute Respiratory illness", "asset_class": "Asset Class", "asset_location": "Asset Location", "asset_name": "Asset Name", @@ -310,9 +340,16 @@ "asset_qr_id": "Asset QR ID", "asset_type": "Asset Type", "assets": "Assets", + "assign": "Assign", + "assign_a_volunteer_to": "Assign a volunteer to {{name}}", + "assign_bed": "Assign Bed", + "assign_to_volunteer": "Assign to a Volunteer", + "assigned_doctor": "Assigned Doctor", "assigned_facility": "Facility assigned", "assigned_to": "Assigned to", + "assigned_volunteer": "Assigned Volunteer", "async_operation_warning": "This operation may take some time. Please check back later.", + "atypical_presentation_details": "Atypical presentation details", "audio__allow_permission": "Please allow microphone permission in site settings", "audio__allow_permission_button": "Click here to know how to allow", "audio__allow_permission_helper": "You might have denied microphone access in the past.", @@ -329,6 +366,7 @@ "auth_method_unsupported": "This authentication method is not supported, please try a different method", "authorize_shift_delete": "Authorize shift delete", "auto_generated_for_care": "Auto Generated for Care", + "autofilled_fields": "Autofilled Fields", "available_features": "Available Features", "available_in": "Available in", "average_weekly_working_hours": "Average weekly working hours", @@ -341,6 +379,7 @@ "bed_capacity": "Bed Capacity", "bed_created_notification_one": "{{count}} Bed created successfully", "bed_created_notification_other": "{{count}} Beds created successfully", + "bed_history": "Bed History", "bed_not_linked_to_camera": "This bed has not been linked to this camera.", "bed_search_placeholder": "Search by beds name", "bed_type": "Bed Type", @@ -373,6 +412,7 @@ "central_nursing_station": "Central Nursing Station", "change_file": "Change File", "change_password": "Change Password", + "chat_on_whatsapp": "Chat on Whatsapp", "check_eligibility": "Check Eligibility", "check_for_available_update": "Check for available update", "check_for_update": "Check for Update", @@ -469,24 +509,31 @@ "consent_request_rejected": "Patient has rejected the consent request", "consent_request_waiting_approval": "Waiting for the Patient to approve the consent request", "consent_requested_successfully": "Consent requested successfully!", + "consultation_history": "Consultation History", "consultation_missing_warning": "You have not created a consultation for the patient in", "consultation_not_filed": "You have not filed a consultation for this patient yet.", "consultation_not_filed_description": "Please file a consultation for this patient to continue.", "consultation_notes": "General Instructions (Advice)", "consultation_updates": "Consultation updates", + "contact_info": "Contact Info", "contact_number": "Contact Number", "contact_person": "Name of Contact Person at Facility", "contact_person_at_the_facility": "Contact person at the current facility", "contact_person_number": "Contact person number", "contact_phone": "Contact Person Number", + "contact_with_confirmed_carrier": "Contact with confirmed carrier", + "contact_with_suspected_carrier": "Contact with suspected carrier", "contact_your_admin_to_add_skills": "Contact your admin to add skills", "continue": "Continue", "continue_watching": "Continue watching", "contribute_github": "Contribute on Github", "copied_to_clipboard": "Copied to clipboard", + "copilot_thinking": "Copilot is thinking...", + "could_not_autofill": "We could not autofill any fields from what you said", "countries_travelled": "Countries travelled", "covid_19_cat_gov": "Covid_19 Clinical Category as per Govt. of Kerala guideline (A/B/C)", "covid_19_death_reporting_form_1": "Covid-19 Death Reporting : Form 1", + "covid_details": "Covid Details", "create": "Create", "create_abha_address": "Create ABHA Address", "create_add_more": "Create & Add More", @@ -504,6 +551,7 @@ "created_date": "Created Date", "created_on": "Created On", "csv_file_in_the_specified_format": "Select a CSV file in the specified format", + "current_address": "Current Address", "current_password": "Current Password", "customer_support_email": "Customer Support Email", "customer_support_name": "Customer Support Name", @@ -514,16 +562,19 @@ "date_and_time": "Date and Time", "date_declared_positive": "Date of declaring positive", "date_of_admission": "Date of Admission", - "date_of_birth": "Date of birth", + "date_of_birth": "Date of Birth", "date_of_positive_covid_19_swab": "Date of Positive Covid 19 Swab", "date_of_result": "Covid confirmation date", + "date_of_return": "Date of Return", "date_of_test": "Date of sample collection for Covid testing", "days": "Days", + "death_report": "Death Report", "delete": "Delete", "delete_facility": "Delete Facility", "delete_item": "Delete {{name}}", "delete_record": "Delete Record", "deleted_successfully": "{{name}} deleted successfully", + "demography": "Demography", "denied_on": "Denied On", "describe_why_the_asset_is_not_working": "Describe why the asset is not working", "description": "Description", @@ -543,6 +594,8 @@ "diagnosis_at_discharge": "Diagnosis at Discharge", "diastolic": "Diastolic", "differential": "Differential", + "differential_diagnosis": "Differential diagnosis", + "disable_transfer": "Disable Transfer", "discard": "Discard", "discharge": "Discharge", "discharge_from_care": "Discharge from CARE", @@ -550,6 +603,7 @@ "discharge_summary": "Discharge Summary", "discharge_summary_not_ready": "Discharge summary is not ready yet.", "discharged": "Discharged", + "discharged_on": "Discharged On", "discharged_patients": "Discharged Patients", "discharged_patients_empty": "No discharged patients present in this facility", "disclaimer": "Disclaimer", @@ -560,7 +614,9 @@ "district": "District", "district_program_management_supporting_unit": "District Program Management Supporting Unit", "doctor_s_medical_council_registration": "Doctor's Medical Council Registration", + "doctors_name": "Doctor's Name", "domestic_healthcare_support": "Domestic healthcare support", + "domestic_international_travel": "Domestic/international Travel (within last 28 days)", "done": "Done", "dosage": "Dosage", "down": "Down", @@ -582,6 +638,7 @@ "edit_policy": "Edit Insurance Policy", "edit_policy_description": "Add or edit patient's insurance details", "edit_prescriptions": "Edit Prescriptions", + "edit_profile": "Edit Profile", "edit_user_profile": "Edit Profile", "edited_by": "Edited by", "edited_on": "Edited on", @@ -595,7 +652,11 @@ "email_discharge_summary_description": "Enter your valid email address to receive the discharge summary", "email_success": "We will be sending an email shortly. Please check your inbox.", "emergency": "Emergency", + "emergency_contact": "Emergency Contact", "emergency_contact_number": "Emergency Contact Number", + "emergency_contact_person_name": "Emergency Contact Person Name", + "emergency_contact_person_name_volunteer": "Emergency Contact Person Name (Volunteer)", + "emergency_contact_volunteer": "Emergency Contact (Volunteer)", "empty_date_time": "--:-- --; --/--/----", "encounter_date_field_label__A": "Date & Time of Admission to the Facility", "encounter_date_field_label__DC": "Date & Time of Domiciliary Care commencement", @@ -611,6 +672,8 @@ "encounter_suggestion__OP": "Out-patient visit", "encounter_suggestion__R": "Consultation", "encounter_suggestion_edit_disallowed": "Not allowed to switch to this option in edit consultation", + "encounters": "Encounters", + "end_datetime": "End Date/Time", "enter_aadhaar_number": "Enter a 12-digit Aadhaar ID", "enter_aadhaar_otp": "Enter OTP sent to the registered mobile with Aadhaar", "enter_abha_address": "Enter ABHA Address", @@ -627,19 +690,23 @@ "error_while_deleting_record": "Error while deleting record", "escape": "Escape", "estimated_contact_date": "Estimated contact date", + "etiology_identified": "Etiology identified", "events": "Events", "expand_sidebar": "Expand Sidebar", "expected_burn_rate": "Expected Burn Rate", + "expired": "Expired", "expired_on": "Expired On", "expires_on": "Expires On", "facilities": "Facilities", "facility": "Facility", "facility_consent_requests_page_title": "Patient Consent List", + "facility_district_name": "Facility/District Name", "facility_name": "Facility Name", "facility_preference": "Facility preference", "facility_search_placeholder": "Search by Facility / District Name", "facility_type": "Facility Type", "failed_to_link_abha_number": "Failed to link ABHA Number. Please try again later.", + "fast_track_testing_reason": "Fast track testing reason", "features": "Features", "feed_configurations": "Feed Configurations", "feed_is_currently_not_live": "Feed is currently not live", @@ -685,6 +752,8 @@ "goal": "Our goal is to continuously improve the quality and accessibility of public healthcare services using digital tools.", "granted_on": "Granted On", "has_domestic_healthcare_support": "Has domestic healthcare support?", + "has_sari": "Has SARI (Severe Acute Respiratory illness)?", + "health-profile": "Health Profile", "health_facility__config_registration_error": "Health ID registration failed", "health_facility__config_update_error": "Health Facility config update failed", "health_facility__config_update_success": "Health Facility config updated successfully", @@ -699,6 +768,7 @@ "health_facility__registered_2": "No Action Required", "health_facility__registered_3": "Registered", "health_facility__validation__hf_id_required": "Health Facility Id is required", + "hearing": "We are hearing you...", "help_confirmed": "There is sufficient diagnostic and/or clinical evidence to treat this as a confirmed condition.", "help_differential": "One of a set of potential (and typically mutually exclusive) diagnoses asserted to further guide the diagnostic process and preliminary treatment.", "help_entered-in-error": "The statement was entered in error and is not valid.", @@ -714,16 +784,23 @@ "hi__record_not_fetched_title": "This record hasn't been fetched yet", "hi__waiting_for_record": "Waiting for the Host HIP to send the record.", "hide": "Hide", + "high": "High", "home_facility": "Home Facility", "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", + "immunisation-records": "Immunisation", "incomplete_patient_details_warning": "Patient details are incomplete. Please update the details before proceeding.", "inconsistent_dosage_units_error": "Dosage units must be same", "indian_mobile": "Indian Mobile", "indicator": "Indicator", "inidcator_event": "Indicator Event", "instruction_on_titration": "Instruction on titration", + "insurance__insurer_id": "Insurer ID", + "insurance__insurer_name": "Insurer Name", + "insurance__member_id": "Member ID", + "insurance__policy_name": "Policy ID / Policy Name", "insurer_name_required": "Insurer Name is required", "international_mobile": "International Mobile", "invalid_asset_id_msg": "Oops! The asset ID you entered does not appear to be valid.", @@ -732,6 +809,7 @@ "invalid_link_msg": "It appears that the password reset link you have used is either invalid or expired. Please request a new password reset link.", "invalid_password": "Password doesn't meet the requirements", "invalid_password_reset_link": "Invalid password reset link", + "invalid_patient_data": "Invalid Patient Data", "invalid_phone": "Please enter valid phone number", "invalid_phone_number": "Invalid Phone Number", "invalid_pincode": "Invalid Pincode", @@ -750,25 +828,35 @@ "investigations__result": "Result", "investigations__unit": "Unit", "investigations_suggested": "Investigations Suggested", + "investigations_summary": "Investigations Summary", + "ip_encounter": "IP Encounter", "is": "Is", "is_antenatal": "Is Antenatal", + "is_atypical_presentation": "Is Atypical presentation", "is_declared_positive": "Whether declared positive", "is_emergency": "Is emergency", "is_emergency_case": "Is emergency case", "is_it_upshift": "is it upshift", + "is_pregnant": "Is pregnant", "is_this_an_emergency": "Is this an emergency?", "is_this_an_upshift": "Is this an upshift?", + "is_unusual_course": "Is unusual course", "is_up_shift": "Is up shift", "is_upshift_case": "Is upshift case", "is_vaccinated": "Whether vaccinated", + "kasp_enabled_date": "{{kasp_string}} enabled date", + "label": "Label", "landline": "Indian landline", "language_selection": "Language Selection", "last_administered": "Last administered", + "last_discharge_reason": "Last Discharge Reason", "last_edited": "Last Edited", "last_modified": "Last Modified", "last_name": "Last Name", "last_online": "Last Online", "last_serviced_on": "Last Serviced On", + "last_updated_by": "Last updated by", + "last_vaccinated_on": "Last Vaccinated on", "latitude_invalid": "Latitude must be between -90 and 90", "left": "Left", "length": "Length ({{unit}})", @@ -795,8 +883,11 @@ "location_management": "Location Management", "log_lab_results": "Log Lab Results", "log_report": "Log Report", + "log_update": "Log Update", + "log_updates": "Log Updates", "login": "Login", "longitude_invalid": "Longitude must be between -180 and 180", + "low": "Low", "lsg": "Lsg", "make_multiple_beds_label": "Do you want to make multiple beds?", "manage_bed_presets": "Manage Presets of Bed", @@ -814,6 +905,7 @@ "max_size_for_image_uploaded_should_be": "Max size for image uploaded should be", "measured_after": "Measured after", "measured_before": "Measured before", + "medical": "Medical", "medical_council_registration": "Medical Council Registration", "medical_worker": "Medical Worker", "medicine": "Medicine", @@ -824,6 +916,7 @@ "middleware_hostname": "Middleware Hostname", "middleware_hostname_example": "e.g. example.ohc.network", "middleware_hostname_sourced_from": "Middleware hostname sourced from {{ source }}", + "min_char_length_error": "Must be at least {{ min_length }} characters", "min_password_len_8": "Minimum password length 8", "min_time_bw_doses": "Min. time b/w doses", "minimize": "Minimize", @@ -853,10 +946,13 @@ "next_sessions": "Next Sessions", "no": "No", "no_attachments_found": "This communication has no attachments.", + "no_bed_asset_linked_allocated": "No bed/asset linked allocated", "no_bed_types_found": "No Bed Types found", "no_beds_available": "No beds available", "no_changes": "No changes", "no_changes_made": "No changes made", + "no_consultation_filed": "No consultation filed", + "no_consultation_history": "No consultation history available", "no_consultation_updates": "No consultation updates", "no_data_found": "No data found", "no_duplicate_facility": "You should not create duplicate facilities", @@ -868,7 +964,10 @@ "no_investigation_suggestions": "No Investigation Suggestions", "no_linked_facilities": "No Linked Facilities", "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_notices_for_you": "No notices for you.", + "no_patients_found": "No Patients Found", "no_patients_to_show": "No patients to show.", "no_policy_added": "No Insurance Policy Added", "no_policy_found": "No Insurance Policy Found for this Patient", @@ -876,6 +975,7 @@ "no_records_found": "No Records Found", "no_remarks": "No remarks", "no_results_found": "No Results Found", + "no_social_profile_details_available": "No Social Profile Details Available", "no_staff": "No staff found", "no_tests_taken": "No tests taken", "no_treating_physicians_available": "This facility does not have any home facility doctors. Please contact your admin.", @@ -888,12 +988,14 @@ "notes": "Notes", "notes_placeholder": "Type your Notes", "notice_board": "Notice Board", + "notification_cancelled": "Notification cancelled", "notification_permission_denied": "Notification permission denied", "notification_permission_granted": "Notification permission granted", - "number_of_aged_dependents_above_60": "Number Of Aged Dependents (Above 60)", + "number_of_aged_dependents": "Number of Aged Dependents (Above 60)", "number_of_beds": "Number of beds", "number_of_beds_out_of_range_error": "Number of beds cannot be greater than 100", "number_of_chronic_diseased_dependents": "Number Of Chronic Diseased Dependents", + "number_of_covid_vaccine_doses": "Number of Covid vaccine doses", "nursing_care": "Nursing Care", "nursing_information": "Nursing Information", "nutrition": "Nutrition", @@ -903,6 +1005,8 @@ "on": "On", "ongoing_medications": "Ongoing Medications", "only_indian_mobile_numbers_supported": "Currently only Indian numbers are supported", + "op_encounter": "OP Encounter", + "op_file_closed": "OP file closed", "open": "Open", "open_camera": "Open Camera", "open_live_monitoring": "Open Live Monitoring", @@ -924,6 +1028,12 @@ "password_reset_failure": "Password Reset Failed", "password_reset_success": "Password Reset successfully", "password_sent": "Password Reset Email Sent", + "patient": "Patient", + "patient-notes": "Notes", + "patient__general-info": "General Info", + "patient__insurance-details": "Insurance Details", + "patient__social-profile": "Social Profile", + "patient__volunteer-contact": "Volunteer Contact", "patient_address": "Patient Address", "patient_body": "Patient Body", "patient_category": "Patient Category", @@ -947,6 +1057,8 @@ "patient_notes_thread__Doctors": "Doctor's Discussions", "patient_notes_thread__Nurses": "Nurse's Discussions", "patient_phone_number": "Patient Phone Number", + "patient_profile": "Patient Profile", + "patient_profile_created_by": "Patient profile created by", "patient_registration__address": "Address", "patient_registration__age": "Age", "patient_registration__comorbidities": "Comorbidities", @@ -959,12 +1071,15 @@ "patient_status": "Patient Status", "patient_transfer_birth_match_note": "Note: Year of birth must match the patient to process the transfer request.", "patients": "Patients", + "permanent_address": "Permanent Address", + "permission_denied": "You do not have permission to perform this action", "personal_information": "Personal Information", "phone": "Phone", "phone_no": "Phone no.", "phone_number": "Phone Number", "phone_number_at_current_facility": "Phone Number of Contact person at current Facility", "pincode": "Pincode", + "please_assign_bed_to_patient": "Please assign a bed to this patient", "please_enter_a_reason_for_the_shift": "Please enter a reason for the shift.", "please_select_a_facility": "Please select a facility", "please_select_breathlessness_level": "Please select Breathlessness Level", @@ -986,6 +1101,7 @@ "policy__subscriber_id__example": "SUB001", "policy_id_required": "Policy Id or Policy Name is required", "position": "Position", + "post_partum": "Post-partum", "post_your_comment": "Post Your Comment", "powered_by": "Powered By", "preferred_facility_type": "Preferred Facility Type", @@ -1000,6 +1116,7 @@ "prescriptions__medicine": "Medicine", "prescriptions__route": "Route", "prescriptions__start_date": "Prescribed On", + "present_health": "Present Health", "preset_deleted": "Preset deleted", "preset_name_placeholder": "Specify an identifiable name for the new preset", "preset_updated": "Preset updated", @@ -1012,6 +1129,7 @@ "prn_prescriptions": "PRN Prescriptions", "procedure_suggestions": "Procedure Suggestions", "procedures_select_placeholder": "Select procedures to add details", + "process_transcript": "Process Again", "profile": "Profile", "provisional": "Provisional", "qualification": "Qualification", @@ -1039,6 +1157,7 @@ "refuted": "Refuted", "register_hospital": "Register Hospital", "register_page_title": "Register As Hospital Administrator", + "reject": "Reject", "reload": "Reload", "remove": "Remove", "rename": "Rename", @@ -1048,9 +1167,11 @@ "req_atleast_one_lowercase": "Require at least one lower case letter", "req_atleast_one_symbol": "Require at least one symbol", "req_atleast_one_uppercase": "Require at least one upper case", + "request-sample-test": "Service Request", "request_consent": "Request Consent", "request_description": "Description of Request", "request_description_placeholder": "Type your description here", + "request_sample_test": "Request Sample Test", "request_title": "Request Title", "request_title_placeholder": "Type your title here", "required": "Required", @@ -1062,15 +1183,20 @@ "resource_approving_facility": "Resource approving facility", "resource_origin_facility": "Origin Facility", "resource_request": "Resource Request", + "resource_status": "Resource Status", "result": "Result", "result_date": "Result Date", "result_details": "Result details", + "result_on": "Result on", "resume": "Resume", "retake": "Retake", + "retake_recording": "Retake Recording", "return_to_care": "Return to CARE", "return_to_login": "Return to Login", "return_to_password_reset": "Return to Password Reset", "return_to_patient_dashboard": "Return to Patient Dashboard", + "review_before": "Review Before", + "review_missed": "Review Missed", "revoked_on": "Revoked On", "right": "Right", "route": "Route", @@ -1078,11 +1204,21 @@ "sample_collection_date": "Sample Collection Date", "sample_format": "Sample Format", "sample_test": "Sample Test", + "sample_test_details": "Sample Test Details", + "sample_test_history": "Sample Test History", "sample_type": "Sample Type", + "sample_type_description": "Sample Type Description", + "sari": "SARI - Severe Acute Respiratory illness", "save": "Save", "save_and_continue": "Save and Continue", "save_investigation": "Save Investigation", "scan_asset_qr": "Scan Asset QR!", + "scribe__reviewing_field": "Reviewing field {{currentField}} / {{totalFields}}", + "scribe_error": "Could not autofill fields", + "search_by_emergency_contact_phone_number": "Search by Emergency Contact Phone Number", + "search_by_patient_name": "Search by Patient Name", + "search_by_patient_no": "Search by Patient Number", + "search_by_phone_number": "Search by Phone Number", "search_by_username": "Search by username", "search_for_facility": "Search for Facility", "search_icd11_placeholder": "Search for ICD-11 Diagnoses", @@ -1112,6 +1248,8 @@ "send_otp_error": "Failed to send OTP. Please try again later.", "send_otp_success": "OTP has been sent to the respective mobile number", "send_reset_link": "Send Reset Link", + "send_sample_to_collection_centre_description": "Are you sure you want to send the sample to Collection Centre?", + "send_sample_to_collection_centre_title": "Send sample to collection centre", "serial_number": "Serial Number", "serviced_on": "Serviced on", "session_expired": "Session Expired", @@ -1120,6 +1258,8 @@ "set_your_local_language": "Set your local language", "settings_and_filters": "Settings and Filters", "severity_of_breathlessness": "Severity of Breathlessness", + "sex": "Sex", + "shift": "Shift Patient", "shift_request_updated_successfully": "Shift request updated successfully", "shifting": "Shifting", "shifting_approval_facility": "Shifting approval facility", @@ -1127,6 +1267,7 @@ "shifting_approving_facility_can_not_be_empty": "Shifting approving facility can not be empty.", "shifting_deleted": "Shifting record has been deleted successfully.", "shifting_details": "Shifting details", + "shifting_history": "Shifting History", "shifting_status": "Shifting status", "show_abha_profile": "Show ABHA Profile", "show_all": "Show all", @@ -1136,6 +1277,7 @@ "show_unread_notifications": "Show Unread", "sign_out": "Sign Out", "skills": "Skills", + "social_profile": "Social Profile", "socioeconomic_status": "Socioeconomic status", "software_update": "Software Update", "something_went_wrong": "Something went wrong..!", @@ -1145,10 +1287,13 @@ "spokes": "Spoke Facilities", "srf_id": "SRF ID", "staff_list": "Staff List", + "start_datetime": "Start Date/Time", "start_dosage": "Start Dosage", + "start_review": "Start Review", "state": "State", "status": "Status", "stop": "Stop", + "stop_recording": "Stop Recording", "stream_stop_due_to_inativity": "The live feed will stop streaming due to inactivity", "stream_stopped_due_to_inativity": "The live feed has stopped streaming due to inactivity", "stream_uuid": "Stream UUID", @@ -1157,24 +1302,36 @@ "submitting": "Submitting", "subscribe": "Subscribe", "subscribe_on_this_device": "Subscribe on this device", + "subscribed_successfully": "Subscribed Successfully", "subscription_error": "Subscription Error", + "subscription_failed": "Subscription Failed", "suggested_investigations": "Suggested Investigations", + "suggestion": "Suggestion", "summary": "Summary", "support": "Support", "switch": "Switch", + "switch_bed": "Switch Bed", "switch_camera_is_not_available": "Switch camera is not available.", + "symptoms": "Symptoms", "systolic": "Systolic", "tachycardia": "Tachycardia", "target_dosage": "Target Dosage", "test_type": "Type of test done", + "tested_on": "Tested on", "third_party_software_licenses": "Third Party Software Licenses", "titrate_dosage": "Titrate Dosage", "to_be_conducted": "To be conducted", "total_amount": "Total Amount", "total_beds": "Total Beds", + "total_patients": "Total Patients", "total_staff": "Total Staff", "total_users": "Total Users", + "transcript_edit_info": "You can update this if we made an error", + "transcript_information": "This is what we heard", + "transfer_allowed": "Transfer Allowed", + "transfer_blocked": "Transfer Blocked", "transfer_in_progress": "TRANSFER IN PROGRESS", + "transfer_status_updated": "Transfer Status Updated", "transfer_to_receiving_facility": "Transfer to receiving facility", "travel_within_last_28_days": "Domestic/international Travel (within last 28 days)", "treating_doctor": "Treating Doctor", @@ -1200,6 +1357,7 @@ "unlink_camera_and_bed": "Unlink this bed from this camera", "unsubscribe": "Unsubscribe", "unsubscribe_failed": "Unsubscribe failed.", + "unsubscribed_successfully": "Unsubscribed Successfully.", "unsupported_browser": "Unsupported Browser", "unsupported_browser_description": "Your browser ({{name}} version {{version}}) is not supported. Please update your browser to the latest version or switch to a supported browser for the best experience.", "up": "Up", @@ -1213,6 +1371,7 @@ "update_facility_middleware_success": "Facility middleware updated successfully", "update_log": "Update Log", "update_patient_details": "Update Patient Details", + "update_preset": "Update Preset", "update_preset_position_to_current": "Update preset's position to camera's current position", "update_record": "Update Record", "update_record_for_asset": "Update record for asset", @@ -1227,6 +1386,7 @@ "upload_headings__patient": "Upload New Patient File", "upload_headings__sample_report": "Upload Sample Report", "upload_headings__supporting_info": "Upload Supporting Info", + "upload_report": "Upload Report", "uploading": "Uploading", "use_existing_abha_address": "Use Existing ABHA Address", "user_deleted_successfuly": "User Deleted Successfuly", @@ -1234,27 +1394,47 @@ "username": "Username", "users": "Users", "vacant": "Vacant", + "vaccinated": "Vaccinated", + "vaccine_name": "Vaccine name", "vehicle_preference": "Vehicle preference", "vendor_name": "Vendor Name", + "ventilator_interface": "Respiratory Support Type", + "ventilator_log": "Ventilator Log", + "ventilator_modality": "Modality", + "ventilator_mode": "Ventilator Mode", + "ventilator_oxygen_modality": "Oxygen Modality", + "ventilator_oxygen_modality_oxygen_rate": "Oxygen Flow Rate", + "ventilator_spo2": "SpO₂", "verify_and_link": "Verify and Link", "verify_otp": "Verify OTP", "verify_otp_error": "Failed to verify OTP. Please try again later.", "verify_otp_success": "OTP has been verified successfully.", "verify_patient_identifier": "Please verify the patient identifier", "verify_using": "Verify Using", + "video_call": "Video Call", "video_conference_link": "Video Conference Link", "view": "View", "view_abdm_records": "View ABDM Records", + "view_all_details": "View All Details", "view_asset": "View Assets", "view_cns": "View CNS", + "view_consultation_and_log_updates": "View Consultation / Log Updates", "view_details": "View Details", "view_faciliy": "View Facility", + "view_files": "View Files", "view_patients": "View Patients", + "view_update_patient_files": "View/Update patient files", + "view_updates": "View Updates", "view_users": "View Users", + "village": "Village", "virtual_nursing_assistant": "Virtual Nursing Assistant", "vitals": "Vitals", "vitals_monitor": "Vitals Monitor", "vitals_present": "Vitals Monitor present", + "voice_autofill": "Voice Autofill", + "volunteer_assigned": "Volunteer assigned successfuly", + "volunteer_contact": "Volunteer Contact", + "volunteer_unassigned": "Volunteer unassigned successfuly", "ward": "Ward", "warranty_amc_expiry": "Warranty / AMC Expiry", "what_facility_assign_the_patient_to": "What facility would you like to assign the patient to", @@ -1262,6 +1442,7 @@ "why_the_asset_is_not_working": "Why the asset is not working?", "width": "Width ({{unit}})", "working_status": "Working Status", + "year_of_birth": "Year of Birth", "years": "years", "years_of_experience": "Years of Experience", "years_of_experience_of_the_doctor": "Years of Experience of the Doctor", diff --git a/public/locale/hi.json b/public/locale/hi.json index 0eb0cc28cfd..b3c172021dd 100644 --- a/public/locale/hi.json +++ b/public/locale/hi.json @@ -567,6 +567,7 @@ "patient_name": "मरीज का नाम", "patient_no": "ओपी/आईपी संख्या", "patient_phone_number": "मरीज़ का फ़ोन नंबर", + "patient_profile": "रोगी प्रोफ़ाइल", "patient_registration__address": "पता", "patient_registration__age": "आयु", "patient_registration__comorbidities": "comorbidities", diff --git a/public/locale/kn.json b/public/locale/kn.json index be18432e0ce..faf50da3a23 100644 --- a/public/locale/kn.json +++ b/public/locale/kn.json @@ -568,6 +568,7 @@ "patient_name": "ರೋಗಿಯ ಹೆಸರು", "patient_no": "OP/IP ಸಂ", "patient_phone_number": "ರೋಗಿಯ ಫೋನ್ ಸಂಖ್ಯೆ", + "patient_profile": "ರೋಗಿ ಪ್ರೊಫೈಲ್", "patient_registration__address": "ವಿಳಾಸ", "patient_registration__age": "ವಯಸ್ಸು", "patient_registration__comorbidities": "ಸಹವರ್ತಿ ರೋಗಗಳು", diff --git a/public/locale/ml.json b/public/locale/ml.json index cf381c32c0e..33dadcf9fb7 100644 --- a/public/locale/ml.json +++ b/public/locale/ml.json @@ -567,6 +567,7 @@ "patient_name": "രോഗിയുടെ പേര്", "patient_no": "OP/IP നമ്പർ", "patient_phone_number": "രോഗിയുടെ ഫോൺ നമ്പർ", + "patient_profile": "രോഗിയുടെ പ്രൊഫൈൽ", "patient_registration__address": "വിലാസം", "patient_registration__age": "പ്രായം", "patient_registration__comorbidities": "കോമോർബിഡിറ്റികൾ", diff --git a/public/locale/mr.json b/public/locale/mr.json index 06e9c5bbbde..543278bf867 100644 --- a/public/locale/mr.json +++ b/public/locale/mr.json @@ -49,6 +49,7 @@ "new_password": "नवीन पासवर्ड", "no_duplicate_facility": "बनावट हॉस्पिटल सुविधा मुळीच तयार करू नका", "no_facilities": "कोणतेही हॉस्पिटल नाही", + "patient_profile": "रुग्ण प्रोफाइल", "password": "पासवर्ड", "password_mismatch": "\"पासवर्ड\" आणि \"पासवर्डची खात्री करा\" दोन्ही सारखे हवेत.", "password_reset_failure": "पासवर्ड रिसेट झाला नाही", @@ -62,5 +63,36 @@ "send_reset_link": "रीसेट लिंक पाठवा", "sign_out": "साइन आउट", "something_wrong": "काहीतरी चूक झाली! पुन्हा प्रयत्न करा", - "username": "युजरनेम" + "username": "युजरनेम", + "general_info": "सामान्य माहिती", + "phone": "फोन", + "date_of_birth": "जन्म तारीख", + "sex": "लिंग", + "emergency_contact": "आपत्कालीन संपर्क", + "emergency_contact_person_name": "आपत्कालीन संपर्क व्यक्तीचे नाव", + "covid_details": "कोविड तपशील", + "number_of_covid_vaccine_doses": "कोविड लसीचे डोस", + "vaccine_name": "लस नाव", + "last_vaccinated_on": "शेवटचा लसीकरणाचा दिवस", + "countries_travelled": "प्रवास केलेले देश", + "date_of_return": "परतण्याची तारीख", + "social_profile": "सामाजिक प्रोफाइल", + "no_social_profile_details_available": "कोणतीही सामाजिक प्रोफाइल माहिती उपलब्ध नाही", + "location": "स्थान", + "current_address": "सध्याचा पत्ता", + "permanent_address": "स्थायी पत्ता", + "nationality": "राष्ट्रीयत्व", + "state": "राज्य", + "local_body": "स्थानिक संस्था", + "ward": "वॉर्ड", + "village": "गाव", + "volunteer_contact": "स्वयंसेवक संपर्क", + "emergency_contact_volunteer": "आपत्कालीन संपर्क (स्वयंसेवक)", + "emergency_contact_person_name_volunteer": "आपत्कालीन संपर्क व्यक्तीचे नाव (स्वयंसेवक)", + "medical": "वैद्यकीय", + "no_medical_history_available": "कोणताही वैद्यकीय इतिहास उपलब्ध नाही", + "present_health": "सध्याचे आरोग्य", + "ongoing_medications": "चालू औषधे", + "allergies": "अॅलर्जी", + "is_pregnant": "गर्भवती आहे" } diff --git a/scripts/setup-care-apps.js b/scripts/setup-care-apps.js index 870c73bd247..5f29678c1db 100644 --- a/scripts/setup-care-apps.js +++ b/scripts/setup-care-apps.js @@ -53,6 +53,36 @@ const installApp = (app) => { ); }; +const backupDir = path.join(__dirname, "..", "apps_backup"); + +// Create backup directory if needed +if (!fs.existsSync(backupDir)) { + fs.mkdirSync(backupDir); +} + +try { + fs.readdirSync(appsDir, { withFileTypes: true }) + .filter((dirent) => dirent.isDirectory()) + .map((dirent) => dirent.name) + .filter( + (dir) => + !appsConfig.map((app) => app.package.split("/")[1]).includes(dir), + ) + .forEach((unusedApp) => { + const appPath = path.join(appsDir, unusedApp); + const backupPath = path.join(backupDir, `${unusedApp}_${Date.now()}`); + console.log(`Backing up '${unusedApp}' to ${backupPath}`); + fs.cpSync(appPath, backupPath, { recursive: true }); + console.log( + `Removing existing app '${unusedApp}' as it is not configured.`, + ); + fs.rmSync(appPath, { recursive: true, force: true }); + }); +} catch (error) { + console.error("Error during cleanup:", error); + process.exit(1); +} + // Clone or pull care apps appsConfig.forEach((app) => { const appDir = path.join(appsDir, app.package.split("/")[1]); diff --git a/scripts/sort-locales.js b/scripts/sort-locales.js index adff586a93b..62c3e3d8ba1 100644 --- a/scripts/sort-locales.js +++ b/scripts/sort-locales.js @@ -1,7 +1,7 @@ // eslint-disable-next-line @typescript-eslint/no-var-requires const fs = require("fs"); -const file = "src/Locale/en.json"; +const file = "public/locale/en.json"; const data = JSON.parse(fs.readFileSync(file, "utf8")); diff --git a/src/App.tsx b/src/App.tsx index 62a173c8409..d3fec38dbed 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,23 +11,27 @@ import HistoryAPIProvider from "@/Providers/HistoryAPIProvider"; import Routers from "@/Routers"; import { FeatureFlagsProvider } from "@/Utils/featureFlags"; +import { PubSubProvider } from "./Utils/pubsubContext"; + const App = () => { return ( }> - - - }> - - - - + + + + }> + + + + - {/* Integrations */} - - - - - + {/* Integrations */} + + + + + + ); }; diff --git a/src/CAREUI/display/Chip.tsx b/src/CAREUI/display/Chip.tsx index a2bacf8bd61..e501bf26f90 100644 --- a/src/CAREUI/display/Chip.tsx +++ b/src/CAREUI/display/Chip.tsx @@ -26,7 +26,7 @@ export default function Chip({ + {secondaryPath && ( + + )} ); } diff --git a/src/CAREUI/icons/DuoTonePaths.json b/src/CAREUI/icons/DuoTonePaths.json new file mode 100644 index 00000000000..663f71a7dba --- /dev/null +++ b/src/CAREUI/icons/DuoTonePaths.json @@ -0,0 +1,72 @@ +{ + "d-people": [ + 24, + "M14.6,10.9c.7.7,1.66,1.1,2.65,1.1s1.95-.4,2.65-1.1c.7-.7,1.1-1.66,1.1-2.65s-.4-1.95-1.1-2.65c-.7-.7-1.66-1.1-2.65-1.1s-1.95.4-2.65,1.1c-.7.7-1.1,1.66-1.1,2.65s.4,1.95,1.1,2.65ZM16.5,19.5c0,.52-.1,1.03-.32,1.5h6.32s1.5,0,1.5-1.5-1.5-6-7.5-6c-.98-.01-1.96.13-2.9.42,1.88,1.45,2.9,3.55,2.9,5.58Z", + true, + null, + "M13.5,21s1.5,0,1.5-1.5-1.5-6-7.5-6S0,18,0,19.5s1.5,1.5,1.5,1.5h12ZM7.5,12c-1.19,0-2.34-.47-3.18-1.32-.84-.84-1.32-1.99-1.32-3.18s.47-2.34,1.32-3.18c.84-.84,1.99-1.32,3.18-1.32s2.34.47,3.18,1.32c.84.84,1.32,1.99,1.32,3.18s-.47,2.34-1.32,3.18c-.84.84-1.99,1.32-3.18,1.32Z" + ], + "d-bell": [ + 24, + "M13.62,22.62c-.56.56-1.33.88-2.12.88s-1.56-.32-2.12-.88c-.56-.56-.88-1.33-.88-2.12h6c0,.8-.32,1.56-.88,2.12Z", + true, + null, + "M12.99,1.65c.02-.21,0-.42-.07-.62-.07-.2-.17-.38-.31-.54-.14-.16-.31-.28-.5-.36-.19-.09-.4-.13-.61-.13s-.42.04-.61.13c-.19.09-.36.21-.5.36-.14.16-.25.34-.31.54-.07.2-.09.41-.07.62-1.7.34-3.22,1.26-4.32,2.6-1.09,1.34-1.69,3.02-1.69,4.75,0,1.65-.75,9-3,10.5h21c-2.25-1.5-3-8.85-3-10.5,0-3.63-2.58-6.66-6.01-7.35Z" + ], + "d-book-open": [ + 24, + "M11.75,3.02c1.57-.95,2.95-1.46,4.45-1.73,1.55-.27,3.12-.29,4.7-.29.56,0,.84,0,1.06.11.19.1.34.25.44.44.11.21.11.5.11,1.06v8.96c0,1.59,0,2.39-.29,3-.27.57-.63.97-1.18,1.29-.58.35-1.5.43-3.33.6-.42.04-.83.09-1.24.16-1.73.3-3.25,1.09-4.71,2.03V3.02ZM2.75,18.51c-.41,0-.75.34-.75.75s.34.75.75.75c1.97,0,3.4.12,4.68.47,1.27.35,2.45.93,3.91,1.9.25.17.58.17.83,0,1.46-.97,2.63-1.55,3.91-1.9,1.28-.35,2.7-.47,4.68-.47.41,0,.75-.34.75-.75s-.34-.75-.75-.75c-2.03,0-3.6.13-5.07.53-1.34.37-2.56.95-3.93,1.83-1.37-.88-2.59-1.46-3.93-1.83-1.47-.4-3.05-.53-5.07-.53Z", + true, + null, + "M11.75,3.02c-1.57-.95-2.95-1.46-4.45-1.73-1.55-.27-3.12-.29-4.7-.29-.56,0-.84,0-1.06.11-.19.1-.34.25-.44.44-.11.21-.11.5-.11,1.06v8.96c0,1.59,0,2.39.29,3,.27.57.63.97,1.18,1.29.58.35,1.5.43,3.33.6.42.04.83.09,1.24.16,1.73.3,3.25,1.09,4.71,2.03V3.02Z" + ], + "d-patient": [ + 24, + "M12.5,9.66c2.67,0,4.83-2.16,4.83-4.83S15.17,0,12.5,0s-4.83,2.16-4.83,4.83,2.16,4.83,4.83,4.83Z", + true, + null, + "M19.48,12.64c-.26-.26-.55-.5-.86-.69-.26-.17-.53-.31-.82-.43l-1.61,11.62h-4.15l4.07-12.01c-.1,0-.2,0-.31,0h-6.61c-1.39,0-2.69.54-3.67,1.52-.98.98-1.52,2.29-1.52,3.67v4.51c0,1.27,1.04,2.31,2.31,2.31h4.82l-.1.29c-.05.13-.02.28.06.39.08.11.21.18.35.18h5.13c.22,0,.4-.16.43-.37l.07-.49v-.06c1.04-.23,1.81-1.15,1.81-2.25,0-.86-.47-1.63-1.21-2.03l.12-.9c1.18.49,1.95,1.64,1.95,2.93,0,.91-.38,1.73-1,2.31h2.25v-6.82c0-1.39-.54-2.69-1.52-3.67h0ZM7.67,18.52c-.24,0-.43-.19-.43-.43v-1.77c0-.24.19-.43.43-.43s.43.19.43.43v1.34h4.89l-.29.87h-5.02Z" + ], + "d-calendar": [ + 24, + "M7,2c.55,0,1,.45,1,1v1h7v-1c0-.55.45-1,1-1s1,.45,1,1v1h2.5c1.38,0,2.5,1.12,2.5,2.5v2.5H1v-2.5c0-1.38,1.12-2.5,2.5-2.5h2.5v-1c0-.55.45-1,1-1ZM5,13c-.55,0-1,.45-1,1s.45,1,1,1h.01c.55,0,1-.45,1-1s-.45-1-1-1h-.01ZM5,17c-.55,0-1,.45-1,1s.45,1,1,1h.01c.55,0,1-.45,1-1s-.45-1-1-1h-.01ZM9,14c0-.55.45-1,1-1h.01c.55,0,1,.45,1,1s-.45,1-1,1h-.01c-.55,0-1-.45-1-1ZM10,17c-.55,0-1,.45-1,1s.45,1,1,1h.01c.55,0,1-.45,1-1s-.45-1-1-1h-.01ZM14,14c0-.55.45-1,1-1h.01c.55,0,1,.45,1,1s-.45,1-1,1h-.01c-.55,0-1-.45-1-1Z", + true, + null, + "M1,20v-11h21v11c0,1.66-1.34,3-3,3H4c-1.66,0-3-1.34-3-3Z" + ], + "d-folder": [ + 24, + "M2,10v-5c0-1.66,1.34-3,3-3h4.31c.62,0,1.2.29,1.58.78l1.81,2.34c.19.24.48.39.79.39h6.51c1.1,0,2,.9,2,2v2.5c0,1.1-.9,2-2,2H4c-1.1,0-2-.9-2-2Z", + true, + null, + "M2.24,19.04l-.2-14c-.02-1.67,1.33-3.04,3-3.04h4.23c.61,0,1.19.28,1.57.76l1.88,2.38c.18.22.44.36.73.38l6.46.37c1.05.06,1.87.92,1.89,1.97l.16,11.1c.02,1.67-1.33,3.04-3,3.04H5.24c-1.64,0-2.98-1.32-3-2.96Z" + ], + "d-ambulance": [ + 24, + "M15.44,7.06c0-.25.1-.49.28-.66.18-.18.42-.28.66-.28s.49.1.66.28c.18.18.28.42.28.66v.95h-1.89v-.95ZM19.41,9.05l1.29,2.53,1.91,1.02c.32.17.59.44.79.75.18.31.3.68.3,1.05v.23h0c.08,0,.16.03.23.08.06.06.08.14.08.23v1.47c0,.08-.03.16-.1.23-.06.06-.14.08-.23.08h0v.04c0,.07-.01.14-.04.21s-.07.13-.13.18-.11.1-.18.13-.14.04-.21.04h-2.22c-.01-.66-.3-1.3-.78-1.77s-1.12-.72-1.78-.72-1.31.25-1.78.72c-.48.47-.76,1.1-.78,1.77h-1.26v-8.96h3.73c.24,0,.47.07.66.18.2.13.37.3.47.51h.03ZM15.75,13.09h1.24s.11-.03.14-.06c.04-.04.06-.08.06-.14s-.03-.11-.06-.14c-.04-.04-.08-.06-.14-.06h-1.24s-.11.03-.14.06c-.04.04-.06.08-.06.14s.03.11.06.14c.04.04.08.06.14.06ZM15.54,9.25v2.83h4.31l-1.31-2.47c-.06-.11-.14-.2-.24-.25s-.23-.1-.34-.1h-2.42ZM5.31,15.38c-1.12,0-2.03.91-2.03,2.03s.91,2.03,2.03,2.03,2.03-.91,2.03-2.03-.91-2.03-2.03-2.03ZM5.31,18.23c-.45,0-.82-.37-.82-.82s.37-.82.82-.82.82.37.82.82-.37.82-.82.82ZM18.39,15.38c-1.12,0-2.03.91-2.03,2.03s.91,2.03,2.03,2.03,2.03-.91,2.03-2.03-.91-2.03-2.03-2.03ZM18.39,18.23c-.45,0-.82-.37-.82-.82s.37-.82.82-.82.82.37.82.82-.37.82-.82.82Z", + true, + null, + "M.34,14.62V5.91c0-.1.01-.2.06-.28s.1-.17.17-.24.16-.13.24-.17.18-.06.28-.06h2.09c0-.16.07-.3.17-.41.11-.11.25-.17.41-.17h6.36c.16,0,.3.06.41.17s.17.25.17.41h2.5c.2,0,.4.08.54.23s.23.34.23.54v11.4h-6.09c-.01-.66-.3-1.3-.78-1.77s-1.12-.72-1.78-.72-1.31.25-1.78.72c-.48.47-.76,1.1-.78,1.77h-1.67c-.17,0-.34-.06-.48-.17s-.23-.25-.27-.42h-.03c-.08,0-.16-.03-.23-.08-.06-.06-.08-.14-.08-.23v-1.47c0-.08.03-.16.08-.23.06-.06.23-.08.23-.08l.03-.03ZM5.27,11.4h1.33v1.33h1.45v-1.33h1.33v-1.45h-1.33v-1.33h-1.45v1.33h-1.33v1.45Z" + ], + "d-microscope": [ + 24, + "M2.9,5.43c-.21-.21-.21-.55,0-.76l3.29-3.29c.21-.21.55-.21.76,0l6.07,6.07c.21.21.21.55,0,.76l-3.29,3.29c-.21.21-.55.21-.76,0L2.9,5.43ZM4.97,22.33c0-.3.24-.54.54-.54h10.55c.3,0,.54.24.54.54v1.13c0,.3-.24.54-.54.54H5.5c-.3,0-.54-.24-.54-.54v-1.13ZM15.29,15.68c-.3,0-.54.24-.54.54v.76c0,.3.24.54.54.54h6.88c.3,0,.54-.24.54-.54v-.76c0-.3-.24-.54-.54-.54h-6.88Z", + true, + null, + "M1.67,2.43c-.21.21-.21.55,0,.76l1.35,1.35,3.03-3.03L4.7.16c-.21-.21-.55-.21-.76,0L1.67,2.43ZM19.55,17.52c-.71,1.07-1.67,1.99-2.82,2.71-1.15.71-2.47,1.2-3.86,1.43-1.39.23-2.82.19-4.19-.12s-2.65-.86-3.75-1.64c-1.1-.78-1.99-1.75-2.62-2.86-.63-1.11-.97-2.32-1.01-3.56-.04-1.24.22-2.46.78-3.6.55-1.14,1.38-2.16,2.43-2.99l1.55,1.5c-.8.63-1.43,1.41-1.85,2.28-.42.87-.63,1.81-.59,2.75.03.94.3,1.87.77,2.72.48.85,1.16,1.59,2,2.18.84.59,1.82,1.02,2.86,1.25,1.05.23,2.14.26,3.2.09,1.06-.17,2.07-.54,2.95-1.09.88-.54,1.62-1.25,2.16-2.07l2,1.01ZM9.86,11.37l3.03-3.03,1.35,1.35c.21.21.21.55,0,.76l-2.27,2.27c-.21.21-.55.21-.76,0l-1.35-1.35Z" + ], + "d-notice-board": [ + 24, + "M.97,16.66c-.19,0-.38.08-.52.22-.14.14-.22.32-.22.52s.08.38.22.52c.14.14.32.22.52.22h4.21l-1.24,4.97c-.04.19,0,.38.09.55.1.16.26.28.45.33.19.05.38.02.55-.08.17-.1.29-.25.34-.44l.6-2.38h12.09l.6,2.38c.05.19.17.34.34.44.17.1.36.13.55.08.19-.05.35-.16.45-.33.1-.16.13-.36.09-.55l-1.24-4.97h4.21c.19,0,.38-.08.52-.22s.22-.32.22-.52-.08-.38-.22-.52-.32-.22-.52-.22H.97ZM6.32,19.61l.37-1.47h10.62l.37,1.47H6.32Z", + true, + null, + "M12.66.41c-.06-.12-.15-.22-.27-.3-.12-.07-.25-.11-.39-.11s-.27.04-.39.11c-.12.07-.21.17-.27.3l-.53,1.06H3.91c-.58,0-1.15.23-1.56.65s-.65.97-.65,1.56v11.03h20.59V3.68c0-.58-.23-1.15-.65-1.56-.41-.41-.97-.65-1.56-.65h-6.9l-.53-1.06Z" + ], + "d-hospital": [ + 24, + "M12.7,10.42h1.15v1.41h-1.15v1.15h-1.41v-1.15h-1.15v-1.41h1.15v-1.15h1.41v1.15ZM6.24,10.74v10.61c0,.29-.24.53-.53.53H1.03c-.29,0-.53-.24-.53-.53v-10.61c0-.29.24-.53.53-.53h4.68c.29,0,.53.24.53.53ZM4.96,14.98c0-.29-.24-.53-.53-.53h-2.12c-.29,0-.53.24-.53.53v2.12c0,.29.24.53.53.53h2.12c.29,0,.53-.24.53-.53v-2.12ZM23.5,10.74v10.61c0,.29-.24.53-.53.53h-4.68c-.29,0-.53-.24-.53-.53v-10.61c0-.29.24-.53.53-.53h4.68c.29,0,.53.24.53.53ZM22.22,14.98c0-.29-.24-.53-.53-.53h-2.12c-.29,0-.53.24-.53.53v2.12c0,.29.24.53.53.53h2.12c.29,0,.53-.24.53-.53v-2.12Z", + true, + null, + "M7.3,6.9v14.45c0,.29.24.53.53.53h1.5c.29,0,.53-.24.53-.53v-4.88h4.28v4.88c0,.29.24.53.53.53h1.5c.29,0,.53-.24.53-.53v-11.5s0-2.94,0-2.94c0-.29-.24-.53-.53-.53H7.83c-.29,0-.53.24-.53.53ZM12.02,13.94c-1.54,0-2.82-1.24-2.82-2.82s1.24-2.82,2.82-2.82,2.82,1.24,2.82,2.82-1.28,2.82-2.82,2.82ZM17.3,5.31H6.74c-.31,0-.56-.25-.56-.56v-2.07c0-.31.25-.56.56-.56h10.56c.31,0,.56.25.56.56v2.07c0,.31-.25.56-.56.56Z" + ] +} \ No newline at end of file diff --git a/src/CAREUI/interactive/KeyboardShortcut.tsx b/src/CAREUI/interactive/KeyboardShortcut.tsx index 07f3af6a429..ab825d4aada 100644 --- a/src/CAREUI/interactive/KeyboardShortcut.tsx +++ b/src/CAREUI/interactive/KeyboardShortcut.tsx @@ -1,6 +1,7 @@ +import { Fragment } from "react/jsx-runtime"; import useKeyboardShortcut from "use-keyboard-shortcut"; -import { classNames, isAppleDevice } from "@/Utils/utils"; +import { classNames, isAppleDevice } from "../../Utils/utils"; interface Props { children?: React.ReactNode; @@ -70,3 +71,29 @@ const SHORTCUT_KEY_MAP = { ArrowLeft: "←", ArrowRight: "→", } as Record; + +export function KeyboardShortcutKey(props: { + shortcut: string[]; + useShortKeys?: boolean; +}) { + const { shortcut, useShortKeys } = props; + + return ( +
+ {shortcut.map((key, idx, keys) => ( + + + {SHORTCUT_KEY_MAP[key] + ? useShortKeys + ? SHORTCUT_KEY_MAP[key][0] + : SHORTCUT_KEY_MAP[key] + : key} + + {idx !== keys.length - 1 && ( + + + )} + + ))} +
+ ); +} diff --git a/src/CAREUI/interactive/LegendInput.tsx b/src/CAREUI/interactive/LegendInput.tsx index cb415d76ab1..064eb2ceb0f 100644 --- a/src/CAREUI/interactive/LegendInput.tsx +++ b/src/CAREUI/interactive/LegendInput.tsx @@ -130,7 +130,7 @@ export default function LegendInput(props: InputProps) { required={props.required} autoComplete={props.autoComplete} className={classNames( - "cui-input w-full rounded-md border-secondary-300 bg-secondary-50 shadow-sm focus:border-2 focus:border-primary-500 focus:bg-secondary-100 focus:outline-none focus:ring-0", + "cui-input w-full rounded-md border-2 border-secondary-300 border-transparent bg-secondary-50 shadow-sm focus:border-2 focus:border-primary-500 focus:bg-secondary-100 focus:outline-none focus:ring-0", props.size === "small" && "px-3 py-2 text-xs", (!props.size || !["small", "large"].includes(props.size)) && "px-4 py-3", diff --git a/src/CAREUI/misc/PrintPreview.tsx b/src/CAREUI/misc/PrintPreview.tsx index 53eda1339ac..daf79ecbb34 100644 --- a/src/CAREUI/misc/PrintPreview.tsx +++ b/src/CAREUI/misc/PrintPreview.tsx @@ -8,7 +8,8 @@ import { ZoomTransform, } from "@/CAREUI/interactive/Zoom"; -import ButtonV2 from "@/components/Common/ButtonV2"; +import { Button } from "@/components/ui/button"; + import Page from "@/components/Common/Page"; import useBreakpoints from "@/hooks/useBreakpoints"; @@ -30,10 +31,10 @@ export default function PrintPreview(props: Props) {
- +
diff --git a/src/Integrations/Plausible.tsx b/src/Integrations/Plausible.tsx index dfbb2942e5d..89d0572e9e4 100644 --- a/src/Integrations/Plausible.tsx +++ b/src/Integrations/Plausible.tsx @@ -10,6 +10,16 @@ export default function Plausible() { }); useEffect(() => { + const missingConfig = []; + if (!careConfig.plausible.domain) missingConfig.push("domain"); + if (!careConfig.plausible.server) missingConfig.push("server"); + if (missingConfig.length > 0) { + console.error( + `Plausible analytics disabled. Missing configuration: ${missingConfig.join(", ")}`, + ); + return; + } + plausible("pageview"); }, []); diff --git a/src/Integrations/Sentry.tsx b/src/Integrations/Sentry.tsx index 90a8e78f3a9..1fa3d7e6da1 100644 --- a/src/Integrations/Sentry.tsx +++ b/src/Integrations/Sentry.tsx @@ -7,7 +7,10 @@ interface Props { export default function Sentry({ disabled }: Props) { useEffect(() => { - if (disabled || !careConfig.sentry.dsn) { + if (disabled || !careConfig.sentry.dsn || !careConfig.sentry.environment) { + console.error( + "Sentry is not configured correctly. Please check your environment variables.", + ); return; } diff --git a/src/Routers/AppRouter.tsx b/src/Routers/AppRouter.tsx index c8f6fbec83e..8ba9460e34b 100644 --- a/src/Routers/AppRouter.tsx +++ b/src/Routers/AppRouter.tsx @@ -4,8 +4,6 @@ import { useEffect, useState } from "react"; import IconIndex from "@/CAREUI/icons/Index"; -import ABDMFacilityRecords from "@/components/ABDM/ABDMFacilityRecords"; -import HealthInformation from "@/components/ABDM/HealthInformation"; import { DesktopSidebar, MobileSidebar, @@ -60,13 +58,6 @@ const Routes: AppRoutes = { "/notifications/:id": ({ id }) => , "/notice_board": () => , - "/abdm/health-information/:id": ({ id }) => ( - - ), - "/facility/:facilityId/abdm": ({ facilityId }) => ( - - ), - "/session-expired": () => , "/not-found": () => , "/icons": () => , @@ -120,7 +111,7 @@ export default function AppRouter() { return ( -
+
<>
{" "} @@ -130,7 +121,7 @@ export default function AppRouter() {
-
+
- } - show={show} - onClose={onClose} - className="max-w-[500px]" - fixedWidth={false} - > -
-
- -
-
- {[ - { - label: t("full_name"), - value: - abha?.name || - `${abha?.first_name} ${abha?.middle_name} ${abha?.last_name}`, - }, - { label: t("date_of_birth"), value: abha?.date_of_birth }, - { label: t("gender"), value: abha?.gender }, - { label: t("abha_number"), value: abha?.abha_number }, - { - label: t("abha_address"), - value: abha?.health_id?.split("@")[0], - }, - { label: t("email"), value: abha?.email }, - ].map((item, index) => - item.value ? ( -
-
{item.label}
-
{item.value}
-
- ) : null, - )} -
-
- -
- {abha?.created_date && ( -
- {t("created_on")}: - {formatDateTime(abha.created_date)} -
- )} - {abha?.modified_date && ( -
- {t("modified_on")}: - {formatDateTime(abha.modified_date)} -
- )} -
- - ); -}; - -export default ABHAProfileModal; diff --git a/src/components/ABDM/ConfigureHealthFacility.tsx b/src/components/ABDM/ConfigureHealthFacility.tsx deleted file mode 100644 index ba3eb325dec..00000000000 --- a/src/components/ABDM/ConfigureHealthFacility.tsx +++ /dev/null @@ -1,243 +0,0 @@ -import { navigate } from "raviger"; -import { useReducer, useState } from "react"; -import { useTranslation } from "react-i18next"; - -import { IHealthFacility } from "@/components/ABDM/types/health-facility"; -import { Submit } from "@/components/Common/ButtonV2"; -import Loading from "@/components/Common/Loading"; -import TextFormField from "@/components/Form/FormFields/TextFormField"; -import { FieldChangeEvent } from "@/components/Form/FormFields/Utils"; - -import * as Notification from "@/Utils/Notifications"; -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import useQuery from "@/Utils/request/useQuery"; -import { classNames } from "@/Utils/utils"; - -const initForm = { - health_facility: null as IHealthFacility | null, - hf_id: "", -}; - -const initialState = { - form: { ...initForm }, - errors: {} as Partial>, -}; - -const FormReducer = ( - state = initialState, - action: - | { - type: "set_form"; - form: typeof initialState.form; - } - | { - type: "set_error"; - errors: typeof initialState.errors; - }, -) => { - switch (action.type) { - case "set_form": { - return { - ...state, - form: action.form, - }; - } - case "set_error": { - return { - ...state, - errors: action.errors, - }; - } - default: - return state; - } -}; - -export interface IConfigureHealthFacilityProps { - facilityId: string; -} - -export const ConfigureHealthFacility = ( - props: IConfigureHealthFacilityProps, -) => { - const { t } = useTranslation(); - - const [state, dispatch] = useReducer(FormReducer, initialState); - const { facilityId } = props; - const [isLoading, setIsLoading] = useState(false); - - const { loading } = useQuery(routes.abdm.healthFacility.get, { - pathParams: { facility_id: facilityId }, - silent: true, - onResponse(res) { - if (res.data) { - dispatch({ - type: "set_form", - form: { - ...state.form, - health_facility: res.data, - hf_id: res.data.hf_id, - }, - }); - } - }, - }); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setIsLoading(true); - - if (!state.form.hf_id) { - dispatch({ - type: "set_error", - errors: { hf_id: t("health_facility__validation__hf_id_required") }, - }); - setIsLoading(false); - return; - } - - let response = null; - let responseData = null; - if (state.form.hf_id === state.form.health_facility?.hf_id) { - const { res, data } = await request( - routes.abdm.healthFacility.registerAsService, - { - pathParams: { - facility_id: facilityId, - }, - }, - ); - response = res; - responseData = data; - } else if (state.form.health_facility) { - const { res, data } = await request( - routes.abdm.healthFacility.partialUpdate, - { - pathParams: { - facility_id: facilityId, - }, - body: { - hf_id: state.form.hf_id, - }, - }, - ); - response = res; - responseData = data; - } else { - const { res, data } = await request(routes.abdm.healthFacility.create, { - body: { - facility: facilityId, - hf_id: state.form.hf_id, - }, - silent: true, - }); - response = res; - responseData = data; - } - - if (response?.ok && responseData?.registered) { - Notification.Success({ - msg: t("health_facility__config_update_success"), - }); - navigate(`/facility/${facilityId}`); - } else { - if (responseData?.registered === false) { - Notification.Warn({ - msg: - responseData?.detail || - t("health_facility__config_registration_error"), - }); - navigate(`/facility/${facilityId}`); - } else { - Notification.Error({ - msg: - responseData?.detail || t("health_facility__config_update_error"), - }); - } - } - setIsLoading(false); - }; - - const handleChange = (e: FieldChangeEvent) => { - dispatch({ - type: "set_form", - form: { ...state.form, [e.name]: e.value }, - }); - }; - - if (loading || isLoading) { - return ; - } - - return ( -
-
-
-
- - {state.form.health_facility?.registered ? ( - <> -
- - {t("health_facility__registered_1.1")}{" "} - - {t("health_facility__registered_1.2")} - - - - {t("health_facility__registered_2")} - -
- {t("health_facility__registered_3")} - - ) : ( - <> -
- - {t("health_facility__not_registered_1.1")}{" "} - - {t("health_facility__not_registered_1.2")} - - - - {t("health_facility__not_registered_2")} - - {t("health_facility__not_registered_3")} -
- - )} -

- } - required - value={state.form.hf_id} - onChange={handleChange} - error={state.errors?.hf_id} - /> -
-
-
- -
-
-
- ); -}; diff --git a/src/components/ABDM/FetchRecordsModal.tsx b/src/components/ABDM/FetchRecordsModal.tsx deleted file mode 100644 index 9433374f931..00000000000 --- a/src/components/ABDM/FetchRecordsModal.tsx +++ /dev/null @@ -1,246 +0,0 @@ -import dayjs from "dayjs"; -import { navigate } from "raviger"; -import { useState } from "react"; -import { useTranslation } from "react-i18next"; - -import { AbhaNumberModel } from "@/components/ABDM/types/abha"; -import { ConsentHIType, ConsentPurpose } from "@/components/ABDM/types/consent"; -import ButtonV2 from "@/components/Common/ButtonV2"; -import DialogModal from "@/components/Common/Dialog"; -import DateFormField from "@/components/Form/FormFields/DateFormField"; -import DateRangeFormField from "@/components/Form/FormFields/DateRangeFormField"; -import { - MultiSelectFormField, - SelectFormField, -} from "@/components/Form/FormFields/SelectFormField"; -import TextFormField from "@/components/Form/FormFields/TextFormField"; - -import { useMessageListener } from "@/hooks/useMessageListener"; - -import { ABDM_CONSENT_PURPOSE, ABDM_HI_TYPE } from "@/common/constants"; - -import * as Notification from "@/Utils/Notifications"; -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; - -const getDate = (value: string | Date) => - (value && dayjs(value).isValid() && dayjs(value).toDate()) || undefined; - -interface IProps { - abha?: AbhaNumberModel; - show: boolean; - onClose: () => void; -} - -export default function FetchRecordsModal({ abha, show, onClose }: IProps) { - const { t } = useTranslation(); - - const [idVerificationStatus, setIdVerificationStatus] = useState< - "pending" | "in-progress" | "verified" | "failed" - >("verified"); - const [purpose, setPurpose] = useState("CAREMGT"); - const [fromDate, setFromDate] = useState( - dayjs().subtract(30, "day").toDate(), - ); - const [toDate, setToDate] = useState(dayjs().toDate()); - const [isMakingConsentRequest, setIsMakingConsentRequest] = useState(false); - const [hiTypes, setHiTypes] = useState([]); - const [expiryDate, setExpiryDate] = useState( - dayjs().add(30, "day").toDate(), - ); - const [errors, setErrors] = useState>({}); - // const notificationSubscriptionState = useNotificationSubscriptionState([ - // show, - // ]); - - useMessageListener((data) => { - if (data.type === "MESSAGE" && data.from === "patients/on_find") { - if (data.message?.patient?.id === abha?.health_id) { - setIdVerificationStatus("verified"); - setErrors({ - ...errors, - health_id: "", - }); - } - } - }); - - return ( - - {/* {["unsubscribed", "subscribed_on_other_device"].includes( - notificationSubscriptionState, - ) && ( -

- {" "} - Notifications needs to be enabled on this device to verify the - patient. -

- )} */} - -
- null} - disabled - label={t("consent_request__patient_identifier")} - name="health_id" - error={errors.health_id} - className="flex-1" - /> - - {/* { - const { res } = await request(routes.abha.findPatient, { - body: { - id: abha?.health_id, - }, - reattempts: 0, - }); - - if (res?.status) { - setIdVerificationStatus("in-progress"); - } - }} - loading={idVerificationStatus === "in-progress"} - ghost={idVerificationStatus === "verified"} - disabled={ - idVerificationStatus === "verified" || - ["unsubscribed", "subscribed_on_other_device"].includes( - notificationSubscriptionState, - ) - } - className={classNames( - "mt-1.5 !py-3", - idVerificationStatus === "verified" && - "disabled:cursor-auto disabled:bg-transparent disabled:text-primary-600", - )} - > - {idVerificationStatus === "in-progress" && ( - - )} - {idVerificationStatus === "verified" && } - { - { - pending: "Verify Patient", - "in-progress": "Verifying", - verified: "Verified", - failed: "Retry", - }[idVerificationStatus] - } - */} -
- t(`consent__purpose__${o}`)} - optionValue={(o) => o} - value={purpose} - onChange={({ value }) => setPurpose(value)} - required - /> - - { - setFromDate(e.value.start!); - setToDate(e.value.end!); - }} - label={t("consent_request__date_range")} - required - /> - - { - setHiTypes(ABDM_HI_TYPE); - }} - > - {t("select_all")} - - ) - } - value={hiTypes} - optionLabel={(option) => t(`consent__hi_type__${option}`)} - optionValue={(option) => option} - onChange={(e) => setHiTypes(e.value)} - required - /> - - setExpiryDate(e.value!)} - label={t("consent_request__expiry")} - required - disablePast - /> - -
- { - if (idVerificationStatus !== "verified") { - setErrors({ - ...errors, - health_id: t("verify_patient_identifier"), - }); - - return; - } - - setIsMakingConsentRequest(true); - const { res } = await request(routes.abdm.consent.create, { - body: { - patient_abha: abha?.health_id as string, - hi_types: hiTypes, - purpose, - from_time: fromDate, - to_time: toDate, - expiry: expiryDate, - }, - }); - - if (res?.status === 201) { - Notification.Success({ - msg: t("consent_requested_successfully"), - }); - - navigate( - `/facility/${abha?.patient_object?.facility}/abdm`, - // ?? `/facility/${abha?.patient_object?.facility}/patient/${abha?.patient_object?.id}/consultation/${abha?.patient_object?.last_consultation?.id}/abdm`, - ); - } - setIsMakingConsentRequest(false); - onClose(); - }} - disabled={idVerificationStatus !== "verified"} - loading={isMakingConsentRequest} - > - {t("request_consent")} - -
-
- ); -} diff --git a/src/components/ABDM/HealthInformation.tsx b/src/components/ABDM/HealthInformation.tsx deleted file mode 100644 index e147f050131..00000000000 --- a/src/components/ABDM/HealthInformation.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { HIProfile } from "hi-profiles"; -import { useTranslation } from "react-i18next"; - -import Loading from "@/components/Common/Loading"; -import Page from "@/components/Common/Page"; - -import routes from "@/Utils/request/api"; -import useQuery from "@/Utils/request/useQuery"; - -interface IProps { - artefactId: string; -} - -export default function HealthInformation({ artefactId }: IProps) { - const { t } = useTranslation(); - - const { data, loading, error } = useQuery(routes.abdm.healthInformation.get, { - pathParams: { artefactId }, - silent: true, - }); - - if (loading) { - return ; - } - - const parseData = (data: string) => { - try { - return JSON.parse(data); - } catch (e) { - return JSON.parse( - data.replace(/"/g, '\\"').replace(/'/g, '"'), // eslint-disable-line - ); - } - }; - - return ( - -
- {!!error?.is_archived && ( - <> -

- {t("hi__record_archived__title")} -

-
- {t("hi__record_archived_description")} -
-

- {t("hi__record_archived_on")}{" "} - {new Date(error?.archived_time as string).toLocaleString()} -{" "} - {error?.archived_reason as string} -

- - )} - {error && !error?.is_archived && ( - <> -

- {t("hi__record_not_fetched_title")} -

-
- {t("hi__record_not_fetched_description")} -
-

- {t("hi__waiting_for_record")} -

- - )} - {data?.data.map((item) => ( - - ))} -
-
- ); -} diff --git a/src/components/ABDM/LinkAbhaNumber/CreateWithAadhaar.tsx b/src/components/ABDM/LinkAbhaNumber/CreateWithAadhaar.tsx deleted file mode 100644 index d2697633bea..00000000000 --- a/src/components/ABDM/LinkAbhaNumber/CreateWithAadhaar.tsx +++ /dev/null @@ -1,740 +0,0 @@ -import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; - -import useMultiStepForm, { - InjectedStepProps, -} from "@/components/ABDM/LinkAbhaNumber/useMultiStepForm"; -import { AbhaNumberModel } from "@/components/ABDM/types/abha"; -import ButtonV2, { ButtonWithTimer } from "@/components/Common/ButtonV2"; -import CheckBoxFormField from "@/components/Form/FormFields/CheckBoxFormField"; -import OtpFormField from "@/components/Form/FormFields/OtpFormField"; -import PhoneNumberFormField from "@/components/Form/FormFields/PhoneNumberFormField"; -import TextFormField from "@/components/Form/FormFields/TextFormField"; -import { validateRule } from "@/components/Users/UserAdd"; - -import * as Notify from "@/Utils/Notifications"; -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import { classNames } from "@/Utils/utils"; - -const MAX_OTP_RESEND_ALLOWED = 2; - -type ICreateWithAadhaarProps = { - onSuccess: (abhaNumber: AbhaNumberModel) => void; -}; - -type Memory = { - aadhaarNumber: string; - mobileNumber: string; - - isLoading: boolean; - validationError: string; - - transactionId: string; - abhaNumber: AbhaNumberModel | null; - - resendOtpCount: number; -}; - -export default function CreateWithAadhaar({ - onSuccess, -}: ICreateWithAadhaarProps) { - const { currentStep } = useMultiStepForm( - [ - , - , - , - , - , - , - ], - { - aadhaarNumber: "", - mobileNumber: "+91", - isLoading: false, - validationError: "", - transactionId: "", - abhaNumber: null, - resendOtpCount: 0, - }, - ); - - return
{currentStep}
; -} - -type IEnterAadhaarProps = InjectedStepProps; - -function EnterAadhaar({ memory, setMemory, next }: IEnterAadhaarProps) { - const { t } = useTranslation(); - const [disclaimerAccepted, setDisclaimerAccepted] = useState([ - false, - false, - false, - false, - ]); - - const validateAadhaar = () => { - if ( - memory?.aadhaarNumber.length !== 12 && - memory?.aadhaarNumber.length !== 16 - ) { - setMemory((prev) => ({ - ...prev, - validationError: t("aadhaar_validation_length_error"), - })); - return false; - } - - if (memory?.aadhaarNumber.includes(" ")) { - setMemory((prev) => ({ - ...prev, - validationError: t("aadhaar_validation_space_error"), - })); - return false; - } - - return true; - }; - - const handleSubmit = async () => { - if (!validateAadhaar()) return; - - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateSendAadhaarOtp, - { - body: { - aadhaar: memory!.aadhaarNumber, - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ ...prev, transactionId: data.transaction_id })); - Notify.Success({ - msg: data.detail ?? t("aadhaar_otp_send_success"), - }); - next(); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
-
- - setMemory((prev) => ({ ...prev, aadhaarNumber: value })) - } - error={memory?.validationError} - /> - - {t("aadhaar_number_will_not_be_stored")} - -
- -
- {disclaimerAccepted.map((isAccepted, i) => ( - { - setDisclaimerAccepted( - disclaimerAccepted.map((v, j) => (j === i ? e.value : v)), - ); - }} - className="mr-2 rounded border-gray-700" - labelClassName="text-xs text-gray-800" - errorClassName="hidden" - /> - ))} -
- -
- !v) || - memory?.aadhaarNumber.length === 0 - } - onClick={handleSubmit} - > - {t("send_otp")} - -
-
- ); -} - -type IVerifyAadhaarProps = InjectedStepProps; - -function VerifyAadhaar({ memory, setMemory, next }: IVerifyAadhaarProps) { - const { t } = useTranslation(); - const [otp, setOtp] = useState(""); - - const validateMobileNumber = () => { - const phone = memory?.mobileNumber.replace("+91", "").replace(/ /g, ""); - if (phone?.length !== 10) { - setMemory((prev) => ({ - ...prev, - validationError: t("mobile_number_validation_error"), - })); - return false; - } - - return true; - }; - - const handleSubmit = async () => { - if (!validateMobileNumber()) return; - - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateVerifyAadhaarOtp, - { - body: { - otp: otp, - transaction_id: memory?.transactionId, - mobile: memory?.mobileNumber.replace("+91", "").replace(/ /g, ""), - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - abhaNumber: data.abha_number, - resendOtpCount: 0, - })); - Notify.Success({ - msg: data.detail ?? t("otp_verification_success"), - }); - next(); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - const handleResendOtp = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateSendAadhaarOtp, - { - body: { - aadhaar: memory!.aadhaarNumber, - // transaction_id: memory?.transactionId, - }, - silent: true, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - resendOtpCount: prev.resendOtpCount + 1, - })); - Notify.Success({ - msg: data.detail ?? t("aadhaar_otp_send_success"), - }); - } else { - setMemory((prev) => ({ - ...prev, - resendOtpCount: Infinity, - })); - Notify.Success({ - msg: t("aadhaar_otp_send_error"), - }); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
-
- - setMemory((prev) => ({ ...prev, aadhaarNumber: value })) - } - /> - - {t("aadhaar_number_will_not_be_stored")} - -
- -
- setOtp(value as string)} - value={otp} - label={t("enter_aadhaar_otp")} - disabled={memory?.isLoading} - /> -
- -
- } - name="mobile_number" - value={memory?.mobileNumber} - onChange={(e) => { - if (!memory?.mobileNumber.startsWith("+91")) { - setMemory((prev) => ({ - ...prev, - validationError: t("only_indian_mobile_numbers_supported"), - })); - return; - } - - setMemory((prev) => ({ ...prev, mobileNumber: e.value })); - }} - error={memory?.validationError} - errorClassName="text-xs text-red-500" - types={["mobile"]} - /> -
- -
- 6 || memory?.mobileNumber.length === 0} - onClick={handleSubmit} - > - {t("verify_otp")} - - - {(memory?.resendOtpCount ?? 0) < MAX_OTP_RESEND_ALLOWED && ( - - {t("resend_otp")} - - )} -
-
- ); -} - -type IHandleExistingAbhaNumberProps = InjectedStepProps & { - onSuccess: (abhaNumber: AbhaNumberModel) => void; -}; - -function HandleExistingAbhaNumber({ - memory, - onSuccess, - next, -}: IHandleExistingAbhaNumberProps) { - const { t } = useTranslation(); - - // skip this step for new abha number - useEffect(() => { - if (memory?.abhaNumber?.new) { - next(); - } - }, [memory?.abhaNumber, memory?.mobileNumber]); // eslint-disable-line - - return ( -
-

- {t("abha_number_exists")} -

-

- {t("abha_number_exists_description")} -

-
- - {t("create_new_abha_address")} - - onSuccess(memory?.abhaNumber as AbhaNumberModel)} - > - {t("use_existing_abha_address")} - -

- {memory?.abhaNumber?.health_id} -

-
-
- ); -} - -type ILinkMobileNumberProps = InjectedStepProps; - -function LinkMobileNumber({ - memory, - goTo, - setMemory, - next, -}: ILinkMobileNumberProps) { - const { t } = useTranslation(); - - useEffect(() => { - if ( - memory?.abhaNumber?.mobile === - memory?.mobileNumber.replace("+91", "").replace(/ /g, "") - ) { - goTo(5); // skip linking mobile number - } - }, [memory?.abhaNumber, memory?.mobileNumber]); // eslint-disable-line - - const handleSubmit = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateLinkMobileNumber, - { - body: { - mobile: memory?.mobileNumber.replace("+91", "").replace(/ /g, ""), - transaction_id: memory?.transactionId, - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - })); - Notify.Success({ - msg: data.detail ?? t("mobile_otp_send_success"), - }); - next(); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
-
- } - name="mobile_number" - value={memory?.mobileNumber} - disabled={true} - onChange={() => null} - types={["mobile"]} - /> -
- -

- {t("mobile_number_different_from_aadhaar_mobile_number")} -

- -
- - {t("send_otp")} - -
-
- ); -} - -type IVerifyMobileNumberProps = InjectedStepProps; - -function VerifyMobileNumber({ - memory, - setMemory, - next, -}: IVerifyMobileNumberProps) { - const { t } = useTranslation(); - const [otp, setOtp] = useState(""); - - const handleSubmit = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateVerifyMobileNumber, - { - body: { - transaction_id: memory?.transactionId, - otp: otp, - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - resendOtpCount: 0, - })); - Notify.Success({ - msg: data.detail ?? t("mobile_otp_verify_success"), - }); - next(); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - const handleResendOtp = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateLinkMobileNumber, - { - body: { - mobile: memory?.mobileNumber.replace("+91", "").replace(/ /g, ""), - transaction_id: memory?.transactionId, - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - resendOtpCount: prev.resendOtpCount + 1, - })); - Notify.Success({ - msg: data.detail ?? t("mobile_otp_send_success"), - }); - } else { - setMemory((prev) => ({ - ...prev, - resendOtpCount: Infinity, - })); - Notify.Success({ - msg: t("mobile_otp_send_error"), - }); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
-
- } - name="mobile_number" - value={memory?.mobileNumber} - disabled={true} - onChange={() => null} - types={["mobile"]} - /> -
- -
- setOtp(value as string)} - value={otp} - label={t("enter_mobile_otp")} - disabled={memory?.isLoading} - /> -
- -
- - {t("verify_otp")} - - - {(memory?.resendOtpCount ?? 0) < MAX_OTP_RESEND_ALLOWED && ( - - {t("resend_otp")} - - )} -
-
- ); -} - -type IChooseAbhaAddressProps = InjectedStepProps & { - onSuccess: (abhaNumber: AbhaNumberModel) => void; -}; - -function ChooseAbhaAddress({ - memory, - setMemory, - onSuccess, -}: IChooseAbhaAddressProps) { - const { t } = useTranslation(); - const [healthId, setHealthId] = useState(""); - const [suggestions, setSuggestions] = useState([]); - - useEffect(() => { - const fetchSuggestions = async () => { - const { res, data } = await request( - routes.abdm.healthId.abhaCreateAbhaAddressSuggestion, - { - body: { - transaction_id: memory?.transactionId, - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ ...prev, transactionId: data.transaction_id })); - setSuggestions(data.abha_addresses); - } - }; - - fetchSuggestions(); - }, [healthId, memory?.transactionId, setMemory]); - - const handleSubmit = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaCreateEnrolAbhaAddress, - { - body: { - abha_address: healthId, - transaction_id: memory?.transactionId, - }, - }, - ); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - abhaNumber: data.abha_number, - })); - Notify.Success({ - msg: data.detail ?? t("abha_address_created_success"), - }); - onSuccess(data.abha_number); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
- { - setHealthId(value); - }} - /> - -
- {validateRule( - healthId.length >= 4, - t("abha_address_validation_length_error"), - false, - )} - {validateRule( - Number.isNaN(Number(healthId[0])) && healthId[0] !== ".", - t("abha_address_validation_start_error"), - false, - )} - {validateRule( - healthId[healthId.length - 1] !== ".", - t("abha_address_validation_end_error"), - false, - )} - {validateRule( - /^[0-9a-zA-Z._]+$/.test(healthId), - t("abha_address_validation_character_error"), - false, - )} -
- - {suggestions.length > 0 && ( -
-

- {t("abha_address_suggestions")} -

-
- {suggestions - .filter((suggestion) => suggestion !== healthId) - .map((suggestion) => ( -

setHealthId(suggestion)} - className="cursor-pointer rounded-md bg-primary-400 px-2.5 py-1 text-xs text-white" - > - {suggestion} -

- ))} -
-
- )} - -
- - {t("create_abha_address")} - -
-
- ); -} diff --git a/src/components/ABDM/LinkAbhaNumber/LinkWithOtp.tsx b/src/components/ABDM/LinkAbhaNumber/LinkWithOtp.tsx deleted file mode 100644 index 9b8150dee86..00000000000 --- a/src/components/ABDM/LinkAbhaNumber/LinkWithOtp.tsx +++ /dev/null @@ -1,350 +0,0 @@ -import { useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; - -import useMultiStepForm, { - InjectedStepProps, -} from "@/components/ABDM/LinkAbhaNumber/useMultiStepForm"; -import { AbhaNumberModel } from "@/components/ABDM/types/abha"; -import ButtonV2, { ButtonWithTimer } from "@/components/Common/ButtonV2"; -import Dropdown, { DropdownItem } from "@/components/Common/Menu"; -import CheckBoxFormField from "@/components/Form/FormFields/CheckBoxFormField"; -import OtpFormField from "@/components/Form/FormFields/OtpFormField"; -import TextFormField from "@/components/Form/FormFields/TextFormField"; - -import * as Notify from "@/Utils/Notifications"; -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import { classNames } from "@/Utils/utils"; - -const MAX_OTP_RESEND_ALLOWED = 2; - -type ILoginWithOtpProps = { - onSuccess: (abhaNumber: AbhaNumberModel) => void; -}; - -type Memory = { - id: string; - - isLoading: boolean; - validationError: string; - - transactionId: string; - type: "aadhaar" | "mobile" | "abha-number" | "abha-address"; - otp_system: "abdm" | "aadhaar"; - abhaNumber: AbhaNumberModel | null; - - resendOtpCount: number; -}; - -export default function LinkWithOtp({ onSuccess }: ILoginWithOtpProps) { - const { currentStep } = useMultiStepForm( - [ - , - , - ], - { - id: "", - isLoading: false, - validationError: "", - transactionId: "", - type: "aadhaar", - otp_system: "aadhaar", - abhaNumber: null, - resendOtpCount: 0, - }, - ); - - return
{currentStep}
; -} - -type IEnterIdProps = InjectedStepProps; - -const supportedAuthMethods = ["AADHAAR_OTP", "MOBILE_OTP"]; - -function EnterId({ memory, setMemory, next }: IEnterIdProps) { - const { t } = useTranslation(); - const [disclaimerAccepted, setDisclaimerAccepted] = useState([ - false, - false, - false, - ]); - const [authMethods, setAuthMethods] = useState([]); - - const valueType = useMemo(() => { - const id = memory?.id; - const isNumeric = !isNaN(Number(id?.trim())); - - if (isNumeric && (id?.length === 12 || id?.length === 16)) { - return "aadhaar"; - } else if (isNumeric && id?.length === 10) { - return "mobile"; - } else if (isNumeric && id?.length === 14) { - return "abha-number"; - } else { - return "abha-address"; - } - }, [memory?.id]); - - const handleGetAuthMethods = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - if (valueType === "aadhaar") { - setAuthMethods(["AADHAAR_OTP"]); - } else if (valueType === "mobile") { - setAuthMethods(["MOBILE_OTP"]); - } else { - const { res, data, error } = await request( - routes.abdm.healthId.abhaLoginCheckAuthMethods, - { - body: { - abha_address: memory?.id.replace(/-/g, "").replace(/ /g, ""), - }, - silent: true, - }, - ); - - if (res?.status === 200 && data) { - const methods = data.auth_methods.filter((method: string) => - supportedAuthMethods.find((supported) => supported === method), - ); - - if (methods.length === 0) { - Notify.Warn({ msg: t("get_auth_mode_error") }); - } - } else { - Notify.Error({ msg: error?.message ?? t("get_auth_mode_error") }); - } - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - const handleSendOtp = async (authMethod: string) => { - if (!supportedAuthMethods.includes(authMethod)) { - Notify.Warn({ msg: t("auth_method_unsupported") }); - return; - } - - const otp_system: "aadhaar" | "abdm" = - authMethod === "AADHAAR_OTP" ? "aadhaar" : "abdm"; - - setMemory((prev) => ({ - ...prev, - isLoading: true, - type: valueType, - otp_system, - })); - - const { res, data } = await request(routes.abdm.healthId.abhaLoginSendOtp, { - body: { - value: memory?.id, - type: valueType, - otp_system, - }, - }); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - })); - Notify.Success({ msg: data.detail ?? t("send_otp_success") }); - next(); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
-
- { - setMemory((prev) => ({ ...prev, id: value })); - setAuthMethods([]); - }} - error={memory?.validationError} - /> - - {t("any_id_description")} - -
- -
- {disclaimerAccepted.map((isAccepted, i) => ( - { - setDisclaimerAccepted( - disclaimerAccepted.map((v, j) => (j === i ? e.value : v)), - ); - }} - className="mr-2 rounded border-gray-700" - labelClassName="text-xs text-gray-800" - errorClassName="hidden" - /> - ))} -
- -
- {authMethods.length === 0 ? ( - !v) || memory?.id.length === 0 - } - onClick={handleGetAuthMethods} - > - {t("get_auth_methods")} - - ) : ( - - {authMethods.map((method) => ( - handleSendOtp(method)}> - {t(`abha__auth_method__${method}`)} - - ))} - - )} -
-
- ); -} - -type IVerifyIdProps = InjectedStepProps & { - onSuccess: (abhaNumber: AbhaNumberModel) => void; -}; - -function VerifyId({ memory, setMemory, onSuccess }: IVerifyIdProps) { - const { t } = useTranslation(); - const [otp, setOtp] = useState(""); - - const handleSubmit = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request( - routes.abdm.healthId.abhaLoginVerifyOtp, - { - body: { - type: memory?.type, - transaction_id: memory?.transactionId, - otp, - otp_system: memory?.otp_system, - }, - }, - ); - - if (res?.status === 200 && data) { - Notify.Success({ msg: t("verify_otp_success") }); - onSuccess(data.abha_number); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - const handleResendOtp = async () => { - setMemory((prev) => ({ ...prev, isLoading: true })); - - const { res, data } = await request(routes.abdm.healthId.abhaLoginSendOtp, { - body: { - value: memory?.id, - type: memory?.type, - otp_system: memory?.otp_system, - }, - }); - - if (res?.status === 200 && data) { - setMemory((prev) => ({ - ...prev, - transactionId: data.transaction_id, - resendOtpCount: (prev.resendOtpCount ?? 0) + 1, - })); - Notify.Success({ msg: data.detail ?? t("send_otp_success") }); - } else { - setMemory((prev) => ({ - ...prev, - resendOtpCount: Infinity, - })); - Notify.Error({ msg: t("send_otp_error") }); - } - - setMemory((prev) => ({ ...prev, isLoading: false })); - }; - - return ( -
-
- null} - /> - - {t("any_id_description")} - -
- -
- setOtp(value as string)} - value={otp} - label={t("enter_otp")} - disabled={memory?.isLoading} - /> -
- -
- - {t("verify_and_link")} - - - {(memory?.resendOtpCount ?? 0) < MAX_OTP_RESEND_ALLOWED && ( - - {t("resend_otp")} - - )} -
-
- ); -} diff --git a/src/components/ABDM/LinkAbhaNumber/LinkWithQr.tsx b/src/components/ABDM/LinkAbhaNumber/LinkWithQr.tsx deleted file mode 100644 index 712d28943b4..00000000000 --- a/src/components/ABDM/LinkAbhaNumber/LinkWithQr.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { IDetectedBarcode, Scanner } from "@yudiel/react-qr-scanner"; -import { useState } from "react"; -import { useTranslation } from "react-i18next"; - -import { ABHAQRContent, AbhaNumberModel } from "@/components/ABDM/types/abha"; - -import * as Notification from "@/Utils/Notifications"; -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; - -type ILoginWithQrProps = { - onSuccess: (abhaNumber: AbhaNumberModel) => void; -}; - -export default function LinkWithQr({ onSuccess }: ILoginWithQrProps) { - const { t } = useTranslation(); - const [isLoading, setIsLoading] = useState(false); - - return ( -
- { - if (detectedCodes.length === 0) return; - - const scannedValue = detectedCodes[0].rawValue; - if (!scannedValue || isLoading) return; - - try { - const qrData = JSON.parse(scannedValue) as ABHAQRContent; - - setIsLoading(true); - const { res, data } = await request(routes.abdm.abhaNumber.create, { - body: { - abha_number: qrData.hidn, - health_id: qrData.hid || qrData.phr, - name: qrData.name, - gender: qrData.gender, - date_of_birth: qrData.dob, - address: qrData.address, - district: qrData.district_name || qrData["dist name"], - state: qrData.state_name || qrData["state name"], - mobile: qrData.mobile, - }, - }); - - if (res?.status === 201 && data) { - onSuccess(data); - } - setIsLoading(false); - } catch (e) { - Notification.Error({ - msg: t("abha__qr_scanning_error"), - }); - } - }} - onError={(e: unknown) => { - const errorMessage = e instanceof Error ? e.message : "Unknown error"; - Notification.Error({ - msg: errorMessage, - }); - }} - scanDelay={3000} - constraints={{ - facingMode: "environment", - }} - /> -
- ); -} diff --git a/src/components/ABDM/LinkAbhaNumber/index.tsx b/src/components/ABDM/LinkAbhaNumber/index.tsx deleted file mode 100644 index 45cd0b34d02..00000000000 --- a/src/components/ABDM/LinkAbhaNumber/index.tsx +++ /dev/null @@ -1,142 +0,0 @@ -import { useState } from "react"; -import { useTranslation } from "react-i18next"; - -import CreateWithAadhaar from "@/components/ABDM/LinkAbhaNumber/CreateWithAadhaar"; -import LinkWithOtp from "@/components/ABDM/LinkAbhaNumber/LinkWithOtp"; -import LinkWithQr from "@/components/ABDM/LinkAbhaNumber/LinkWithQr"; -import { AbhaNumberModel } from "@/components/ABDM/types/abha"; -import ButtonV2 from "@/components/Common/ButtonV2"; -import DialogModal from "@/components/Common/Dialog"; - -import { classNames } from "@/Utils/utils"; - -interface ILinkAbhaNumberProps { - show: boolean; - onClose: () => void; - onSuccess: (abhaNumber: AbhaNumberModel) => void; -} - -const ABHA_LINK_OPTIONS = { - create_with_aadhaar: { - title: "abha_link_options__create_with_aadhaar__title", - description: "abha_link_options__create_with_aadhaar__description", - disabled: false, - value: "create_with_aadhaar", - create: true, - }, - link_with_otp: { - title: "abha_link_options__link_with_otp__title", - description: "abha_link_options__link_with_otp__description", - disabled: false, - value: "link_with_otp", - create: false, - }, - create_with_driving_license: { - title: "abha_link_options__create_with_driving_license__title", - description: "abha_link_options__create_with_driving_license__description", - disabled: true, - value: "create_with_driving_license", - create: true, - }, - link_with_demographics: { - title: "abha_link_options__link_with_demographics__title", - description: "abha_link_options__link_with_demographics__description", - disabled: true, - value: "link_with_demographics", - create: false, - }, - link_with_qr: { - title: "abha_link_options__link_with_qr__title", - description: "abha_link_options__link_with_qr__description", - disabled: false, - value: "link_with_qr", - create: false, - }, -}; - -export default function LinkAbhaNumber({ - show, - onClose, - onSuccess, -}: ILinkAbhaNumberProps) { - const { t } = useTranslation(); - const [currentAbhaLinkOption, setCurrentAbhaLinkOption] = useState< - keyof typeof ABHA_LINK_OPTIONS - >("create_with_aadhaar"); - - return ( - - {currentAbhaLinkOption === "create_with_aadhaar" && ( - - )} - - {currentAbhaLinkOption === "link_with_otp" && ( - - )} - - {currentAbhaLinkOption === "link_with_qr" && ( - - )} - -
-

- setCurrentAbhaLinkOption( - ABHA_LINK_OPTIONS[currentAbhaLinkOption].create - ? "link_with_otp" - : "create_with_aadhaar", - ) - } - className="cursor-pointer text-center text-sm text-blue-800" - > - {ABHA_LINK_OPTIONS[currentAbhaLinkOption].create - ? t("link_existing_abha_profile") - : t("create_new_abha_profile")} -

-
- -
-

- {t("try_different_abha_linking_option")} -

-
- {Object.values(ABHA_LINK_OPTIONS) - .filter( - (option) => - option.value !== currentAbhaLinkOption && - ABHA_LINK_OPTIONS[currentAbhaLinkOption]?.create === - option.create, - ) - .sort((a) => (a.disabled ? 1 : -1)) - .map((option) => ( - - setCurrentAbhaLinkOption( - option.value as keyof typeof ABHA_LINK_OPTIONS, - ) - } - ghost - tooltip={ - option.disabled - ? t("abha_link_options__disabled_tooltip") - : t(option.description) - } - disabled={option.disabled} - tooltipClassName="top-full mt-1" - className={classNames( - "w-full border border-gray-400 text-secondary-800", - !option.disabled && "hover:border-primary-100", - )} - > - {t(option.title)} - - ))} -
-
-
- ); -} diff --git a/src/components/ABDM/LinkAbhaNumber/useMultiStepForm.ts b/src/components/ABDM/LinkAbhaNumber/useMultiStepForm.ts deleted file mode 100644 index 79bc9ec71c6..00000000000 --- a/src/components/ABDM/LinkAbhaNumber/useMultiStepForm.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { - Dispatch, - ReactElement, - SetStateAction, - cloneElement, - useCallback, - useMemo, - useState, -} from "react"; - -export interface InjectedStepProps { - currentStepIndex: number; - isFirstStep: boolean; - isLastStep: boolean; - next: () => void; - prev: () => void; - goTo: (step: number) => void; - memory: T | null; - setMemory: Dispatch>; -} - -export default function useMultiStepForm( - steps: ReactElement[], - initialValues?: T, -) { - const [currentStepIndex, setCurrentStepIndex] = useState(0); - const [memory, setMemory] = useState(initialValues as T); - - const next = useCallback( - () => - setCurrentStepIndex((prev) => - steps.length - 1 > prev ? prev + 1 : prev, - ), - [steps.length], - ); - - const prev = useCallback( - () => setCurrentStepIndex((prev) => (prev > 0 ? prev - 1 : prev)), - [], - ); - - const goTo = useCallback( - (step: number) => - setCurrentStepIndex((prev) => - step >= 0 && step <= steps.length - 1 ? step : prev, - ), - [steps.length], - ); - - const options = useMemo( - () => ({ - currentStepIndex, - isFirstStep: currentStepIndex === 0, - isLastStep: currentStepIndex === steps.length - 1, - next, - prev, - goTo, - memory, - setMemory, - }), - [currentStepIndex, memory, next, prev, goTo, steps.length], - ); - - const currentStep = cloneElement(steps[currentStepIndex], { - ...options, - ...steps[currentStepIndex].props, - }); - - return { currentStep, ...options }; -} diff --git a/src/components/ABDM/types/abha.ts b/src/components/ABDM/types/abha.ts deleted file mode 100644 index f189bd111cb..00000000000 --- a/src/components/ABDM/types/abha.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { PatientModel } from "@/components/Patient/models"; - -export type AbhaNumberModel = { - id: number; - external_id: string; - created_date: string; - modified_date: string; - abha_number: string; - health_id: string; - name: string; - first_name: string | null; - middle_name: string | null; - last_name: string | null; - gender: "F" | "M" | "O"; - date_of_birth: string | null; - address: string | null; - district: string | null; - state: string | null; - pincode: string | null; - mobile: string | null; - email: string | null; - profile_photo: string | null; - new: boolean; - patient: string | null; - patient_object: PatientModel | null; -}; - -export type ABHAQRContent = { - hidn: string; - name: string; - gender: "M" | "F" | "O"; - dob: string; - mobile: string; - address: string; - distlgd: string; - statelgd: string; -} & ({ hid: string; phr?: never } | { phr: string; hid?: never }) & - ( - | { district_name: string; "dist name"?: never } - | { "dist name": string; district_name?: never } - ) & - ( - | { state_name: string; "state name"?: never } - | { "state name": string; state_name?: never } - ); diff --git a/src/components/ABDM/types/consent.ts b/src/components/ABDM/types/consent.ts deleted file mode 100644 index a5041f5767d..00000000000 --- a/src/components/ABDM/types/consent.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { AbhaNumberModel } from "@/components/ABDM/types/abha"; -import { UserBaseModel } from "@/components/Users/models"; - -export type ConsentPurpose = - | "CAREMGT" - | "BTG" - | "PUBHLTH" - | "HPAYMT" - | "DSRCH" - | "PATRQT"; - -export type ConsentStatus = - | "REQUESTED" - | "GRANTED" - | "DENIED" - | "EXPIRED" - | "REVOKED"; - -export type ConsentHIType = - | "Prescription" - | "DiagnosticReport" - | "OPConsultation" - | "DischargeSummary" - | "ImmunizationRecord" - | "HealthDocumentRecord" - | "WellnessRecord"; - -export type ConsentAccessMode = "VIEW" | "STORE" | "QUERY" | "STREAM"; - -export type ConsentFrequencyUnit = "HOUR" | "DAY" | "WEEK" | "MONTH" | "YEAR"; - -export type ConsentCareContext = { - patientReference: string; - careContextReference: string; -}; - -export type ConsentModel = { - id: string; - consent_id: null | string; - - patient_abha: string; - care_contexts: ConsentCareContext[]; - - status: ConsentStatus; - purpose: ConsentPurpose; - hi_types: ConsentHIType[]; - - access_mode: ConsentAccessMode; - from_time: string; - to_time: string; - expiry: string; - - frequency_unit: ConsentFrequencyUnit; - frequency_value: number; - frequency_repeats: number; - - hip: null | string; - hiu: null | string; - - created_date: string; - modified_date: string; -}; - -export type CreateConsentTBody = { - patient_abha: string; - hi_types: ConsentHIType[]; - purpose: ConsentPurpose; - from_time: Date | string; - to_time: Date | string; - expiry: Date | string; - - access_mode?: ConsentAccessMode; - frequency_unit?: ConsentFrequencyUnit; - frequency_value?: number; - frequency_repeats?: number; - hip?: null | string; -}; - -export type ConsentArtefactModel = { - consent_request: string; - - cm: null | string; -} & ConsentModel; - -export type ConsentRequestModel = { - requester: UserBaseModel; - patient_abha_object: AbhaNumberModel; - consent_artefacts: ConsentArtefactModel[]; -} & ConsentModel; diff --git a/src/components/ABDM/types/health-facility.ts b/src/components/ABDM/types/health-facility.ts deleted file mode 100644 index 419003dbf8e..00000000000 --- a/src/components/ABDM/types/health-facility.ts +++ /dev/null @@ -1,19 +0,0 @@ -export interface IHealthFacility { - id: string; - registered: boolean; - external_id: string; - created_date: string; - modified_date: string; - hf_id: string; - facility: string; - detail?: string; -} - -export interface IcreateHealthFacilityTBody { - facility: string; - hf_id: string; -} - -export interface IpartialUpdateHealthFacilityTBody { - hf_id: string; -} diff --git a/src/components/ABDM/types/health-information.ts b/src/components/ABDM/types/health-information.ts deleted file mode 100644 index eeb1c53a4fb..00000000000 --- a/src/components/ABDM/types/health-information.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type HealthInformationModel = { - data: { - content: string; - care_context_reference: string; - }[]; -}; diff --git a/src/components/Assets/AssetManage.tsx b/src/components/Assets/AssetManage.tsx index b56cb908c42..b4377d2e1aa 100644 --- a/src/components/Assets/AssetManage.tsx +++ b/src/components/Assets/AssetManage.tsx @@ -1,5 +1,5 @@ import dayjs from "dayjs"; -import QRCode from "qrcode.react"; +import { QRCodeSVG } from "qrcode.react"; import { navigate } from "raviger"; import { ReactElement, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -69,7 +69,11 @@ const AssetManage = (props: AssetManageProps) => { >(); const [transactionFilter, setTransactionFilter] = useState({}); - const { data: asset, loading } = useQuery(routes.getAsset, { + const { + data: asset, + loading, + refetch, + } = useQuery(routes.getAsset, { pathParams: { external_id: assetId, }, @@ -132,7 +136,7 @@ const AssetManage = (props: AssetManageProps) => {

Print Preview

- +
); @@ -594,7 +598,10 @@ const AssetManage = (props: AssetManageProps) => { handleClose={() => setServiceEditData({ ...serviceEditData, open: false }) } - handleUpdate={() => serviceRefetch()} + handleUpdate={() => { + serviceRefetch(); + refetch(); + }} show={serviceEditData.open} viewOnly={serviceEditData.viewOnly} /> diff --git a/src/components/Assets/AssetsList.tsx b/src/components/Assets/AssetsList.tsx index eceee4887e8..4212fae5d96 100644 --- a/src/components/Assets/AssetsList.tsx +++ b/src/components/Assets/AssetsList.tsx @@ -372,11 +372,12 @@ const AssetsList = () => { text="Total Assets" count={totalCount} loading={loading} - icon="l-monitor-heart-rate" + icon="d-folder" className="flex-1" />
updateQuery({ [e.name]: e.value })} diff --git a/src/components/Auth/Login.tsx b/src/components/Auth/Login.tsx index bcf0d4e3415..4255161194a 100644 --- a/src/components/Auth/Login.tsx +++ b/src/components/Auth/Login.tsx @@ -335,6 +335,7 @@ const Login = (props: { forgot?: boolean }) => { setForgotPassword(true); }} type="button" + id="forgot-pass-btn" className="text-sm text-primary-400 hover:text-primary-500" > {t("forget_password")} @@ -347,8 +348,9 @@ const Login = (props: { forgot?: boolean }) => {
) : ( @@ -370,6 +372,7 @@ const Login = (props: { forgot?: boolean }) => { setForgotPassword(false); }} type="button" + id="back-to-login-btn" className="mb-4 text-sm text-primary-400 hover:text-primary-500" >
@@ -377,11 +380,14 @@ const Login = (props: { forgot?: boolean }) => { {t("back_to_login")}
-
+
{t("forget_password")}
-
+
{t("forget_password_instruction")} { ) : ( @@ -91,32 +91,26 @@ export default function Breadcrumbs({