From d9bdc461e32d4842f452e19143ff4cf541ac12ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Wed, 19 Nov 2025 18:47:05 -0300 Subject: [PATCH] add paymentsd list --- .../app/components/app-sidebar.tsx | 8 +- .../app/components/nav-main.tsx | 2 +- .../app/entry.server.tsx | 11 +- .../routes/_app.payments._index/columns.tsx | 118 ++++++++++++++++++ .../app/routes/_app.payments._index/route.tsx | 46 ++++++- .../app/routes/_app.users._index/columns.tsx | 2 +- .../app/routes/_app.webhooks._index/route.tsx | 19 --- 7 files changed, 171 insertions(+), 35 deletions(-) create mode 100644 apps/insights.saladeaula.digital/app/routes/_app.payments._index/columns.tsx delete mode 100644 apps/insights.saladeaula.digital/app/routes/_app.webhooks._index/route.tsx diff --git a/apps/insights.saladeaula.digital/app/components/app-sidebar.tsx b/apps/insights.saladeaula.digital/app/components/app-sidebar.tsx index a94c508..fef5abd 100644 --- a/apps/insights.saladeaula.digital/app/components/app-sidebar.tsx +++ b/apps/insights.saladeaula.digital/app/components/app-sidebar.tsx @@ -5,8 +5,7 @@ import { DollarSign, GraduationCap, LayoutDashboard, - UsersIcon, - WebhookIcon + UsersIcon } from 'lucide-react' import { NavMain } from '@/components/nav-main' @@ -41,11 +40,6 @@ const navMain = [ title: 'Empresas', url: '/orgs', icon: Building2Icon - }, - { - title: 'Webhooks', - url: '/webhooks', - icon: WebhookIcon } ] diff --git a/apps/insights.saladeaula.digital/app/components/nav-main.tsx b/apps/insights.saladeaula.digital/app/components/nav-main.tsx index 40252f0..2a3d6c8 100644 --- a/apps/insights.saladeaula.digital/app/components/nav-main.tsx +++ b/apps/insights.saladeaula.digital/app/components/nav-main.tsx @@ -11,7 +11,7 @@ import { import { useIsMobile } from '@repo/ui/hooks/use-mobile' import { type LucideIcon } from 'lucide-react' -import { NavLink, useParams } from 'react-router' +import { NavLink } from 'react-router' type NavItem = { title: string diff --git a/apps/insights.saladeaula.digital/app/entry.server.tsx b/apps/insights.saladeaula.digital/app/entry.server.tsx index b7ce22e..abc0ac7 100644 --- a/apps/insights.saladeaula.digital/app/entry.server.tsx +++ b/apps/insights.saladeaula.digital/app/entry.server.tsx @@ -1,7 +1,7 @@ import { isbot } from 'isbot' import { renderToReadableStream } from 'react-dom/server' import type { AppLoadContext, EntryContext } from 'react-router' -import { ServerRouter } from 'react-router' +import { ServerRouter, type HandleErrorFunction } from 'react-router' export default async function handleRequest( request: Request, @@ -43,4 +43,11 @@ export default async function handleRequest( } // https://reactrouter.com/how-to/suspense#timeouts -export const streamTimeout = 6_000 +export const streamTimeout = 7_000 + +// https://reactrouter.com/how-to/error-reporting +export const handleError: HandleErrorFunction = (error, { request }) => { + if (!request.signal.aborted) { + console.error(error) + } +} diff --git a/apps/insights.saladeaula.digital/app/routes/_app.payments._index/columns.tsx b/apps/insights.saladeaula.digital/app/routes/_app.payments._index/columns.tsx new file mode 100644 index 0000000..24bd5d6 --- /dev/null +++ b/apps/insights.saladeaula.digital/app/routes/_app.payments._index/columns.tsx @@ -0,0 +1,118 @@ +'use client' + +import { formatCNPJ, formatCPF } from '@brazilian-utils/brazilian-utils' +import { type ColumnDef } from '@tanstack/react-table' + +import { Abbr } from '@repo/ui/components/abbr' +import { Avatar, AvatarFallback } from '@repo/ui/components/ui/avatar' +import { initials } from '@repo/ui/lib/utils' + +// This type is used to define the shape of our data. +// You can use a Zod schema here if you want. +export type Order = { + id: string + total: number + status: 'pending' | 'processing' | 'success' | 'failed' + payment_method: 'PIX' | 'CREDIT_CARD' | 'MANUAL' | 'failed' + name: string +} + +const formatted = new Intl.DateTimeFormat('pt-BR', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit' +}) + +export const columns: ColumnDef[] = [ + { + header: 'Comprador', + cell: ({ row }) => { + const { name, email } = row.original + + return ( +
+ + {initials(name)} + + +
    +
  • + {name} +
  • +
  • + {email} +
  • +
+
+ ) + } + }, + { + header: 'CNPJ/CPF', + cell: ({ row }) => { + const { cpf, cnpj } = row.original + + if (cpf) { + return <>{formatCPF(cpf)} + } + + if (cnpj) { + return <>{formatCNPJ(cnpj)} + } + + return <> + } + }, + { + accessorKey: 'payment_method', + header: 'Forma de pag.' + }, + { + accessorKey: 'status', + header: 'Status' + }, + { + accessorKey: 'total', + header: 'Valor total', + cell: ({ row }) => { + const amount = parseFloat(row.getValue('total')) + const formatted = new Intl.NumberFormat('pt-BR', { + style: 'currency', + currency: 'BRL' + }).format(amount) + + return
{formatted}
+ } + }, + { + header: 'Comprado em', + cell: ({ row }) => { + const createdAt = new Date(row.original.create_date) + return formatted.format(createdAt) + } + }, + { + header: 'Vencimento em', + cell: ({ row }) => { + try { + const dueDate = new Date(row.original.due_date) + return formatted.format(dueDate) + } catch { + return 'N/A' + } + } + }, + { + header: 'Pago em', + cell: ({ row }) => { + if (row.original.payment_date) { + const createdAt = new Date(row.original.payment_date) + return formatted.format(createdAt) + } + + return <> + } + } +] diff --git a/apps/insights.saladeaula.digital/app/routes/_app.payments._index/route.tsx b/apps/insights.saladeaula.digital/app/routes/_app.payments._index/route.tsx index ab07bee..2ad7182 100644 --- a/apps/insights.saladeaula.digital/app/routes/_app.payments._index/route.tsx +++ b/apps/insights.saladeaula.digital/app/routes/_app.payments._index/route.tsx @@ -1,19 +1,55 @@ import type { Route } from './+types' +import { Suspense } from 'react' +import { Await } from 'react-router' + +import { DataTable } from '@repo/ui/components/data-table' +import { Skeleton } from '@repo/ui/components/skeleton' +import { createSearch } from '@repo/util/meili' + +import { columns, type Order } from './columns' + export function meta({}: Route.MetaArgs) { return [{ title: 'Pagamentos' }] } -export function loader({ context }: Route.LoaderArgs) { - return { message: context.cloudflare.env.VALUE_FROM_CLOUDFLARE } +export async function loader({ context, request }: Route.LoaderArgs) { + const { searchParams } = new URL(request.url) + const page = Number(searchParams.get('p')) + 1 + const hitsPerPage = Number(searchParams.get('perPage')) || 25 + + return { + data: createSearch({ + index: 'betaeducacao-prod-orders', + sort: ['create_date:desc'], + page, + hitsPerPage, + env: context.cloudflare.env + }) + } } -export default function Route({}: Route.ComponentProps) { +export default function Route({ loaderData: { data } }) { return ( - <> + }>

Pagamentos

- + + + {({ hits, page, hitsPerPage, totalHits }) => { + return ( + + ) + }} + +
) } diff --git a/apps/insights.saladeaula.digital/app/routes/_app.users._index/columns.tsx b/apps/insights.saladeaula.digital/app/routes/_app.users._index/columns.tsx index eb7a749..2b7ab9c 100644 --- a/apps/insights.saladeaula.digital/app/routes/_app.users._index/columns.tsx +++ b/apps/insights.saladeaula.digital/app/routes/_app.users._index/columns.tsx @@ -26,7 +26,7 @@ const formatted = new Intl.DateTimeFormat('pt-BR', { export const columns: ColumnDef[] = [ { - header: 'Colaborador', + header: 'Usuário', cell: ({ row }) => { const { name, email } = row.original diff --git a/apps/insights.saladeaula.digital/app/routes/_app.webhooks._index/route.tsx b/apps/insights.saladeaula.digital/app/routes/_app.webhooks._index/route.tsx deleted file mode 100644 index 411eb84..0000000 --- a/apps/insights.saladeaula.digital/app/routes/_app.webhooks._index/route.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import type { Route } from './+types' - -export function meta({}: Route.MetaArgs) { - return [{ title: 'Webhooks' }] -} - -export function loader({}: Route.LoaderArgs) { - return {} -} - -export default function Route({}: Route.ComponentProps) { - return ( - <> -
-

Webhooks

-
- - ) -}