reditect to order

This commit is contained in:
2026-01-14 21:08:23 -03:00
parent d893114e38
commit a3e4fe887d
22 changed files with 1105 additions and 1157 deletions

View File

@@ -1,15 +1,15 @@
import { useSearchParams } from 'react-router'
import { ChevronRightIcon, ChevronLeftIcon } from 'lucide-react'
import { subMonths, addMonths } from 'date-fns'
import { addMonths, subMonths } from 'date-fns'
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { DateTime as LuxonDateTime } from 'luxon'
import { useSearchParams } from 'react-router'
import { TZ } from '@/conf'
import { DateTime } from '@repo/ui/components/datetime'
import { Badge } from '@repo/ui/components/ui/badge'
import { Button } from '@repo/ui/components/ui/button'
import { ButtonGroup } from '@repo/ui/components/ui/button-group'
import { Badge } from '@repo/ui/components/ui/badge'
import { DateTime } from '@repo/ui/components/datetime'
import { formatDate, billingPeriod } from './util'
import { billingPeriod, formatDate } from './util'
type RangePeriodProps = {
startDate: Date

View File

@@ -1,15 +1,26 @@
import type { Route } from './+types/route'
import Fuse from 'fuse.js'
import { BanIcon } from 'lucide-react'
import { DateTime as LuxonDateTime } from 'luxon'
import { Suspense, useMemo } from 'react'
import { BanIcon } from 'lucide-react'
import { Await, useSearchParams } from 'react-router'
import { cn } from '@repo/ui/lib/utils'
import { request as req } from '@repo/util/request'
import { Abbr } from '@repo/ui/components/abbr'
import { Currency } from '@repo/ui/components/currency'
import { DateTime } from '@repo/ui/components/datetime'
import { SearchForm } from '@repo/ui/components/search-form'
import { Skeleton } from '@repo/ui/components/skeleton'
import { Button } from '@repo/ui/components/ui/button'
import { Card, CardContent } from '@repo/ui/components/ui/card'
import {
Empty,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle
} from '@repo/ui/components/ui/empty'
import { Kbd } from '@repo/ui/components/ui/kbd'
import {
Table,
TableBody,
@@ -19,24 +30,13 @@ import {
TableHeader,
TableRow
} from '@repo/ui/components/ui/table'
import { Abbr } from '@repo/ui/components/abbr'
import { Button } from '@repo/ui/components/ui/button'
import { SearchForm } from '@repo/ui/components/search-form'
import {
Empty,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle
} from '@repo/ui/components/ui/empty'
import { Kbd } from '@repo/ui/components/ui/kbd'
import { Currency } from '@repo/ui/components/currency'
import { DateTime } from '@repo/ui/components/datetime'
import { cn } from '@repo/ui/lib/utils'
import { request as req } from '@repo/util/request'
import { TZ } from '@/conf'
import { billingPeriod, formatDate } from './util'
import { RangePeriod } from './range-period'
import { statuses } from './data'
import { RangePeriod } from './range-period'
import { billingPeriod, formatDate } from './util'
export function meta({}) {
return [{ title: 'Resumo de cobranças' }]

View File

@@ -2,27 +2,36 @@ import type { Route } from './+types/route'
import {
AlertCircleIcon,
BanIcon,
CalendarIcon,
CheckCircle2Icon,
ClockIcon,
CalendarIcon,
UserIcon,
BanIcon,
PlusIcon,
EllipsisIcon,
RotateCcw
PlusIcon,
RotateCcw,
UserIcon
} from 'lucide-react'
import { Link, useParams } from 'react-router'
import { Suspense } from 'react'
import { DateTime as LuxonDateTime } from 'luxon'
import { Suspense } from 'react'
import { Link, useParams } from 'react-router'
import { Abbr } from '@repo/ui/components/abbr'
import { DateTime } from '@repo/ui/components/datetime'
import { Skeleton } from '@repo/ui/components/skeleton'
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle
} from '@repo/ui/components/ui/empty'
Alert,
AlertDescription,
AlertTitle
} from '@repo/ui/components/ui/alert'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator
} from '@repo/ui/components/ui/breadcrumb'
import { Button } from '@repo/ui/components/ui/button'
import {
Card,
CardContent,
@@ -31,31 +40,22 @@ import {
CardHeader,
CardTitle
} from '@repo/ui/components/ui/card'
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator
} from '@repo/ui/components/ui/breadcrumb'
import {
Alert,
AlertDescription,
AlertTitle
} from '@repo/ui/components/ui/alert'
import { request as req } from '@repo/util/request'
import { Skeleton } from '@repo/ui/components/skeleton'
import { Await } from 'react-router'
import { Abbr } from '@repo/ui/components/abbr'
import { Button } from '@repo/ui/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger
} from '@repo/ui/components/ui/dropdown-menu'
import { DateTime } from '@repo/ui/components/datetime'
import {
Empty,
EmptyContent,
EmptyDescription,
EmptyHeader,
EmptyMedia,
EmptyTitle
} from '@repo/ui/components/ui/empty'
import { request as req } from '@repo/util/request'
import { Await } from 'react-router'
export function meta({}: Route.MetaArgs) {
return [{ title: 'Relatório de matrículas' }]
@@ -69,9 +69,7 @@ export async function loader({ context, request, params }: Route.LoaderArgs) {
request
}).then((r) => r.json())
return {
submission
}
return { submission }
}
export default function Route({

View File

@@ -1,17 +1,12 @@
import type { Route } from './+types/route'
import { useEffect, useState } from 'react'
import { useFetcher, Link } from 'react-router'
import { useMount } from 'ahooks'
import { BookSearchIcon, CircleCheckBigIcon, WalletIcon } from 'lucide-react'
import { use, useEffect, useState } from 'react'
import { Link, redirect, useFetcher } from 'react-router'
import {
Card,
CardContent,
CardHeader,
CardDescription,
CardTitle
} from '@repo/ui/components/ui/card'
import { cloudflareContext, userContext } from '@repo/auth/context'
import { Skeleton } from '@repo/ui/components/skeleton'
import {
Breadcrumb,
BreadcrumbItem,
@@ -20,22 +15,27 @@ import {
BreadcrumbPage,
BreadcrumbSeparator
} from '@repo/ui/components/ui/breadcrumb'
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle
} from '@repo/ui/components/ui/card'
import { Label } from '@repo/ui/components/ui/label'
import { Switch } from '@repo/ui/components/ui/switch'
import { createSearch } from '@repo/util/meili'
import { cloudflareContext, userContext } from '@repo/auth/context'
import { Label } from '@repo/ui/components/ui/label'
import { Skeleton } from '@repo/ui/components/skeleton'
import { request as req, HttpMethod } from '@repo/util/request'
import { HttpMethod, request as req } from '@repo/util/request'
import { INTERNAL_EMAIL_DOMAIN } from '@/conf'
import { workspaceContext } from '@/middleware/workspace'
import { useWorksapce } from '@/components/workspace-switcher'
import { Step, StepItem, StepSeparator } from '@/components/step'
import { Wizard, WizardStep } from '@/components/wizard'
import { useWorksapce } from '@/components/workspace-switcher'
import { INTERNAL_EMAIL_DOMAIN } from '@/conf'
import { workspaceContext } from '@/middleware/workspace'
import type { Course } from '../_.$orgid.enrollments.add/data'
import { Assigned } from './assigned'
import { Bulk } from './bulk'
import { Payment } from './payment'
import { Assigned } from './assigned'
import { Review } from './review'
import { useWizardStore } from './store'
@@ -43,7 +43,7 @@ export function meta({}: Route.MetaArgs) {
return [{ title: 'Comprar matrículas' }]
}
export async function loader({ context }: Route.LoaderArgs) {
export async function loader({ context, params, request }: Route.LoaderArgs) {
const cloudflare = context.get(cloudflareContext)
const courses = createSearch<Course>({
index: 'saladeaula_courses',
@@ -53,10 +53,16 @@ export async function loader({ context }: Route.LoaderArgs) {
env: cloudflare.env
})
return { courses }
const seats = req({
url: `/orgs/${params.orgid}/seats`,
request,
context
}).then((r) => r.json() as any)
return { courses, seats }
}
export async function action({ params, request, context }: Route.ActionArgs) {
export async function action({ request, context }: Route.ActionArgs) {
const body = (await request.json()) as object
const user = context.get(userContext)!
const { activeWorkspace } = context.get(workspaceContext)
@@ -83,13 +89,12 @@ export async function action({ params, request, context }: Route.ActionArgs) {
return { ok: false, error }
}
console.log(await r.json())
return { ok: true }
const { id } = (await r.json()) as { id: string }
throw redirect(`../payments/${id}`)
}
export default function Route({
loaderData: { courses }
loaderData: { courses, seats: seats_ }
}: Route.ComponentProps) {
const fetcher = useFetcher()
const [mounted, setMounted] = useState(false)
@@ -97,6 +102,9 @@ export default function Route({
const { index, kind, setIndex, setKind, reset, update, ...state } =
useWizardStore()
// @TODO
const seats = use(seats_)
const onSubmit = async () => {
const items = state.items.map(({ course, quantity }) => ({
...course,
@@ -119,14 +127,12 @@ export default function Route({
}
}, [address])
useEffect(() => {
console.log(fetcher.data)
}, [fetcher.data])
if (!mounted) {
return <Skeleton />
}
console.log(seats)
return (
<div className="space-y-2.5">
<Breadcrumb>

View File

@@ -1,8 +1,11 @@
import type { Route } from './+types/route'
import { Link } from 'react-router'
import { formatCEP } from '@brazilian-utils/brazilian-utils'
import { Suspense, useEffect } from 'react'
import { Await, Link } from 'react-router'
import { request as req } from '@repo/util/request'
import { Currency } from '@repo/ui/components/currency'
import { Skeleton } from '@repo/ui/components/skeleton'
import {
Breadcrumb,
BreadcrumbItem,
@@ -11,6 +14,22 @@ import {
BreadcrumbPage,
BreadcrumbSeparator
} from '@repo/ui/components/ui/breadcrumb'
import {
Card,
CardContent,
CardHeader,
CardTitle
} from '@repo/ui/components/ui/card'
import {
Item,
ItemContent,
ItemDescription,
ItemGroup,
ItemTitle
} from '@repo/ui/components/ui/item'
import { paymentMethods } from '@repo/ui/routes/orders/data'
import { request as req } from '@repo/util/request'
import { useWizardStore } from '../_.$orgid.enrollments.buy/store'
export function meta() {
return [
@@ -20,28 +39,32 @@ export function meta() {
]
}
export async function loader({ params, request, context }: Route.LoaderArgs) {
const r = await req({
export async function loader({ context, request, params }: Route.LoaderArgs) {
const order = await req({
url: `/orders/${params.id}`,
request,
context
})
context,
request
}).then((r) => r.json())
if (!r.ok) {
throw new Response(null, { status: r.status })
}
return { order: await r.json() }
return { order }
}
export default function Route({ loaderData: { order } }: Route.ComponentProps) {
const { reset } = useWizardStore()
const { address, total, credit_card, payment_method, invoice, installments } =
order
useEffect(() => {
reset()
}, [])
return (
<div className="space-y-2.5">
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link to="../payments">Histórico de pagamentos</Link>
<Link to="../payments">Pagamentos</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
@@ -50,7 +73,55 @@ export default function Route({ loaderData: { order } }: Route.ComponentProps) {
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
<pre>{JSON.stringify(order, null, 2)}</pre>
<Card className="lg:max-w-4xl mx-auto space-y-2.5">
<CardHeader>
<CardTitle className="text-2xl">Detalhes do pagamento</CardTitle>
</CardHeader>
<CardContent>
<ItemGroup className="grid lg:grid-cols-2 gap-4">
<Item variant="outline">
<ItemContent>
<ItemTitle>Endereço de cobrança</ItemTitle>
<ul className="text-muted-foreground text-sm leading-normal font-normal text-balance">
{address?.address1}
{address?.address2 ? <>, {address?.address2}</> : null}
<br />
{address?.neighborhood}
<br />
{address?.city}, {address?.state}
<br />
{formatCEP(address?.postcode)}
</ul>
</ItemContent>
</Item>
<Item variant="outline" className="items-start">
<ItemContent>
<ItemTitle>Forma de pagamento</ItemTitle>
<ItemDescription>
{credit_card ? (
<>
{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>
</Item>
</ItemGroup>
{/*<pre>{JSON.stringify(order, null, 2)}</pre>*/}
</CardContent>
</Card>
</div>
)
}