From c8b4d9beeb5c3e720899ba901a3007d6176de9b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Fri, 7 Nov 2025 07:44:40 -0300 Subject: [PATCH] update select --- .../components/data-table/column-header.tsx | 2 +- .../app/components/data-table/data-table.tsx | 4 +- .../app/components/data-table/pagination.tsx | 101 +++++++-------- .../app/components/range-calendar-filter.tsx | 122 +++++++++++++----- .../_.$orgid.enrollments._index/columns.tsx | 5 +- .../_.$orgid.enrollments._index/data.tsx | 10 +- .../_.$orgid.enrollments._index/route.tsx | 120 ++++++----------- id.saladeaula.digital/app/oauth2.py | 3 +- packages/ui/src/components/faceted-filter.tsx | 4 +- 9 files changed, 192 insertions(+), 179 deletions(-) diff --git a/apps/admin.saladeaula.digital/app/components/data-table/column-header.tsx b/apps/admin.saladeaula.digital/app/components/data-table/column-header.tsx index 723604e..0c52b82 100644 --- a/apps/admin.saladeaula.digital/app/components/data-table/column-header.tsx +++ b/apps/admin.saladeaula.digital/app/components/data-table/column-header.tsx @@ -27,7 +27,7 @@ export function DataTableColumnHeader({ - - +
+ +
) diff --git a/apps/admin.saladeaula.digital/app/components/range-calendar-filter.tsx b/apps/admin.saladeaula.digital/app/components/range-calendar-filter.tsx index d25221b..13f11fe 100644 --- a/apps/admin.saladeaula.digital/app/components/range-calendar-filter.tsx +++ b/apps/admin.saladeaula.digital/app/components/range-calendar-filter.tsx @@ -1,13 +1,20 @@ 'use client' -import { CalendarIcon } from 'lucide-react' -import { useState, type ReactNode } from 'react' +import { EllipsisIcon } from 'lucide-react' +import { useState } from 'react' import { type DateRange } from 'react-day-picker' import { ptBR } from 'react-day-picker/locale' import { Badge } from '@repo/ui/components/ui/badge' import { Button } from '@repo/ui/components/ui/button' import { Calendar } from '@repo/ui/components/ui/calendar' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuTrigger +} from '@repo/ui/components/ui/dropdown-menu' import { Popover, PopoverContent, @@ -23,53 +30,100 @@ const formatted = new Intl.DateTimeFormat('pt-BR', { year: '2-digit' }) +type FilterProps = { + rangeField?: string + dateRange?: DateRange +} + type RangeCalendarFilterProps = { - children?: ReactNode - value?: DateRange + title: string + icon: React.ComponentType + value?: FilterProps + options: { value: string; label: string }[] className?: string - onChange?: (values: DateRange | undefined) => void + onChange?: (values: FilterProps | undefined) => void } export function RangeCalendarFilter({ - children, + title, + icon: Icon, value = undefined, + options = [], className, onChange }: RangeCalendarFilterProps) { - const [dateRange, setDateRange] = useState(value) + const [rangeField, setRangeField] = useState( + value?.rangeField || options?.[0]?.value + ) + + const [dateRange, setDateRange] = useState( + value?.dateRange + ) return ( - - - - - {children && ( +
+ + + + + {dateRange && ( <> - {children} - + + + + + + + { + setRangeField(rangeField) + onChange?.({ rangeField, dateRange }) + }} + className="*:cursor-pointer" + > + {options.map(({ label, value }, idx) => ( + + {label} + + ))} + + + )} +
+ diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/columns.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/columns.tsx index 12d3608..9e6f97b 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/columns.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/columns.tsx @@ -52,6 +52,7 @@ export const columns: ColumnDef[] = [ cell: ({ row }) => ( row.toggleSelected(!!value)} aria-label="Selecionar linha" /> @@ -149,9 +150,9 @@ export const columns: ColumnDef[] = [ { accessorKey: 'completed_at', header: ({ column }) => ( - + ), - meta: { title: 'Aprovado em' }, + meta: { title: 'Concluído em' }, enableSorting: true, enableHiding: true, cell: cellDate diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/data.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/data.tsx index ae66993..e35dd19 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/data.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/data.tsx @@ -23,7 +23,7 @@ export const statuses: Record< COMPLETED: { icon: CircleCheckIcon, color: 'text-green-400 [&_svg]:text-background [&_svg]:fill-green-500', - label: 'Aprovado' + label: 'Concluído' }, FAILED: { icon: CircleXIcon, @@ -44,3 +44,11 @@ export const labels: Record = { FAILED: 'Reprovado', CANCELED: 'Cancelado' } + +export const sortings: Record = { + created_at: 'Matriculado em', + started_at: 'Iniciado em', + completed_at: 'Concluído em', + failed_at: 'Reprovado em', + canceled_at: 'Cancelado em' +} diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/route.tsx index 9571d37..74822b3 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/route.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments._index/route.tsx @@ -1,8 +1,8 @@ import type { Route } from './+types' -import { PlusCircleIcon, PlusIcon } from 'lucide-react' +import { CalendarIcon, PlusCircleIcon, PlusIcon } from 'lucide-react' import { MeiliSearchFilterBuilder } from 'meilisearch-helper' -import { Suspense, useState } from 'react' +import { Suspense } from 'react' import { Await, Link, useSearchParams } from 'react-router' import { DataTable, DataTableViewOptions } from '@/components/data-table' @@ -14,16 +14,8 @@ import { SearchForm } from '@repo/ui/components/search-form' import { Skeleton } from '@repo/ui/components/skeleton' import { Button } from '@repo/ui/components/ui/button' import { Kbd } from '@repo/ui/components/ui/kbd' -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectTrigger, - SelectValue -} from '@repo/ui/components/ui/select' import { columns, type Enrollment } from './columns' -import { statuses } from './data' +import { sortings, statuses } from './data' export function meta({}: Route.MetaArgs) { return [{ title: 'Matrículas' }] @@ -33,17 +25,17 @@ export async function loader({ params, context, request }: Route.LoaderArgs) { const { searchParams } = new URL(request.url) const { orgid } = params const query = searchParams.get('q') || '' - const from = searchParams.get('from') || '' - const to = searchParams.get('to') || '' + const from = searchParams.get('from') + const to = searchParams.get('to') const sort = searchParams.get('sort') || 'created_at:desc' - const status = searchParams.getAll('status') || [] + const status = searchParams.get('status') const page = Number(searchParams.get('p')) + 1 const hitsPerPage = Number(searchParams.get('perPage')) || 25 let builder = new MeiliSearchFilterBuilder().where('org_id', '=', orgid) - if (status.length) { - builder = builder.where('status', 'in', status) + if (status) { + builder = builder.where('status', 'in', status.split(',')) } if (from && to) { @@ -72,8 +64,8 @@ const formatted = new Intl.DateTimeFormat('en-CA', { export default function Route({ loaderData: { data } }) { const [searchParams, setSearchParams] = useSearchParams() - // const [rangeField, setRangeField] = useState('created_at') - const { rangeField, dateRange } = useRangeParams('created_at') + const status = searchParams.get('status') + const rangeParams = useRangeParams() return ( }> @@ -126,26 +118,22 @@ export default function Route({ loaderData: { data } }) {
{ setSearchParams((searchParams) => { searchParams.delete('status') searchParams.delete('p') if (statuses.length) { - statuses.forEach((s) => - searchParams.has('status', s) - ? null - : searchParams.append('status', s) - ) + searchParams.set('status', statuses.join(',')) } return searchParams }) }} - title="Status" options={Object.entries(statuses).map(([key, value]) => ({ value: key, ...value @@ -153,69 +141,39 @@ export default function Route({ loaderData: { data } }) { /> { + options={Object.entries(sortings).map( + ([value, label]) => ({ + value, + label + }) + )} + onChange={(props) => { setSearchParams((searchParams) => { - if (dateRange) { - searchParams.set( - 'from', - `${rangeField}:${formatted.format(dateRange.from)}` - ) - searchParams.set( - 'to', - formatted.format(dateRange.to) - ) - } else { + if (!props) { searchParams.delete('from') searchParams.delete('to') + return searchParams } + const { rangeField, dateRange } = props + + searchParams.set( + 'from', + `${rangeField}:${formatted.format(dateRange?.from)}` + ) + searchParams.set( + 'to', + formatted.format(dateRange?.to) + ) + return searchParams }) }} - > -
- -
-
+ />
@@ -237,12 +195,12 @@ export default function Route({ loaderData: { data } }) { ) } -function useRangeParams(initRangeField: string) { +function useRangeParams() { const [searchParams] = useSearchParams() const [from, to] = [searchParams.get('from'), searchParams.get('to')] if (!from || !to) { - return { rangeField: initRangeField, dateRange: undefined } + return {} } const [rangeField, from_] = from.split(':') diff --git a/id.saladeaula.digital/app/oauth2.py b/id.saladeaula.digital/app/oauth2.py index 0ec507e..aaa6604 100644 --- a/id.saladeaula.digital/app/oauth2.py +++ b/id.saladeaula.digital/app/oauth2.py @@ -42,8 +42,7 @@ private_jwk = JsonWebKey.import_key(private_key) # https://docs.authlib.org/en/v0.12/specs/rfc6750.html#authlib.oauth2.rfc6750.BearerToken.GRANT_TYPES_EXPIRES_IN GRANT_TYPES_EXPIRES_IN = { 'authorization_code': 60 * 3, # 3 minutes - 'refresh_token': 60 * 3, # 3 minutes - # 'refresh_token': 3600, # 1 hour + 'refresh_token': 3600, # 1 hour } diff --git a/packages/ui/src/components/faceted-filter.tsx b/packages/ui/src/components/faceted-filter.tsx index 5cc2056..168f533 100644 --- a/packages/ui/src/components/faceted-filter.tsx +++ b/packages/ui/src/components/faceted-filter.tsx @@ -21,8 +21,8 @@ import { Separator } from '@repo/ui/components/ui/separator' import { cn } from '@repo/ui/lib/utils' interface FacetedFilterProps { - value?: string[] title?: string + value?: string[] icon: React.ComponentType className?: string options: { @@ -55,7 +55,7 @@ export function FacetedFilter({ {title} {selectedValues?.size > 0 && ( <> - +
{selectedValues.size > 2 ? (