check status to payment retries
This commit is contained in:
@@ -490,10 +490,11 @@ function ActionMenu() {
|
||||
}}
|
||||
>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="ghost" className="cursor-pointer">
|
||||
<Button variant="ghost" className="cursor-pointer" size="icon-sm">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
||||
<PopoverContent align="end" className="p-0 overflow-hidden w-56">
|
||||
<div className="border-b p-2 text-xs text-muted-foreground font-medium">
|
||||
Envios recentes
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Route } from './+types/route'
|
||||
|
||||
import { formatCEP } from '@brazilian-utils/brazilian-utils'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { useRequest } from 'ahooks'
|
||||
import { useRequest, useToggle } from 'ahooks'
|
||||
import {
|
||||
AlertCircleIcon,
|
||||
ArrowLeftRightIcon,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from 'lucide-react'
|
||||
import { useEffect } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { Link } from 'react-router'
|
||||
import { Link, useRevalidator } from 'react-router'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { Currency } from '@repo/ui/components/currency'
|
||||
@@ -31,13 +31,6 @@ import {
|
||||
CardHeader,
|
||||
CardTitle
|
||||
} from '@repo/ui/components/ui/card'
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandList
|
||||
} from '@repo/ui/components/ui/command'
|
||||
import {
|
||||
Item,
|
||||
ItemActions,
|
||||
@@ -121,6 +114,13 @@ type User = {
|
||||
type Invoice = {
|
||||
invoice_id: string
|
||||
secure_url: string
|
||||
bank_slip?: {
|
||||
bank_slip_pdf_url: string
|
||||
}
|
||||
pix?: {
|
||||
qrcode: string
|
||||
qrcode_text: string
|
||||
}
|
||||
}
|
||||
|
||||
type Attempts = {
|
||||
@@ -180,6 +180,8 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
||||
reset()
|
||||
}, [])
|
||||
|
||||
console.log(order)
|
||||
|
||||
return (
|
||||
<div className="space-y-2.5">
|
||||
<Breadcrumb>
|
||||
@@ -203,7 +205,8 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
||||
|
||||
<CardContent className="space-y-4">
|
||||
<ItemGroup className="grid lg:grid-cols-2 gap-4">
|
||||
<Item variant="outline">
|
||||
<Item variant="outline" className="items-start">
|
||||
{/* Billing address */}
|
||||
<ItemContent>
|
||||
<ItemTitle>Endereço de cobrança</ItemTitle>
|
||||
<ul className="text-muted-foreground text-sm leading-normal font-normal text-balance">
|
||||
@@ -218,14 +221,12 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
||||
</ul>
|
||||
</ItemContent>
|
||||
</Item>
|
||||
|
||||
{/* Payment method */}
|
||||
<Item variant="outline" className="items-start">
|
||||
<ItemContent>
|
||||
<ItemTitle>Forma de pagamento</ItemTitle>
|
||||
<div className="text-muted-foreground text-sm leading-normal font-normal text-balance">
|
||||
{Component && (
|
||||
<Component {...order} invoice_id={invoice['invoice_id']} />
|
||||
)}
|
||||
{Component && <Component {...order} invoice={invoice} />}
|
||||
</div>
|
||||
</ItemContent>
|
||||
|
||||
@@ -315,8 +316,6 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
||||
</Table>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/*<pre>{JSON.stringify(order, null, 2)}</pre>*/}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -326,7 +325,7 @@ function Status({ status: s }: { status: string }) {
|
||||
const { icon: Icon, color } = statuses?.[s] ?? { icon: HelpCircleIcon }
|
||||
|
||||
return (
|
||||
<Badge variant="outline" className={cn(color, ' px-1.5')}>
|
||||
<Badge variant="outline" className={cn(color, 'px-1.5')}>
|
||||
<Icon className={cn('stroke-2', color)} />
|
||||
{status}
|
||||
</Badge>
|
||||
@@ -337,7 +336,7 @@ type PaymentMethodProps = {
|
||||
id: string
|
||||
status: string
|
||||
total: number
|
||||
invoice_id: string
|
||||
invoice: Invoice
|
||||
installments: number
|
||||
}
|
||||
|
||||
@@ -345,7 +344,7 @@ type BankSlipPaymentMethodProps = PaymentMethodProps & {}
|
||||
|
||||
function BankSlipPaymentMethod({ status }: BankSlipPaymentMethodProps) {
|
||||
return (
|
||||
<ul className="flex max-lg:flex-col gap-x-1.5">
|
||||
<ul className="flex gap-x-1.5">
|
||||
<li>Boleto bancário</li>
|
||||
<li>
|
||||
<Status status={status} />
|
||||
@@ -356,8 +355,27 @@ function BankSlipPaymentMethod({ status }: BankSlipPaymentMethodProps) {
|
||||
|
||||
type PixPaymentMethodrops = PaymentMethodProps & {}
|
||||
|
||||
function PixPaymentMethod({}: PixPaymentMethodrops) {
|
||||
return <>Pix</>
|
||||
function PixPaymentMethod({ invoice, status }: PixPaymentMethodrops) {
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<ul className="flex gap-x-1.5">
|
||||
<li>Pix</li>
|
||||
<li>
|
||||
<Status status={status} />
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{invoice?.pix ? (
|
||||
<div
|
||||
className="font-mono text-xs break-all p-2.5 border
|
||||
rounded-md text-red-900 dark:text-yellow-600
|
||||
bg-gray-50 dark:bg-muted/50 select-all"
|
||||
>
|
||||
{invoice.pix.qrcode_text}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function UnknownPaymentMethod() {
|
||||
@@ -365,7 +383,7 @@ function UnknownPaymentMethod() {
|
||||
}
|
||||
|
||||
type CreditCardPaymentMethodProps = PaymentMethodProps & {
|
||||
stats: { last_attempt_succeeded: boolean }
|
||||
stats?: { last_attempt_succeeded: boolean }
|
||||
credit_card: { last4: string; brand: string }
|
||||
}
|
||||
|
||||
@@ -375,22 +393,20 @@ function CreditCardPaymentMethod({
|
||||
total,
|
||||
credit_card,
|
||||
installments,
|
||||
invoice_id,
|
||||
invoice,
|
||||
stats
|
||||
}: CreditCardPaymentMethodProps) {
|
||||
return (
|
||||
<>
|
||||
<ul className="flex max-lg:flex-col gap-x-1.5">
|
||||
<ul className="lg:flex gap-x-1">
|
||||
<li>
|
||||
{credit_card.brand} (Crédito) **** {credit_card.last4}
|
||||
<Abbr maxLen={6}>{credit_card.brand}</Abbr>
|
||||
</li>
|
||||
<li>(Crédito) **** {credit_card.last4}</li>
|
||||
<li>
|
||||
{stats.last_attempt_succeeded === false ? (
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="text-red-400 border-red-400 px-1.5"
|
||||
>
|
||||
<AlertCircleIcon /> Pagamento não aprovado
|
||||
{stats?.last_attempt_succeeded === false ? (
|
||||
<Badge variant="outline" className="text-red-400 px-1.5">
|
||||
<AlertCircleIcon /> Negado
|
||||
</Badge>
|
||||
) : (
|
||||
<Status status={status} />
|
||||
@@ -402,13 +418,13 @@ function CreditCardPaymentMethod({
|
||||
{installments}x <Currency>{total / Number(installments)}</Currency>
|
||||
</p>
|
||||
|
||||
{stats.last_attempt_succeeded === false ? (
|
||||
<div className="flex justify-center mt-2">
|
||||
{stats?.last_attempt_succeeded === false && invoice?.invoice_id ? (
|
||||
<div className="lg:flex justify-center mt-2">
|
||||
<CreditCardPaymentDialog
|
||||
id={id}
|
||||
total={total}
|
||||
installments={installments}
|
||||
invoice_id={invoice_id}
|
||||
invoice_id={invoice.invoice_id}
|
||||
>
|
||||
<Button size="sm" variant="secondary" className="cursor-pointer">
|
||||
<ArrowLeftRightIcon /> Pagar com outro cartão
|
||||
@@ -433,6 +449,8 @@ function CreditCardPaymentDialog({
|
||||
invoice_id,
|
||||
total
|
||||
}) {
|
||||
const revalidator = useRevalidator()
|
||||
const [open, { set: setOpen, toggle }] = useToggle()
|
||||
const { runAsync } = useRequest(
|
||||
async ({ credit_card }) => {
|
||||
return await fetch(`/~/api/orders/${id}/payment-retries`, {
|
||||
@@ -448,13 +466,13 @@ function CreditCardPaymentDialog({
|
||||
})
|
||||
|
||||
const onSubmit = async ({ credit_card }: Schema) => {
|
||||
const r = await runAsync({ credit_card })
|
||||
console.log(r.ok)
|
||||
console.log(await r.json())
|
||||
await runAsync({ credit_card })
|
||||
revalidator.revalidate()
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<Dialog open={open} onOpenChange={toggle}>
|
||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
@@ -502,49 +520,44 @@ function PaymentAttemptsMenu({
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="ghost" className="cursor-pointer">
|
||||
<Button variant="ghost" className="cursor-pointer" size="icon-sm">
|
||||
<EllipsisIcon />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" className="w-76">
|
||||
{/* <div className="border-b p-2 text-xs text-muted-foreground font-medium">
|
||||
Transações
|
||||
</div>*/}
|
||||
<div className="p-2 space-y-1.5">
|
||||
{payment_attempts.map(
|
||||
({ sk, brand, last4, status, ...props }, index) => {
|
||||
const [, , created_at] = sk.split('#')
|
||||
{payment_attempts.map(({ sk, brand, last4, status }, index) => {
|
||||
const [, , created_at] = sk.split('#')
|
||||
|
||||
return (
|
||||
<ul key={index} className="text-sm flex gap-1.5">
|
||||
<li>
|
||||
<Kbd>
|
||||
<DateTime
|
||||
options={{
|
||||
year: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}}
|
||||
>
|
||||
{created_at}
|
||||
</DateTime>
|
||||
</Kbd>
|
||||
</li>
|
||||
<li>
|
||||
<Abbr maxLen={6}>{brand}</Abbr>
|
||||
</li>
|
||||
<li className="ml-auto">**** {last4}</li>
|
||||
<li className="flex items-center">
|
||||
{status === 'FAILED' ? (
|
||||
<CircleXIcon className="size-4 text-red-500" />
|
||||
) : (
|
||||
<CircleCheckIcon className="size-4 text-green-500" />
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
)}
|
||||
return (
|
||||
<ul key={index} className="text-sm flex gap-1.5">
|
||||
<li>
|
||||
<Kbd>
|
||||
<DateTime
|
||||
options={{
|
||||
year: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}}
|
||||
>
|
||||
{created_at}
|
||||
</DateTime>
|
||||
</Kbd>
|
||||
</li>
|
||||
<li>
|
||||
<Abbr maxLen={6}>{brand}</Abbr>
|
||||
</li>
|
||||
<li className="ml-auto">**** {last4}</li>
|
||||
<li className="flex items-center">
|
||||
{status === 'FAILED' ? (
|
||||
<CircleXIcon className="size-4 text-red-400" />
|
||||
) : (
|
||||
<CircleCheckIcon className="size-4 text-green-400" />
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
Reference in New Issue
Block a user