diff --git a/src/app/(dashboard)/aprovacoes/page.tsx b/src/app/(dashboard)/aprovacoes/page.tsx
index 1cbb52bc..52dfda76 100644
--- a/src/app/(dashboard)/aprovacoes/page.tsx
+++ b/src/app/(dashboard)/aprovacoes/page.tsx
@@ -1,9 +1,11 @@
import type { Metadata } from 'next'
+import { UnderReviewPatientRequirements } from '@/modules/patient-requirements/under-review-requirements'
+
export const metadata: Metadata = {
title: 'Aprovações pendentes',
}
export default function Page() {
- return
Aprovações pendentes
+ return
}
diff --git a/src/components/ui/search-input.tsx b/src/components/ui/search-input.tsx
new file mode 100644
index 00000000..8447652f
--- /dev/null
+++ b/src/components/ui/search-input.tsx
@@ -0,0 +1,60 @@
+'use client'
+
+import { SearchIcon, XIcon } from 'lucide-react'
+import { useEffect, useState } from 'react'
+
+import { Button } from '@/components/ui/button'
+import { Input, type InputProps } from '@/components/ui/input'
+import { QUERY_PARAMS } from '@/constants/params'
+import { useDebounce } from '@/hooks/debounce'
+import { useParams } from '@/hooks/params'
+import { cn } from '@/utils/class-name-merge'
+
+export function SearchInput({ className, ...props }: Readonly) {
+ const queryParam = QUERY_PARAMS.search
+ const pageParam = QUERY_PARAMS.page
+
+ const { getParam, updateParams } = useParams()
+ const searchQuery = getParam(queryParam) || ''
+
+ const [query, setQuery] = useState(searchQuery)
+ const debouncedQuery = useDebounce(query)
+
+ useEffect(() => {
+ updateParams({
+ set: [{ key: queryParam, value: debouncedQuery }],
+ remove: !debouncedQuery ? [queryParam, pageParam] : [pageParam],
+ })
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [debouncedQuery])
+
+ useEffect(() => {
+ if (!searchQuery) setQuery('')
+ }, [searchQuery])
+
+ return (
+
+ setQuery(e.target.value)}
+ className={cn('w-52 pr-10', className)}
+ {...props}
+ />
+
+ {query && (
+
+ )}
+
+ )
+}
diff --git a/src/helpers/get-time-distance-to-now.ts b/src/helpers/get-time-distance-to-now.ts
new file mode 100644
index 00000000..9023b25c
--- /dev/null
+++ b/src/helpers/get-time-distance-to-now.ts
@@ -0,0 +1,6 @@
+import { formatDistanceToNow } from 'date-fns'
+import { ptBR } from 'date-fns/locale'
+
+export function getTimeDistanceToNow(date: string | Date) {
+ return formatDistanceToNow(date, { addSuffix: true, locale: ptBR })
+}
diff --git a/src/modules/patient-requirements/pending-requirements.tsx b/src/modules/patient-requirements/pending-requirements.tsx
index 5bb05470..8a91aa64 100644
--- a/src/modules/patient-requirements/pending-requirements.tsx
+++ b/src/modules/patient-requirements/pending-requirements.tsx
@@ -15,6 +15,7 @@ import { Skeleton } from '@/components/ui/skeleton'
import { Tag } from '@/components/ui/tag'
import { QUERY_CACHE_KEYS } from '@/constants/cache'
import { QUERY_PARAMS } from '@/constants/params'
+import { getTimeDistanceToNow } from '@/helpers/get-time-distance-to-now'
import { useParams } from '@/hooks/params'
import { api } from '@/lib/api'
import type { OrderMappingType } from '@/types/order'
@@ -123,9 +124,9 @@ export function PendingPatientRequirements() {
variant={severityVariant()}
className='flex flex-col gap-1 rounded-xl shadow-none'
>
-
+
{requirement.patient.name}
-
+
Pendência:
@@ -135,7 +136,7 @@ export function PendingPatientRequirements() {
-
+
Solicitado em {formatDate(requirement.created_at)}
@@ -149,12 +150,8 @@ export function PendingPatientRequirements() {
'data-[severity="error"]:text-error',
)}
>
-
-
- {pendingDays <= 1
- ? 'Pendente há 1 dia'
- : `Pendente há ${pendingDays} dias`}
-
+
+
Pendente {getTimeDistanceToNow(requirement.created_at)}
)
diff --git a/src/modules/patient-requirements/under-review-requirements.tsx b/src/modules/patient-requirements/under-review-requirements.tsx
new file mode 100644
index 00000000..e265393a
--- /dev/null
+++ b/src/modules/patient-requirements/under-review-requirements.tsx
@@ -0,0 +1,135 @@
+'use client'
+
+import { useQuery } from '@tanstack/react-query'
+import { CircleAlertIcon } from 'lucide-react'
+import { useEffect, useState } from 'react'
+
+import { DataTableHeader } from '@/components/data-table/header'
+import { DataTableHeaderActions } from '@/components/data-table/header/actions'
+import { DataTableHeaderOrderBy } from '@/components/data-table/header/order-by'
+import { DataTableHeaderSearch } from '@/components/data-table/header/search'
+import { Pagination } from '@/components/pagination'
+import { Card } from '@/components/ui/card'
+import { Skeleton } from '@/components/ui/skeleton'
+import { Tag } from '@/components/ui/tag'
+import { QUERY_CACHE_KEYS } from '@/constants/cache'
+import { QUERY_PARAMS } from '@/constants/params'
+import { getTimeDistanceToNow } from '@/helpers/get-time-distance-to-now'
+import { useParams } from '@/hooks/params'
+import { api } from '@/lib/api'
+import type { OrderMappingType } from '@/types/order'
+import type { PatientRequirement } from '@/types/patient-requirements'
+import {
+ PATIENT_REQUIREMENT_TYPES,
+ PATIENT_REQUIREMENTS_ORDER_OPTIONS,
+ type PatientRequirementsOrder,
+} from '@/types/patient-requirements'
+
+import { AddPatientRequirementButton } from './add-patient-requirement-button'
+
+// TODO: add dropdown actions menu
+export function UnderReviewPatientRequirements() {
+ const [stableTotal, setStableTotal] = useState(0)
+ const { getParam } = useParams()
+
+ const perPage = 12
+ const page = getParam(QUERY_PARAMS.page)
+ const search = getParam(QUERY_PARAMS.search)
+ const orderBy = getParam(QUERY_PARAMS.orderBy)
+
+ const ORDER_MAPPING: OrderMappingType = {
+ name_asc: { orderBy: 'name', order: 'ASC' },
+ name_desc: { orderBy: 'name', order: 'DESC' },
+ date_asc: { orderBy: 'submitted_at', order: 'ASC' },
+ date_desc: { orderBy: 'submitted_at', order: 'DESC' },
+ type_asc: { orderBy: 'type', order: 'ASC' },
+ type_desc: { orderBy: 'type', order: 'DESC' },
+ }
+
+ const orderByQuery = ORDER_MAPPING[orderBy as PatientRequirementsOrder] ?? {
+ orderBy: 'submitted_at',
+ order: 'DESC',
+ }
+
+ const { data: response, isLoading } = useQuery({
+ queryKey: [QUERY_CACHE_KEYS.approvals.pending, search, page, orderByQuery],
+ queryFn: () =>
+ api<{ requirements: PatientRequirement[]; total: number }>(
+ '/patient-requirements',
+ {
+ params: {
+ page,
+ perPage,
+ search,
+ status: 'under_review',
+ ...orderByQuery,
+ },
+ },
+ ),
+ })
+
+ const requirements = response?.data?.requirements ?? []
+ const isEmpty = requirements.length === 0
+ const hasActiveFilters = !!search
+
+ useEffect(() => {
+ if (response?.data) {
+ setStableTotal(response.data.total)
+ }
+ }, [response?.data])
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {isLoading && }
+
+ {isEmpty && !isLoading && (
+
+ {hasActiveFilters
+ ? 'Nenhuma aprovação encontrada para os filtros aplicados.'
+ : 'Nenhuma aprovação em análise encontrada.'}
+
+ )}
+
+ {!isEmpty &&
+ requirements.map((requirement) => (
+
+
+ {requirement.patient.name}
+
+
+
+
+ Recebido{' '}
+ {getTimeDistanceToNow(requirement.submitted_at ?? '')}
+
+
+
+
+ Tipo de solicitação:
+
+ {PATIENT_REQUIREMENT_TYPES[requirement.type]}
+
+
+
+ ))}
+
+
+
+ >
+ )
+}