add dialog

This commit is contained in:
2025-12-27 20:48:04 -03:00
parent 976a7da0a9
commit 8b81d5c245
2 changed files with 357 additions and 161 deletions

View File

@@ -176,19 +176,13 @@ export function CreditCard({ control }: { control: Control<Schema> }) {
<CardContent>
<FieldGroup>
<FieldSet>
<FieldGroup>
{/* Credir card number */}
<Controller
control={control}
name="credit_card.number"
render={({
field: { onChange, ref, ...field },
fieldState
}) => (
render={({ field: { onChange, ref, ...field }, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>
Número do cartão
</FieldLabel>
<FieldLabel htmlFor={field.name}>Número do cartão</FieldLabel>
<PatternFormat
id={field.name}
format="#### #### #### ####"
@@ -216,9 +210,7 @@ export function CreditCard({ control }: { control: Control<Schema> }) {
defaultValue=""
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>
Nome do titular
</FieldLabel>
<FieldLabel htmlFor={field.name}>Nome do titular</FieldLabel>
<Input
id={field.name}
aria-invalid={fieldState.invalid}
@@ -231,7 +223,7 @@ export function CreditCard({ control }: { control: Control<Schema> }) {
)}
/>
<div className="grid grid-cols-3 gap-4">
<FieldSet className="grid grid-cols-3 gap-4">
<Controller
control={control}
name="credit_card.exp_month"
@@ -328,8 +320,7 @@ export function CreditCard({ control }: { control: Control<Schema> }) {
</Field>
)}
/>
</div>
</FieldGroup>
</FieldSet>
</FieldSet>
</FieldGroup>
</CardContent>

View File

@@ -1,6 +1,9 @@
import { useToggle } from 'ahooks'
import { PencilIcon } from 'lucide-react'
import { useForm } from 'react-hook-form'
import { PatternFormat } from 'react-number-format'
import { ExternalLinkIcon, PencilIcon, SearchIcon } from 'lucide-react'
import { Controller, useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import valid from 'card-validator'
import { Currency } from '@repo/ui/components/currency'
@@ -39,6 +42,21 @@ import { useWizard } from '@/components/wizard'
import { type WizardState } from './route'
import { applyDiscount } from './discount'
import { paymentMethods } from '@repo/ui/routes/orders/data'
import {
Field,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldSet
} from '@repo/ui/components/ui/field'
import { Input } from '@repo/ui/components/ui/input'
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput
} from '@repo/ui/components/ui/input-group'
type ReviewProps = {
state: WizardState
@@ -64,7 +82,7 @@ export function Review({ state, onSubmit }: ReviewProps) {
return (
<>
<Address {...state} />
<Address total={total} {...state} />
<form
onSubmit={async (e) => {
@@ -150,9 +168,12 @@ export function Review({ state, onSubmit }: ReviewProps) {
)
}
export function Address({ payment_method, credit_card }: WizardState) {
export function Address({
total,
payment_method,
credit_card
}: WizardState & { total: number }) {
const numberValidation = valid.number(credit_card?.number)
// console.log(numberValidation)
return (
<ItemGroup className="grid lg:grid-cols-2 gap-4">
@@ -170,7 +191,7 @@ export function Address({ payment_method, credit_card }: WizardState) {
</ul>
</ItemContent>
<ItemActions>
<DialogDemo />
<AddressDialog />
</ItemActions>
</Item>
@@ -178,14 +199,20 @@ export function Address({ payment_method, credit_card }: WizardState) {
<ItemContent>
<ItemTitle>Forma de pagamento</ItemTitle>
<ItemDescription>
{payment_method ? paymentMethods[payment_method] : payment_method}
{credit_card ? (
<>
<br />
{numberValidation.card?.niceType} ****{' '}
{numberValidation.card?.niceType} (Crédito) ****{' '}
{credit_card.number.slice(-4)}
<br />
1x <Currency>{total}</Currency>
</>
) : null}
) : (
<>
{payment_method
? paymentMethods[payment_method]
: payment_method}
</>
)}
</ItemDescription>
</ItemContent>
</Item>
@@ -193,14 +220,27 @@ export function Address({ payment_method, credit_card }: WizardState) {
)
}
export function DialogDemo() {
const form = useForm()
const { handleSubmit } = form
const formSchema = z.object({
postcode: z.string().min(1, 'Digite um CEP'),
address1: z.string().min(1, 'Digite um endereço'),
address2: z.string().optional(),
neighborhood: z.string().min(1, 'Digite o bairro'),
city: z.string().min(1, 'Digite a cidade'),
state: z.string().min(1, 'Digite o estado')
})
const onSubmit = async () => {}
type Schema = z.infer<typeof formSchema>
export function AddressDialog() {
const { handleSubmit, control } = useForm({
resolver: zodResolver(formSchema)
})
const onSubmit = async (data: Schema) => {
console.log(data)
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Dialog>
<DialogTrigger asChild>
<Button
@@ -214,6 +254,7 @@ export function DialogDemo() {
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<DialogHeader>
<DialogTitle>Editar endereço</DialogTitle>
<DialogDescription>
@@ -221,6 +262,170 @@ export function DialogDemo() {
</DialogDescription>
</DialogHeader>
<FieldGroup>
<FieldSet>
<Controller
control={control}
name="postcode"
defaultValue=""
render={({
field: { onChange, ref, ...field },
fieldState
}) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>CEP</FieldLabel>
<InputGroup>
{/*<InputGroupInput
id={field.name}
aria-invalid={fieldState.invalid}
{...field}
/>*/}
<PatternFormat
id={field.name}
format="#####-###"
mask="_"
placeholder="_____-___"
customInput={InputGroupInput}
getInputRef={ref}
aria-invalid={fieldState.invalid}
onValueChange={({ value }) => {
onChange(value)
}}
{...field}
/>
<InputGroupAddon align="inline-end">
<InputGroupButton type="button" variant="secondary">
<SearchIcon />
</InputGroupButton>
</InputGroupAddon>
</InputGroup>
<FieldDescription>
<a
href="https://buscacepinter.correios.com.br/app/endereco/index.php"
target="_blank"
rel="noopener noreferrer"
className="inline-flex gap-1 items-center "
>
Não sei o CEP <ExternalLinkIcon className="size-4" />
</a>
</FieldDescription>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={control}
name="address1"
defaultValue=""
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>Endereço</FieldLabel>
<Input
id={field.name}
aria-invalid={fieldState.invalid}
{...field}
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
<Controller
control={control}
name="address2"
defaultValue=""
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>
Complemento{' '}
<span className="text-muted-foreground">(opcional)</span>
</FieldLabel>
<Input
id={field.name}
aria-invalid={fieldState.invalid}
{...field}
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
</FieldSet>
<FieldSet className="grid grid-cols-3">
{/* Neighborhood */}
<Controller
control={control}
name="neighborhood"
defaultValue=""
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>Bairro</FieldLabel>
<Input
id={field.name}
aria-invalid={fieldState.invalid}
{...field}
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
{/* City */}
<Controller
control={control}
name="city"
defaultValue=""
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>Cidade</FieldLabel>
<Input
id={field.name}
aria-invalid={fieldState.invalid}
{...field}
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
{/* State */}
<Controller
control={control}
name="state"
defaultValue=""
render={({ field, fieldState }) => (
<Field data-invalid={fieldState.invalid}>
<FieldLabel htmlFor={field.name}>Estado</FieldLabel>
<Input
id={field.name}
aria-invalid={fieldState.invalid}
{...field}
/>
{fieldState.invalid && (
<FieldError errors={[fieldState.error]} />
)}
</Field>
)}
/>
</FieldSet>
</FieldGroup>
<DialogFooter className="*:cursor-pointer">
<DialogClose asChild>
<Button
@@ -234,8 +439,8 @@ export function DialogDemo() {
<Button type="submit">Atualizar endereço</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
</form>
)
}