diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index 7a37f65dff7..7ceb3eca6ca 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -2,8 +2,7 @@ export class AssetPage { createAsset() { - cy.get("button").should("contain", "Create Asset"); - cy.get("[data-testid=create-asset-buttom] button").click(); + cy.get("#create-asset-button").click(); } selectFacility(facilityName: string) { diff --git a/cypress/pageobject/utils/advanceFilterHelpers.ts b/cypress/pageobject/utils/advanceFilterHelpers.ts index 14e3ab41bda..2841c1d600b 100644 --- a/cypress/pageobject/utils/advanceFilterHelpers.ts +++ b/cypress/pageobject/utils/advanceFilterHelpers.ts @@ -1,6 +1,6 @@ export const advanceFilters = { clickAdvancedFiltersButton() { - cy.verifyAndClickElement("#advanced-filter", "Advanced Filters"); + cy.verifyAndClickElement("#filter", "Filters"); }, selectState(state: string) { diff --git a/src/CAREUI/interactive/FiltersSlideover.tsx b/src/CAREUI/interactive/FiltersSlideover.tsx index 959fd0621e8..344ef16cef6 100644 --- a/src/CAREUI/interactive/FiltersSlideover.tsx +++ b/src/CAREUI/interactive/FiltersSlideover.tsx @@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"; import CareIcon from "@/CAREUI/icons/CareIcon"; import SlideOver from "@/CAREUI/interactive/SlideOver"; -import ButtonV2 from "@/components/Common/ButtonV2"; +import { Button } from "@/components/ui/button"; import useFilters from "@/hooks/useFilters"; @@ -33,18 +33,23 @@ export default function FiltersSlideover({
{t("advanced_filters")}
- {t("clear")} - - + +
} @@ -55,18 +60,17 @@ export default function FiltersSlideover({ ); } -export const AdvancedFilterButton = ({ onClick }: { onClick: () => void }) => { +export const FilterButton = ({ onClick }: { onClick: () => void }) => { const { t } = useTranslation(); return ( - - {t("advanced_filters")} - + {t("filters")} + ); }; diff --git a/src/components/Assets/AssetsList.tsx b/src/components/Assets/AssetsList.tsx index c0e47610766..7a1b203d88a 100644 --- a/src/components/Assets/AssetsList.tsx +++ b/src/components/Assets/AssetsList.tsx @@ -6,18 +6,19 @@ import { useTranslation } from "react-i18next"; import Chip from "@/CAREUI/display/Chip"; import CountBlock from "@/CAREUI/display/Count"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; +import { FilterButton } from "@/CAREUI/interactive/FiltersSlideover"; + +import { Button } from "@/components/ui/button"; import AssetFilter from "@/components/Assets/AssetFilter"; import AssetImportModal from "@/components/Assets/AssetImportModal"; import { AssetData, assetClassProps } from "@/components/Assets/AssetTypes"; -import ButtonV2 from "@/components/Common/ButtonV2"; import ExportMenu from "@/components/Common/Export"; import Loading from "@/components/Common/Loading"; import Page from "@/components/Common/Page"; +import SearchByMultipleFields from "@/components/Common/SearchByMultipleFields"; import FacilitiesSelectDialogue from "@/components/ExternalResult/FacilitiesSelectDialogue"; import { FacilityModel } from "@/components/Facility/models"; -import SearchInput from "@/components/Form/SearchInput"; import useFilters from "@/hooks/useFilters"; import { useIsAuthorized } from "@/hooks/useIsAuthorized"; @@ -38,6 +39,7 @@ const AssetsList = () => { FilterBadges, advancedFilter, resultsPerPage, + clearSearch, } = useFilters({ limit: 18, cacheBlacklist: ["search"], @@ -317,9 +319,52 @@ const AssetsList = () => { breadcrumbs={false} hideBack options={ - <> +
+
+
+ +
+ +
+ +
+
+ + {/* Advanced Filter Button */} +
+ advancedFilter.setShow(true)} /> +
+ + {/* Import/Export Menu */} {authorizedForImportExport && ( -
+
{ />
)} - +
} > -
+
+ updateQuery({ search: value })} + clearSearch={clearSearch} /> -
- updateQuery({ [e.name]: e.value })} - placeholder="Search by name/serial no./QR code ID" - /> -
-
-
-
- advancedFilter.setShow(true)} - /> -
- setIsScannerActive(true)} - > - Scan Asset - QR - -
-
- { - if (qParams.facility) { - navigate(`/facility/${qParams.facility}/assets/new`); - } else { - setShowFacilityDialog(true); - } - }} - > - - {t("create_asset")} - -
-
+ {isLoading ? ( diff --git a/src/components/Common/Export.tsx b/src/components/Common/Export.tsx index 6cd786977ed..60e00569a1e 100644 --- a/src/components/Common/Export.tsx +++ b/src/components/Common/Export.tsx @@ -1,18 +1,24 @@ import CareIcon from "@/CAREUI/icons/CareIcon"; -import ButtonV2 from "@/components/Common/ButtonV2"; -import DropdownMenu, { - DropdownItem, - DropdownItemProps, -} from "@/components/Common/Menu"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; + +import { ShadcnMenuDropdownItemProps } from "@/components/Common/Menu"; import useExport from "@/hooks/useExport"; +import { useIsAuthorized } from "@/hooks/useIsAuthorized"; +import { Anyone } from "@/Utils/AuthorizeFor"; import request from "@/Utils/request/request"; import { Route } from "@/Utils/request/types"; interface ExportItem { - options?: DropdownItemProps; + options?: ShadcnMenuDropdownItemProps; type?: "csv" | "json"; filePrefix?: string; label: string; @@ -37,7 +43,47 @@ interface ExportButtonProps { parse?: (data: string) => string; filenamePrefix: string; } +function ExportMenuItem({ + item, + exportFile, +}: { + item: ExportItem; + exportFile: ( + action: Parameters["exportFile"]>[0], + filePrefix?: string, + type?: "csv" | "json", + parse?: (data: string) => string, + ) => void; +}) { + const isAuthorized = useIsAuthorized(item.options?.authorizeFor || Anyone); + return ( + { + if (item.action) { + let action = item.action; + if (item.route) { + action = async () => { + const { data } = await request(item.route!); + return data ?? null; + }; + } + exportFile(action, item.filePrefix, item.type, item.parse); + } else if (item.options?.onClick) { + item.options.onClick(); + } + }} + disabled={item.options?.disabled || !isAuthorized} + id={item.options?.id} + className={item.options?.className} + > +
+ {item.options?.icon} + {item.label} +
+
+ ); +} export const ExportMenu = ({ label = "Export", disabled, @@ -49,8 +95,9 @@ export const ExportMenu = ({ const item = exportItems[0]; return ( - { let action = item.action; if (item.route) { @@ -63,44 +110,38 @@ export const ExportMenu = ({ exportFile(action, item.filePrefix, item.type, item.parse); } }} - border - ghost + variant="outline_primary" className="py-2.5" > - + {isExporting ? "Exporting..." : label} - + ); } return (
- } - className="tooltip border-primary-500 bg-white text-primary-500 hover:bg-primary-100 enabled:border" - > - {exportItems.map((item) => ( - { - let action = item.action; - if (item.route) { - action = async () => { - const { data } = await request(item.route!); - return data ?? null; - }; - } - if (action) { - exportFile(action, item.filePrefix, item.type, item.parse); - } - }} - {...item.options} + + + + + + {exportItems.map((item) => ( + + ))} +
); @@ -116,7 +157,7 @@ export const ExportButton = ({ return ( <> - { let action = props.action; @@ -131,9 +172,7 @@ export const ExportButton = ({ } }} className="tooltip mx-2 p-4 text-lg text-secondary-800 disabled:bg-transparent disabled:text-secondary-500" - variant="secondary" - ghost - circle + variant="link" > {isExporting ? ( @@ -142,8 +181,8 @@ export const ExportButton = ({ )} {props.tooltip || "Export"} - - + {" "} + ); }; diff --git a/src/components/Common/Menu.tsx b/src/components/Common/Menu.tsx index aa647a3dedb..7777b8b41ae 100644 --- a/src/components/Common/Menu.tsx +++ b/src/components/Common/Menu.tsx @@ -76,6 +76,15 @@ export type DropdownItemProps = RawDivProps & disabled?: boolean | undefined; }; +export type ShadcnMenuDropdownItemProps = RawDivProps & + AuthorizedElementProps & { + onClick?: () => void; + disabled?: boolean; + icon?: ReactNode | undefined; + className?: string; + children?: ReactNode; + }; + export function DropdownItem({ authorizeFor = Anyone, variant = "primary", diff --git a/src/components/Facility/DischargedPatientsList.tsx b/src/components/Facility/DischargedPatientsList.tsx index 74bb6d95626..3395f6a0c95 100644 --- a/src/components/Facility/DischargedPatientsList.tsx +++ b/src/components/Facility/DischargedPatientsList.tsx @@ -6,7 +6,7 @@ import CountBlock from "@/CAREUI/display/Count"; import FilterBadge from "@/CAREUI/display/FilterBadge"; import RecordMeta from "@/CAREUI/display/RecordMeta"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; +import { FilterButton } from "@/CAREUI/interactive/FiltersSlideover"; import PaginatedList from "@/CAREUI/misc/PaginatedList"; import Loading from "@/components/Common/Loading"; @@ -285,9 +285,7 @@ const DischargedPatientsList = ({ onTabChange={() => navigate("/patients")} currentTab={1} /> - advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} /> { hideBack options={
- advancedFilter.setShow(true)} /> + advancedFilter.setShow(true)} />
{ )} - advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} /> {t("list_view")} - advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} />
diff --git a/src/components/Resource/ResourceList.tsx b/src/components/Resource/ResourceList.tsx index 0175c9d63ea..56c5e4ec693 100644 --- a/src/components/Resource/ResourceList.tsx +++ b/src/components/Resource/ResourceList.tsx @@ -3,7 +3,7 @@ import { useTranslation } from "react-i18next"; import Chip from "@/CAREUI/display/Chip"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; +import { FilterButton } from "@/CAREUI/interactive/FiltersSlideover"; import { Button } from "@/components/ui/button"; @@ -237,9 +237,7 @@ export default function ListView() { {t("board_view")} - advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} />
diff --git a/src/components/Shifting/ShiftingBoard.tsx b/src/components/Shifting/ShiftingBoard.tsx index 068820d3311..df892be2435 100644 --- a/src/components/Shifting/ShiftingBoard.tsx +++ b/src/components/Shifting/ShiftingBoard.tsx @@ -4,7 +4,7 @@ import { Suspense, lazy, useState } from "react"; import { useTranslation } from "react-i18next"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; +import { FilterButton } from "@/CAREUI/interactive/FiltersSlideover"; import { Button } from "@/components/ui/button"; @@ -132,9 +132,7 @@ export default function BoardView() { {t("list_view")} - advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} /> diff --git a/src/components/Shifting/ShiftingList.tsx b/src/components/Shifting/ShiftingList.tsx index e9051b1449b..f90df9f73a5 100644 --- a/src/components/Shifting/ShiftingList.tsx +++ b/src/components/Shifting/ShiftingList.tsx @@ -2,7 +2,7 @@ import { navigate } from "raviger"; import { useTranslation } from "react-i18next"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; +import { FilterButton } from "@/CAREUI/interactive/FiltersSlideover"; import { Button } from "@/components/ui/button"; @@ -88,9 +88,7 @@ export default function ListView() { {t("board_view")} - advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} /> diff --git a/src/components/Users/ManageUsers.tsx b/src/components/Users/ManageUsers.tsx index d28a0aeea52..89fd0252728 100644 --- a/src/components/Users/ManageUsers.tsx +++ b/src/components/Users/ManageUsers.tsx @@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next"; import CountBlock from "@/CAREUI/display/Count"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; +import { FilterButton } from "@/CAREUI/interactive/FiltersSlideover"; import ButtonV2 from "@/components/Common/ButtonV2"; import Loading from "@/components/Common/Loading"; @@ -123,9 +123,7 @@ export default function ManageUsers() { />
- advancedFilter.setShow(true)} - /> + advancedFilter.setShow(true)} /> {userTypes.length && addUser}
diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 0125726ce73..da54aca978f 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -9,6 +9,7 @@ const buttonVariants = cva( { variants: { variant: { + none: "", default: "bg-gray-900 text-gray-50 shadow hover:bg-gray-900/90 dark:bg-gray-50 dark:text-gray-900 dark:hover:bg-gray-50/90", destructive: