diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-16 17:06:25 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-01-16 17:06:25 +0700 |
| commit | 3a8b28198e51fff0a6f7d97b0ae2f6e0d3b73d47 (patch) | |
| tree | 5c0362c2998b5aa21ac1fdc95ba71b6121c2f149 /src | |
| parent | ecb4e0be9f7649f448191b016e744980541e6c75 (diff) | |
Fix delay input form
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/Fields.js | 19 | ||||
| -rw-r--r-- | src/pages/my/address/[id]/edit.js | 307 | ||||
| -rw-r--r-- | src/pages/my/address/create.js | 323 |
3 files changed, 327 insertions, 322 deletions
diff --git a/src/components/Fields.js b/src/components/Fields.js index 3db8bfdd..586a6a22 100644 --- a/src/components/Fields.js +++ b/src/components/Fields.js @@ -1,20 +1,19 @@ import ReactSelect from "react-select"; const Select = ({ - options, - name, - setFieldValue, - value, - disabled + field, + ...props }) => ( + <> <ReactSelect classNamePrefix="form-select" - options={options} - name={name} - onChange={(option) => setFieldValue(name, option.value)} - value={value ? options.find(option => option.value === value) : ''} - isDisabled={disabled} + ref={field.ref} + onChange={(option) => field.onChange(option.value)} + value={field.value ? props.options.find(option => option.value === field.value) : ''} + isDisabled={props.disabled} + {...props} /> + </> ); export { diff --git a/src/pages/my/address/[id]/edit.js b/src/pages/my/address/[id]/edit.js index 98bd05e7..78eef635 100644 --- a/src/pages/my/address/[id]/edit.js +++ b/src/pages/my/address/[id]/edit.js @@ -1,8 +1,9 @@ -import { useFormik } from "formik"; -import * as Yup from "yup"; +import { Controller, useForm } from "react-hook-form" import WithAuth from "../../../../components/WithAuth"; import Layout from "../../../../components/Layout"; import AppBar from "../../../../components/AppBar"; +import { yupResolver } from "@hookform/resolvers/yup"; +import * as Yup from "yup"; import { Select } from "../../../../components/Fields"; import { useEffect, useState } from "react"; import apiOdoo from "../../../../helpers/apiOdoo"; @@ -29,7 +30,7 @@ const types = [ export async function getServerSideProps( context ) { const { id } = context.query; const address = await apiOdoo('GET', `/api/v1/partner/${id}/address`); - let initialValues = { + let defaultValues = { type: address.type, name: address.name, email: address.email, @@ -37,197 +38,199 @@ export async function getServerSideProps( context ) { street: address.street, zip: address.zip, city: address.city?.id, - district: address.district?.id || null, - subDistrict: address.sub_district?.id || null + district: address.district?.id || '', + subDistrict: address.sub_district?.id || '' }; - return { props: { id, initialValues } }; + return { props: { id, defaultValues } }; } -export default function EditAddress({ id, initialValues }) { +export default function CreateAddress({ id, defaultValues }) { const router = useRouter(); - - const onSubmit = async (values) => { - const parameters = { - ...values, - city_id: values.city, - district_id: values.district, - sub_district_id: values.subDistrict - } - - const address = await apiOdoo('PUT', `/api/v1/partner/${id}/address`, parameters); - if (address?.id) { - toast.success('Berhasil mengubah alamat'); - router.back(); - } - }; - - const form = useFormik({ initialValues, validationSchema, onSubmit }); - const { - values, - errors, - touched, - handleChange, + register, + formState: { errors }, handleSubmit, - setFieldValue, - } = form; + watch, + setValue, + control, + } = useForm({ + resolver: yupResolver(validationSchema), + defaultValues + }); const [ cities, setCities ] = useState([]); const [ districts, setDistricts ] = useState([]); const [ subDistricts, setSubDistricts ] = useState([]); - useEffect(() => { - const loadCities = async () => { - let dataCities = await apiOdoo('GET', '/api/v1/city'); + useEffect(() => { + const loadCities = async () => { + let dataCities = await apiOdoo('GET', '/api/v1/city'); dataCities = dataCities.map((city) => ({ value: city.id, label: city.name })); setCities(dataCities); }; loadCities(); }, []); - + + const watchCity = watch('city'); useEffect(() => { - setFieldValue('district', ''); - if (values.city) { + setValue('district', ''); + if (watchCity) { const loadDistricts = async () => { - let dataDistricts = await apiOdoo('GET', `/api/v1/district?city_id=${values.city}`); + let dataDistricts = await apiOdoo('GET', `/api/v1/district?city_id=${watchCity}`); dataDistricts = dataDistricts.map((district) => ({ value: district.id, label: district.name })); setDistricts(dataDistricts); }; loadDistricts(); } - }, [ values.city, setFieldValue ]); - - useEffect(() => { - setFieldValue('subDistrict', ''); - if (values.district) { + }, [ watchCity, setValue ]); + + const watchDistrict = watch('district'); + useEffect(() => { + setValue('subDistrict', ''); + if (watchDistrict) { const loadSubDistricts = async () => { - let dataSubDistricts = await apiOdoo('GET', `/api/v1/sub_district?district_id=${values.district}`); + let dataSubDistricts = await apiOdoo('GET', `/api/v1/sub_district?district_id=${watchDistrict}`); dataSubDistricts = dataSubDistricts.map((district) => ({ value: district.id, label: district.name })); setSubDistricts(dataSubDistricts); }; loadSubDistricts(); } - }, [ values.district, setFieldValue ]); + }, [ watchDistrict, setValue ]) + + const onSubmitHandler = async (values) => { + const parameters = { + ...values, + city_id: values.city, + district_id: values.district, + sub_district_id: values.subDistrict + } + + const address = await apiOdoo('PUT', `/api/v1/partner/${id}/address`, parameters); + if (address?.id) { + toast.success('Berhasil mengubah alamat'); + router.back(); + } + }; return ( <WithAuth> <Layout> <AppBar title="Ubah Alamat" /> - <form onSubmit={handleSubmit} className="p-4 pt-0"> - <label className="form-label mt-4 mb-2">Label Alamat</label> - <Select - name="type" - options={types} - setFieldValue={setFieldValue} - value={values.type} - /> - { errors.type && touched.type && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.type }</div> - ) } - - <label className="form-label mt-4 mb-2">Nama</label> - <input - type="text" - className="form-input" - placeholder="John Doe" - onChange={handleChange} - value={values.name} - name="name" - /> - { errors.name && touched.name && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.name }</div> - ) } - - <label className="form-label mt-4 mb-2">Email</label> - <input - type="email" - className="form-input" - placeholder="johndoe@example.com" - onChange={handleChange} - value={values.email} - name="email" - /> - { errors.email && touched.email && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.email }</div> - ) } - - <label className="form-label mt-4 mb-2">No. Handphone</label> - <input - type="tel" - className="form-input" - placeholder="08xxxxxxxx" - onChange={handleChange} - value={values.mobile} - name="mobile" - /> - { errors.mobile && touched.mobile && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.mobile }</div> - ) } - - <label className="form-label mt-4 mb-2">Alamat</label> - <input - type="text" - className="form-input" - placeholder="Jl. Bandengan Utara 85A" - onChange={handleChange} - value={values.street} - name="street" - /> - { errors.street && touched.street && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.street }</div> - ) } - - <label className="form-label mt-4 mb-2">Kode Pos</label> - <input - type="number" - className="form-input" - placeholder="10100" - onChange={handleChange} - value={values.zip} - name="zip" - /> - { errors.zip && touched.zip && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.zip }</div> - ) } - - <label className="form-label mt-4 mb-2">Kota</label> - <Select - name="city" - options={cities} - setFieldValue={setFieldValue} - value={values.city} - /> - { errors.city && touched.city && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.city }</div> - ) } - - <label className="form-label mt-4 mb-2">Kecamatan</label> - <Select - name="district" - options={districts} - setFieldValue={setFieldValue} - value={values.district} - disabled={!values.city} - /> - - <label className="form-label mt-4 mb-2">Kelurahan</label> - <Select - name="subDistrict" - options={subDistricts} - setFieldValue={setFieldValue} - value={values.subDistrict} - disabled={!values.district} - /> + <form className="p-4 flex flex-col gap-y-4" onSubmit={handleSubmit(onSubmitHandler)}> + <div> + <label className="form-label mb-2">Label Alamat</label> + <Controller + name="type" + control={control} + render={props => <Select {...props} options={types} />} + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.type?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Nama</label> + <input + {...register('name')} + placeholder="John Doe" + type="text" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.name?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Email</label> + <input + {...register('email')} + placeholder="johndoe@example.com" + type="email" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.email?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Mobile</label> + <input + {...register('mobile')} + placeholder="08xxxxxxxx" + type="tel" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.mobile?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Alamat</label> + <input + {...register('street')} + placeholder="Jl. Bandengan Utara 85A" + type="text" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.street?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Kode Pos</label> + <input + {...register('zip')} + placeholder="10100" + type="number" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.zip?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Kota</label> + <Controller + name="city" + control={control} + render={props => <Select {...props} options={cities} />} + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.city?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Kecamatan</label> + <Controller + name="district" + control={control} + render={props => ( + <Select + {...props} + options={districts} + disabled={!watchCity} + /> + )} + /> + </div> + + <div> + <label className="form-label mb-2">Kelurahan</label> + <Controller + name="subDistrict" + control={control} + render={props => ( + <Select + {...props} + options={subDistricts} + disabled={!watchDistrict} + /> + )} + /> + </div> <button type="submit" - className="btn-yellow mt-6 w-full" + className="btn-yellow mt-2 w-full" > Simpan </button> </form> </Layout> </WithAuth> - ); + ) }
\ No newline at end of file diff --git a/src/pages/my/address/create.js b/src/pages/my/address/create.js index b04e67ec..5e9aaab8 100644 --- a/src/pages/my/address/create.js +++ b/src/pages/my/address/create.js @@ -1,8 +1,9 @@ -import { useFormik } from "formik"; -import * as Yup from "yup"; +import { Controller, useForm } from "react-hook-form" import WithAuth from "../../../components/WithAuth"; import Layout from "../../../components/Layout"; import AppBar from "../../../components/AppBar"; +import { yupResolver } from "@hookform/resolvers/yup"; +import * as Yup from "yup"; import { Select } from "../../../components/Fields"; import { useEffect, useState } from "react"; import apiOdoo from "../../../helpers/apiOdoo"; @@ -10,7 +11,17 @@ import { useAuth } from "../../../helpers/auth"; import { toast } from "react-hot-toast"; import { useRouter } from "next/router"; -const initialValues = { +const validationSchema = Yup.object().shape({ + type: Yup.string().required('Harus di-pilih'), + name: Yup.string().min(3, 'Minimal 3 karakter').required('Harus di-isi'), + email: Yup.string().email('Format harus seperti johndoe@example.com').required('Harus di-isi'), + mobile: Yup.string().required('Harus di-isi'), + street: Yup.string().required('Harus di-isi'), + zip: Yup.string().required('Harus di-isi'), + city: Yup.number().required('Harus di-pilih'), +}); + +const defaultValues = { type: '', name: '', email: '', @@ -22,16 +33,6 @@ const initialValues = { zip: '', }; -const validationSchema = Yup.object().shape({ - type: Yup.string().required('Harus di-pilih'), - name: Yup.string().min(3, 'Minimal 3 karakter').required('Harus di-isi'), - email: Yup.string().email('Format harus seperti johndoe@example.com').required('Harus di-isi'), - mobile: Yup.string().required('Harus di-isi'), - street: Yup.string().required('Harus di-isi'), - zip: Yup.string().required('Harus di-isi'), - city: Yup.number().required('Harus di-pilih'), -}); - const types = [ { value: 'contact', label: 'Contact Address' }, { value: 'invoice', label: 'Invoice Address' }, @@ -40,192 +41,194 @@ const types = [ ]; export default function CreateAddress() { - const [auth] = useAuth(); + const [ auth ] = useAuth(); const router = useRouter(); - - const onSubmit = async (values) => { - const parameters = { - ...values, - city_id: values.city, - district_id: values.district, - sub_district_id: values.subDistrict, - parent_id: auth.partner_id - } - - const address = await apiOdoo('POST', '/api/v1/partner/address', parameters); - if (address?.id) { - toast.success('Berhasil menambahkan alamat'); - router.back(); - } - }; - - const form = useFormik({ initialValues, validationSchema, onSubmit }); - const { - values, - errors, - touched, - handleChange, + register, + formState: { errors }, handleSubmit, - setFieldValue, - } = form; + watch, + setValue, + control, + } = useForm({ + resolver: yupResolver(validationSchema), + defaultValues + }); const [ cities, setCities ] = useState([]); const [ districts, setDistricts ] = useState([]); const [ subDistricts, setSubDistricts ] = useState([]); - useEffect(() => { - const loadCities = async () => { - let dataCities = await apiOdoo('GET', '/api/v1/city'); + useEffect(() => { + const loadCities = async () => { + let dataCities = await apiOdoo('GET', '/api/v1/city'); dataCities = dataCities.map((city) => ({ value: city.id, label: city.name })); setCities(dataCities); }; loadCities(); }, []); - + + const watchCity = watch('city'); useEffect(() => { - setFieldValue('district', ''); - if (values.city) { + setValue('district', ''); + if (watchCity) { const loadDistricts = async () => { - let dataDistricts = await apiOdoo('GET', `/api/v1/district?city_id=${values.city}`); + let dataDistricts = await apiOdoo('GET', `/api/v1/district?city_id=${watchCity}`); dataDistricts = dataDistricts.map((district) => ({ value: district.id, label: district.name })); setDistricts(dataDistricts); }; loadDistricts(); } - }, [ values.city, setFieldValue ]); - - useEffect(() => { - setFieldValue('subDistrict', ''); - if (values.district) { + }, [ watchCity, setValue ]); + + const watchDistrict = watch('district'); + useEffect(() => { + setValue('subDistrict', ''); + if (watchDistrict) { const loadSubDistricts = async () => { - let dataSubDistricts = await apiOdoo('GET', `/api/v1/sub_district?district_id=${values.district}`); + let dataSubDistricts = await apiOdoo('GET', `/api/v1/sub_district?district_id=${watchDistrict}`); dataSubDistricts = dataSubDistricts.map((district) => ({ value: district.id, label: district.name })); setSubDistricts(dataSubDistricts); }; loadSubDistricts(); } - }, [ values.district, setFieldValue ]); + }, [ watchDistrict, setValue ]) + + const onSubmitHandler = async (values) => { + const parameters = { + ...values, + city_id: values.city, + district_id: values.district, + sub_district_id: values.subDistrict, + parent_id: auth.partner_id + }; + + const address = await apiOdoo('POST', '/api/v1/partner/address', parameters); + if (address?.id) { + toast.success('Berhasil menambahkan alamat'); + router.back(); + } + }; return ( <WithAuth> <Layout> <AppBar title="Tambah Alamat" /> - <form onSubmit={handleSubmit} className="p-4 pt-0"> - <label className="form-label mt-4 mb-2">Label Alamat</label> - <Select - name="type" - options={types} - setFieldValue={setFieldValue} - value={values.type} - /> - { errors.type && touched.type && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.type }</div> - ) } - - <label className="form-label mt-4 mb-2">Nama</label> - <input - type="text" - className="form-input" - placeholder="John Doe" - onChange={handleChange} - value={values.name} - name="name" - /> - { errors.name && touched.name && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.name }</div> - ) } - - <label className="form-label mt-4 mb-2">Email</label> - <input - type="email" - className="form-input" - placeholder="johndoe@example.com" - onChange={handleChange} - value={values.email} - name="email" - /> - { errors.email && touched.email && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.email }</div> - ) } - - <label className="form-label mt-4 mb-2">No. Handphone</label> - <input - type="tel" - className="form-input" - placeholder="08xxxxxxxx" - onChange={handleChange} - value={values.mobile} - name="mobile" - /> - { errors.mobile && touched.mobile && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.mobile }</div> - ) } - - <label className="form-label mt-4 mb-2">Alamat</label> - <input - type="text" - className="form-input" - placeholder="Jl. Bandengan Utara 85A" - onChange={handleChange} - value={values.street} - name="street" - /> - { errors.street && touched.street && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.street }</div> - ) } - - <label className="form-label mt-4 mb-2">Kode Pos</label> - <input - type="number" - className="form-input" - placeholder="10100" - onChange={handleChange} - value={values.zip} - name="zip" - /> - { errors.zip && touched.zip && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.zip }</div> - ) } - - <label className="form-label mt-4 mb-2">Kota</label> - <Select - name="city" - options={cities} - setFieldValue={setFieldValue} - value={values.city} - /> - { errors.city && touched.city && ( - <div className="text-caption-2 text-red_r-11 mt-1">{ errors.city }</div> - ) } - - <label className="form-label mt-4 mb-2">Kecamatan</label> - <Select - name="district" - options={districts} - setFieldValue={setFieldValue} - value={values.district} - disabled={!values.city} - /> - - <label className="form-label mt-4 mb-2">Kelurahan</label> - <Select - name="subDistrict" - options={subDistricts} - setFieldValue={setFieldValue} - value={values.subDistrict} - disabled={!values.district} - /> + <form className="p-4 flex flex-col gap-y-4" onSubmit={handleSubmit(onSubmitHandler)}> + <div> + <label className="form-label mb-2">Label Alamat</label> + <Controller + name="type" + control={control} + render={props => <Select {...props} options={types} />} + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.type?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Nama</label> + <input + {...register('name')} + placeholder="John Doe" + type="text" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.name?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Email</label> + <input + {...register('email')} + placeholder="johndoe@example.com" + type="email" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.email?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Mobile</label> + <input + {...register('mobile')} + placeholder="08xxxxxxxx" + type="tel" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.mobile?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Alamat</label> + <input + {...register('street')} + placeholder="Jl. Bandengan Utara 85A" + type="text" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.street?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Kode Pos</label> + <input + {...register('zip')} + placeholder="10100" + type="number" + className="form-input" + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.zip?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Kota</label> + <Controller + name="city" + control={control} + render={props => <Select {...props} options={cities} />} + /> + <div className="text-caption-2 text-red_r-11 mt-1">{ errors.city?.message }</div> + </div> + + <div> + <label className="form-label mb-2">Kecamatan</label> + <Controller + name="district" + control={control} + render={props => ( + <Select + {...props} + options={districts} + disabled={!watchCity} + /> + )} + /> + </div> + + <div> + <label className="form-label mb-2">Kelurahan</label> + <Controller + name="subDistrict" + control={control} + render={props => ( + <Select + {...props} + options={subDistricts} + disabled={!watchDistrict} + /> + )} + /> + </div> <button type="submit" - className="btn-yellow mt-6 w-full" + className="btn-yellow mt-2 w-full" > Simpan </button> </form> </Layout> </WithAuth> - ); + ) }
\ No newline at end of file |
