update payment details
This commit is contained in:
@@ -1,21 +1,40 @@
|
|||||||
import type { Route } from './+types/route'
|
import type { Route } from './+types/route'
|
||||||
|
|
||||||
import { Fragment, use, useEffect, type ReactNode } from 'react'
|
|
||||||
import { useRequest, useToggle } from 'ahooks'
|
|
||||||
import { ErrorMessage } from '@hookform/error-message'
|
import { ErrorMessage } from '@hookform/error-message'
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod'
|
||||||
|
import { useRequest, useToggle } from 'ahooks'
|
||||||
import {
|
import {
|
||||||
|
CircleQuestionMarkIcon,
|
||||||
CopyIcon,
|
CopyIcon,
|
||||||
CopyPlusIcon,
|
CopyPlusIcon,
|
||||||
Trash2Icon,
|
|
||||||
PlusIcon,
|
|
||||||
EllipsisIcon,
|
EllipsisIcon,
|
||||||
CircleQuestionMarkIcon
|
PlusIcon,
|
||||||
|
Trash2Icon
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import { redirect, Link, useParams, useFetcher } from 'react-router'
|
|
||||||
import { Controller, useFieldArray, useForm } from 'react-hook-form'
|
|
||||||
import { zodResolver } from '@hookform/resolvers/zod'
|
|
||||||
import { pick } from 'ramda'
|
import { pick } from 'ramda'
|
||||||
|
import { Fragment, use, useEffect, type ReactNode } from 'react'
|
||||||
|
import { Controller, useFieldArray, useForm } from 'react-hook-form'
|
||||||
|
import { Link, redirect, useFetcher, useParams } from 'react-router'
|
||||||
|
|
||||||
|
import { cloudflareContext } from '@repo/auth/context'
|
||||||
|
import { DateTime } from '@repo/ui/components/datetime'
|
||||||
|
import {
|
||||||
|
Breadcrumb,
|
||||||
|
BreadcrumbItem,
|
||||||
|
BreadcrumbLink,
|
||||||
|
BreadcrumbList,
|
||||||
|
BreadcrumbPage,
|
||||||
|
BreadcrumbSeparator
|
||||||
|
} from '@repo/ui/components/ui/breadcrumb'
|
||||||
|
import { Button } from '@repo/ui/components/ui/button'
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle
|
||||||
|
} from '@repo/ui/components/ui/card'
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
CommandEmpty,
|
CommandEmpty,
|
||||||
@@ -28,51 +47,32 @@ import {
|
|||||||
HoverCardContent,
|
HoverCardContent,
|
||||||
HoverCardTrigger
|
HoverCardTrigger
|
||||||
} from '@repo/ui/components/ui/hover-card'
|
} from '@repo/ui/components/ui/hover-card'
|
||||||
import {
|
|
||||||
Breadcrumb,
|
|
||||||
BreadcrumbItem,
|
|
||||||
BreadcrumbLink,
|
|
||||||
BreadcrumbList,
|
|
||||||
BreadcrumbPage,
|
|
||||||
BreadcrumbSeparator
|
|
||||||
} from '@repo/ui/components/ui/breadcrumb'
|
|
||||||
import {
|
|
||||||
Card,
|
|
||||||
CardAction,
|
|
||||||
CardContent,
|
|
||||||
CardDescription,
|
|
||||||
CardHeader,
|
|
||||||
CardTitle
|
|
||||||
} from '@repo/ui/components/ui/card'
|
|
||||||
import { DateTime } from '@repo/ui/components/datetime'
|
|
||||||
import { Spinner } from '@repo/ui/components/ui/spinner'
|
|
||||||
import { Input } from '@repo/ui/components/ui/input'
|
import { Input } from '@repo/ui/components/ui/input'
|
||||||
import { Button } from '@repo/ui/components/ui/button'
|
import { Kbd } from '@repo/ui/components/ui/kbd'
|
||||||
import { Separator } from '@repo/ui/components/ui/separator'
|
import { Label } from '@repo/ui/components/ui/label'
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger
|
PopoverTrigger
|
||||||
} from '@repo/ui/components/ui/popover'
|
} from '@repo/ui/components/ui/popover'
|
||||||
import { Kbd } from '@repo/ui/components/ui/kbd'
|
import { Separator } from '@repo/ui/components/ui/separator'
|
||||||
import { Label } from '@repo/ui/components/ui/label'
|
import { Spinner } from '@repo/ui/components/ui/spinner'
|
||||||
|
import { useIsMobile } from '@repo/ui/hooks/use-mobile'
|
||||||
import { createSearch } from '@repo/util/meili'
|
import { createSearch } from '@repo/util/meili'
|
||||||
import { HttpMethod, request as req } from '@repo/util/request'
|
import { HttpMethod, request as req } from '@repo/util/request'
|
||||||
import { useIsMobile } from '@repo/ui/hooks/use-mobile'
|
|
||||||
import { cloudflareContext } from '@repo/auth/context'
|
|
||||||
|
|
||||||
|
import { workspaceContext } from '@/middleware/workspace'
|
||||||
|
import { cn } from '@repo/ui/lib/utils'
|
||||||
|
import { CoursePicker } from './course-picker'
|
||||||
import {
|
import {
|
||||||
MAX_ITEMS,
|
|
||||||
formSchema,
|
formSchema,
|
||||||
|
MAX_ITEMS,
|
||||||
|
type Enrolled,
|
||||||
type Schema,
|
type Schema,
|
||||||
type User,
|
type User
|
||||||
type Enrolled
|
|
||||||
} from './data'
|
} from './data'
|
||||||
import { ScheduledForInput } from './scheduled-for'
|
import { ScheduledForInput } from './scheduled-for'
|
||||||
import { CoursePicker } from './course-picker'
|
|
||||||
import { UserPicker } from './user-picker'
|
import { UserPicker } from './user-picker'
|
||||||
import { cn } from '@repo/ui/lib/utils'
|
|
||||||
import { workspaceContext } from '@/middleware/workspace'
|
|
||||||
|
|
||||||
const emptyRow = {
|
const emptyRow = {
|
||||||
user: undefined,
|
user: undefined,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Fragment, useEffect } from 'react'
|
import { ErrorMessage } from '@hookform/error-message'
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod'
|
||||||
import {
|
import {
|
||||||
ArrowRightIcon,
|
ArrowRightIcon,
|
||||||
MinusIcon,
|
MinusIcon,
|
||||||
@@ -6,31 +7,30 @@ import {
|
|||||||
Trash2Icon,
|
Trash2Icon,
|
||||||
XIcon
|
XIcon
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import { useForm, useFieldArray, Controller, useWatch } from 'react-hook-form'
|
import { Fragment, useEffect } from 'react'
|
||||||
import { ErrorMessage } from '@hookform/error-message'
|
import { Controller, useFieldArray, useForm, useWatch } from 'react-hook-form'
|
||||||
import { zodResolver } from '@hookform/resolvers/zod'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
|
|
||||||
|
import { Abbr } from '@repo/ui/components/abbr'
|
||||||
|
import { Button } from '@repo/ui/components/ui/button'
|
||||||
|
import { Form } from '@repo/ui/components/ui/form'
|
||||||
import {
|
import {
|
||||||
InputGroup,
|
InputGroup,
|
||||||
InputGroupAddon,
|
InputGroupAddon,
|
||||||
InputGroupButton,
|
InputGroupButton,
|
||||||
InputGroupInput
|
InputGroupInput
|
||||||
} from '@repo/ui/components/ui/input-group'
|
} from '@repo/ui/components/ui/input-group'
|
||||||
import { Form } from '@repo/ui/components/ui/form'
|
import { Kbd } from '@repo/ui/components/ui/kbd'
|
||||||
import { Button } from '@repo/ui/components/ui/button'
|
|
||||||
import { Separator } from '@repo/ui/components/ui/separator'
|
import { Separator } from '@repo/ui/components/ui/separator'
|
||||||
import { Spinner } from '@repo/ui/components/ui/spinner'
|
import { Spinner } from '@repo/ui/components/ui/spinner'
|
||||||
import { Kbd } from '@repo/ui/components/ui/kbd'
|
|
||||||
import { Abbr } from '@repo/ui/components/abbr'
|
|
||||||
|
|
||||||
import { Cell } from '../_.$orgid.enrollments.add/route'
|
import { useWizard } from '@/components/wizard'
|
||||||
import { CoursePicker } from '../_.$orgid.enrollments.add/course-picker'
|
import { CoursePicker } from '../_.$orgid.enrollments.add/course-picker'
|
||||||
import { MAX_ITEMS, type Course } from '../_.$orgid.enrollments.add/data'
|
import { MAX_ITEMS, type Course } from '../_.$orgid.enrollments.add/data'
|
||||||
import { Discount, applyDiscount, type Coupon } from './discount'
|
import { Cell } from '../_.$orgid.enrollments.add/route'
|
||||||
import { currency } from './utils'
|
import { Discount } from './discount'
|
||||||
import { useWizard } from '@/components/wizard'
|
|
||||||
import { useWizardStore } from './store'
|
import { useWizardStore } from './store'
|
||||||
|
import { currency } from './utils'
|
||||||
|
|
||||||
const emptyRow = {
|
const emptyRow = {
|
||||||
course: undefined as any,
|
course: undefined as any,
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import { z } from 'zod'
|
|||||||
import valid from 'card-validator'
|
import valid from 'card-validator'
|
||||||
|
|
||||||
import { Currency } from '@repo/ui/components/currency'
|
import { Currency } from '@repo/ui/components/currency'
|
||||||
|
import { Kbd } from '@repo/ui/components/ui/kbd'
|
||||||
|
import { Abbr } from '@repo/ui/components/abbr'
|
||||||
import { Button } from '@repo/ui/components/ui/button'
|
import { Button } from '@repo/ui/components/ui/button'
|
||||||
import { Separator } from '@repo/ui/components/ui/separator'
|
import { Separator } from '@repo/ui/components/ui/separator'
|
||||||
import { Spinner } from '@repo/ui/components/ui/spinner'
|
import { Spinner } from '@repo/ui/components/ui/spinner'
|
||||||
@@ -73,7 +75,7 @@ type ReviewProps = {
|
|||||||
|
|
||||||
export function Review({ onSubmit }: ReviewProps) {
|
export function Review({ onSubmit }: ReviewProps) {
|
||||||
const wizard = useWizard()
|
const wizard = useWizard()
|
||||||
const { items, summary, address } = useWizardStore()
|
const { items, summary, address, coupon } = useWizardStore()
|
||||||
const { subtotal, discount, interest_amount, total } = summary()
|
const { subtotal, discount, interest_amount, total } = summary()
|
||||||
const [loading, { set }] = useToggle()
|
const [loading, { set }] = useToggle()
|
||||||
|
|
||||||
@@ -127,8 +129,15 @@ export function Review({ onSubmit }: ReviewProps) {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
{/* Discount */}
|
{/* Discount */}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className="text-right" colSpan={3}>
|
<TableCell colSpan={3}>
|
||||||
|
<span className="flex gap-1 justify-end">
|
||||||
Descontos
|
Descontos
|
||||||
|
{coupon && (
|
||||||
|
<Kbd>
|
||||||
|
<Abbr maxLen={8}>{coupon.code}</Abbr>
|
||||||
|
</Kbd>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Currency>{discount}</Currency>
|
<Currency>{discount}</Currency>
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import type { Route } from './+types/route'
|
import type { Route } from './+types/route'
|
||||||
|
|
||||||
import { formatCEP } from '@brazilian-utils/brazilian-utils'
|
import { formatCEP } from '@brazilian-utils/brazilian-utils'
|
||||||
import { CalendarClockIcon, CalendarIcon, UserIcon } from 'lucide-react'
|
import {
|
||||||
|
AlertCircleIcon,
|
||||||
|
ArrowLeftRightIcon,
|
||||||
|
HelpCircleIcon
|
||||||
|
} from 'lucide-react'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { Link } from 'react-router'
|
import { Link } from 'react-router'
|
||||||
|
|
||||||
import { Currency } from '@repo/ui/components/currency'
|
import { Currency } from '@repo/ui/components/currency'
|
||||||
import { DateTime } from '@repo/ui/components/datetime'
|
|
||||||
import {
|
import {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
BreadcrumbItem,
|
BreadcrumbItem,
|
||||||
@@ -18,15 +21,12 @@ import {
|
|||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardDescription,
|
|
||||||
CardFooter,
|
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle
|
CardTitle
|
||||||
} from '@repo/ui/components/ui/card'
|
} from '@repo/ui/components/ui/card'
|
||||||
import {
|
import {
|
||||||
Item,
|
Item,
|
||||||
ItemContent,
|
ItemContent,
|
||||||
ItemDescription,
|
|
||||||
ItemGroup,
|
ItemGroup,
|
||||||
ItemTitle
|
ItemTitle
|
||||||
} from '@repo/ui/components/ui/item'
|
} from '@repo/ui/components/ui/item'
|
||||||
@@ -39,8 +39,21 @@ import {
|
|||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow
|
TableRow
|
||||||
} from '@repo/ui/components/ui/table'
|
} from '@repo/ui/components/ui/table'
|
||||||
import { paymentMethods } from '@repo/ui/routes/orders/data'
|
|
||||||
import { request as req } from '@repo/util/request'
|
import { request as req } from '@repo/util/request'
|
||||||
|
|
||||||
|
import { Abbr } from '@repo/ui/components/abbr'
|
||||||
|
import { Badge } from '@repo/ui/components/ui/badge'
|
||||||
|
import { Button } from '@repo/ui/components/ui/button'
|
||||||
|
import { Kbd } from '@repo/ui/components/ui/kbd'
|
||||||
|
import { cn } from '@repo/ui/lib/utils'
|
||||||
|
import {
|
||||||
|
labels,
|
||||||
|
statuses,
|
||||||
|
type Order as Order_
|
||||||
|
} from '@repo/ui/routes/orders/data'
|
||||||
|
|
||||||
|
import type { CreditCard as CreditCard_ } from '../_.$orgid.enrollments.buy/payment'
|
||||||
|
import type { Address } from '../_.$orgid.enrollments.buy/review'
|
||||||
import { useWizardStore } from '../_.$orgid.enrollments.buy/store'
|
import { useWizardStore } from '../_.$orgid.enrollments.buy/store'
|
||||||
|
|
||||||
export function meta() {
|
export function meta() {
|
||||||
@@ -51,12 +64,44 @@ export function meta() {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PaymentMethodComponent = {
|
||||||
|
PIX: Pix,
|
||||||
|
BANK_SLIP: BankSlip,
|
||||||
|
CREDIT_CARD: CreditCard
|
||||||
|
}
|
||||||
|
|
||||||
|
type Item_ = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
unit_price: number
|
||||||
|
quantity: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type User = {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Order = Order_ & {
|
||||||
|
items: Item_[]
|
||||||
|
interest_amount: number
|
||||||
|
due_date: string
|
||||||
|
created_at: string
|
||||||
|
subtotal: number
|
||||||
|
discount: number
|
||||||
|
address: Address
|
||||||
|
credit_card?: CreditCard_
|
||||||
|
coupon?: string
|
||||||
|
installments?: number
|
||||||
|
created_by?: User
|
||||||
|
}
|
||||||
|
|
||||||
export async function loader({ context, request, params }: Route.LoaderArgs) {
|
export async function loader({ context, request, params }: Route.LoaderArgs) {
|
||||||
const order = await req({
|
const order = (await req({
|
||||||
url: `/orders/${params.id}`,
|
url: `/orders/${params.id}`,
|
||||||
context,
|
context,
|
||||||
request
|
request
|
||||||
}).then((r) => r.json())
|
}).then((r) => r.json())) as Order
|
||||||
|
|
||||||
return { order }
|
return { order }
|
||||||
}
|
}
|
||||||
@@ -64,22 +109,18 @@ export async function loader({ context, request, params }: Route.LoaderArgs) {
|
|||||||
export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
||||||
const { reset } = useWizardStore()
|
const { reset } = useWizardStore()
|
||||||
const {
|
const {
|
||||||
status,
|
coupon,
|
||||||
address,
|
address,
|
||||||
total,
|
total,
|
||||||
credit_card,
|
|
||||||
payment_method,
|
payment_method,
|
||||||
due_date,
|
|
||||||
created_at,
|
|
||||||
invoice,
|
|
||||||
installments,
|
|
||||||
interest_amount,
|
interest_amount,
|
||||||
discount,
|
discount,
|
||||||
subtotal,
|
subtotal,
|
||||||
items = [],
|
items = []
|
||||||
created_by
|
|
||||||
} = order
|
} = order
|
||||||
|
|
||||||
|
const Component = PaymentMethodComponent[payment_method]
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
reset()
|
reset()
|
||||||
}, [])
|
}, [])
|
||||||
@@ -103,14 +144,6 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
|||||||
<Card className="lg:max-w-4xl mx-auto">
|
<Card className="lg:max-w-4xl mx-auto">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="text-2xl">Detalhes do pagamento</CardTitle>
|
<CardTitle className="text-2xl">Detalhes do pagamento</CardTitle>
|
||||||
{status}
|
|
||||||
<CardDescription>
|
|
||||||
<ul className="flex gap-2.5 *:flex *:gap-1 *:items-center [&_svg]:size-3.5">
|
|
||||||
<li>
|
|
||||||
<CalendarClockIcon /> <DateTime>{due_date}</DateTime>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
@@ -134,26 +167,12 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
|||||||
<Item variant="outline" className="items-start">
|
<Item variant="outline" className="items-start">
|
||||||
<ItemContent>
|
<ItemContent>
|
||||||
<ItemTitle>Forma de pagamento</ItemTitle>
|
<ItemTitle>Forma de pagamento</ItemTitle>
|
||||||
<ItemDescription>
|
<div className="text-muted-foreground text-sm leading-normal font-normal text-balance">
|
||||||
{credit_card ? (
|
{Component && <Component {...order} />}
|
||||||
<>
|
</div>
|
||||||
{credit_card.brand} (Crédito) **** {credit_card.last4}
|
|
||||||
<br />
|
|
||||||
{installments}x{' '}
|
|
||||||
<Currency>{total / Number(installments)}</Currency>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{payment_method
|
|
||||||
? paymentMethods[payment_method]
|
|
||||||
: payment_method}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ItemDescription>
|
|
||||||
</ItemContent>
|
</ItemContent>
|
||||||
</Item>
|
</Item>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
{/*<pre>{JSON.stringify(order, null, 2)}</pre>*/}
|
|
||||||
|
|
||||||
<Table className="pointer-events-none">
|
<Table className="pointer-events-none">
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
@@ -193,8 +212,15 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
{/* Discount */}
|
{/* Discount */}
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell className="text-right" colSpan={3}>
|
<TableCell colSpan={3}>
|
||||||
|
<span className="flex gap-1 justify-end">
|
||||||
Descontos
|
Descontos
|
||||||
|
{coupon && (
|
||||||
|
<Kbd>
|
||||||
|
<Abbr maxLen={8}>{coupon}</Abbr>
|
||||||
|
</Kbd>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Currency>{discount}</Currency>
|
<Currency>{discount}</Currency>
|
||||||
@@ -225,18 +251,93 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
|
|||||||
</TableFooter>
|
</TableFooter>
|
||||||
</Table>
|
</Table>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
||||||
{/* <CardFooter>
|
|
||||||
<ul className="flex gap-2.5 *:flex *:gap-1 *:items-center [&_svg]:size-3.5">
|
|
||||||
<li>
|
|
||||||
<CalendarIcon /> <DateTime>{created_at}</DateTime>
|
|
||||||
</li>{' '}
|
|
||||||
<li>
|
|
||||||
<UserIcon /> {created_by.name}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</CardFooter>*/}
|
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
{/*<pre>{JSON.stringify(order, null, 2)}</pre>*/}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Status({ status: s }: { status: string }) {
|
||||||
|
const status = labels[s] ?? s
|
||||||
|
const { icon: Icon, color } = statuses?.[s] ?? { icon: HelpCircleIcon }
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Badge variant="outline" className={cn(color, ' px-1.5')}>
|
||||||
|
<Icon className={cn('stroke-2', color)} />
|
||||||
|
{status}
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PaymentMethodProps = {
|
||||||
|
status: string
|
||||||
|
total: number
|
||||||
|
installments: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreditCardProps = PaymentMethodProps & {
|
||||||
|
stats: { last_attempt_succeeded: boolean }
|
||||||
|
credit_card: { last4: string; brand: string }
|
||||||
|
}
|
||||||
|
|
||||||
|
function CreditCard({
|
||||||
|
status,
|
||||||
|
total,
|
||||||
|
credit_card,
|
||||||
|
installments,
|
||||||
|
stats
|
||||||
|
}: CreditCardProps) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ul className="flex max-lg:flex-col gap-x-1.5">
|
||||||
|
<li>
|
||||||
|
{credit_card.brand} (Crédito) **** {credit_card.last4}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{!stats.last_attempt_succeeded ? (
|
||||||
|
<Badge
|
||||||
|
variant="outline"
|
||||||
|
className="text-red-400 border-red-400 px-1.5"
|
||||||
|
>
|
||||||
|
<AlertCircleIcon /> Transação negada
|
||||||
|
</Badge>
|
||||||
|
) : (
|
||||||
|
<Status status={status} />
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
{installments}x <Currency>{total / Number(installments)}</Currency>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{!stats.last_attempt_succeeded ? (
|
||||||
|
<div className="flex justify-center mt-2">
|
||||||
|
<Button size="sm" variant="secondary" className="cursor-pointer">
|
||||||
|
<ArrowLeftRightIcon /> Tentar com outro cartão
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BankSlipProps = PaymentMethodProps & {}
|
||||||
|
|
||||||
|
function BankSlip({ status }: BankSlipProps) {
|
||||||
|
return (
|
||||||
|
<ul className="flex max-lg:flex-col gap-x-1.5">
|
||||||
|
<li>Boleto bancário</li>
|
||||||
|
<li>
|
||||||
|
<Status status={status} />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type PixProps = PaymentMethodProps & {}
|
||||||
|
|
||||||
|
function Pix({}: PixProps) {
|
||||||
|
return <>Pix</>
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
import { type ColumnDef } from '@tanstack/react-table'
|
import { type ColumnDef } from '@tanstack/react-table'
|
||||||
|
|
||||||
import {
|
// import {
|
||||||
DataTableColumnHeaderSelect,
|
// DataTableColumnHeaderSelect,
|
||||||
DataTableColumnSelect
|
// DataTableColumnSelect
|
||||||
} from '@repo/ui/components/data-table'
|
// } from '@repo/ui/components/data-table'
|
||||||
import { columns as columns_, type Order } from '@repo/ui/routes/orders/columns'
|
import { columns as columns_, type Order } from '@repo/ui/routes/orders/columns'
|
||||||
|
|
||||||
export type { Order }
|
export type { Order }
|
||||||
|
|||||||
@@ -44,21 +44,6 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
with dyn.transact_writer() as transact:
|
with dyn.transact_writer() as transact:
|
||||||
transact.delete(key=KeyPair(order_id, 'TRANSACTION'))
|
|
||||||
transact.update(
|
|
||||||
key=KeyPair(order_id, 'TRANSACTION#STATS'),
|
|
||||||
update_expr='SET #count = if_not_exists(#count, :zero) + :one, \
|
|
||||||
updated_at = :now',
|
|
||||||
expr_attr_names={
|
|
||||||
'#count': 'payment_attempts',
|
|
||||||
},
|
|
||||||
expr_attr_values={
|
|
||||||
':zero': 0,
|
|
||||||
':one': 1,
|
|
||||||
':now': now(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if charge['success'] is True:
|
if charge['success'] is True:
|
||||||
transact.update(
|
transact.update(
|
||||||
key=KeyPair(order_id, '0'),
|
key=KeyPair(order_id, '0'),
|
||||||
@@ -97,4 +82,21 @@ def lambda_handler(event: EventBridgeEvent, context: LambdaContext) -> bool:
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
transact.delete(key=KeyPair(order_id, 'TRANSACTION'))
|
||||||
|
transact.update(
|
||||||
|
key=KeyPair(order_id, 'TRANSACTION#STATS'),
|
||||||
|
update_expr='SET #count = if_not_exists(#count, :zero) + :one, \
|
||||||
|
last_attempt_succeeded = :succeeded, \
|
||||||
|
updated_at = :now',
|
||||||
|
expr_attr_names={
|
||||||
|
'#count': 'payment_attempts',
|
||||||
|
},
|
||||||
|
expr_attr_values={
|
||||||
|
':succeeded': charge['success'],
|
||||||
|
':zero': 0,
|
||||||
|
':one': 1,
|
||||||
|
':now': now(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
return charge['success']
|
return charge['success']
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DataTableColumnDatetime,
|
|
||||||
DataTableColumnCurrency,
|
DataTableColumnCurrency,
|
||||||
|
DataTableColumnDatetime,
|
||||||
DataTableColumnHeaderSort
|
DataTableColumnHeaderSort
|
||||||
} from '@repo/ui/components/data-table'
|
} from '@repo/ui/components/data-table'
|
||||||
import { type ColumnDef } from '@tanstack/react-table'
|
import { type ColumnDef } from '@tanstack/react-table'
|
||||||
import { HelpCircleIcon } from 'lucide-react'
|
import { HelpCircleIcon } from 'lucide-react'
|
||||||
|
|
||||||
import { cn } from '@repo/ui/lib/utils'
|
|
||||||
import { Badge } from '@repo/ui/components/ui/badge'
|
import { Badge } from '@repo/ui/components/ui/badge'
|
||||||
|
import { cn } from '@repo/ui/lib/utils'
|
||||||
|
|
||||||
import { labels, paymentMethods, statuses, type Order } from './data'
|
import { labels, paymentMethods, statuses, type Order } from './data'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user