= {}
+
+ if (!firstName) {
+ errors.firstName = 'El nombre is required'
+ }else if(firstName.length < 3 ){
+ errors.firstName = 'El nombre min length >=3'
+ }
+ if (!lastName) {
+ errors.lastName = 'El apellido is required'
+ }else if(lastName.length < 3 ){
+ errors.lastName = 'El apellido min length >=3'
+ }
+ if (!email) {
+ errors.email = 'El email is required';
+ } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
+ errors.email = 'Invalid email address';
+ }
+
+ return errors
+ }
+
+ const { handleChange, values, handleSubmit, errors, touched, handleBlur } = useFormik({
+ initialValues: {
+ firstName: '',
+ lastName: '',
+ email: ''
+ },
+ onSubmit: (values) => {
+ console.log({values})
+ },
+ validate: (values) => validate(values)
+ })
+
+
+ return (
+
+
Formik Basic Tutorial
+
+
+ )
+}
+
+export default FormikBasicPage
\ No newline at end of file
diff --git a/src/03-forms/pages/FormikComponentPage.tsx b/src/03-forms/pages/FormikComponentPage.tsx
new file mode 100644
index 000000000..8c37360a1
--- /dev/null
+++ b/src/03-forms/pages/FormikComponentPage.tsx
@@ -0,0 +1,87 @@
+import { Field, ErrorMessage, Form, Formik } from 'formik'
+import React from 'react'
+import * as Yup from 'yup'
+import '../styles/styles.css'
+
+
+
+const FormikComponentPage = () => {
+
+
+ return (
+
+
Formik Component Tutorial
+ {
+ console.log( values )
+ }}
+ validationSchema={Yup.object({
+ firstName: Yup.string()
+ .max(15, 'Debe de tener 15 caracteres o menos')
+ .required('Requerido'),
+ lastName: Yup.string()
+ .max(15, 'Debe de tener 15 caracteres o menos')
+ .required('Requerido'),
+ email: Yup.string()
+ .email('El correo no tiene un formato válido')
+ .required('Requerido'),
+ terms: Yup.boolean()
+ .oneOf([true], 'Debe de aceptar las condiciones'),
+ jobType: Yup.string()
+ .notOneOf([ 'it-jr' ], 'Esta opción no es permitida.')
+ .required('Requerido')
+ })
+ }>
+
+ {(formik) => (
+
+ )
+ }
+
+
+
+
+
+ )
+}
+
+export default FormikComponentPage
\ No newline at end of file
diff --git a/src/03-forms/pages/FormikDynamicForm.tsx b/src/03-forms/pages/FormikDynamicForm.tsx
new file mode 100644
index 000000000..ed7f29e49
--- /dev/null
+++ b/src/03-forms/pages/FormikDynamicForm.tsx
@@ -0,0 +1,89 @@
+import React from 'react'
+import {Field, Form, Formik} from 'formik'
+import formJson from '../data/custom-form.json'
+import { MySelect, MyTextInput } from '../components'
+import * as Yup from 'yup';
+
+const initialValues: { [key:string] : any} = {}
+const requiredFields: { [key:string] : any} = {}
+
+for (const item of formJson) {
+ Object.assign(initialValues, {[item.name]: item.value})
+
+ if (!item.validations) { continue }
+ let schema = Yup.string()
+ for (const validation of item.validations) {
+ if (validation.type === 'required') {
+ schema = schema.required("Required")
+ }
+ if (validation.type === 'email') {
+ schema = schema.email("Formato de email no valido")
+ }
+ if (validation.type === 'minLength') {
+ schema = schema.min((validation as any).value, `Minimo ${(validation as any).value} caracteres`)
+ }
+ }
+ requiredFields[item.name] = schema
+}
+
+const FormikDynamicFormPage = () => {
+ return (
+
+
Formik Dynamic Form
+ {
+ console.log({values})
+ }}
+ validationSchema={
+ Yup.object({...requiredFields})
+ }
+ >
+ {(formik)=>(
+
+ )}
+
+
+ )
+}
+
+export default FormikDynamicFormPage
\ No newline at end of file
diff --git a/src/03-forms/pages/FormikYupPage.tsx b/src/03-forms/pages/FormikYupPage.tsx
new file mode 100644
index 000000000..dbd9c14cd
--- /dev/null
+++ b/src/03-forms/pages/FormikYupPage.tsx
@@ -0,0 +1,68 @@
+import { useFormik } from 'formik'
+import React from 'react'
+import * as Yup from 'yup'
+import '../styles/styles.css'
+
+
+
+const FormikYupPage = () => {
+
+
+ const {
+ handleSubmit, errors,
+ touched, getFieldProps
+} = useFormik({
+ initialValues: {
+ firstName: '',
+ lastName: '',
+ email: ''
+ },
+ onSubmit: (values) => {
+ console.log({values})
+ },
+ validationSchema: Yup.object({
+ firstName: Yup.string().required('El nombre es requerido').min(3, 'Minimo 3 caracteres'),
+ lastName: Yup.string().required('El apellido es requerido').min(3, 'Minimo 3 caracteres'),
+ email: Yup.string().required('El nombre es requerido').email('Debe de ser un email valido')
+ })
+ })
+
+
+ return (
+
+
Formik Yup Tutorial
+
+
+ )
+}
+
+export default FormikYupPage
\ No newline at end of file
diff --git a/src/03-forms/pages/RegisterFormikPage.tsx b/src/03-forms/pages/RegisterFormikPage.tsx
new file mode 100644
index 000000000..1cad5c1fb
--- /dev/null
+++ b/src/03-forms/pages/RegisterFormikPage.tsx
@@ -0,0 +1,78 @@
+import '../styles/styles.css'
+import { ErrorMessage, Field, Form, Formik } from 'formik'
+import * as Yup from 'yup'
+import { MyTextInput } from '../components/MyTextInput';
+
+type DataForm = {
+ name: string
+ email: string
+ password1: string
+ password2: string
+}
+
+
+const RegisterFormikPage = () => {
+
+ return (
+
+
Register Formik Page
+ {
+ console.log( values )
+ }}
+ onReset={ ()=> console.log('reset') }
+ validationSchema={Yup.object({
+ name: Yup.string()
+ .required('Requerido')
+ .min(3, 'Debe de tener 3 o mas caracteres')
+ .max(15, 'Debe de tener 15 caracteres o menos'),
+ email: Yup.string()
+ .required('Requerido')
+ .email('El correo no tiene un formato válido'),
+ password1: Yup.string()
+ .required()
+ .min(6, 'Minimo 6 caracteres'),
+ password2: Yup.string()
+ .required()
+ .min(6, 'Minimo 6 caracteres' )
+ .oneOf([Yup.ref('password1')], 'Los password deben ser iguales')
+ })
+ }
+ >
+
+ {
+ (formik) => (
+
+ )
+ }
+
+
+
+
+ )
+}
+
+export default RegisterFormikPage
\ No newline at end of file
diff --git a/src/03-forms/pages/RegisterPage.tsx b/src/03-forms/pages/RegisterPage.tsx
new file mode 100644
index 000000000..4bf2e1d9e
--- /dev/null
+++ b/src/03-forms/pages/RegisterPage.tsx
@@ -0,0 +1,86 @@
+import { useRef } from 'react'
+import { useForm } from '../hooks/useForm'
+import '../styles/styles.css'
+
+type DataForm = {
+ name: string
+ email: string
+ password1: string
+ password2: string
+}
+
+
+const RegisterPage = () => {
+
+ const { formData: { name, email, password1, password2 }, onChange, onSubmit, reset, isValidEmail } = useForm({
+ name: '',
+ email: '',
+ password1: '',
+ password2: ''
+ })
+
+ const nameFocus = useRef(false)
+ const emailFocus = useRef(false)
+ const password1Focus = useRef(false)
+ const password2Focus = useRef(false)
+
+ return (
+
+
RegisterPage
+
+
+
+ )
+}
+
+export default RegisterPage
\ No newline at end of file
diff --git a/src/03-forms/pages/index.ts b/src/03-forms/pages/index.ts
new file mode 100644
index 000000000..10084f18b
--- /dev/null
+++ b/src/03-forms/pages/index.ts
@@ -0,0 +1,6 @@
+export * as FormikAbstractionPage from './FormikAbstractionPage'
+export * as FormikYupPage from './FormikYupPage'
+export * as FormikComponentPage from './FormikComponentPage'
+export * as FormikBasicPage from './FormikBasicPage'
+export * as RegisterPage from './RegisterPage'
+export * as FormikDynamicFormPage from './FormikDynamicForm'
diff --git a/src/03-forms/styles/styles.css b/src/03-forms/styles/styles.css
new file mode 100644
index 000000000..8ef67738e
--- /dev/null
+++ b/src/03-forms/styles/styles.css
@@ -0,0 +1,25 @@
+form {
+ display: flex;
+ flex-direction: column;
+ width: 400px;
+}
+
+input, select {
+ margin-top: 5px;
+ outline: none;
+ padding: 10px;
+}
+
+
+button {
+ margin-top: 20px;
+ padding: 10px;
+}
+
+span, .error-message {
+ color: red;
+}
+
+.has-error {
+ border: 1px solid red;
+}
\ No newline at end of file
diff --git a/src/routes/Navigation.tsx b/src/routes/Navigation.tsx
index a9bfe83b0..efc48972e 100644
--- a/src/routes/Navigation.tsx
+++ b/src/routes/Navigation.tsx
@@ -4,8 +4,17 @@ import {
Route,
NavLink
} from 'react-router-dom';
-
import logo from '../logo.svg';
+import RegisterPage from '../03-forms/pages/RegisterPage';
+import FormikBasicPage from '../03-forms/pages/FormikBasicPage';
+import FormikYupPage from '../03-forms/pages/FormikYupPage';
+import FormikComponentPage from '../03-forms/pages/FormikComponentPage';
+import FormikAbstractionPage from '../03-forms/pages/FormikAbstractionPage';
+import RegisterFormikPage from '../03-forms/pages/RegisterFormikPage';
+import FormikDynamicFormPage from '../03-forms/pages/FormikDynamicForm';
+
+
+
export const Navigation = () => {
return (
@@ -17,6 +26,28 @@ export const Navigation = () => {
Home
+
+
+ Register Page
+
+
+ Register Formik Page
+
+
+ Formik Basic
+
+
+ Formik Yup
+
+
+ Formik Component
+
+
+ Formik Abstraction
+
+
+ Formik Dynamic
+
About
@@ -29,6 +60,27 @@ export const Navigation = () => {
{/* A looks through its children s and
renders the first one that matches the current URL. */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
About
diff --git a/yarn.lock b/yarn.lock
index de24f7d62..7dc79833e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4001,6 +4001,11 @@ deep-is@^0.1.3, deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
+deepmerge@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
+ integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
+
deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
@@ -5125,6 +5130,19 @@ form-data@~2.3.2:
combined-stream "^1.0.6"
mime-types "^2.1.12"
+formik@^2.2.9:
+ version "2.2.9"
+ resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0"
+ integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==
+ dependencies:
+ deepmerge "^2.1.1"
+ hoist-non-react-statics "^3.3.0"
+ lodash "^4.17.21"
+ lodash-es "^4.17.21"
+ react-fast-compare "^2.0.1"
+ tiny-warning "^1.0.2"
+ tslib "^1.10.0"
+
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -5510,7 +5528,7 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-hoist-non-react-statics@^3.1.0:
+hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@@ -7008,6 +7026,11 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
+lodash-es@^4.17.21:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
+ integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -7043,7 +7066,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
-"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5:
+"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -8907,6 +8930,11 @@ prop-types@^15.6.2, prop-types@^15.7.2:
object-assign "^4.1.1"
react-is "^16.8.1"
+property-expr@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4"
+ integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==
+
proxy-addr@~2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
@@ -9118,6 +9146,11 @@ react-error-overlay@^6.0.9:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==
+react-fast-compare@^2.0.1:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
+ integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
+
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -10626,12 +10659,17 @@ timsort@^0.3.0:
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
+tiny-case@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03"
+ integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==
+
tiny-invariant@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875"
integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==
-tiny-warning@^1.0.0, tiny-warning@^1.0.3:
+tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
@@ -10688,6 +10726,11 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+toposort@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
+ integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==
+
tough-cookie@^2.3.3, tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@@ -10732,7 +10775,7 @@ tsconfig-paths@^3.9.0:
minimist "^1.2.0"
strip-bom "^3.0.0"
-tslib@^1.8.1, tslib@^1.9.0:
+tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
@@ -10805,6 +10848,11 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+type-fest@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
+ integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
+
type-is@~1.6.17, type-is@~1.6.18:
version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
@@ -11617,3 +11665,13 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+yup@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/yup/-/yup-1.0.2.tgz#1cf485f407f77e0407b450311f2981a1e66f7c58"
+ integrity sha512-Lpi8nITFKjWtCoK3yQP8MUk78LJmHWqbFd0OOMXTar+yjejlQ4OIIoZgnTW1bnEUKDw6dZBcy3/IdXnt2KDUow==
+ dependencies:
+ property-expr "^2.0.5"
+ tiny-case "^1.0.3"
+ toposort "^2.0.2"
+ type-fest "^2.19.0"