From 3cdded360fa9ccb4df7f339d89f2a72b1de19102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Rafael=20Siqueira?= Date: Fri, 26 Dec 2025 11:19:14 -0300 Subject: [PATCH] update items --- .../routes/_.$orgid.enrollments.add/data.ts | 2 + .../routes/_.$orgid.enrollments.add/route.tsx | 2 +- .../scheduled-for.tsx | 15 +- .../_.$orgid.enrollments.add/user-picker.tsx | 13 +- .../_.$orgid.enrollments.buy/assigned.tsx | 25 +- .../routes/_.$orgid.enrollments.buy/bulk.tsx | 2 +- .../_.$orgid.enrollments.buy/payment.tsx | 101 ++++++- .../components/data-table/view-options.tsx | 4 +- packages/ui/src/components/nav-user.tsx | 4 +- packages/ui/src/components/ui/field.tsx | 248 ++++++++++++++++++ packages/ui/src/components/ui/label.tsx | 2 + 11 files changed, 392 insertions(+), 26 deletions(-) create mode 100644 packages/ui/src/components/ui/field.tsx 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 4c2d29d..8ab80b3 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 @@ -43,6 +43,8 @@ export const formSchema = z.object({ export type Schema = z.infer +export type Enrollment = z.infer + export type User = { id: string name: string 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 666607d..52274df 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 @@ -213,7 +213,7 @@ export default function Route({ -
+
{/* Header */} <> Colaborador diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/scheduled-for.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/scheduled-for.tsx index fa1b600..ae60c9b 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/scheduled-for.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/scheduled-for.tsx @@ -5,11 +5,11 @@ import { useToggle } from 'ahooks' import { format } from 'date-fns' import { ptBR } from 'react-day-picker/locale' -import { Button } from '@repo/ui/components/ui/button' import { Calendar } from '@repo/ui/components/ui/calendar' import { InputGroup, InputGroupAddon, + InputGroupButton, InputGroupInput } from '@repo/ui/components/ui/input-group' import { @@ -46,11 +46,12 @@ export function ScheduledForInput({ value, onChange }: ScheduledForInputProps) { {selected && ( - - + )} diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/user-picker.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/user-picker.tsx index d056f83..e768a29 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/user-picker.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.add/user-picker.tsx @@ -3,13 +3,13 @@ import { XIcon, CheckIcon, AlertTriangleIcon, UserIcon } from 'lucide-react' import { formatCPF } from '@brazilian-utils/brazilian-utils' import { cn, initials } from '@repo/ui/lib/utils' -import { Button } from '@repo/ui/components/ui/button' import { Avatar, AvatarFallback } from '@repo/ui/components/ui/avatar' import { Abbr } from '@repo/ui/components/abbr' import { Spinner } from '@repo/ui/components/ui/spinner' import { InputGroup, InputGroupAddon, + InputGroupButton, InputGroupInput } from '@repo/ui/components/ui/input-group' import { CommandItem } from '@repo/ui/components/ui/command' @@ -100,17 +100,18 @@ export function UserPicker({ {value && ( - + )} diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/assigned.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/assigned.tsx index 0705fed..e065416 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/assigned.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/assigned.tsx @@ -30,6 +30,7 @@ import { import { MAX_ITEMS, formSchema, + type Enrollment, type Course, type User } from '../_.$orgid.enrollments.add/data' @@ -38,7 +39,6 @@ import { Cell } from '../_.$orgid.enrollments.add/route' import { CoursePicker } from '../_.$orgid.enrollments.add/course-picker' import { UserPicker } from '../_.$orgid.enrollments.add/user-picker' import { Summary } from './bulk' -import { applyDiscount } from './discount' import { currency } from './utils' import { useWizard } from '@/components/wizard' @@ -48,6 +48,11 @@ const emptyRow = { scheduled_for: undefined } +type Item = { + course: Enrollment['course'] + quantity: number +} + const formSchemaAssigned = formSchema.extend({ coupon: z .object({ @@ -101,8 +106,6 @@ export function Assigned({ 0 ) - console.log(coupon) - const onSearch = async (search: string) => { const params = new URLSearchParams({ q: search }) const r = await fetch(`/${orgid}/users.json?${params.toString()}`) @@ -110,15 +113,25 @@ export function Assigned({ return hits } - const onSubmit_ = async (data: Schema) => { - await onSubmit(data) + const onSubmit_ = async ({ enrollments }: Schema) => { + const items = Object.values( + enrollments.reduce>((acc, e) => { + const id = e.course.id + + acc[id] ??= { course: e.course, quantity: 0 } + acc[id].quantity++ + + return acc + }, {}) + ) + await onSubmit({ enrollments, items }) wizard('payment') } return (
-
+
{/* Header */} <> Colaborador diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/bulk.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/bulk.tsx index 15d06f4..8a0e491 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/bulk.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/bulk.tsx @@ -125,7 +125,7 @@ export function Bulk({ return ( -
+
{/* Header */} <> Curso diff --git a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/payment.tsx b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/payment.tsx index 3245a45..593db49 100644 --- a/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/payment.tsx +++ b/apps/admin.saladeaula.digital/app/routes/_.$orgid.enrollments.buy/payment.tsx @@ -1,4 +1,4 @@ -import { useForm, Controller } from 'react-hook-form' +import { useForm, Controller, useWatch } from 'react-hook-form' import { zodResolver } from '@hookform/resolvers/zod' import { ErrorMessage } from '@hookform/error-message' import z from 'zod' @@ -9,7 +9,28 @@ import { Label } from '@repo/ui/components/ui/label' import { RadioGroup, RadioGroupItem } from '@repo/ui/components/ui/radio-group' import { Separator } from '@repo/ui/components/ui/separator' +import { Checkbox } from '@repo/ui/components/ui/checkbox' +import { + Field, + FieldDescription, + FieldGroup, + FieldLabel, + FieldLegend, + FieldSeparator, + FieldSet +} from '@repo/ui/components/ui/field' +import { Input } from '@repo/ui/components/ui/input' +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@repo/ui/components/ui/select' +import { Textarea } from '@repo/ui/components/ui/textarea' + import { useWizard } from '@/components/wizard' +import { Card, CardContent } from '@repo/ui/components/ui/card' const formSchema = z.object({ payment_method: z.enum(['PIX', 'BANK_SLIP', 'CREDIT_CARD'], { @@ -33,6 +54,7 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) { }, resolver: zodResolver(formSchema) }) + const paymentMethod = useWatch({ control, name: 'payment_method' }) const onSubmit_ = async (data: Schema) => { await onSubmit(data) @@ -82,6 +104,8 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) { )} /> + {paymentMethod === 'CREDIT_CARD' ? : null} +
@@ -100,3 +124,78 @@ export function Payment({ onSubmit, defaultValues }: PaymentProps) { ) } + +export function CreditCard() { + return ( + + + +
+ + + + Número do cartão + + + + + + + Nome do titular + + + + +
+ + Mês + + + + + Ano + + + + + CVC + + +
+
+
+
+
+
+ ) +} diff --git a/packages/ui/src/components/data-table/view-options.tsx b/packages/ui/src/components/data-table/view-options.tsx index cbd2987..ee73110 100644 --- a/packages/ui/src/components/data-table/view-options.tsx +++ b/packages/ui/src/components/data-table/view-options.tsx @@ -25,10 +25,10 @@ export function DataTableViewOptions({ className }: { className?: string }) { - + Exibir colunas - + {/**/} {table .getAllColumns() diff --git a/packages/ui/src/components/nav-user.tsx b/packages/ui/src/components/nav-user.tsx index 594c169..1990f1e 100644 --- a/packages/ui/src/components/nav-user.tsx +++ b/packages/ui/src/components/nav-user.tsx @@ -136,7 +136,7 @@ export function NavUser({ ) && ( <> - + Aplicações @@ -155,7 +155,7 @@ export function NavUser({ - + Sair diff --git a/packages/ui/src/components/ui/field.tsx b/packages/ui/src/components/ui/field.tsx new file mode 100644 index 0000000..235d00e --- /dev/null +++ b/packages/ui/src/components/ui/field.tsx @@ -0,0 +1,248 @@ +"use client" + +import { useMemo } from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" +import { Separator } from "@/components/ui/separator" + +function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { + return ( +
[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", + className + )} + {...props} + /> + ) +} + +function FieldLegend({ + className, + variant = "legend", + ...props +}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { + return ( + + ) +} + +function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
[data-slot=field-group]]:gap-4", + className + )} + {...props} + /> + ) +} + +const fieldVariants = cva( + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", + { + variants: { + orientation: { + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], + horizontal: [ + "flex-row items-center", + "[&>[data-slot=field-label]]:flex-auto", + "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + responsive: [ + "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto", + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + }, + }, + defaultVariants: { + orientation: "vertical", + }, + } +) + +function Field({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ) +} + +function FieldContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function FieldLabel({ + className, + ...props +}: React.ComponentProps) { + return ( +