diff --git a/public/locale/en.json b/public/locale/en.json index b4baf2c5f19..794d07c5993 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -323,6 +323,7 @@ "additional_instructions": "Additional Instructions", "address": "Address", "address_is_required": "Address is required", + "adjust_resource_filters": "Try adjusting your filters or create a new resource", "administer": "Administer", "administer_medicine": "Administer Medicine", "administer_medicines": "Administer Medicines", @@ -1363,6 +1364,7 @@ "no_records_found": "No Records Found", "no_remarks": "No remarks", "no_resource_requests_found": "No requests found", + "no_resources_found": "No resources found", "no_results": "No results", "no_results_found": "No Results Found", "no_schedule_templates_found": "No schedule templates found for this month.", @@ -1729,6 +1731,14 @@ "resource_request_details_description": "Provide detailed information about what resource is needed and why.", "resource_requests": "Requests", "resource_status": "Request Status", + "resource_status__approved": "Approved", + "resource_status__cancelled": "Cancelled", + "resource_status__completed": "Completed", + "resource_status__pending": "Pending", + "resource_status__rejected": "Rejected", + "resource_status__transfer_in_progress": "Transfer in progress", + "resource_status__transportation_to_be_arranged": "Transportation to be arranged", + "resource_title": "Resource Title", "resource_type": "Request Type", "result": "Result", "result_date": "Result Date", @@ -1799,6 +1809,7 @@ "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_resource_title": "Search by resource title", "search_by_username": "Search by username", "search_country": "Search country...", "search_encounters": "Search Encounters", @@ -1993,6 +2004,7 @@ "third_party_software_licenses": "Third Party Software Licenses", "time": "Time", "time_slot": "Time Slot", + "title": "Title", "title_of_request": "Title of Request", "titrate_dosage": "Titrate Dosage", "to": "to", @@ -2011,7 +2023,6 @@ "total_users": "Total Users", "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)", diff --git a/public/locale/hi.json b/public/locale/hi.json index 5afef1fa777..28b6d1f3531 100644 --- a/public/locale/hi.json +++ b/public/locale/hi.json @@ -733,7 +733,6 @@ "to_be_conducted": "संचालित किया जाना है", "total_beds": "कुल बिस्तर", "total_users": "कुल उपयोगकर्ता", - "transfer_in_progress": "स्थानांतरण प्रगति पर है", "transfer_to_receiving_facility": "प्राप्ति सुविधा में स्थानांतरण", "travel_within_last_28_days": "घरेलू/अंतर्राष्ट्रीय यात्रा (पिछले 28 दिनों के भीतर)", "treating_doctor": "इलाज करने वाला डॉक्टर", diff --git a/public/locale/kn.json b/public/locale/kn.json index 0d73df7f8b8..45c08a5568a 100644 --- a/public/locale/kn.json +++ b/public/locale/kn.json @@ -735,7 +735,6 @@ "to_be_conducted": "ನಡೆಸಲಾಗುವುದು", "total_beds": "ಒಟ್ಟು ಹಾಸಿಗೆಗಳು", "total_users": "ಒಟ್ಟು ಬಳಕೆದಾರರು", - "transfer_in_progress": "ವರ್ಗಾವಣೆ ಪ್ರಗತಿಯಲ್ಲಿದೆ", "transfer_to_receiving_facility": "ಸ್ವೀಕರಿಸುವ ಸೌಲಭ್ಯಕ್ಕೆ ವರ್ಗಾಯಿಸಿ", "travel_within_last_28_days": "ದೇಶೀಯ/ಅಂತರರಾಷ್ಟ್ರೀಯ ಪ್ರಯಾಣ (ಕಳೆದ 28 ದಿನಗಳಲ್ಲಿ)", "treating_doctor": "ಚಿಕಿತ್ಸೆ ನೀಡುತ್ತಿರುವ ವೈದ್ಯರು", diff --git a/public/locale/ml.json b/public/locale/ml.json index 3d18c5890ae..c341eed70ab 100644 --- a/public/locale/ml.json +++ b/public/locale/ml.json @@ -1778,7 +1778,6 @@ "transcript_information": "ഇതാണ് നമ്മൾ കേട്ടത്", "transfer_allowed": "കൈമാറ്റം അനുവദിച്ചു", "transfer_blocked": "കൈമാറ്റം തടഞ്ഞു", - "transfer_in_progress": "കൈമാറ്റം പുരോഗമിക്കുന്നു", "transfer_status_updated": "ട്രാൻസ്ഫർ സ്റ്റാറ്റസ് അപ്ഡേറ്റ് ചെയ്തു", "transfer_to_receiving_facility": "സ്വീകരിക്കാനുള്ള സൗകര്യത്തിലേക്ക് ട്രാൻസ്ഫർ ചെയ്യുക", "travel_within_last_28_days": "ആഭ്യന്തര/അന്താരാഷ്ട്ര യാത്ര (കഴിഞ്ഞ 28 ദിവസത്തിനുള്ളിൽ)", diff --git a/public/locale/ta.json b/public/locale/ta.json index 50e884b2d1d..2813031dc81 100644 --- a/public/locale/ta.json +++ b/public/locale/ta.json @@ -733,7 +733,6 @@ "to_be_conducted": "நடத்தப்பட வேண்டும்", "total_beds": "மொத்த படுக்கைகள்", "total_users": "மொத்த பயனர்கள்", - "transfer_in_progress": "இடமாற்றம் நடைபெறுகிறது", "transfer_to_receiving_facility": "பெறும் வசதிக்கு இடமாற்றம்", "travel_within_last_28_days": "உள்நாட்டு/சர்வதேச பயணம் (கடந்த 28 நாட்களுக்குள்)", "treating_doctor": "சிகிச்சை அளிக்கும் மருத்துவர்", diff --git a/src/Routers/routes/ResourceRoutes.tsx b/src/Routers/routes/ResourceRoutes.tsx index 357b7812513..74d96ba622b 100644 --- a/src/Routers/routes/ResourceRoutes.tsx +++ b/src/Routers/routes/ResourceRoutes.tsx @@ -1,13 +1,11 @@ -import View from "@/components/Common/View"; -import BoardView from "@/components/Resource/ResourceBoard"; import ResourceDetails from "@/components/Resource/ResourceDetails"; import { ResourceDetailsUpdate } from "@/components/Resource/ResourceDetailsUpdate"; -import ListView from "@/components/Resource/ResourceList"; +import ResourceList from "@/components/Resource/ResourceList"; import { AppRoutes } from "@/Routers/AppRouter"; const ResourceRoutes: AppRoutes = { - "/resource": () => , + "/resource": () => , "/resource/:id": ({ id }) => , "/resource/:id/update": ({ id }) => , }; diff --git a/src/common/constants.tsx b/src/common/constants.tsx index 820ace57839..4ed7bb19f19 100644 --- a/src/common/constants.tsx +++ b/src/common/constants.tsx @@ -162,16 +162,15 @@ export const RESOURCE_CATEGORY_CHOICES = [ { id: "FINANCIAL", text: "Financial" }, { id: "OTHERS", text: "Other" }, ]; - -export const RESOURCE_CHOICES: Array = [ - { id: 10, text: "PENDING" }, - { id: 15, text: "ON HOLD" }, - { id: 20, text: "APPROVED" }, - { id: 30, text: "REJECTED" }, - { id: 55, text: "TRANSPORTATION TO BE ARRANGED" }, - { id: 70, text: "TRANSFER IN PROGRESS" }, - { id: 80, text: "COMPLETED" }, -]; +export const RESOURCE_STATUS_CHOICES = [ + { icon: "l-clock", text: "pending" }, + { icon: "l-check", text: "approved" }, + { icon: "l-ban", text: "rejected" }, + { icon: "l-file-slash", text: "cancelled" }, + { icon: "l-truck", text: "transportation_to_be_arranged" }, + { icon: "l-spinner", text: "transfer_in_progress" }, + { icon: "l-check-circle", text: "completed" }, +] as const; export const RESOURCE_FILTER_ORDER: Array = [ { id: 1, text: "created_date", desc: "ASC Created Date" }, diff --git a/src/components/Resource/ResourceBadges.tsx b/src/components/Resource/ResourceBadges.tsx deleted file mode 100644 index 7be946c27a9..00000000000 --- a/src/components/Resource/ResourceBadges.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { SHIFTING_FILTER_ORDER } from "@/common/constants"; - -import routes from "@/Utils/request/api"; -import useTanStackQueryInstead from "@/Utils/request/useQuery"; - -export function useFacilityQuery(facilityId: string | undefined) { - return useTanStackQueryInstead(routes.getAnyFacility, { - pathParams: { id: facilityId as string }, - prefetch: !!facilityId, - }); -} - -export default function BadgesList(props: any) { - const { appliedFilters, FilterBadges } = props; - const originFacility = useFacilityQuery(appliedFilters.origin_facility); - const approvingFacility = useFacilityQuery(appliedFilters.approving_facility); - const assignedFacility = useFacilityQuery(appliedFilters.assigned_facility); - - const getDescShiftingFilterOrder = (ordering: any) => { - const foundItem = SHIFTING_FILTER_ORDER.find( - (item) => item.text === ordering, - ); - return foundItem ? foundItem.desc : ""; - }; - - return ( - [ - value( - "Ordering", - "ordering", - getDescShiftingFilterOrder(appliedFilters.ordering), - ), - badge("Status", "status"), - badge("Title", "title"), - boolean("Emergency", "emergency", { - trueValue: "yes", - falseValue: "no", - }), - ...dateRange("Modified", "modified_date"), - ...dateRange("Created", "created_date"), - value( - "Origin facility", - "origin_facility", - appliedFilters.origin_facility - ? originFacility?.data?.name || "" - : "", - ), - value( - "Approving facility", - "approving_facility", - appliedFilters.approving_facility - ? approvingFacility?.data?.name || "" - : "", - ), - value( - "Assigned facility", - "assigned_facility", - appliedFilters.assigned_facility - ? assignedFacility?.data?.name || "" - : "", - ), - ]} - /> - ); -} diff --git a/src/components/Resource/ResourceBlock.tsx b/src/components/Resource/ResourceBlock.tsx deleted file mode 100644 index 76420952b97..00000000000 --- a/src/components/Resource/ResourceBlock.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import dayjs from "dayjs"; -import { Link } from "raviger"; -import { useTranslation } from "react-i18next"; - -import CareIcon from "@/CAREUI/icons/CareIcon"; - -import { classNames, formatDateTime, formatName } from "@/Utils/utils"; -import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; - -export default function ResourceBlock(props: { resource: ResourceRequest }) { - const { resource } = props; - const { t } = useTranslation(); - - return ( -
-
-
-
-
{resource.title}
-
-
- {resource.emergency && ( - - {t("emergency")} - - )} -
-
-
- {( - [ - { - title: "origin_facility", - icon: "l-plane-departure", - data: resource?.origin_facility?.name, - }, - { - title: "resource_approving_facility", - icon: "l-user-check", - data: resource?.approving_facility?.name, - }, - { - title: "assigned_facility", - icon: "l-plane-arrival", - data: - resource.assigned_facility?.name || t("yet_to_be_decided"), - }, - { - title: "last_modified", - icon: "l-stopwatch", - data: formatDateTime(resource.modified_date), - className: dayjs() - .subtract(2, "hours") - .isBefore(resource?.modified_date) - ? "text-secondary-900" - : "rounded bg-red-500 border border-red-600 text-white w-full font-bold", - }, - { - title: "assigned_to", - icon: "l-user", - data: resource?.assigned_to - ? formatName(resource.assigned_to) + - " - " + - resource.assigned_to.user_type - : undefined, - }, - ] as const - ) - .filter((d) => d.data) - .map((datapoint, i) => ( -
-
- -
-
{datapoint.data}
-
- ))} -
-
-
- - {t("all_details")} - -
-
- ); -} diff --git a/src/components/Resource/ResourceBoard.tsx b/src/components/Resource/ResourceBoard.tsx deleted file mode 100644 index b048c3c6cd4..00000000000 --- a/src/components/Resource/ResourceBoard.tsx +++ /dev/null @@ -1,159 +0,0 @@ -import { navigate } from "raviger"; -import { Suspense, lazy, useState } from "react"; -import { useTranslation } from "react-i18next"; - -import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; - -import { Button } from "@/components/ui/button"; - -import { ExportButton } from "@/components/Common/Export"; -import Loading from "@/components/Common/Loading"; -import PageTitle from "@/components/Common/PageTitle"; -import Tabs from "@/components/Common/Tabs"; -import SearchInput from "@/components/Form/SearchInput"; -import type { KanbanBoardType } from "@/components/Kanban/Board"; -import BadgesList from "@/components/Resource/ResourceBadges"; -import ResourceBlock from "@/components/Resource/ResourceBlock"; -import { formatFilter } from "@/components/Resource/ResourceCommons"; -import ListFilter from "@/components/Resource/ResourceFilter"; - -import useFilters from "@/hooks/useFilters"; - -import { RESOURCE_CHOICES } from "@/common/constants"; - -import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import { useView } from "@/Utils/useView"; -import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; - -const KanbanBoard = lazy( - () => import("@/components/Kanban/Board"), -) as KanbanBoardType; - -const resourceStatusOptions = RESOURCE_CHOICES.map((obj) => obj.text); - -const COMPLETED = ["COMPLETED", "REJECTED"]; -const ACTIVE = resourceStatusOptions.filter((o) => !COMPLETED.includes(o)); - -export default function BoardView() { - const [, setView] = useView("resource", "board"); - const { qParams, FilterBadges, advancedFilter, updateQuery } = useFilters({ - limit: -1, - cacheBlacklist: ["title"], - }); - const [boardFilter, setBoardFilter] = useState(ACTIVE); - - const appliedFilters = formatFilter(qParams); - const { t } = useTranslation(); - - return ( -
-
-
- { - const { data } = await request( - routes.downloadResourceRequests, - { - query: { ...appliedFilters, csv: true }, - }, - ); - return data ?? null; - }} - filenamePrefix="resource_requests" - /> - } - breadcrumbs={false} - /> -
- -
- updateQuery({ [e.name]: e.value })} - placeholder={t("search_resource")} - className="w-full md:w-60" - /> - setBoardFilter(tab ? COMPLETED : ACTIVE)} - currentTab={boardFilter !== ACTIVE ? 1 : 0} - /> -
- - advancedFilter.setShow(true)} - /> -
-
-
- }> - - title={} - sections={boardFilter.map((board) => ({ - id: board, - title: ( -

- {board}{" "} - { - const { data } = await request( - routes.downloadResourceRequests, - { - query: { - ...formatFilter({ ...qParams, status: board }), - csv: true, - }, - }, - ); - return data ?? null; - }} - filenamePrefix={`resource_requests_${board}`} - /> -

- ), - fetchOptions: (id) => ({ - route: routes.listResourceRequests, - options: { - query: formatFilter({ - ...qParams, - status: id, - }), - }, - }), - }))} - onDragEnd={(result) => { - if (result.source.droppableId !== result.destination?.droppableId) - navigate( - `/resource/${result.draggableId}/update?status=${result.destination?.droppableId}`, - ); - }} - itemRender={(resource) => } - /> -
- - -
- ); -} diff --git a/src/components/Resource/ResourceCommons.tsx b/src/components/Resource/ResourceCommons.tsx deleted file mode 100644 index e63eb9a71b2..00000000000 --- a/src/components/Resource/ResourceCommons.tsx +++ /dev/null @@ -1,41 +0,0 @@ -export const initialFilterData = { - status: "--", - facility: "", - origin_facility: "", - approving_facility: "", - assigned_facility: "", - emergency: "--", - limit: 14, - created_date_before: null, - created_date_after: null, - modified_date_before: null, - modified_date_after: null, - offset: 0, - ordering: null, - title: "", -}; - -export const formatFilter = (params: any) => { - const filter = { ...initialFilterData, ...params }; - return { - status: filter.status === "--" ? null : filter.status, - facility: "", - origin_facility: filter.origin_facility || undefined, - approving_facility: filter.approving_facility || undefined, - assigned_facility: filter.assigned_facility || undefined, - emergency: - (filter.emergency && filter.emergency) === "--" - ? "" - : filter.emergency === "yes" - ? "true" - : "false", - limit: filter.limit || 14, - offset: filter.offset, - created_date_before: filter.created_date_before || undefined, - created_date_after: filter.created_date_after || undefined, - modified_date_before: filter.modified_date_before || undefined, - modified_date_after: filter.modified_date_after || undefined, - ordering: filter.ordering || undefined, - title: filter.title || undefined, - }; -}; diff --git a/src/components/Resource/ResourceDetailsUpdate.tsx b/src/components/Resource/ResourceDetailsUpdate.tsx index 8d3bb755796..8af456caeaa 100644 --- a/src/components/Resource/ResourceDetailsUpdate.tsx +++ b/src/components/Resource/ResourceDetailsUpdate.tsx @@ -23,7 +23,7 @@ import { UserModel } from "@/components/Users/models"; import useAppHistory from "@/hooks/useAppHistory"; -import { RESOURCE_CHOICES } from "@/common/constants"; +import { RESOURCE_STATUS_CHOICES } from "@/common/constants"; import routes from "@/Utils/request/api"; import request from "@/Utils/request/request"; @@ -34,8 +34,6 @@ interface resourceProps { id: string; } -const resourceStatusOptions = RESOURCE_CHOICES.map((obj) => obj.text); - const initForm: Partial = { assigned_facility: null, emergency: false, @@ -205,9 +203,9 @@ export const ResourceDetailsUpdate = (props: resourceProps) => { label="Status" name="status" value={state.form.status} - options={resourceStatusOptions} + options={RESOURCE_STATUS_CHOICES} onChange={handleChange} - optionLabel={(option) => option} + optionLabel={(option) => t(`resource_status__${option}`)} />
diff --git a/src/components/Resource/ResourceFilter.tsx b/src/components/Resource/ResourceFilter.tsx deleted file mode 100644 index e161fcf819a..00000000000 --- a/src/components/Resource/ResourceFilter.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import dayjs from "dayjs"; - -import FiltersSlideover from "@/CAREUI/interactive/FiltersSlideover"; - -import CircularProgress from "@/components/Common/CircularProgress"; -import { DateRange } from "@/components/Common/DateRangeInputV2"; -import { FacilitySelect } from "@/components/Common/FacilitySelect"; -import DateRangeFormField from "@/components/Form/FormFields/DateRangeFormField"; -import { FieldLabel } from "@/components/Form/FormFields/FormField"; -import { SelectFormField } from "@/components/Form/FormFields/SelectFormField"; -import { FieldChangeEvent } from "@/components/Form/FormFields/Utils"; - -import useMergeState from "@/hooks/useMergeState"; - -import { RESOURCE_FILTER_ORDER } from "@/common/constants"; -import { RESOURCE_CHOICES } from "@/common/constants"; - -import routes from "@/Utils/request/api"; -import useTanStackQueryInstead from "@/Utils/request/useQuery"; -import { dateQueryString } from "@/Utils/utils"; - -const getDate = (value: any) => - value && dayjs(value).isValid() && dayjs(value).toDate(); - -export default function ListFilter(props: any) { - const { filter, onChange, closeFilter, removeFilters } = props; - const [filterState, setFilterState] = useMergeState({ - origin_facility: filter.origin_facility || null, - origin_facility_ref: null, - approving_facility: filter.approving_facility || null, - approving_facility_ref: null, - assigned_facility: filter.assigned_facility || null, - assigned_facility_ref: null, - emergency: filter.emergency || null, - created_date_before: filter.created_date_before || null, - created_date_after: filter.created_date_after || null, - modified_date_before: filter.modified_date_before || null, - modified_date_after: filter.modified_date_after || null, - ordering: filter.ordering || null, - status: filter.status || null, - }); - - const { loading: orginFacilityLoading } = useTanStackQueryInstead( - routes.getAnyFacility, - { - prefetch: filter.origin_facility !== undefined, - pathParams: { id: filter.origin_facility }, - onResponse: ({ res, data }) => { - if (res && data) { - setFilterState({ - origin_facility_ref: filter.origin_facility === "" ? "" : data, - }); - } - }, - }, - ); - - const { loading: resourceFacilityLoading } = useTanStackQueryInstead( - routes.getAnyFacility, - { - prefetch: filter.approving_facility !== undefined, - pathParams: { id: filter.approving_facility }, - onResponse: ({ res, data }) => { - if (res && data) { - setFilterState({ - approving_facility_ref: - filter.approving_facility === "" ? "" : data, - }); - } - }, - }, - ); - - const setFacility = (selected: any, name: string) => { - setFilterState({ - ...filterState, - [`${name}_ref`]: selected, - [name]: (selected || {}).id, - }); - }; - - const handleChange = (e: FieldChangeEvent) => { - setFilterState({ ...filterState, [e.name]: e.value }); - }; - - const applyFilter = () => { - const { - origin_facility, - approving_facility, - assigned_facility, - emergency, - created_date_before, - created_date_after, - modified_date_before, - modified_date_after, - ordering, - status, - } = filterState; - const data = { - origin_facility: origin_facility || "", - approving_facility: approving_facility || "", - assigned_facility: assigned_facility || "", - emergency: emergency || "", - created_date_before: dateQueryString(created_date_before), - created_date_after: dateQueryString(created_date_after), - modified_date_before: dateQueryString(modified_date_before), - modified_date_after: dateQueryString(modified_date_after), - ordering: ordering || "", - status: status || "", - }; - onChange(data); - }; - - const handleDateRangeChange = (event: FieldChangeEvent) => { - const filterData = { ...filterState }; - filterData[`${event.name}_after`] = event.value.start?.toString(); - filterData[`${event.name}_before`] = event.value.end?.toString(); - setFilterState(filterData); - }; - - return ( - { - removeFilters(); - closeFilter(); - }} - > - {props.showResourceStatus && ( - option.text} - optionValue={(option) => option.text} - onChange={handleChange} - placeholder="Show all" - errorClassName="hidden" - /> - )} - -
- Origin facility - {orginFacilityLoading && filter.origin_facility ? ( - - ) : ( - setFacility(obj, "origin_facility")} - className="resource-page-filter-dropdown" - errors={""} - /> - )} -
- -
- Request approving facility - {filter.approving_facility && resourceFacilityLoading ? ( - - ) : ( - setFacility(obj, "approving_facility")} - className="resource-page-filter-dropdown" - errors={""} - /> - )} -
- - option.desc} - optionValue={(option) => option.text} - onChange={handleChange} - placeholder="None" - errorClassName="hidden" - /> - - option} - optionValue={(option) => option} - onChange={handleChange} - placeholder="Show all" - errorClassName="hidden" - /> - - - -
- ); -} diff --git a/src/components/Resource/ResourceList.tsx b/src/components/Resource/ResourceList.tsx index a754455b772..acf363305ac 100644 --- a/src/components/Resource/ResourceList.tsx +++ b/src/components/Resource/ResourceList.tsx @@ -1,285 +1,304 @@ +import { useQuery } from "@tanstack/react-query"; +import { t } from "i18next"; import { Link } from "raviger"; -import { useTranslation } from "react-i18next"; + +import { cn } from "@/lib/utils"; import CareIcon from "@/CAREUI/icons/CareIcon"; -import { AdvancedFilterButton } from "@/CAREUI/interactive/FiltersSlideover"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { Separator } from "@/components/ui/separator"; +import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { ExportButton } from "@/components/Common/Export"; -import Loading from "@/components/Common/Loading"; import Page from "@/components/Common/Page"; -import SearchInput from "@/components/Form/SearchInput"; -import BadgesList from "@/components/Resource/ResourceBadges"; -import { formatFilter } from "@/components/Resource/ResourceCommons"; -import ListFilter from "@/components/Resource/ResourceFilter"; +import SearchByMultipleFields from "@/components/Common/SearchByMultipleFields"; +import { CardGridSkeleton } from "@/components/Common/SkeletonLoading"; import useFilters from "@/hooks/useFilters"; +import { + RESOURCE_CATEGORY_CHOICES, + RESOURCE_STATUS_CHOICES, +} from "@/common/constants"; + import routes from "@/Utils/request/api"; -import request from "@/Utils/request/request"; -import useTanStackQueryInstead from "@/Utils/request/useQuery"; -import { useView } from "@/Utils/useView"; -import { formatDateTime } from "@/Utils/utils"; +import query from "@/Utils/request/query"; +import { PaginatedResponse } from "@/Utils/request/types"; import { ResourceRequest } from "@/types/resourceRequest/resourceRequest"; -export default function ListView() { - const [, setView] = useView("resource", "list"); - const { - qParams, - Pagination, - FilterBadges, - advancedFilter, - resultsPerPage, - updateQuery, - } = useFilters({ cacheBlacklist: ["title"], limit: 12 }); +const COMPLETED = ["completed", "rejected", "cancelled"]; +const ACTIVE = RESOURCE_STATUS_CHOICES.map((o) => o.text).filter( + (o) => !COMPLETED.includes(o), +); - const { t } = useTranslation(); +function EmptyState() { + return ( + +
+ +
+

{t("no_resources_found")}

+

+ {t("adjust_resource_filters")} +

+
+ ); +} - const appliedFilters = formatFilter(qParams); +export default function ResourceList() { + const { qParams, updateQuery, Pagination, resultsPerPage } = useFilters({ + limit: 15, + cacheBlacklist: ["title"], + }); + const { status, title } = qParams; - const { loading, data, refetch } = useTanStackQueryInstead( - routes.listResourceRequests, + const searchOptions = [ { - query: formatFilter({ - ...qParams, - limit: resultsPerPage, - offset: (qParams.page ? qParams.page - 1 : 0) * resultsPerPage, - }), + key: "title", + label: "Title", + type: "text" as const, + placeholder: t("search_by_resource_title"), + value: title || "", }, - ); + ]; - const showResourceCardList = (data: ResourceRequest[]) => { - if (data && !data.length) { - return ( -
- {t("no_results_found")} -
- ); - } + const isActive = !status || !COMPLETED.includes(status); + const currentStatuses = isActive ? ACTIVE : COMPLETED; - return data.map((resource: ResourceRequest, i) => ( -
-
-
-
{resource.title}
-
+ // Set default status based on active/completed tab + const defaultStatus = isActive ? "pending" : "completed"; + const currentStatus = status || defaultStatus; -
-
-
- -
- {resource.category || ""} -
- -
-
+ const { data: queryResources, isLoading } = useQuery< + PaginatedResponse + >({ + queryKey: ["resources", qParams], + queryFn: query.debounced(routes.listResourceRequests, { + queryParams: { + status: currentStatus, + title, + limit: resultsPerPage, + offset: ((qParams.page || 1) - 1) * resultsPerPage, + }, + }), + }); -
-
- {resource.status === "TRANSPORTATION TO BE ARRANGED" ? ( -
- - - - - {t(`${resource.status}`)} - -
- ) : ( -
- - - - - {t(`${resource.status}`)} - -
- )} + const resources = queryResources?.results || []; -
- {resource.emergency && ( - - {t("emergency")} - - )} + return ( + +
+
+
+
+
+ + + + + event.preventDefault()} + > +
+

+ {t("search_resource")} +

+ + updateQuery({ + status: currentStatus, + title: undefined, + }) + } + onSearch={(key, value) => + updateQuery({ + status: currentStatus, + [key]: value || undefined, + }) + } + className="w-full border-none shadow-none" + /> +
+
+
-
-
-
- -
- {formatDateTime(resource.modified_date) || "--"} -
- +
+ + + + updateQuery({ + status: "pending", + title, + }) + } + > + {t("active")} + + + updateQuery({ + status: "completed", + title, + }) + } + > + {t("completed")} + + + +
-
- -
-
- -
- {resource.origin_facility?.name} -
- -
- -
- {resource.approving_facility?.name} -
- + -
- -
- {resource.assigned_facility?.name || t("yet_to_be_decided")} -
- -
-
- - {t("all_details")} - +
+ + + {currentStatuses.map((statusOption) => ( + + updateQuery({ + status: statusOption, + title, + }) + } + > + o.text === statusOption, + )?.icon || "l-folder-open" + } + className="mr-2 h-4 w-4" + /> + {t(`resource_status__${statusOption}`)} + + ))} + + +
-
- )); - }; - - return ( - { - const { data } = await request(routes.downloadResourceRequests, { - query: { ...appliedFilters, csv: true }, - }); - return data ?? null; - }} - filenamePrefix="resource_requests" - /> - } - breadcrumbs={false} - options={ - <> -
-
- updateQuery({ [e.name]: e.value })} - placeholder={t("search_resource")} - /> -
- -
- - advancedFilter.setShow(true)} - /> -
- - } - > - -
- {loading ? ( - - ) : ( -
-
- +
+ {isLoading ? ( + + ) : resources.length === 0 ? ( +
+
-
-
- {t("resource")} -
-
- {t("LOG_UPDATE_FIELD_LABEL__patient_category")} -
-
- {t("consent__status")} -
-
- {t("facilities")} -
-
- {t("LOG_UPDATE_FIELD_LABEL__action")} -
-
-
{showResourceCardList(data?.results || [])}
-
- -
-
- )} + ) : ( + <> + {resources.map((resource: ResourceRequest) => ( + + +
+ + {resource.title} + +
+ + {resource.reason} + +
+ +
+
+ {resource.emergency && ( + + {t("emergency")} + + )} + + { + RESOURCE_CATEGORY_CHOICES.find( + (o) => o.id === resource.category, + )?.text + } + +
+ + + View Details + + +
+
+
+ ))} + {queryResources?.count && + queryResources.count > resultsPerPage && ( +
+ +
+ )} + + )} +
- ); }