diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx
index 6b3a83b..2702a10 100644
--- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx
+++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx
@@ -1,12 +1,14 @@
import type { Route } from './+types/route'
+import Fuse from 'fuse.js'
import { DateTime } from 'luxon'
-import { Suspense } from 'react'
+import { Suspense, useMemo } from 'react'
import { BanIcon } from 'lucide-react'
+import { Await, useSearchParams } from 'react-router'
+import { cn } from '@repo/ui/lib/utils'
import { request as req } from '@repo/util/request'
import { Skeleton } from '@repo/ui/components/skeleton'
-import { Await } from 'react-router'
import { Card, CardContent } from '@repo/ui/components/ui/card'
import {
Table,
@@ -19,7 +21,7 @@ import {
} from '@repo/ui/components/ui/table'
import { Abbr } from '@repo/ui/components/abbr'
import { Button } from '@repo/ui/components/ui/button'
-import { cn } from '@repo/ui/lib/utils'
+import { SearchForm } from '@repo/ui/components/search-form'
import {
Empty,
EmptyDescription,
@@ -27,6 +29,7 @@ import {
EmptyMedia,
EmptyTitle
} from '@repo/ui/components/ui/empty'
+import { Kbd } from '@repo/ui/components/ui/kbd'
import { billingPeriod, formatDate } from './util'
import { RangePeriod } from './range-period'
@@ -68,6 +71,9 @@ export async function loader({ context, request, params }: Route.LoaderArgs) {
export default function Route({
loaderData: { subscription, billing, startDate, endDate }
}: Route.ComponentProps) {
+ const [searchParams, setSearchParams] = useSearchParams()
+ const search = searchParams.get('s') as string
+
return (
<>
}>
@@ -88,19 +94,36 @@ export default function Route({
label: status,
color
} = statuses?.[billing?.status || 'CLOSED']
- const charges = items
- ?.filter((item) => 'course' in item && item?.unit_price > 0)
- ?.sort(sortBy('enrolled_at'))
- const credits = items
- ?.filter((item) => 'course' in item && item?.unit_price < 0)
- ?.sort(sortBy('created_at'))
return (
+
+
+ Digite / para pesquisar
+ >
+ }
+ onChange={(value) =>
+ setSearchParams((searchParams) => {
+ searchParams.set('s', String(value))
+ return searchParams
+ })
+ }
+ />
+
+
+
+
-
-
- {items.length ? (
-
-
- {charges.length ? (
- <>
-
-
- Colaborador
- Curso
- Matriculado por
- Matriculado em
- Valor unit.
-
-
-
- {charges?.map(
- (
- {
- user,
- course,
- author: created_by,
- unit_price,
- enrolled_at
- },
- index
- ) => (
-
-
- {user.name}
-
-
- {course.name}
-
-
-
- {created_by ? created_by.name : 'N/A'}
-
-
-
- {datetime.format(new Date(enrolled_at))}
-
-
- {currency.format(unit_price)}
-
-
- )
- )}
-
- >
- ) : null}
-
- {credits.length ? (
- <>
-
-
-
- Cancelado por
- Cancelado em
-
-
-
- {credits?.map(
- (
- {
- user,
- course,
- author: canceled_by,
- unit_price,
- created_at
- },
- index
- ) => (
-
-
- {user.name}
-
-
- {course.name}
-
-
-
- {canceled_by ? canceled_by.name : 'N/A'}
-
-
-
- {datetime.format(new Date(created_at))}
-
-
- {currency.format(unit_price)}
-
-
- )
- )}
-
- >
- ) : null}
-
-
-
-
- Total
-
-
- {currency.format(
- items
- ?.filter((x) => 'course' in x)
- .reduce(
- (acc, { unit_price }) => acc + unit_price,
- 0
- )
- )}
-
-
-
-
-
- ) : (
-
-
-
-
-
- Nenhuma cobrança encontrada
-
- Não há nenhuma cobrança para este período.
-
-
-
- )}
+
)
@@ -257,6 +143,159 @@ export default function Route({
>
)
}
+
+function List({ items, search }) {
+ const fuse = useMemo(() => {
+ return new Fuse(items, {
+ keys: ['user.name'],
+ threshold: 0.3,
+ includeMatches: true
+ })
+ }, [items])
+
+ const filtered = useMemo(() => {
+ if (!search) {
+ return items
+ }
+
+ return fuse.search(search).map(({ item }) => item)
+ }, [search, fuse, items])
+
+ const charges = filtered
+ ?.filter((item) => 'course' in item && item?.unit_price > 0)
+ ?.sort(sortBy('enrolled_at'))
+ const credits = filtered
+ ?.filter((item) => 'course' in item && item?.unit_price < 0)
+ ?.sort(sortBy('created_at'))
+
+ if (items.length === 0) {
+ return (
+
+
+
+
+
+ Nenhuma cobrança encontrada
+
+ Não há nenhuma cobrança para este período.
+
+
+
+ )
+ }
+
+ if (filtered.length === 0) {
+ return (
+
+
+
+
+
+ Nada encontrado
+
+ Nenhum resultado para {search}.
+
+
+
+ )
+ }
+
+ return (
+
+
+ {charges.length ? (
+ <>
+
+
+ Colaborador
+ Curso
+ Matriculado por
+ Matriculado em
+ Valor unit.
+
+
+
+ {charges?.map(
+ (
+ { user, course, author: created_by, unit_price, enrolled_at },
+ index
+ ) => (
+
+
+ {user.name}
+
+
+ {course.name}
+
+
+ {created_by ? created_by.name : 'N/A'}
+
+
+ {datetime.format(new Date(enrolled_at))}
+
+ {currency.format(unit_price)}
+
+ )
+ )}
+
+ >
+ ) : null}
+
+ {credits.length ? (
+ <>
+
+
+
+ Cancelado por
+ Cancelado em
+
+
+
+ {credits?.map(
+ (
+ { user, course, author: canceled_by, unit_price, created_at },
+ index
+ ) => (
+
+
+ {user.name}
+
+
+ {course.name}
+
+
+ {canceled_by ? canceled_by.name : 'N/A'}
+
+
+ {datetime.format(new Date(created_at))}
+
+ {currency.format(unit_price)}
+
+ )
+ )}
+
+ >
+ ) : null}
+
+
+
+
+ Total
+
+
+ {currency.format(
+ filtered
+ ?.filter((x) => 'course' in x)
+ .reduce((acc, { unit_price }) => acc + unit_price, 0)
+ )}
+
+
+
+
+
+ )
+}
+
const currency = new Intl.NumberFormat('pt-BR', {
style: 'currency',
currency: 'BRL'
diff --git a/apps/saladeaula.digital/app/routes/index.tsx b/apps/saladeaula.digital/app/routes/index.tsx
index b278656..3cf73d4 100644
--- a/apps/saladeaula.digital/app/routes/index.tsx
+++ b/apps/saladeaula.digital/app/routes/index.tsx
@@ -181,7 +181,7 @@ function List({ search, hits = [] }: { search: string; hits: Enrollment[] }) {
<>
Nada encontrado
- Nenhum resultado para {s}.
+ Nenhum resultado para {search}.
>
) : (