This commit is contained in:
2025-11-06 19:17:50 -03:00
parent 14f8b65df5
commit 58e2bf0c32
15 changed files with 559 additions and 382 deletions

View File

@@ -1,12 +1,11 @@
import type { Route } from './+types'
import { PlusCircleIcon, PlusIcon } from 'lucide-react'
import { DateTime } from 'luxon'
import { MeiliSearchFilterBuilder } from 'meilisearch-helper'
import { Suspense, useState } from 'react'
import { Await, Link, useSearchParams } from 'react-router'
import { CustomizeColumns, DataTable } from '@/components/data-table'
import { DataTable, DataTableViewOptions } from '@/components/data-table'
import { RangeCalendarFilter } from '@/components/range-calendar-filter'
import { createSearch } from '@/lib/meili'
@@ -23,23 +22,20 @@ import {
SelectTrigger,
SelectValue
} from '@repo/ui/components/ui/select'
import { columns, statuses, type Enrollment } from './columns'
import { columns, type Enrollment } from './columns'
import { statuses } from './data'
export function meta({}: Route.MetaArgs) {
return [{ title: 'Matrículas' }]
}
const dtOptions = {
zone: 'America/Sao_Paulo'
}
export async function loader({ params, context, request }: Route.LoaderArgs) {
const { searchParams } = new URL(request.url)
const { orgid } = params
const query = searchParams.get('q') || ''
const field = searchParams.get('field') || ''
const from = searchParams.get('from') || ''
const to = searchParams.get('to') || ''
const sort = searchParams.get('sort') || 'created_at:desc'
const status = searchParams.getAll('status') || []
const page = Number(searchParams.get('p')) + 1
const hitsPerPage = Number(searchParams.get('perPage')) || 25
@@ -50,15 +46,16 @@ export async function loader({ params, context, request }: Route.LoaderArgs) {
builder = builder.where('status', 'in', status)
}
if (field && from && to) {
builder = builder.where(field, 'between', [from, to])
if (from && to) {
const [field, from_] = from.split(':')
builder = builder.where(field, 'between', [from_, to])
}
return {
data: createSearch({
index: 'betaeducacao-prod-enrollments',
sort: ['created_at:desc'],
filter: builder.build(),
sort: [sort],
query,
page,
hitsPerPage,
@@ -75,10 +72,8 @@ const formatted = new Intl.DateTimeFormat('en-CA', {
export default function Route({ loaderData: { data } }) {
const [searchParams, setSearchParams] = useSearchParams()
const [from, to] = [searchParams.get('from'), searchParams.get('to')]
const [rangeField, setRangeField] = useState<string>(
searchParams.get('field') || 'created_at'
)
// const [rangeField, setRangeField] = useState<string>('created_at')
const { rangeField, dateRange } = useRangeParams('created_at')
return (
<Suspense fallback={<Skeleton />}>
@@ -95,6 +90,7 @@ export default function Route({ loaderData: { data } }) {
{({ hits, page, hitsPerPage, totalHits }) => {
return (
<DataTable
sort={[{ id: 'created_at', desc: true }]}
columns={columns}
data={hits as Enrollment[]}
pageIndex={page - 1}
@@ -158,21 +154,13 @@ export default function Route({ loaderData: { data } }) {
<RangeCalendarFilter
className="lg:flex-1"
value={
from && to
? {
from: DateTime.fromISO(from, dtOptions),
to: DateTime.fromISO(to, dtOptions)
}
: undefined
}
value={dateRange}
onChange={(dateRange) => {
setSearchParams((searchParams) => {
if (dateRange) {
searchParams.set('field', rangeField)
searchParams.set(
'from',
formatted.format(dateRange.from)
`${rangeField}:${formatted.format(dateRange.from)}`
)
searchParams.set(
'to',
@@ -181,7 +169,6 @@ export default function Route({ loaderData: { data } }) {
} else {
searchParams.delete('from')
searchParams.delete('to')
searchParams.delete('field')
}
return searchParams
@@ -191,11 +178,13 @@ export default function Route({ loaderData: { data } }) {
<div className="p-2.5">
<Select
defaultValue={rangeField}
onValueChange={(field) => {
setRangeField(field)
onValueChange={(value) => {
setSearchParams((searchParams) => {
if (searchParams.has('from')) {
searchParams.set('field', field)
searchParams.set(
'from',
`${value}:${dateRange?.from?.getTime()}`
)
}
return searchParams
@@ -230,7 +219,7 @@ export default function Route({ loaderData: { data } }) {
</div>
<div className="lg:ml-auto flex gap-2.5">
<CustomizeColumns className="flex-1" />
<DataTableViewOptions className="flex-1" />
<Button className="flex-1" asChild>
<Link to="add">
@@ -247,3 +236,22 @@ export default function Route({ loaderData: { data } }) {
</Suspense>
)
}
function useRangeParams(initRangeField: string) {
const [searchParams] = useSearchParams()
const [from, to] = [searchParams.get('from'), searchParams.get('to')]
if (!from || !to) {
return { rangeField: initRangeField, dateRange: undefined }
}
const [rangeField, from_] = from.split(':')
return {
rangeField,
dateRange: {
from: new Date(from_),
to: new Date(to)
}
}
}