From 1a59ad9e91d61d6920a6eabeccc581d52cc0b048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Tue, 23 Dec 2025 20:23:43 -0300 Subject: [PATCH] update billing --- .../routes/_.$orgid.billing._index/route.tsx | 36 ++++- .../app/routes/_.$orgid.checkout/assigned.tsx | 115 ++++++++++++++-- .../app/routes/_.$orgid.checkout/bulk.tsx | 128 +++++++++++++++--- .../routes/_.$orgid.enrollments.add/data.ts | 3 +- .../routes/_.$orgid.enrollments.add/route.tsx | 26 ++-- 5 files changed, 254 insertions(+), 54 deletions(-) diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx index d60ae10..c253e8d 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.billing._index/route.tsx @@ -169,10 +169,10 @@ function List({ items, search }) { }, [search, fuse, items]) const charges = filtered - ?.filter((item) => 'course' in item && item?.unit_price > 0) + ?.filter((item) => item?.unit_price > 0) ?.sort(sortBy('enrolled_at')) const credits = filtered - ?.filter((item) => 'course' in item && item?.unit_price < 0) + ?.filter((item) => item?.unit_price < 0) ?.sort(sortBy('created_at')) if (items.length === 0) { @@ -207,6 +207,16 @@ function List({ items, search }) { ) } + const subtotal = filtered + ?.filter(({ unit_price }) => unit_price > 0) + ?.reduce((acc, { unit_price }) => acc + unit_price, 0) + + const discounts = filtered + ?.filter(({ unit_price }) => unit_price < 0) + ?.reduce((acc, { unit_price }) => acc + unit_price, 0) + + const total = filtered?.reduce((acc, { unit_price }) => acc + unit_price, 0) + return ( {charges.length ? ( @@ -288,16 +298,28 @@ function List({ items, search }) { ) : null} + + + Subtotal + + + {subtotal} + + + + + Descontos + + + {discounts} + + Total - - {filtered - ?.filter((x) => 'course' in x) - ?.reduce((acc, { unit_price }) => acc + unit_price, 0)} - + {total} diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/assigned.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/assigned.tsx index 3f98116..10a2fb7 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/assigned.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/assigned.tsx @@ -6,7 +6,11 @@ import { ErrorMessage } from '@hookform/error-message' import { zodResolver } from '@hookform/resolvers/zod' import { Form } from '@repo/ui/components/ui/form' -import { InputGroup, InputGroupInput } from '@repo/ui/components/ui/input-group' +import { + InputGroup, + InputGroupAddon, + InputGroupInput +} from '@repo/ui/components/ui/input-group' import { Button } from '@repo/ui/components/ui/button' import { Separator } from '@repo/ui/components/ui/separator' import { @@ -17,6 +21,7 @@ import { import { MAX_ITEMS, + formSchema, type Course, type User } from '../_.$orgid.enrollments.add/data' @@ -39,11 +44,11 @@ type AssignedProps = { export function Assigned({ courses }: AssignedProps) { const { orgid } = useParams() const form = useForm({ - // resolver: zodResolver(formSchema), + resolver: zodResolver(formSchema), defaultValues: { enrollments: [emptyRow] } }) const { formState, control, handleSubmit } = form - const { fields, insert, remove, append } = useFieldArray({ + const { fields, remove, append } = useFieldArray({ control, name: 'enrollments' }) @@ -51,6 +56,10 @@ export function Assigned({ courses }: AssignedProps) { control, name: 'enrollments' }) + const subtotal = items.reduce( + (acc, { course }) => acc + (course?.unit_price || 0), + 0 + ) const onSearch = async (search: string) => { const params = new URLSearchParams({ q: search }) @@ -108,6 +117,7 @@ export function Assigned({ courses }: AssignedProps) { {/* Separator only for mobile */} {index >= 1 &&
} + {/* User */} + {/* Course */} + {/* Scheduled for */} + {/* Unit price */} + + Valor unit. + + + {/* Action */} + {/* Add button */} +
+ +
+ + {/* Subtotal */} + <> +
+ Subtotal +
+ + + + Subtotal + + + + + + {/* Discount */} + <> +
+ Cupom +
+ + + Cupom + + + + + + + + + {/* Total */} + <> +
+ Total +
+ + + Total + + + + + diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/bulk.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/bulk.tsx index ee1e542..041770b 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/bulk.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.checkout/bulk.tsx @@ -5,14 +5,15 @@ import { ErrorMessage } from '@hookform/error-message' import { zodResolver } from '@hookform/resolvers/zod' import { z } from 'zod' -import { Form } from '@repo/ui/components/ui/form' -import { Button } from '@repo/ui/components/ui/button' import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from '@repo/ui/components/ui/input-group' +import { Input } from '@repo/ui/components/ui/input' +import { Form } from '@repo/ui/components/ui/form' +import { Button } from '@repo/ui/components/ui/button' import { Separator } from '@repo/ui/components/ui/separator' import { Cell } from '../_.$orgid.enrollments.add/route' @@ -70,6 +71,13 @@ export function Bulk({ courses }: BulkProps) { control, name: 'items' }) + const subtotal = items.reduce( + (acc, { course, quantity }) => + acc + + (course?.unit_price || 0) * + (Number.isFinite(quantity) && quantity > 0 ? quantity : 1), + 0 + ) const onSubmit = async (data: Schema) => { console.log(data) @@ -98,6 +106,7 @@ export function Bulk({ courses }: BulkProps) { {/* Separator only for mobile */} {index >= 1 &&
} + {/* Course */} + {/* Quantity */} + + Qtd. + + + {/* Unit price */} + + Valor unit. + + {/* Total */} + + Total + + + {/* Action */} + {/* Add button */} +
+ +
+ + {/* Subtotal */} + <> +
+ Subtotal +
+ + + + Subtotal + + + + + + {/* Discount */} + <> +
+ Cupom +
+ + + Cupom + + + + + + + + + {/* Total */} + <> +
+ Total +
+ + + Total + + + + + diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/data.ts b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/data.ts index a0af187..4c2d29d 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/data.ts +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/data.ts @@ -20,7 +20,8 @@ export const enrollment = z.object({ { id: z.string(), name: z.string(), - access_period: z.number() + access_period: z.number(), + unit_price: z.number().optional() }, { error: 'Escolha um curso' } ) diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx index 50aed52..6514ec0 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/route.tsx @@ -349,19 +349,21 @@ export default function Route({ ))} - - +
+ +
+