Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Update the button layout in Assets Page #9392

Closed
Closed
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
45ab474
Enhancement: Update the button layout in Assets Page
manmeetnagii Dec 12, 2024
e662368
Merge branch 'develop' of https://github.com/manmeetnagii/care_fe int…
manmeetnagii Dec 12, 2024
f22c421
Merge branch 'ohcnetwork:develop' into enhanced-asset-header
manmeetnagii Dec 12, 2024
6a3670d
Refactored: Updated ButtonV2 to use ShadCN button
manmeetnagii Dec 12, 2024
ca130ab
fixes mobile view
manmeetnagii Dec 12, 2024
6d535b7
Merge branch 'ohcnetwork:develop' into enhanced-asset-header
manmeetnagii Dec 13, 2024
9640f77
Merge branch 'ohcnetwork:develop' into enhanced-asset-header
manmeetnagii Dec 13, 2024
bac9003
Checked cypress tests
manmeetnagii Dec 13, 2024
2361ba9
Merge branch 'develop' into enhanced-asset-header
manmeetnagii Dec 14, 2024
91af7ac
Merge branch 'develop' of https://github.com/ohcnetwork/care_fe into …
manmeetnagii Dec 14, 2024
e4541ee
Merge branch 'enhanced-asset-header' of https://github.com/manmeetnag…
manmeetnagii Dec 14, 2024
1b02dc2
changed dropdown to Shadcn dropdown
manmeetnagii Dec 14, 2024
e011a76
changed dropdown to Shadcn dropdown
manmeetnagii Dec 14, 2024
0d41eb1
Merge branch 'ohcnetwork:develop' into enhanced-asset-header
manmeetnagii Dec 15, 2024
c7a2a4d
changed dropdown to Shadcn dropdown
manmeetnagii Dec 15, 2024
b3547b5
changed dropdown to Shadcn dropdown
manmeetnagii Dec 15, 2024
b9e0197
Merge branch 'ohcnetwork:develop' into enhanced-asset-header
manmeetnagii Dec 15, 2024
3225fe5
changed dropdown to Shadcn dropdown
manmeetnagii Dec 15, 2024
4a9858f
changed dropdown to Shadcn dropdown
manmeetnagii Dec 15, 2024
ce0bdb8
changed dropdown to Shadcn dropdown
manmeetnagii Dec 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/CAREUI/interactive/FiltersSlideover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useTranslation } from "react-i18next";
import CareIcon from "@/CAREUI/icons/CareIcon";
import SlideOver from "@/CAREUI/interactive/SlideOver";

import { Button } from "@/components/ui/button";

import ButtonV2 from "@/components/Common/ButtonV2";

import useFilters from "@/hooks/useFilters";
Expand Down Expand Up @@ -58,15 +60,15 @@ export default function FiltersSlideover({
export const AdvancedFilterButton = ({ onClick }: { onClick: () => void }) => {
const { t } = useTranslation();
return (
<ButtonV2
ghost
border
className="w-full bg-white md:w-auto"
<Button
variant={"outline_primary"}
size={"lg"}
className="w-full bg-white md:w-auto gap-2"
onClick={onClick}
id="advanced-filter"
>
<CareIcon icon="l-filter" />
<span className="py-0.5">{t("advanced_filters")}</span>
</ButtonV2>
</Button>
);
};
239 changes: 142 additions & 97 deletions src/components/Assets/AssetsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover";
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 FacilitiesSelectDialogue from "@/components/ExternalResult/FacilitiesSelectDialogue";
import { FacilityModel } from "@/components/Facility/models";
import SearchInput from "@/components/Form/SearchInput";

import useAuthUser from "@/hooks/useAuthUser";
import useFilters from "@/hooks/useFilters";
import { useIsAuthorized } from "@/hooks/useIsAuthorized";

Expand All @@ -29,6 +28,9 @@ import routes from "@/Utils/request/api";
import request from "@/Utils/request/request";
import useTanStackQueryInstead from "@/Utils/request/useQuery";

import SearchByMultipleFields from "../Common/SearchByMultipleFields";
import { Button } from "../ui/button";
rithviknishad marked this conversation as resolved.
Show resolved Hide resolved

const AssetsList = () => {
const { t } = useTranslation();
const {
Expand All @@ -38,9 +40,10 @@ const AssetsList = () => {
FilterBadges,
advancedFilter,
resultsPerPage,
clearSearch,
} = useFilters({
limit: 18,
cacheBlacklist: ["search"],
cacheBlacklist: ["name", "serial_number", "qr_code_id"],
});
const [assets, setAssets] = useState([{} as AssetData]);
const [isLoading, setIsLoading] = useState(false);
Expand All @@ -56,6 +59,9 @@ const AssetsList = () => {
const params = {
limit: resultsPerPage,
page: qParams.page,
name: qParams.name || "",
serial_number: qParams.serial_number || "",
qr_code_id: qParams.qr_code_id || "",
offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage,
search_text: qParams.search || "",
facility: qParams.facility || "",
Expand Down Expand Up @@ -114,6 +120,9 @@ const AssetsList = () => {
},
);

const authUser = useAuthUser();
const isDisabled = !NonReadOnlyUsers(authUser.user_type);

function isValidURL(url: string) {
try {
new URL(url);
Expand Down Expand Up @@ -311,108 +320,50 @@ const AssetsList = () => {
);
}

const searchOptions = [
{
key: "name",
label: "Name",
type: "text" as const,
placeholder: "Search by Name",
value: qParams.name || "",
shortcutKey: "n",
},
{
key: "serial_number",
label: "Serial No.",
type: "text" as const,
placeholder: "Search by Serial No.",
value: qParams.serial_number || "",
shortcutKey: "u",
},
{
key: "asset_qr_id",
label: "QR Code ID",
type: "text" as const,
placeholder: "Search by QR Code ID",
value: qParams.qr_code_id || "",
shortcutKey: "p",
},
];

return (
<Page
title="Assets"
breadcrumbs={false}
className="px-4 md:px-6"
hideBack
options={
<>
{authorizedForImportExport && (
<div className="tooltip" data-testid="import-asset-button">
<ExportMenu
label={importAssetModalOpen ? "Importing..." : "Import/Export"}
exportItems={[
{
label: "Import Assets",
options: {
icon: (
<CareIcon
icon="l-import"
className="import-assets-button"
/>
),
onClick: () => setImportAssetModalOpen(true),
},
},
{
label: "Export Assets (JSON)",
action: async () => {
const { data } = await request(routes.listAssets, {
query: { ...qParams, json: true, limit: totalCount },
});
return data ?? null;
},
type: "json",
filePrefix: `assets_${facility?.name ?? "all"}`,
options: {
icon: <CareIcon icon="l-export" />,
disabled: totalCount === 0 || !authorizedForImportExport,
id: "export-json-option",
},
},
{
label: "Export Assets (CSV)",
action: async () => {
const { data } = await request(routes.listAssets, {
query: { ...qParams, csv: true, limit: totalCount },
});
return data ?? null;
},
type: "csv",
filePrefix: `assets_${facility?.name ?? "all"}`,
options: {
icon: <CareIcon icon="l-export" />,
disabled: totalCount === 0 || !authorizedForImportExport,
id: "export-csv-option",
},
},
]}
/>
</div>
)}
</>
}
>
<div className="mt-5 gap-3 space-y-2 lg:flex">
<CountBlock
text="Total Assets"
count={totalCount}
loading={loading}
icon="d-folder"
className="flex-1"
/>
<div className="flex-1">
<SearchInput
id="asset-search"
name="search"
value={qParams.search}
onChange={(e) => updateQuery({ [e.name]: e.value })}
placeholder="Search by name/serial no./QR code ID"
/>
</div>
<div className="flex flex-col items-start justify-start gap-2 lg:ml-2">
<div className="flex w-full flex-col gap-2 md:flex-row lg:w-auto">
<div className="w-full">
<AdvancedFilterButton
onClick={() => advancedFilter.setShow(true)}
/>
</div>
<ButtonV2
className="w-full py-[11px]"
onClick={() => setIsScannerActive(true)}
>
<CareIcon icon="l-search" className="mr-1 text-base" /> Scan Asset
QR
</ButtonV2>
</div>
<div className="flex w-full flex-col items-center justify-between lg:flex-row">
<div
className="flex w-full flex-col md:flex-row"
className="mb-2 flex w-full flex-col items-center lg:mb-0 lg:w-fit lg:flex-row lg:gap-5"
data-testid="create-asset-buttom"
>
<ButtonV2
authorizeFor={NonReadOnlyUsers}
className="inline-flex w-full items-center justify-center"
<Button
disabled={isDisabled}
variant={"primary"}
size={"lg"}
className="gap-2 w-full lg:w-fit"
onClick={() => {
if (qParams.facility) {
navigate(`/facility/${qParams.facility}/assets/new`);
Expand All @@ -423,9 +374,103 @@ const AssetsList = () => {
>
<CareIcon icon="l-plus-circle" className="text-lg" />
<span>{t("create_asset")}</span>
</ButtonV2>
</Button>
</div>
<div className="flex w-full flex-col items-center justify-end gap-2 lg:ml-3 lg:w-fit lg:flex-row lg:gap-3">
<AdvancedFilterButton
onClick={() => advancedFilter.setShow(true)}
/>

<Button
variant={"primary"}
size={"lg"}
className="gap-2 w-full"
onClick={() => setIsScannerActive(true)}
>
<CareIcon icon="l-search" className="mr-1 text-base" />
Scan Asset QR
</Button>

<div
className="tooltip w-full md:w-auto"
data-testid="import-asset-button"
>
{authorizedForImportExport && (
<ExportMenu
label={
importAssetModalOpen ? "Importing..." : "Import/Export"
}
exportItems={[
{
label: "Import Assets",
options: {
icon: (
<CareIcon
icon="l-import"
className="import-assets-button"
/>
),
onClick: () => setImportAssetModalOpen(true),
},
},
{
label: "Export Assets (JSON)",
action: async () => {
const { data } = await request(routes.listAssets, {
query: { ...qParams, json: true, limit: totalCount },
});
return data ?? null;
},
type: "json",
filePrefix: `assets_${facility?.name ?? "all"}`,
options: {
icon: <CareIcon icon="l-export" />,
disabled:
totalCount === 0 || !authorizedForImportExport,
id: "export-json-option",
},
},
{
label: "Export Assets (CSV)",
action: async () => {
const { data } = await request(routes.listAssets, {
query: { ...qParams, csv: true, limit: totalCount },
});
return data ?? null;
},
type: "csv",
filePrefix: `assets_${facility?.name ?? "all"}`,
options: {
icon: <CareIcon icon="l-export" />,
disabled:
totalCount === 0 || !authorizedForImportExport,
id: "export-csv-option",
},
},
]}
/>
)}
</div>
</div>
</div>
}
>
<div className="mt-4 gap-4 lg:gap-16 flex flex-col lg:flex-row lg:items-center">
<CountBlock
text="Total Assets"
count={totalCount}
loading={loading}
icon="d-folder"
className="flex-1"
/>

<SearchByMultipleFields
id="asset-search"
options={searchOptions}
onSearch={(key, value) => updateQuery({ search: value })}
clearSearch={clearSearch}
className="w-full"
/>
</div>
<AssetFilter {...advancedFilter} key={window.location.search} />
{isLoading ? (
Expand Down
Loading
Loading