@greatapps/common 1.1.290 → 1.1.291

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
1
  "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useCallback } from "react";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useState } from "react";
4
4
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from "../../ui/overlay/Dialog";
5
5
  import { Button } from "../../ui/buttons/Button";
6
6
  import { Toast } from "../../ui/feedback/Toast";
7
7
  import { useModalManager } from "../../../store/useModalManager";
8
8
  import { useCreateCard } from "../../../modules/cards/hooks/create-card.hook";
9
- import { CardFormFields, cardFormSchema } from "./CardFormFields";
9
+ import { useUpdateAccount } from "../../../modules/accounts/hooks/useAccountManagement";
10
+ import { CardFormFields, BillingFormFields, cardFormSchema, STEP1_FIELDS } from "./CardFormFields";
10
11
  import { IconX } from "@tabler/icons-react";
11
12
  import { useForm } from "react-hook-form";
12
13
  import { zodResolver } from "@hookform/resolvers/zod";
@@ -15,8 +16,10 @@ import { toast } from "sonner";
15
16
  function AddCardModal() {
16
17
  const { activeModal, modalData, closeModal } = useModalManager();
17
18
  const isOpen = activeModal === "addCardModal";
19
+ const [currentStep, setCurrentStep] = useState(1);
18
20
  const onCardAdded = modalData.onCardAdded;
19
21
  const createCardMutation = useCreateCard();
22
+ const updateAccountMutation = useUpdateAccount();
20
23
  const elements = useElements();
21
24
  const stripe = useStripe();
22
25
  const form = useForm({
@@ -24,13 +27,24 @@ function AddCardModal() {
24
27
  mode: "onSubmit",
25
28
  reValidateMode: "onChange",
26
29
  defaultValues: {
27
- country: "BR"
30
+ country: "BR",
31
+ personType: "pf"
28
32
  }
29
33
  });
30
34
  const handleClose = useCallback(() => {
31
35
  form.reset();
36
+ setCurrentStep(1);
32
37
  closeModal();
33
38
  }, [form, closeModal]);
39
+ const handleContinue = useCallback(async () => {
40
+ const valid = await form.trigger(STEP1_FIELDS);
41
+ if (valid) {
42
+ setCurrentStep(2);
43
+ }
44
+ }, [form]);
45
+ const handleBack = useCallback(() => {
46
+ setCurrentStep(1);
47
+ }, []);
34
48
  async function handleSubmit(data) {
35
49
  if (!stripe || !elements) return;
36
50
  const cardElement = elements.getElement(CardNumberElement);
@@ -39,10 +53,14 @@ function AddCardModal() {
39
53
  type: "card",
40
54
  card: cardElement,
41
55
  billing_details: {
42
- name: data.name,
56
+ name: data.fullName,
43
57
  address: {
44
58
  country: data.country,
45
- postal_code: data.postalCode
59
+ postal_code: data.cep,
60
+ line1: `${data.street}, ${data.streetNumber}`,
61
+ line2: data.complement || void 0,
62
+ city: data.city,
63
+ state: data.state
46
64
  }
47
65
  }
48
66
  });
@@ -60,36 +78,44 @@ function AddCardModal() {
60
78
  );
61
79
  return;
62
80
  }
63
- const result = await createCardMutation.mutateAsync(
64
- { payment_method_id: paymentMethod.id },
65
- {
66
- onError: () => {
67
- handleClose();
68
- toast.custom(
69
- (t) => /* @__PURE__ */ jsx(
70
- Toast,
71
- {
72
- variant: "error",
73
- message: "N\xE3o foi poss\xEDvel salvar o seu novo cart\xE3o, tente novamente.",
74
- toastId: t
75
- }
76
- ),
77
- { duration: 5e3 }
78
- );
79
- }
81
+ try {
82
+ const [cardResult] = await Promise.all([
83
+ createCardMutation.mutateAsync({ payment_method_id: paymentMethod.id }),
84
+ updateAccountMutation.mutateAsync({
85
+ financial_document_type: data.personType === "pf" ? 1 : 2,
86
+ financial_document: data.personType === "pf" ? data.cpf : data.cnpj,
87
+ financial_name: data.fullName,
88
+ zipcode: data.cep,
89
+ address: data.street,
90
+ address_number: data.streetNumber,
91
+ address_complement: data.complement || "",
92
+ city: data.city,
93
+ state: data.state
94
+ })
95
+ ]);
96
+ if (cardResult.success && cardResult.data?.id != null) {
97
+ onCardAdded?.(cardResult.data.id.toString());
80
98
  }
81
- );
82
- if (result.success && result.data?.id != null) {
83
- onCardAdded?.(result.data.id.toString());
99
+ toast.custom(
100
+ (t) => /* @__PURE__ */ jsx(Toast, { variant: "success", message: "Cart\xE3o adicionado com sucesso.", toastId: t }),
101
+ { duration: 5e3 }
102
+ );
103
+ handleClose();
104
+ } catch {
105
+ toast.custom(
106
+ (t) => /* @__PURE__ */ jsx(
107
+ Toast,
108
+ {
109
+ variant: "error",
110
+ message: "N\xE3o foi poss\xEDvel salvar o seu novo cart\xE3o, tente novamente.",
111
+ toastId: t
112
+ }
113
+ ),
114
+ { duration: 5e3 }
115
+ );
84
116
  }
85
- toast.custom(
86
- (t) => /* @__PURE__ */ jsx(Toast, { variant: "success", message: "Cart\xE3o adicionado com sucesso.", toastId: t }),
87
- { duration: 5e3 }
88
- );
89
- handleClose();
90
117
  }
91
- const isSubmitting = createCardMutation.isPending || form.formState.isSubmitting;
92
- const isValid = form.formState.isValid;
118
+ const isSubmitting = createCardMutation.isPending || updateAccountMutation.isPending || form.formState.isSubmitting;
93
119
  return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(
94
120
  DialogContent,
95
121
  {
@@ -97,7 +123,7 @@ function AddCardModal() {
97
123
  className: "flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] overflow-y-auto",
98
124
  children: [
99
125
  /* @__PURE__ */ jsx(DialogHeader, { className: "p-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center px-4 py-3 relative border-b border-zinc-200 lg:border-b-0", children: [
100
- /* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-zinc-950 text-center", children: "Adicionar cart\xE3o" }),
126
+ /* @__PURE__ */ jsx(DialogTitle, { className: "paragraph-medium-semibold text-zinc-950 text-center", children: currentStep === 1 ? "Adicionar cart\xE3o" : "Dados de cobran\xE7a" }),
101
127
  /* @__PURE__ */ jsx(
102
128
  Button,
103
129
  {
@@ -109,17 +135,27 @@ function AddCardModal() {
109
135
  }
110
136
  )
111
137
  ] }) }),
138
+ /* @__PURE__ */ jsx("div", { className: "h-1 bg-zinc-100 w-full", children: /* @__PURE__ */ jsx(
139
+ "div",
140
+ {
141
+ className: "h-full bg-cyan-400 transition-all duration-300 ease-in-out",
142
+ style: { width: currentStep === 1 ? "50%" : "100%" }
143
+ }
144
+ ) }),
112
145
  /* @__PURE__ */ jsxs(
113
146
  "form",
114
147
  {
115
148
  onSubmit: form.handleSubmit(handleSubmit),
116
149
  className: "flex flex-col flex-1 lg:flex-none",
117
150
  children: [
118
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none", children: /* @__PURE__ */ jsx(CardFormFields, { form }) }),
119
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0", children: [
151
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none", children: currentStep === 1 ? /* @__PURE__ */ jsx(CardFormFields, { form }) : /* @__PURE__ */ jsx(BillingFormFields, { form }) }),
152
+ /* @__PURE__ */ jsx("div", { className: "flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0", children: currentStep === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
120
153
  /* @__PURE__ */ jsx(Button, { variant: "secondary", type: "button", onClick: handleClose, className: "h-10!", children: "Cancelar" }),
121
- /* @__PURE__ */ jsx(Button, { type: "submit", className: "h-10!", disabled: isSubmitting || !isValid, children: isSubmitting ? "Adicionando cart\xE3o..." : "Adicionar cart\xE3o" })
122
- ] })
154
+ /* @__PURE__ */ jsx(Button, { type: "button", className: "h-10!", onClick: handleContinue, children: "Continuar" })
155
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
156
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", type: "button", onClick: handleBack, className: "h-10!", children: "Voltar" }),
157
+ /* @__PURE__ */ jsx(Button, { type: "submit", className: "h-10!", disabled: isSubmitting, children: isSubmitting ? "Adicionando cart\xE3o..." : "Adicionar cart\xE3o" })
158
+ ] }) })
123
159
  ]
124
160
  }
125
161
  )
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/modals/cards/AddCardModal.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback } from 'react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Button } from '../../ui/buttons/Button';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { useModalManager } from '../../../store/useModalManager';\nimport { useCreateCard } from '../../../modules/cards/hooks/create-card.hook';\nimport { CardFormFields, cardFormSchema } from './CardFormFields';\nimport type { CardFormData } from './CardFormFields';\nimport { IconX } from '@tabler/icons-react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { CardNumberElement, useElements, useStripe } from '@stripe/react-stripe-js';\nimport { toast } from 'sonner';\n\nexport default function AddCardModal() {\n const { activeModal, modalData, closeModal } = useModalManager();\n const isOpen = activeModal === 'addCardModal';\n\n const onCardAdded = modalData.onCardAdded as ((cardId: string) => void) | undefined;\n\n const createCardMutation = useCreateCard();\n const elements = useElements();\n const stripe = useStripe();\n\n const form = useForm<CardFormData>({\n resolver: zodResolver(cardFormSchema),\n mode: 'onSubmit',\n reValidateMode: 'onChange',\n defaultValues: {\n country: 'BR',\n },\n });\n\n const handleClose = useCallback(() => {\n form.reset();\n closeModal();\n }, [form, closeModal]);\n\n async function handleSubmit(data: CardFormData) {\n if (!stripe || !elements) return;\n\n const cardElement = elements.getElement(CardNumberElement);\n if (!cardElement) return;\n\n const { error, paymentMethod } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardElement,\n billing_details: {\n name: data.name,\n address: {\n country: data.country,\n postal_code: data.postalCode,\n },\n },\n });\n\n if (error) {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível adicionar o cartão na Stripe, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n return;\n }\n\n const result = await createCardMutation.mutateAsync(\n { payment_method_id: paymentMethod.id },\n {\n onError: () => {\n handleClose();\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível salvar o seu novo cartão, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n },\n }\n );\n\n if (result.success && result.data?.id != null) {\n onCardAdded?.(result.data.id.toString());\n }\n\n toast.custom(\n (t) => <Toast variant=\"success\" message=\"Cartão adicionado com sucesso.\" toastId={t} />,\n { duration: 5000 }\n );\n handleClose();\n }\n\n const isSubmitting = createCardMutation.isPending || form.formState.isSubmitting;\n const isValid = form.formState.isValid;\n\n return (\n <Dialog open={isOpen} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] overflow-y-auto\"\n >\n <DialogHeader className=\"p-0\">\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-zinc-200 lg:border-b-0\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950 text-center\">\n Adicionar cartão\n </DialogTitle>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n </DialogHeader>\n\n <form\n onSubmit={form.handleSubmit(handleSubmit)}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none\">\n <CardFormFields form={form} />\n </div>\n\n <div className=\"flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0\">\n <Button variant=\"secondary\" type=\"button\" onClick={handleClose} className=\"h-10!\">\n Cancelar\n </Button>\n <Button type=\"submit\" className=\"h-10!\" disabled={isSubmitting || !isValid}>\n {isSubmitting ? 'Adicionando cartão...' : 'Adicionar cartão'}\n </Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/modals/cards/AddCardModal.tsx"],"sourcesContent":["'use client';\n\nimport { useCallback, useState } from 'react';\nimport { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';\nimport { Button } from '../../ui/buttons/Button';\nimport { Toast } from '../../ui/feedback/Toast';\nimport { useModalManager } from '../../../store/useModalManager';\nimport { useCreateCard } from '../../../modules/cards/hooks/create-card.hook';\nimport { useUpdateAccount } from '../../../modules/accounts/hooks/useAccountManagement';\nimport { CardFormFields, BillingFormFields, cardFormSchema, STEP1_FIELDS } from './CardFormFields';\nimport type { CardFormData } from './CardFormFields';\nimport { IconX } from '@tabler/icons-react';\nimport { useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { CardNumberElement, useElements, useStripe } from '@stripe/react-stripe-js';\nimport { toast } from 'sonner';\n\nexport default function AddCardModal() {\n const { activeModal, modalData, closeModal } = useModalManager();\n const isOpen = activeModal === 'addCardModal';\n const [currentStep, setCurrentStep] = useState(1);\n\n const onCardAdded = modalData.onCardAdded as ((cardId: string) => void) | undefined;\n\n const createCardMutation = useCreateCard();\n const updateAccountMutation = useUpdateAccount();\n const elements = useElements();\n const stripe = useStripe();\n\n const form = useForm<CardFormData>({\n resolver: zodResolver(cardFormSchema),\n mode: 'onSubmit',\n reValidateMode: 'onChange',\n defaultValues: {\n country: 'BR',\n personType: 'pf',\n },\n });\n\n const handleClose = useCallback(() => {\n form.reset();\n setCurrentStep(1);\n closeModal();\n }, [form, closeModal]);\n\n const handleContinue = useCallback(async () => {\n const valid = await form.trigger(STEP1_FIELDS as unknown as (keyof CardFormData)[]);\n if (valid) {\n setCurrentStep(2);\n }\n }, [form]);\n\n const handleBack = useCallback(() => {\n setCurrentStep(1);\n }, []);\n\n async function handleSubmit(data: CardFormData) {\n if (!stripe || !elements) return;\n\n const cardElement = elements.getElement(CardNumberElement);\n if (!cardElement) return;\n\n const { error, paymentMethod } = await stripe.createPaymentMethod({\n type: 'card',\n card: cardElement,\n billing_details: {\n name: data.fullName,\n address: {\n country: data.country,\n postal_code: data.cep,\n line1: `${data.street}, ${data.streetNumber}`,\n line2: data.complement || undefined,\n city: data.city,\n state: data.state,\n },\n },\n });\n\n if (error) {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível adicionar o cartão na Stripe, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n return;\n }\n\n try {\n const [cardResult] = await Promise.all([\n createCardMutation.mutateAsync({ payment_method_id: paymentMethod.id }),\n updateAccountMutation.mutateAsync({\n financial_document_type: data.personType === 'pf' ? 1 : 2,\n financial_document: data.personType === 'pf' ? data.cpf : data.cnpj,\n financial_name: data.fullName,\n zipcode: data.cep,\n address: data.street,\n address_number: data.streetNumber,\n address_complement: data.complement || '',\n city: data.city,\n state: data.state,\n }),\n ]);\n\n if (cardResult.success && cardResult.data?.id != null) {\n onCardAdded?.(cardResult.data.id.toString());\n }\n\n toast.custom(\n (t) => <Toast variant=\"success\" message=\"Cartão adicionado com sucesso.\" toastId={t} />,\n { duration: 5000 }\n );\n handleClose();\n } catch {\n toast.custom(\n (t) => (\n <Toast\n variant=\"error\"\n message=\"Não foi possível salvar o seu novo cartão, tente novamente.\"\n toastId={t}\n />\n ),\n { duration: 5000 }\n );\n }\n }\n\n const isSubmitting =\n createCardMutation.isPending ||\n updateAccountMutation.isPending ||\n form.formState.isSubmitting;\n\n return (\n <Dialog open={isOpen} onOpenChange={handleClose}>\n <DialogContent\n showCloseButton={false}\n className=\"flex flex-col p-0 gap-0 max-w-full sm:max-w-full border-0 rounded-t-2xl rounded-b-none h-dvh top-0 bottom-0 left-0 right-0 translate-x-0 translate-y-0 lg:max-w-[470px] lg:h-auto lg:max-h-[90vh] lg:rounded-lg lg:border lg:top-[50%] lg:left-[50%] lg:right-auto lg:bottom-auto lg:translate-x-[-50%] lg:translate-y-[-50%] overflow-y-auto\"\n >\n <DialogHeader className=\"p-0\">\n <div className=\"flex items-center justify-center px-4 py-3 relative border-b border-zinc-200 lg:border-b-0\">\n <DialogTitle className=\"paragraph-medium-semibold text-zinc-950 text-center\">\n {currentStep === 1 ? 'Adicionar cartão' : 'Dados de cobrança'}\n </DialogTitle>\n <Button\n type=\"button\"\n variant=\"ghost\"\n className=\"size-8! p-0 absolute right-4\"\n onClick={handleClose}\n >\n <IconX size={18} />\n </Button>\n </div>\n </DialogHeader>\n\n {/* Progress bar */}\n <div className=\"h-1 bg-zinc-100 w-full\">\n <div\n className=\"h-full bg-cyan-400 transition-all duration-300 ease-in-out\"\n style={{ width: currentStep === 1 ? '50%' : '100%' }}\n />\n </div>\n\n <form\n onSubmit={form.handleSubmit(handleSubmit)}\n className=\"flex flex-col flex-1 lg:flex-none\"\n >\n <div className=\"flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none\">\n {currentStep === 1 ? (\n <CardFormFields form={form} />\n ) : (\n <BillingFormFields form={form} />\n )}\n </div>\n\n <div className=\"flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0\">\n {currentStep === 1 ? (\n <>\n <Button variant=\"secondary\" type=\"button\" onClick={handleClose} className=\"h-10!\">\n Cancelar\n </Button>\n <Button type=\"button\" className=\"h-10!\" onClick={handleContinue}>\n Continuar\n </Button>\n </>\n ) : (\n <>\n <Button variant=\"secondary\" type=\"button\" onClick={handleBack} className=\"h-10!\">\n Voltar\n </Button>\n <Button type=\"submit\" className=\"h-10!\" disabled={isSubmitting}>\n {isSubmitting ? 'Adicionando cartão...' : 'Adicionar cartão'}\n </Button>\n </>\n )}\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":"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","names":[]}
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { FormField } from "../../ui/form/FormField";
4
4
  import { SelectField } from "../../ui/form/SelectField";
5
- import { formatCPF, formatPostalCode } from "../../../utils/format/masks";
5
+ import { formatCPF, formatCNPJ, formatPostalCode } from "../../../utils/format/masks";
6
6
  import z from "zod";
7
7
  import { CardCvcElement, CardExpiryElement, CardNumberElement } from "@stripe/react-stripe-js";
8
8
  const stripeElementOptions = {
@@ -23,9 +23,27 @@ const cardFormSchema = z.object({
23
23
  expiry: z.string().min(1, "Data de validade \xE9 obrigat\xF3ria"),
24
24
  cvv: z.string().min(1, "C\xF3digo de seguran\xE7a \xE9 obrigat\xF3rio"),
25
25
  country: z.string().min(1, "Pa\xEDs \xE9 obrigat\xF3rio"),
26
- postalCode: z.string().optional(),
27
- cpf: z.string().min(14, "CPF \xE9 obrigat\xF3rio")
28
- });
26
+ personType: z.enum(["pf", "pj"]),
27
+ cpf: z.string().optional(),
28
+ cnpj: z.string().optional(),
29
+ fullName: z.string().min(1, "Nome completo \xE9 obrigat\xF3rio"),
30
+ cep: z.string().min(9, "CEP \xE9 obrigat\xF3rio"),
31
+ street: z.string().min(1, "Endere\xE7o \xE9 obrigat\xF3rio"),
32
+ streetNumber: z.string().min(1, "N\xFAmero \xE9 obrigat\xF3rio"),
33
+ city: z.string().min(1, "Cidade \xE9 obrigat\xF3ria"),
34
+ state: z.string().min(1, "UF \xE9 obrigat\xF3rio"),
35
+ complement: z.string().optional()
36
+ }).refine(
37
+ (data) => {
38
+ if (data.personType === "pf") return !!data.cpf && data.cpf.length >= 14;
39
+ return !!data.cnpj && data.cnpj.length >= 18;
40
+ },
41
+ {
42
+ message: "Documento \xE9 obrigat\xF3rio",
43
+ path: ["cpf"]
44
+ }
45
+ );
46
+ const STEP1_FIELDS = ["name", "number", "expiry", "cvv", "country", "personType", "cpf", "cnpj"];
29
47
  function CardFormFields({ form }) {
30
48
  const {
31
49
  register,
@@ -33,6 +51,7 @@ function CardFormFields({ form }) {
33
51
  setValue,
34
52
  formState: { errors }
35
53
  } = form;
54
+ const personType = watch("personType");
36
55
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5", children: [
37
56
  /* @__PURE__ */ jsx(
38
57
  FormField,
@@ -79,56 +98,161 @@ function CardFormFields({ form }) {
79
98
  errors.cvv && /* @__PURE__ */ jsx("p", { className: "paragraph-xsmall-semibold text-red-600", children: errors.cvv.message })
80
99
  ] })
81
100
  ] }),
101
+ /* @__PURE__ */ jsx(
102
+ SelectField,
103
+ {
104
+ label: "Pa\xEDs",
105
+ placeholder: "Selecione",
106
+ value: watch("country"),
107
+ onChange: (value) => setValue("country", value),
108
+ options: [
109
+ { value: "BR", label: "Brasil" },
110
+ { value: "ES", label: "Espanha" },
111
+ { value: "US", label: "Estados Unidos" }
112
+ ]
113
+ }
114
+ ),
82
115
  /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
83
116
  /* @__PURE__ */ jsx(
84
117
  SelectField,
85
118
  {
86
- label: "Pa\xEDs",
119
+ label: "Tipo de pessoa",
87
120
  placeholder: "Selecione",
88
- value: watch("country"),
89
- onChange: (value) => setValue("country", value),
121
+ value: personType,
122
+ onChange: (value) => {
123
+ setValue("personType", value);
124
+ setValue("cpf", "");
125
+ setValue("cnpj", "");
126
+ },
90
127
  options: [
91
- { value: "BR", label: "Brasil" },
92
- { value: "ES", label: "Espanha" },
93
- { value: "US", label: "Estados Unidos" }
128
+ { value: "pf", label: "Pessoa f\xEDsica" },
129
+ { value: "pj", label: "Pessoa jur\xEDdica" }
94
130
  ],
95
131
  containerClassName: "flex-1"
96
132
  }
97
133
  ),
98
- /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
134
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: personType === "pj" ? /* @__PURE__ */ jsx(
99
135
  FormField,
100
136
  {
101
- label: "C\xF3digo postal",
102
- optional: true,
103
- placeholder: "",
104
- ...register("postalCode", {
137
+ label: "CNPJ",
138
+ placeholder: "__.___.___/____-__",
139
+ ...register("cnpj", {
105
140
  onChange: (e) => {
106
- setValue("postalCode", formatPostalCode(e.target.value));
141
+ setValue("cnpj", formatCNPJ(e.target.value));
107
142
  }
108
143
  }),
109
- error: !!errors.postalCode,
110
- errorMessage: errors.postalCode?.message
144
+ error: !!errors.cpf,
145
+ errorMessage: errors.cpf?.message
146
+ }
147
+ ) : /* @__PURE__ */ jsx(
148
+ FormField,
149
+ {
150
+ label: "CPF",
151
+ placeholder: "___.___.___-__",
152
+ ...register("cpf", {
153
+ onChange: (e) => {
154
+ setValue("cpf", formatCPF(e.target.value));
155
+ }
156
+ }),
157
+ error: !!errors.cpf,
158
+ errorMessage: errors.cpf?.message
111
159
  }
112
160
  ) })
113
- ] }),
161
+ ] })
162
+ ] });
163
+ }
164
+ function BillingFormFields({ form }) {
165
+ const {
166
+ register,
167
+ setValue,
168
+ formState: { errors }
169
+ } = form;
170
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-5", children: [
114
171
  /* @__PURE__ */ jsx(
115
172
  FormField,
116
173
  {
117
- label: "CPF",
118
- placeholder: "___.___.___-__",
119
- ...register("cpf", {
174
+ label: "Nome completo",
175
+ placeholder: "Digite aqui",
176
+ ...register("fullName"),
177
+ error: !!errors.fullName,
178
+ errorMessage: errors.fullName?.message
179
+ }
180
+ ),
181
+ /* @__PURE__ */ jsx(
182
+ FormField,
183
+ {
184
+ label: "CEP",
185
+ placeholder: "_____-___",
186
+ ...register("cep", {
120
187
  onChange: (e) => {
121
- setValue("cpf", formatCPF(e.target.value));
188
+ setValue("cep", formatPostalCode(e.target.value));
122
189
  }
123
190
  }),
124
- error: !!errors.cpf,
125
- errorMessage: errors.cpf?.message
191
+ error: !!errors.cep,
192
+ errorMessage: errors.cep?.message
193
+ }
194
+ ),
195
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
196
+ /* @__PURE__ */ jsx("div", { className: "flex-[2]", children: /* @__PURE__ */ jsx(
197
+ FormField,
198
+ {
199
+ label: "Endere\xE7o",
200
+ placeholder: "",
201
+ ...register("street"),
202
+ error: !!errors.street,
203
+ errorMessage: errors.street?.message
204
+ }
205
+ ) }),
206
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
207
+ FormField,
208
+ {
209
+ label: "N\xFAmero",
210
+ placeholder: "",
211
+ ...register("streetNumber"),
212
+ error: !!errors.streetNumber,
213
+ errorMessage: errors.streetNumber?.message
214
+ }
215
+ ) })
216
+ ] }),
217
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
218
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
219
+ FormField,
220
+ {
221
+ label: "Cidade",
222
+ placeholder: "",
223
+ ...register("city"),
224
+ error: !!errors.city,
225
+ errorMessage: errors.city?.message
226
+ }
227
+ ) }),
228
+ /* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
229
+ FormField,
230
+ {
231
+ label: "UF",
232
+ placeholder: "",
233
+ ...register("state"),
234
+ error: !!errors.state,
235
+ errorMessage: errors.state?.message
236
+ }
237
+ ) })
238
+ ] }),
239
+ /* @__PURE__ */ jsx(
240
+ FormField,
241
+ {
242
+ label: "Complemento",
243
+ optional: true,
244
+ placeholder: "",
245
+ ...register("complement"),
246
+ error: !!errors.complement,
247
+ errorMessage: errors.complement?.message
126
248
  }
127
249
  )
128
250
  ] });
129
251
  }
130
252
  export {
253
+ BillingFormFields,
131
254
  CardFormFields,
255
+ STEP1_FIELDS,
132
256
  cardFormSchema
133
257
  };
134
258
  //# sourceMappingURL=CardFormFields.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/modals/cards/CardFormFields.tsx"],"sourcesContent":["'use client';\n\nimport { UseFormReturn } from 'react-hook-form';\nimport { FormField } from '../../ui/form/FormField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport { formatCPF, formatPostalCode } from '../../../utils/format/masks';\nimport z from 'zod';\nimport { CardCvcElement, CardExpiryElement, CardNumberElement } from '@stripe/react-stripe-js';\n\nconst stripeElementOptions = {\n style: {\n base: {\n fontSize: '16px',\n color: '#030712',\n fontFamily: 'Inter, sans-serif',\n '::placeholder': {\n color: '#9ca3af',\n },\n },\n },\n};\n\nexport const cardFormSchema = z.object({\n name: z.string().min(1, 'Nome é obrigatório'),\n number: z.string().min(1, 'Número do cartão é obrigatório'),\n expiry: z.string().min(1, 'Data de validade é obrigatória'),\n cvv: z.string().min(1, 'Código de segurança é obrigatório'),\n country: z.string().min(1, 'País é obrigatório'),\n postalCode: z.string().optional(),\n cpf: z.string().min(14, 'CPF é obrigatório'),\n});\n\nexport type CardFormData = z.infer<typeof cardFormSchema>;\n\ntype CardFormFieldsProps = {\n readonly form: UseFormReturn<CardFormData>;\n};\n\nexport function CardFormFields({ form }: CardFormFieldsProps) {\n const {\n register,\n watch,\n setValue,\n formState: { errors },\n } = form;\n\n return (\n <div className=\"flex flex-col gap-5\">\n <FormField\n label=\"Nome impresso no cartão\"\n placeholder=\"Digite aqui\"\n {...register('name')}\n error={!!errors.name}\n errorMessage={errors.name?.message}\n />\n\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"paragraph-xsmall-semibold text-zinc-600\">\n Número do cartão\n </label>\n <div className=\"h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400 relative\">\n <div className=\"w-full\">\n <CardNumberElement\n options={{ ...stripeElementOptions, showIcon: true }}\n onChange={(e) =>\n setValue('number', e.complete ? 'complete' : '', { shouldValidate: true })\n }\n />\n </div>\n </div>\n {errors.number && (\n <p className=\"paragraph-xsmall-semibold text-red-600\">{errors.number.message}</p>\n )}\n </div>\n\n <div className=\"flex gap-4\">\n <div className=\"flex-1 flex flex-col gap-1.5\">\n <label className=\"paragraph-xsmall-semibold text-zinc-600\">\n Data de validade\n </label>\n <div className=\"h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400\">\n <div className=\"w-full\">\n <CardExpiryElement\n options={stripeElementOptions}\n onChange={(e) =>\n setValue('expiry', e.complete ? 'complete' : '', { shouldValidate: true })\n }\n />\n </div>\n </div>\n {errors.expiry && (\n <p className=\"paragraph-xsmall-semibold text-red-600\">{errors.expiry.message}</p>\n )}\n </div>\n\n <div className=\"flex-1 flex flex-col gap-1.5\">\n <label className=\"paragraph-xsmall-semibold text-zinc-600\">\n CVC\n </label>\n <div className=\"h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400\">\n <div className=\"w-full\">\n <CardCvcElement\n options={stripeElementOptions}\n onChange={(e) =>\n setValue('cvv', e.complete ? 'complete' : '', { shouldValidate: true })\n }\n />\n </div>\n </div>\n {errors.cvv && (\n <p className=\"paragraph-xsmall-semibold text-red-600\">{errors.cvv.message}</p>\n )}\n </div>\n </div>\n\n <div className=\"flex gap-4\">\n <SelectField\n label=\"País\"\n placeholder=\"Selecione\"\n value={watch('country')}\n onChange={(value) => setValue('country', value as string)}\n options={[\n { value: 'BR', label: 'Brasil' },\n { value: 'ES', label: 'Espanha' },\n { value: 'US', label: 'Estados Unidos' },\n ]}\n containerClassName=\"flex-1\"\n />\n <div className=\"flex-1\">\n <FormField\n label=\"Código postal\"\n optional\n placeholder=\"\"\n {...register('postalCode', {\n onChange: (e) => {\n setValue('postalCode', formatPostalCode(e.target.value));\n },\n })}\n error={!!errors.postalCode}\n errorMessage={errors.postalCode?.message}\n />\n </div>\n </div>\n\n <FormField\n label=\"CPF\"\n placeholder=\"___.___.___-__\"\n {...register('cpf', {\n onChange: (e) => {\n setValue('cpf', formatCPF(e.target.value));\n },\n })}\n error={!!errors.cpf}\n errorMessage={errors.cpf?.message}\n />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/components/modals/cards/CardFormFields.tsx"],"sourcesContent":["'use client';\n\nimport { UseFormReturn } from 'react-hook-form';\nimport { FormField } from '../../ui/form/FormField';\nimport { SelectField } from '../../ui/form/SelectField';\nimport { formatCPF, formatCNPJ, formatPostalCode } from '../../../utils/format/masks';\nimport z from 'zod';\nimport { CardCvcElement, CardExpiryElement, CardNumberElement } from '@stripe/react-stripe-js';\n\nconst stripeElementOptions = {\n style: {\n base: {\n fontSize: '16px',\n color: '#030712',\n fontFamily: 'Inter, sans-serif',\n '::placeholder': {\n color: '#9ca3af',\n },\n },\n },\n};\n\nexport const cardFormSchema = z\n .object({\n name: z.string().min(1, 'Nome é obrigatório'),\n number: z.string().min(1, 'Número do cartão é obrigatório'),\n expiry: z.string().min(1, 'Data de validade é obrigatória'),\n cvv: z.string().min(1, 'Código de segurança é obrigatório'),\n country: z.string().min(1, 'País é obrigatório'),\n personType: z.enum(['pf', 'pj']),\n cpf: z.string().optional(),\n cnpj: z.string().optional(),\n fullName: z.string().min(1, 'Nome completo é obrigatório'),\n cep: z.string().min(9, 'CEP é obrigatório'),\n street: z.string().min(1, 'Endereço é obrigatório'),\n streetNumber: z.string().min(1, 'Número é obrigatório'),\n city: z.string().min(1, 'Cidade é obrigatória'),\n state: z.string().min(1, 'UF é obrigatório'),\n complement: z.string().optional(),\n })\n .refine(\n (data) => {\n if (data.personType === 'pf') return !!data.cpf && data.cpf.length >= 14;\n return !!data.cnpj && data.cnpj.length >= 18;\n },\n {\n message: 'Documento é obrigatório',\n path: ['cpf'],\n }\n );\n\nexport type CardFormData = z.infer<typeof cardFormSchema>;\n\nexport const STEP1_FIELDS = ['name', 'number', 'expiry', 'cvv', 'country', 'personType', 'cpf', 'cnpj'] as const;\n\ntype CardFormFieldsProps = {\n readonly form: UseFormReturn<CardFormData>;\n};\n\nexport function CardFormFields({ form }: CardFormFieldsProps) {\n const {\n register,\n watch,\n setValue,\n formState: { errors },\n } = form;\n\n const personType = watch('personType');\n\n return (\n <div className=\"flex flex-col gap-5\">\n <FormField\n label=\"Nome impresso no cartão\"\n placeholder=\"Digite aqui\"\n {...register('name')}\n error={!!errors.name}\n errorMessage={errors.name?.message}\n />\n\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"paragraph-xsmall-semibold text-zinc-600\">Número do cartão</label>\n <div className=\"h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400 relative\">\n <div className=\"w-full\">\n <CardNumberElement\n options={{ ...stripeElementOptions, showIcon: true }}\n onChange={(e) =>\n setValue('number', e.complete ? 'complete' : '', { shouldValidate: true })\n }\n />\n </div>\n </div>\n {errors.number && (\n <p className=\"paragraph-xsmall-semibold text-red-600\">{errors.number.message}</p>\n )}\n </div>\n\n <div className=\"flex gap-4\">\n <div className=\"flex-1 flex flex-col gap-1.5\">\n <label className=\"paragraph-xsmall-semibold text-zinc-600\">Data de validade</label>\n <div className=\"h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400\">\n <div className=\"w-full\">\n <CardExpiryElement\n options={stripeElementOptions}\n onChange={(e) =>\n setValue('expiry', e.complete ? 'complete' : '', { shouldValidate: true })\n }\n />\n </div>\n </div>\n {errors.expiry && (\n <p className=\"paragraph-xsmall-semibold text-red-600\">{errors.expiry.message}</p>\n )}\n </div>\n\n <div className=\"flex-1 flex flex-col gap-1.5\">\n <label className=\"paragraph-xsmall-semibold text-zinc-600\">CVC</label>\n <div className=\"h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400\">\n <div className=\"w-full\">\n <CardCvcElement\n options={stripeElementOptions}\n onChange={(e) =>\n setValue('cvv', e.complete ? 'complete' : '', { shouldValidate: true })\n }\n />\n </div>\n </div>\n {errors.cvv && (\n <p className=\"paragraph-xsmall-semibold text-red-600\">{errors.cvv.message}</p>\n )}\n </div>\n </div>\n\n <SelectField\n label=\"País\"\n placeholder=\"Selecione\"\n value={watch('country')}\n onChange={(value) => setValue('country', value as string)}\n options={[\n { value: 'BR', label: 'Brasil' },\n { value: 'ES', label: 'Espanha' },\n { value: 'US', label: 'Estados Unidos' },\n ]}\n />\n\n <div className=\"flex gap-4\">\n <SelectField\n label=\"Tipo de pessoa\"\n placeholder=\"Selecione\"\n value={personType}\n onChange={(value) => {\n setValue('personType', value as 'pf' | 'pj');\n setValue('cpf', '');\n setValue('cnpj', '');\n }}\n options={[\n { value: 'pf', label: 'Pessoa física' },\n { value: 'pj', label: 'Pessoa jurídica' },\n ]}\n containerClassName=\"flex-1\"\n />\n <div className=\"flex-1\">\n {personType === 'pj' ? (\n <FormField\n label=\"CNPJ\"\n placeholder=\"__.___.___/____-__\"\n {...register('cnpj', {\n onChange: (e) => {\n setValue('cnpj', formatCNPJ(e.target.value));\n },\n })}\n error={!!errors.cpf}\n errorMessage={errors.cpf?.message}\n />\n ) : (\n <FormField\n label=\"CPF\"\n placeholder=\"___.___.___-__\"\n {...register('cpf', {\n onChange: (e) => {\n setValue('cpf', formatCPF(e.target.value));\n },\n })}\n error={!!errors.cpf}\n errorMessage={errors.cpf?.message}\n />\n )}\n </div>\n </div>\n </div>\n );\n}\n\ntype BillingFormFieldsProps = {\n readonly form: UseFormReturn<CardFormData>;\n};\n\nexport function BillingFormFields({ form }: BillingFormFieldsProps) {\n const {\n register,\n setValue,\n formState: { errors },\n } = form;\n\n return (\n <div className=\"flex flex-col gap-5\">\n <FormField\n label=\"Nome completo\"\n placeholder=\"Digite aqui\"\n {...register('fullName')}\n error={!!errors.fullName}\n errorMessage={errors.fullName?.message}\n />\n\n <FormField\n label=\"CEP\"\n placeholder=\"_____-___\"\n {...register('cep', {\n onChange: (e) => {\n setValue('cep', formatPostalCode(e.target.value));\n },\n })}\n error={!!errors.cep}\n errorMessage={errors.cep?.message}\n />\n\n <div className=\"flex gap-4\">\n <div className=\"flex-[2]\">\n <FormField\n label=\"Endereço\"\n placeholder=\"\"\n {...register('street')}\n error={!!errors.street}\n errorMessage={errors.street?.message}\n />\n </div>\n <div className=\"flex-1\">\n <FormField\n label=\"Número\"\n placeholder=\"\"\n {...register('streetNumber')}\n error={!!errors.streetNumber}\n errorMessage={errors.streetNumber?.message}\n />\n </div>\n </div>\n\n <div className=\"flex gap-4\">\n <div className=\"flex-1\">\n <FormField\n label=\"Cidade\"\n placeholder=\"\"\n {...register('city')}\n error={!!errors.city}\n errorMessage={errors.city?.message}\n />\n </div>\n <div className=\"flex-1\">\n <FormField\n label=\"UF\"\n placeholder=\"\"\n {...register('state')}\n error={!!errors.state}\n errorMessage={errors.state?.message}\n />\n </div>\n </div>\n\n <FormField\n label=\"Complemento\"\n optional\n placeholder=\"\"\n {...register('complement')}\n error={!!errors.complement}\n errorMessage={errors.complement?.message}\n />\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,33 @@
1
+ const BR_STATE_OPTIONS = [
2
+ { value: "AC", label: "AC" },
3
+ { value: "AL", label: "AL" },
4
+ { value: "AP", label: "AP" },
5
+ { value: "AM", label: "AM" },
6
+ { value: "BA", label: "BA" },
7
+ { value: "CE", label: "CE" },
8
+ { value: "DF", label: "DF" },
9
+ { value: "ES", label: "ES" },
10
+ { value: "GO", label: "GO" },
11
+ { value: "MA", label: "MA" },
12
+ { value: "MT", label: "MT" },
13
+ { value: "MS", label: "MS" },
14
+ { value: "MG", label: "MG" },
15
+ { value: "PA", label: "PA" },
16
+ { value: "PB", label: "PB" },
17
+ { value: "PR", label: "PR" },
18
+ { value: "PE", label: "PE" },
19
+ { value: "PI", label: "PI" },
20
+ { value: "RJ", label: "RJ" },
21
+ { value: "RN", label: "RN" },
22
+ { value: "RS", label: "RS" },
23
+ { value: "RO", label: "RO" },
24
+ { value: "RR", label: "RR" },
25
+ { value: "SC", label: "SC" },
26
+ { value: "SP", label: "SP" },
27
+ { value: "SE", label: "SE" },
28
+ { value: "TO", label: "TO" }
29
+ ];
30
+ export {
31
+ BR_STATE_OPTIONS
32
+ };
33
+ //# sourceMappingURL=br-states.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/constants/br-states.ts"],"sourcesContent":["export const BR_STATE_OPTIONS = [\n { value: 'AC', label: 'AC' },\n { value: 'AL', label: 'AL' },\n { value: 'AP', label: 'AP' },\n { value: 'AM', label: 'AM' },\n { value: 'BA', label: 'BA' },\n { value: 'CE', label: 'CE' },\n { value: 'DF', label: 'DF' },\n { value: 'ES', label: 'ES' },\n { value: 'GO', label: 'GO' },\n { value: 'MA', label: 'MA' },\n { value: 'MT', label: 'MT' },\n { value: 'MS', label: 'MS' },\n { value: 'MG', label: 'MG' },\n { value: 'PA', label: 'PA' },\n { value: 'PB', label: 'PB' },\n { value: 'PR', label: 'PR' },\n { value: 'PE', label: 'PE' },\n { value: 'PI', label: 'PI' },\n { value: 'RJ', label: 'RJ' },\n { value: 'RN', label: 'RN' },\n { value: 'RS', label: 'RS' },\n { value: 'RO', label: 'RO' },\n { value: 'RR', label: 'RR' },\n { value: 'SC', label: 'SC' },\n { value: 'SP', label: 'SP' },\n { value: 'SE', label: 'SE' },\n { value: 'TO', label: 'TO' },\n];\n"],"mappings":"AAAO,MAAM,mBAAmB;AAAA,EAC9B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAAA,EAC3B,EAAE,OAAO,MAAM,OAAO,KAAK;AAC7B;","names":[]}
@@ -27,6 +27,16 @@ function formatPostalCode(value) {
27
27
  if (numbers.length <= 5) return numbers;
28
28
  return `${numbers.slice(0, 5)}-${numbers.slice(5, 8)}`;
29
29
  }
30
+ function formatCNPJ(value) {
31
+ const numbers = value.replace(/\D/g, "");
32
+ if (numbers.length <= 2) return numbers;
33
+ if (numbers.length <= 5) return `${numbers.slice(0, 2)}.${numbers.slice(2)}`;
34
+ if (numbers.length <= 8)
35
+ return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5)}`;
36
+ if (numbers.length <= 12)
37
+ return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5, 8)}/${numbers.slice(8)}`;
38
+ return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5, 8)}/${numbers.slice(8, 12)}-${numbers.slice(12, 14)}`;
39
+ }
30
40
  function formatPhone(value) {
31
41
  const numbers = value.replace(/\D/g, "").substring(0, 11);
32
42
  if (numbers.length <= 2) return numbers;
@@ -44,6 +54,7 @@ function formatTimer(seconds) {
44
54
  return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
45
55
  }
46
56
  export {
57
+ formatCNPJ,
47
58
  formatCPF,
48
59
  formatCardNumber,
49
60
  formatCvv,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/format/masks.ts"],"sourcesContent":["export function formatCardNumber(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n const groups = numbers.match(/.{1,4}/g);\r\n return groups ? groups.join(' ').substring(0, 19) : '';\r\n}\r\n\r\nexport function formatExpiry(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length >= 2) {\r\n return numbers.substring(0, 2) + '/' + numbers.substring(2, 4);\r\n }\r\n return numbers;\r\n}\r\n\r\nexport function formatCvv(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n return numbers.substring(0, 4);\r\n}\r\n\r\nexport function formatCPF(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length <= 3) return numbers;\r\n if (numbers.length <= 6) return `${numbers.slice(0, 3)}.${numbers.slice(3)}`;\r\n if (numbers.length <= 9)\r\n return `${numbers.slice(0, 3)}.${numbers.slice(3, 6)}.${numbers.slice(6)}`;\r\n return `${numbers.slice(0, 3)}.${numbers.slice(3, 6)}.${numbers.slice(6, 9)}-${numbers.slice(9, 11)}`;\r\n}\r\n\r\nexport function formatPostalCode(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length <= 5) return numbers;\r\n return `${numbers.slice(0, 5)}-${numbers.slice(5, 8)}`;\r\n}\r\n\r\nexport function formatPhone(value: string): string {\r\n const numbers = value.replace(/\\D/g, '').substring(0, 11);\r\n if (numbers.length <= 2) return numbers;\r\n if (numbers.length <= 6) return `(${numbers.slice(0, 2)}) ${numbers.slice(2)}`;\r\n if (numbers.length <= 10)\r\n return `(${numbers.slice(0, 2)}) ${numbers.slice(2, 6)}-${numbers.slice(6)}`;\r\n return `(${numbers.slice(0, 2)}) ${numbers.slice(2, 3)} ${numbers.slice(3, 7)}-${numbers.slice(7)}`;\r\n}\r\n\r\nexport function formatFullName(value: string): string {\r\n return value.replace(/[^a-zA-ZÀ-ÿ\\s]/g, '');\r\n}\r\n\r\nexport function formatTimer(seconds: number): string {\r\n const m = Math.floor(seconds / 60);\r\n const s = seconds % 60;\r\n return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\r\n}\r\n"],"mappings":"AAAO,SAAS,iBAAiB,OAAuB;AACtD,QAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;AACvC,QAAM,SAAS,QAAQ,MAAM,SAAS;AACtC,SAAO,SAAS,OAAO,KAAK,GAAG,EAAE,UAAU,GAAG,EAAE,IAAI;AACtD;AAEO,SAAS,aAAa,OAAuB;AAClD,QAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;AACvC,MAAI,QAAQ,UAAU,GAAG;AACvB,WAAO,QAAQ,UAAU,GAAG,CAAC,IAAI,MAAM,QAAQ,UAAU,GAAG,CAAC;AAAA,EAC/D;AACA,SAAO;AACT;AAEO,SAAS,UAAU,OAAuB;AAC/C,QAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;AACvC,SAAO,QAAQ,UAAU,GAAG,CAAC;AAC/B;AAEO,SAAS,UAAU,OAAuB;AAC/C,QAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;AACvC,MAAI,QAAQ,UAAU,EAAG,QAAO;AAChC,MAAI,QAAQ,UAAU,EAAG,QAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AAC1E,MAAI,QAAQ,UAAU;AACpB,WAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AAC1E,SAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,GAAG,EAAE,CAAC;AACrG;AAEO,SAAS,iBAAiB,OAAuB;AACtD,QAAM,UAAU,MAAM,QAAQ,OAAO,EAAE;AACvC,MAAI,QAAQ,UAAU,EAAG,QAAO;AAChC,SAAO,GAAG,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC;AACtD;AAEO,SAAS,YAAY,OAAuB;AACjD,QAAM,UAAU,MAAM,QAAQ,OAAO,EAAE,EAAE,UAAU,GAAG,EAAE;AACxD,MAAI,QAAQ,UAAU,EAAG,QAAO;AAChC,MAAI,QAAQ,UAAU,EAAG,QAAO,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,MAAM,CAAC,CAAC;AAC5E,MAAI,QAAQ,UAAU;AACpB,WAAO,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AAC5E,SAAO,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AACnG;AAEO,SAAS,eAAe,OAAuB;AACpD,SAAO,MAAM,QAAQ,mBAAmB,EAAE;AAC5C;AAEO,SAAS,YAAY,SAAyB;AACnD,QAAM,IAAI,KAAK,MAAM,UAAU,EAAE;AACjC,QAAM,IAAI,UAAU;AACpB,SAAO,GAAG,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AACpE;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/format/masks.ts"],"sourcesContent":["export function formatCardNumber(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n const groups = numbers.match(/.{1,4}/g);\r\n return groups ? groups.join(' ').substring(0, 19) : '';\r\n}\r\n\r\nexport function formatExpiry(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length >= 2) {\r\n return numbers.substring(0, 2) + '/' + numbers.substring(2, 4);\r\n }\r\n return numbers;\r\n}\r\n\r\nexport function formatCvv(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n return numbers.substring(0, 4);\r\n}\r\n\r\nexport function formatCPF(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length <= 3) return numbers;\r\n if (numbers.length <= 6) return `${numbers.slice(0, 3)}.${numbers.slice(3)}`;\r\n if (numbers.length <= 9)\r\n return `${numbers.slice(0, 3)}.${numbers.slice(3, 6)}.${numbers.slice(6)}`;\r\n return `${numbers.slice(0, 3)}.${numbers.slice(3, 6)}.${numbers.slice(6, 9)}-${numbers.slice(9, 11)}`;\r\n}\r\n\r\nexport function formatPostalCode(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length <= 5) return numbers;\r\n return `${numbers.slice(0, 5)}-${numbers.slice(5, 8)}`;\r\n}\r\n\r\nexport function formatCNPJ(value: string): string {\r\n const numbers = value.replace(/\\D/g, '');\r\n if (numbers.length <= 2) return numbers;\r\n if (numbers.length <= 5) return `${numbers.slice(0, 2)}.${numbers.slice(2)}`;\r\n if (numbers.length <= 8)\r\n return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5)}`;\r\n if (numbers.length <= 12)\r\n return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5, 8)}/${numbers.slice(8)}`;\r\n return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5, 8)}/${numbers.slice(8, 12)}-${numbers.slice(12, 14)}`;\r\n}\r\n\r\nexport function formatPhone(value: string): string {\r\n const numbers = value.replace(/\\D/g, '').substring(0, 11);\r\n if (numbers.length <= 2) return numbers;\r\n if (numbers.length <= 6) return `(${numbers.slice(0, 2)}) ${numbers.slice(2)}`;\r\n if (numbers.length <= 10)\r\n return `(${numbers.slice(0, 2)}) ${numbers.slice(2, 6)}-${numbers.slice(6)}`;\r\n return `(${numbers.slice(0, 2)}) ${numbers.slice(2, 3)} ${numbers.slice(3, 7)}-${numbers.slice(7)}`;\r\n}\r\n\r\nexport function formatFullName(value: string): string {\r\n return value.replace(/[^a-zA-ZÀ-ÿ\\s]/g, '');\r\n}\r\n\r\nexport function formatTimer(seconds: number): string {\r\n const m = Math.floor(seconds / 60);\r\n const s = seconds % 60;\r\n return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.290",
3
+ "version": "1.1.291",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -16,6 +16,14 @@
16
16
  "./middleware": {
17
17
  "import": "./dist/middleware.mjs",
18
18
  "types": "./src/middleware.ts"
19
+ },
20
+ "./utils/constants/br-states": {
21
+ "import": "./dist/utils/constants/br-states.mjs",
22
+ "types": "./src/utils/constants/br-states.ts"
23
+ },
24
+ "./utils/format/masks": {
25
+ "import": "./dist/utils/format/masks.mjs",
26
+ "types": "./src/utils/format/masks.ts"
19
27
  }
20
28
  },
21
29
  "files": [
@@ -1,12 +1,13 @@
1
1
  'use client';
2
2
 
3
- import { useCallback } from 'react';
3
+ import { useCallback, useState } from 'react';
4
4
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../../ui/overlay/Dialog';
5
5
  import { Button } from '../../ui/buttons/Button';
6
6
  import { Toast } from '../../ui/feedback/Toast';
7
7
  import { useModalManager } from '../../../store/useModalManager';
8
8
  import { useCreateCard } from '../../../modules/cards/hooks/create-card.hook';
9
- import { CardFormFields, cardFormSchema } from './CardFormFields';
9
+ import { useUpdateAccount } from '../../../modules/accounts/hooks/useAccountManagement';
10
+ import { CardFormFields, BillingFormFields, cardFormSchema, STEP1_FIELDS } from './CardFormFields';
10
11
  import type { CardFormData } from './CardFormFields';
11
12
  import { IconX } from '@tabler/icons-react';
12
13
  import { useForm } from 'react-hook-form';
@@ -17,10 +18,12 @@ import { toast } from 'sonner';
17
18
  export default function AddCardModal() {
18
19
  const { activeModal, modalData, closeModal } = useModalManager();
19
20
  const isOpen = activeModal === 'addCardModal';
21
+ const [currentStep, setCurrentStep] = useState(1);
20
22
 
21
23
  const onCardAdded = modalData.onCardAdded as ((cardId: string) => void) | undefined;
22
24
 
23
25
  const createCardMutation = useCreateCard();
26
+ const updateAccountMutation = useUpdateAccount();
24
27
  const elements = useElements();
25
28
  const stripe = useStripe();
26
29
 
@@ -30,14 +33,27 @@ export default function AddCardModal() {
30
33
  reValidateMode: 'onChange',
31
34
  defaultValues: {
32
35
  country: 'BR',
36
+ personType: 'pf',
33
37
  },
34
38
  });
35
39
 
36
40
  const handleClose = useCallback(() => {
37
41
  form.reset();
42
+ setCurrentStep(1);
38
43
  closeModal();
39
44
  }, [form, closeModal]);
40
45
 
46
+ const handleContinue = useCallback(async () => {
47
+ const valid = await form.trigger(STEP1_FIELDS as unknown as (keyof CardFormData)[]);
48
+ if (valid) {
49
+ setCurrentStep(2);
50
+ }
51
+ }, [form]);
52
+
53
+ const handleBack = useCallback(() => {
54
+ setCurrentStep(1);
55
+ }, []);
56
+
41
57
  async function handleSubmit(data: CardFormData) {
42
58
  if (!stripe || !elements) return;
43
59
 
@@ -48,10 +64,14 @@ export default function AddCardModal() {
48
64
  type: 'card',
49
65
  card: cardElement,
50
66
  billing_details: {
51
- name: data.name,
67
+ name: data.fullName,
52
68
  address: {
53
69
  country: data.country,
54
- postal_code: data.postalCode,
70
+ postal_code: data.cep,
71
+ line1: `${data.street}, ${data.streetNumber}`,
72
+ line2: data.complement || undefined,
73
+ city: data.city,
74
+ state: data.state,
55
75
  },
56
76
  },
57
77
  });
@@ -70,38 +90,49 @@ export default function AddCardModal() {
70
90
  return;
71
91
  }
72
92
 
73
- const result = await createCardMutation.mutateAsync(
74
- { payment_method_id: paymentMethod.id },
75
- {
76
- onError: () => {
77
- handleClose();
78
- toast.custom(
79
- (t) => (
80
- <Toast
81
- variant="error"
82
- message="Não foi possível salvar o seu novo cartão, tente novamente."
83
- toastId={t}
84
- />
85
- ),
86
- { duration: 5000 }
87
- );
88
- },
93
+ try {
94
+ const [cardResult] = await Promise.all([
95
+ createCardMutation.mutateAsync({ payment_method_id: paymentMethod.id }),
96
+ updateAccountMutation.mutateAsync({
97
+ financial_document_type: data.personType === 'pf' ? 1 : 2,
98
+ financial_document: data.personType === 'pf' ? data.cpf : data.cnpj,
99
+ financial_name: data.fullName,
100
+ zipcode: data.cep,
101
+ address: data.street,
102
+ address_number: data.streetNumber,
103
+ address_complement: data.complement || '',
104
+ city: data.city,
105
+ state: data.state,
106
+ }),
107
+ ]);
108
+
109
+ if (cardResult.success && cardResult.data?.id != null) {
110
+ onCardAdded?.(cardResult.data.id.toString());
89
111
  }
90
- );
91
112
 
92
- if (result.success && result.data?.id != null) {
93
- onCardAdded?.(result.data.id.toString());
113
+ toast.custom(
114
+ (t) => <Toast variant="success" message="Cartão adicionado com sucesso." toastId={t} />,
115
+ { duration: 5000 }
116
+ );
117
+ handleClose();
118
+ } catch {
119
+ toast.custom(
120
+ (t) => (
121
+ <Toast
122
+ variant="error"
123
+ message="Não foi possível salvar o seu novo cartão, tente novamente."
124
+ toastId={t}
125
+ />
126
+ ),
127
+ { duration: 5000 }
128
+ );
94
129
  }
95
-
96
- toast.custom(
97
- (t) => <Toast variant="success" message="Cartão adicionado com sucesso." toastId={t} />,
98
- { duration: 5000 }
99
- );
100
- handleClose();
101
130
  }
102
131
 
103
- const isSubmitting = createCardMutation.isPending || form.formState.isSubmitting;
104
- const isValid = form.formState.isValid;
132
+ const isSubmitting =
133
+ createCardMutation.isPending ||
134
+ updateAccountMutation.isPending ||
135
+ form.formState.isSubmitting;
105
136
 
106
137
  return (
107
138
  <Dialog open={isOpen} onOpenChange={handleClose}>
@@ -112,7 +143,7 @@ export default function AddCardModal() {
112
143
  <DialogHeader className="p-0">
113
144
  <div className="flex items-center justify-center px-4 py-3 relative border-b border-zinc-200 lg:border-b-0">
114
145
  <DialogTitle className="paragraph-medium-semibold text-zinc-950 text-center">
115
- Adicionar cartão
146
+ {currentStep === 1 ? 'Adicionar cartão' : 'Dados de cobrança'}
116
147
  </DialogTitle>
117
148
  <Button
118
149
  type="button"
@@ -125,21 +156,46 @@ export default function AddCardModal() {
125
156
  </div>
126
157
  </DialogHeader>
127
158
 
159
+ {/* Progress bar */}
160
+ <div className="h-1 bg-zinc-100 w-full">
161
+ <div
162
+ className="h-full bg-cyan-400 transition-all duration-300 ease-in-out"
163
+ style={{ width: currentStep === 1 ? '50%' : '100%' }}
164
+ />
165
+ </div>
166
+
128
167
  <form
129
168
  onSubmit={form.handleSubmit(handleSubmit)}
130
169
  className="flex flex-col flex-1 lg:flex-none"
131
170
  >
132
171
  <div className="flex flex-col gap-6 lg:gap-8 p-4 lg:p-5 flex-1 lg:flex-none">
133
- <CardFormFields form={form} />
172
+ {currentStep === 1 ? (
173
+ <CardFormFields form={form} />
174
+ ) : (
175
+ <BillingFormFields form={form} />
176
+ )}
134
177
  </div>
135
178
 
136
179
  <div className="flex justify-between items-center p-4 lg:p-5 border-t border-zinc-200 gap-2 mt-auto lg:mt-0">
137
- <Button variant="secondary" type="button" onClick={handleClose} className="h-10!">
138
- Cancelar
139
- </Button>
140
- <Button type="submit" className="h-10!" disabled={isSubmitting || !isValid}>
141
- {isSubmitting ? 'Adicionando cartão...' : 'Adicionar cartão'}
142
- </Button>
180
+ {currentStep === 1 ? (
181
+ <>
182
+ <Button variant="secondary" type="button" onClick={handleClose} className="h-10!">
183
+ Cancelar
184
+ </Button>
185
+ <Button type="button" className="h-10!" onClick={handleContinue}>
186
+ Continuar
187
+ </Button>
188
+ </>
189
+ ) : (
190
+ <>
191
+ <Button variant="secondary" type="button" onClick={handleBack} className="h-10!">
192
+ Voltar
193
+ </Button>
194
+ <Button type="submit" className="h-10!" disabled={isSubmitting}>
195
+ {isSubmitting ? 'Adicionando cartão...' : 'Adicionar cartão'}
196
+ </Button>
197
+ </>
198
+ )}
143
199
  </div>
144
200
  </form>
145
201
  </DialogContent>
@@ -3,7 +3,7 @@
3
3
  import { UseFormReturn } from 'react-hook-form';
4
4
  import { FormField } from '../../ui/form/FormField';
5
5
  import { SelectField } from '../../ui/form/SelectField';
6
- import { formatCPF, formatPostalCode } from '../../../utils/format/masks';
6
+ import { formatCPF, formatCNPJ, formatPostalCode } from '../../../utils/format/masks';
7
7
  import z from 'zod';
8
8
  import { CardCvcElement, CardExpiryElement, CardNumberElement } from '@stripe/react-stripe-js';
9
9
 
@@ -20,18 +20,39 @@ const stripeElementOptions = {
20
20
  },
21
21
  };
22
22
 
23
- export const cardFormSchema = z.object({
24
- name: z.string().min(1, 'Nome é obrigatório'),
25
- number: z.string().min(1, 'Número do cartão é obrigatório'),
26
- expiry: z.string().min(1, 'Data de validade é obrigatória'),
27
- cvv: z.string().min(1, 'Código de segurança é obrigatório'),
28
- country: z.string().min(1, 'País é obrigatório'),
29
- postalCode: z.string().optional(),
30
- cpf: z.string().min(14, 'CPF é obrigatório'),
31
- });
23
+ export const cardFormSchema = z
24
+ .object({
25
+ name: z.string().min(1, 'Nome é obrigatório'),
26
+ number: z.string().min(1, 'Número do cartão é obrigatório'),
27
+ expiry: z.string().min(1, 'Data de validade é obrigatória'),
28
+ cvv: z.string().min(1, 'Código de segurança é obrigatório'),
29
+ country: z.string().min(1, 'País é obrigatório'),
30
+ personType: z.enum(['pf', 'pj']),
31
+ cpf: z.string().optional(),
32
+ cnpj: z.string().optional(),
33
+ fullName: z.string().min(1, 'Nome completo é obrigatório'),
34
+ cep: z.string().min(9, 'CEP é obrigatório'),
35
+ street: z.string().min(1, 'Endereço é obrigatório'),
36
+ streetNumber: z.string().min(1, 'Número é obrigatório'),
37
+ city: z.string().min(1, 'Cidade é obrigatória'),
38
+ state: z.string().min(1, 'UF é obrigatório'),
39
+ complement: z.string().optional(),
40
+ })
41
+ .refine(
42
+ (data) => {
43
+ if (data.personType === 'pf') return !!data.cpf && data.cpf.length >= 14;
44
+ return !!data.cnpj && data.cnpj.length >= 18;
45
+ },
46
+ {
47
+ message: 'Documento é obrigatório',
48
+ path: ['cpf'],
49
+ }
50
+ );
32
51
 
33
52
  export type CardFormData = z.infer<typeof cardFormSchema>;
34
53
 
54
+ export const STEP1_FIELDS = ['name', 'number', 'expiry', 'cvv', 'country', 'personType', 'cpf', 'cnpj'] as const;
55
+
35
56
  type CardFormFieldsProps = {
36
57
  readonly form: UseFormReturn<CardFormData>;
37
58
  };
@@ -44,6 +65,8 @@ export function CardFormFields({ form }: CardFormFieldsProps) {
44
65
  formState: { errors },
45
66
  } = form;
46
67
 
68
+ const personType = watch('personType');
69
+
47
70
  return (
48
71
  <div className="flex flex-col gap-5">
49
72
  <FormField
@@ -55,9 +78,7 @@ export function CardFormFields({ form }: CardFormFieldsProps) {
55
78
  />
56
79
 
57
80
  <div className="flex flex-col gap-1.5">
58
- <label className="paragraph-xsmall-semibold text-zinc-600">
59
- Número do cartão
60
- </label>
81
+ <label className="paragraph-xsmall-semibold text-zinc-600">Número do cartão</label>
61
82
  <div className="h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400 relative">
62
83
  <div className="w-full">
63
84
  <CardNumberElement
@@ -75,9 +96,7 @@ export function CardFormFields({ form }: CardFormFieldsProps) {
75
96
 
76
97
  <div className="flex gap-4">
77
98
  <div className="flex-1 flex flex-col gap-1.5">
78
- <label className="paragraph-xsmall-semibold text-zinc-600">
79
- Data de validade
80
- </label>
99
+ <label className="paragraph-xsmall-semibold text-zinc-600">Data de validade</label>
81
100
  <div className="h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400">
82
101
  <div className="w-full">
83
102
  <CardExpiryElement
@@ -94,9 +113,7 @@ export function CardFormFields({ form }: CardFormFieldsProps) {
94
113
  </div>
95
114
 
96
115
  <div className="flex-1 flex flex-col gap-1.5">
97
- <label className="paragraph-xsmall-semibold text-zinc-600">
98
- CVC
99
- </label>
116
+ <label className="paragraph-xsmall-semibold text-zinc-600">CVC</label>
100
117
  <div className="h-10 px-3 flex items-center w-full border border-zinc-200 rounded-lg bg-white transition-colors focus-within:border-zinc-400">
101
118
  <div className="w-full">
102
119
  <CardCvcElement
@@ -113,45 +130,148 @@ export function CardFormFields({ form }: CardFormFieldsProps) {
113
130
  </div>
114
131
  </div>
115
132
 
133
+ <SelectField
134
+ label="País"
135
+ placeholder="Selecione"
136
+ value={watch('country')}
137
+ onChange={(value) => setValue('country', value as string)}
138
+ options={[
139
+ { value: 'BR', label: 'Brasil' },
140
+ { value: 'ES', label: 'Espanha' },
141
+ { value: 'US', label: 'Estados Unidos' },
142
+ ]}
143
+ />
144
+
116
145
  <div className="flex gap-4">
117
146
  <SelectField
118
- label="País"
147
+ label="Tipo de pessoa"
119
148
  placeholder="Selecione"
120
- value={watch('country')}
121
- onChange={(value) => setValue('country', value as string)}
149
+ value={personType}
150
+ onChange={(value) => {
151
+ setValue('personType', value as 'pf' | 'pj');
152
+ setValue('cpf', '');
153
+ setValue('cnpj', '');
154
+ }}
122
155
  options={[
123
- { value: 'BR', label: 'Brasil' },
124
- { value: 'ES', label: 'Espanha' },
125
- { value: 'US', label: 'Estados Unidos' },
156
+ { value: 'pf', label: 'Pessoa física' },
157
+ { value: 'pj', label: 'Pessoa jurídica' },
126
158
  ]}
127
159
  containerClassName="flex-1"
128
160
  />
129
161
  <div className="flex-1">
130
- <FormField
131
- label="Código postal"
132
- optional
133
- placeholder=""
134
- {...register('postalCode', {
135
- onChange: (e) => {
136
- setValue('postalCode', formatPostalCode(e.target.value));
137
- },
138
- })}
139
- error={!!errors.postalCode}
140
- errorMessage={errors.postalCode?.message}
141
- />
162
+ {personType === 'pj' ? (
163
+ <FormField
164
+ label="CNPJ"
165
+ placeholder="__.___.___/____-__"
166
+ {...register('cnpj', {
167
+ onChange: (e) => {
168
+ setValue('cnpj', formatCNPJ(e.target.value));
169
+ },
170
+ })}
171
+ error={!!errors.cpf}
172
+ errorMessage={errors.cpf?.message}
173
+ />
174
+ ) : (
175
+ <FormField
176
+ label="CPF"
177
+ placeholder="___.___.___-__"
178
+ {...register('cpf', {
179
+ onChange: (e) => {
180
+ setValue('cpf', formatCPF(e.target.value));
181
+ },
182
+ })}
183
+ error={!!errors.cpf}
184
+ errorMessage={errors.cpf?.message}
185
+ />
186
+ )}
142
187
  </div>
143
188
  </div>
189
+ </div>
190
+ );
191
+ }
192
+
193
+ type BillingFormFieldsProps = {
194
+ readonly form: UseFormReturn<CardFormData>;
195
+ };
196
+
197
+ export function BillingFormFields({ form }: BillingFormFieldsProps) {
198
+ const {
199
+ register,
200
+ setValue,
201
+ formState: { errors },
202
+ } = form;
203
+
204
+ return (
205
+ <div className="flex flex-col gap-5">
206
+ <FormField
207
+ label="Nome completo"
208
+ placeholder="Digite aqui"
209
+ {...register('fullName')}
210
+ error={!!errors.fullName}
211
+ errorMessage={errors.fullName?.message}
212
+ />
144
213
 
145
214
  <FormField
146
- label="CPF"
147
- placeholder="___.___.___-__"
148
- {...register('cpf', {
215
+ label="CEP"
216
+ placeholder="_____-___"
217
+ {...register('cep', {
149
218
  onChange: (e) => {
150
- setValue('cpf', formatCPF(e.target.value));
219
+ setValue('cep', formatPostalCode(e.target.value));
151
220
  },
152
221
  })}
153
- error={!!errors.cpf}
154
- errorMessage={errors.cpf?.message}
222
+ error={!!errors.cep}
223
+ errorMessage={errors.cep?.message}
224
+ />
225
+
226
+ <div className="flex gap-4">
227
+ <div className="flex-[2]">
228
+ <FormField
229
+ label="Endereço"
230
+ placeholder=""
231
+ {...register('street')}
232
+ error={!!errors.street}
233
+ errorMessage={errors.street?.message}
234
+ />
235
+ </div>
236
+ <div className="flex-1">
237
+ <FormField
238
+ label="Número"
239
+ placeholder=""
240
+ {...register('streetNumber')}
241
+ error={!!errors.streetNumber}
242
+ errorMessage={errors.streetNumber?.message}
243
+ />
244
+ </div>
245
+ </div>
246
+
247
+ <div className="flex gap-4">
248
+ <div className="flex-1">
249
+ <FormField
250
+ label="Cidade"
251
+ placeholder=""
252
+ {...register('city')}
253
+ error={!!errors.city}
254
+ errorMessage={errors.city?.message}
255
+ />
256
+ </div>
257
+ <div className="flex-1">
258
+ <FormField
259
+ label="UF"
260
+ placeholder=""
261
+ {...register('state')}
262
+ error={!!errors.state}
263
+ errorMessage={errors.state?.message}
264
+ />
265
+ </div>
266
+ </div>
267
+
268
+ <FormField
269
+ label="Complemento"
270
+ optional
271
+ placeholder=""
272
+ {...register('complement')}
273
+ error={!!errors.complement}
274
+ errorMessage={errors.complement?.message}
155
275
  />
156
276
  </div>
157
277
  );
@@ -146,6 +146,16 @@ export interface UpdateAccountRequest {
146
146
  currency?: string;
147
147
  timezone?: string;
148
148
  bussiness_type?: number;
149
+ financial_document_type?: number;
150
+ financial_document?: string;
151
+ financial_name?: string;
152
+ zipcode?: string;
153
+ address?: string;
154
+ address_number?: string;
155
+ address_complement?: string;
156
+ neighborhood?: string;
157
+ city?: string;
158
+ state?: string;
149
159
  }
150
160
 
151
161
  export interface UpdateAccountResponse {
@@ -0,0 +1,29 @@
1
+ export const BR_STATE_OPTIONS = [
2
+ { value: 'AC', label: 'AC' },
3
+ { value: 'AL', label: 'AL' },
4
+ { value: 'AP', label: 'AP' },
5
+ { value: 'AM', label: 'AM' },
6
+ { value: 'BA', label: 'BA' },
7
+ { value: 'CE', label: 'CE' },
8
+ { value: 'DF', label: 'DF' },
9
+ { value: 'ES', label: 'ES' },
10
+ { value: 'GO', label: 'GO' },
11
+ { value: 'MA', label: 'MA' },
12
+ { value: 'MT', label: 'MT' },
13
+ { value: 'MS', label: 'MS' },
14
+ { value: 'MG', label: 'MG' },
15
+ { value: 'PA', label: 'PA' },
16
+ { value: 'PB', label: 'PB' },
17
+ { value: 'PR', label: 'PR' },
18
+ { value: 'PE', label: 'PE' },
19
+ { value: 'PI', label: 'PI' },
20
+ { value: 'RJ', label: 'RJ' },
21
+ { value: 'RN', label: 'RN' },
22
+ { value: 'RS', label: 'RS' },
23
+ { value: 'RO', label: 'RO' },
24
+ { value: 'RR', label: 'RR' },
25
+ { value: 'SC', label: 'SC' },
26
+ { value: 'SP', label: 'SP' },
27
+ { value: 'SE', label: 'SE' },
28
+ { value: 'TO', label: 'TO' },
29
+ ];
@@ -32,6 +32,17 @@ export function formatPostalCode(value: string): string {
32
32
  return `${numbers.slice(0, 5)}-${numbers.slice(5, 8)}`;
33
33
  }
34
34
 
35
+ export function formatCNPJ(value: string): string {
36
+ const numbers = value.replace(/\D/g, '');
37
+ if (numbers.length <= 2) return numbers;
38
+ if (numbers.length <= 5) return `${numbers.slice(0, 2)}.${numbers.slice(2)}`;
39
+ if (numbers.length <= 8)
40
+ return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5)}`;
41
+ if (numbers.length <= 12)
42
+ return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5, 8)}/${numbers.slice(8)}`;
43
+ return `${numbers.slice(0, 2)}.${numbers.slice(2, 5)}.${numbers.slice(5, 8)}/${numbers.slice(8, 12)}-${numbers.slice(12, 14)}`;
44
+ }
45
+
35
46
  export function formatPhone(value: string): string {
36
47
  const numbers = value.replace(/\D/g, '').substring(0, 11);
37
48
  if (numbers.length <= 2) return numbers;