Viewing File: /home/ubuntu/walnutminds-ecom-frontend-base/src/components/Profile/NewAddressForm.jsx

import { apiConstants } from "../Constant/constants";
import Map, { GoogleApiWrapper, Marker } from "google-maps-react";
import React, { useEffect, useRef, useState } from "react";
import {
  Row,
  Col,
  Container,
  Form,
  Image,
  Button,
  Tab,
  Nav,
  FormControl,
} from "react-bootstrap";
import { withTranslation, useTranslation } from "react-multi-lang";
import {
  saveDeliveryAddressesStart,
  fetchDeliveryAddressesListStart,
  getCountriesStart,
  getStatesStart,
} from "../store/actions/DeliveryAction";
import { Formik, Form as FORM, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import { connect } from "react-redux";
import Select from "react-select";
import {
  CountrySelect,
  StateSelect,
  CitySelect,
  GetCity,
} from "react-country-state-city";
import "react-country-state-city/dist/react-country-state-city.css";
import { GetCountries, GetState, GetAllCities } from "react-country-state-city";
import axios from "axios";

const NewAddressForm = ({ isModal = false, ...props }) => {
  const t = useTranslation();
  const [address, setAddress] = useState("");
  const [skipRender, setSkipRender] = useState(true);
  const [manualPincode, setManualPincode] = useState(false);

  const validationSchema = Yup.object().shape({
    name: Yup.string(),
    contact_number: Yup.string().required(t("required")).min(5, t("min_10")),
    city: Yup.string().required(t("required")),
    state: Yup.string().required(t("required")),
    country: Yup.string().required(t("required")),
    pincode: Yup.string().required(t("required"))
      .matches(/^[1-9][0-9]{5}$/, t("invalid")),
    landmark: Yup.string().required(t("required")),
    address: Yup.string().required(t("required")),
  });

  const [country, setCountry] = useState(null);
  const [currentState, setCurrentState] = useState(null);
  const [currentCity, setCurrentCity] = useState(null);
  const [currentPinCode, setCurrentPinCode] = useState(null);
  const [countriesList, setCountriesList] = useState([]);
  const [stateList, setStateList] = useState([]);
  const [citiesList, setCitiesList] = useState([]);
  const [pincodeList, setPincodeList] = useState([]);
  const [loading, setLoading] = useState(false);

  const handleSubmit = (values) => {
    props.dispatch(
      saveDeliveryAddressesStart(
        props?.editAddress?.delivery_address_id
          ? {
              ...values,
              delivery_address_id: props.editAddress.delivery_address_id,
            }
          : {
              ...values,
            }
      )
    );
  };

  useEffect(() => {
    props.dispatch(getCountriesStart({ all_countries: 1 }));
  }, []);

  useEffect(() => {
    GetCountries().then((result) =>
      setCountriesList(
        result.filter(item => item.name == "India").map((items) => ({
          label: items.name,
          value: items.name,
          ...items,
        }))
      )
    );
  }, []);

  useEffect(() => {
    if (country && Object.keys(country).length > 0 && country.id)
      GetState(parseInt(country.id)).then((result) => {
        setStateList(
          result.map((items) => ({
            label: items.name,
            value: items.name,
            ...items,
          }))
        );
      });
  }, [country]);

  useEffect(() => {
    if (currentState && Object.keys(currentState).length > 0 && currentState.id)
      GetCity(parseInt(country.id), parseInt(currentState.id)).then(
        (result) => {
          setCitiesList(
            result.map((items) => ({
              label: items.name,
              value: items.name,
              ...items,
            }))
          );
        }
      );
  }, [currentState]);

  useEffect(() => {
    if (currentCity) {
      let decoded = decodeURIComponent(currentCity.value);
      let cityName = decoded.split(" ");
      let pins = fetchPinCodeList(cityName[0]);
    }
  }, [currentCity]);

  const fetchPinCodeList = async (data) => {
    let pins = [];
    setLoading(true);
    const apiUrl = `https://api.postalpincode.in/postoffice/${data}`;
    await axios.get(apiUrl).then((response) => {
      pins = response.data[0]?.PostOffice?.map((office) => ({
        label: office.Pincode + ` (${office.Name})`,
        value: office.Pincode,
      }));
      setPincodeList(pins || []);
      if(!pins.length > 0){
        setManualPincode(true)
      }
    });
    setLoading(false);
    return pins;
  };

  useEffect(() => {
    if (
      !skipRender &&
      !props.deliveryAddressesSave.loading &&
      Object.keys(props.deliveryAddressesSave.data).length > 0
    ) {
      if (!isModal) {
        props.setActiveTab("saved_billing");
        props.dispatch(fetchDeliveryAddressesListStart());
      }
    }
    setSkipRender(false);
  }, [props.deliveryAddressesSave]);


  const customStyles = {
    ///.....
    menuPortal: (provided) => ({ ...provided, zIndex: 9999 }),
    menu: (provided) => ({
      ...provided,
      zIndex: 9999,
      left: "0px",
      borderRadius: "0px",
      overflow: "hidden",
    }),
    menuList: (provided) => ({
      ...provided,
      padding: 0,
      minWidth: 250,
      // fontSize: "0.85em",
      "&::-webkit-scrollbar-track": {
        boxShadow: "inset 0 0 6px rgba(0,0,0,0.3)",
        borderRadius: "8px",
        backgroundColor: "#fff",
      },
      "&::-webkit-scrollbar": {
        width: "4px",
        backgroundColor: "#fff",
      },
      "&::-webkit-scrollbar-thumb": {
        borderRadius: "3px",
        boxShadow: "inset 0 0 6px rgba(0, 0, 0, .3)",
        backgroundColor: "#555",
      },
    }),
    container: (provided) => ({ ...provided, width: "auto" }),
    control: (provided) => ({
      ...provided,
      backgroundColor: "transparent!important",
      border: "1px solid #E7E7E7!important",
      borderRadius: "8px!important",
      boxShadow: "none!important",
      height: "45px",
      minWidth: "150px",
      cursor: "pointer",
      // fontSize: "0.9em",
    }),
    placeholder: (provided) => ({
      ...provided,
      color: "#212529",
      // fontSize: "0.85em",
      fontWeight: "600",
    }),
    singleValue: (provided) => ({
      ...provided,
      color: "#212529",
      display: "flex",
      alignItems: "center",
      gap: "0.5em",
      // fontSize: "0.9em",
      fontWeight: "600",
    }),
    indicatorContainer: (provided) => ({
      ...provided,
      color: "#212529!important",
    }),
    indicatorContainer: (provided) => ({
      ...provided,
      fill: "#212529!important",
    }),
    indicatorSeparator: (base) => ({
      ...base,
      display: "none",
    }),
    dropdownIndicator: (provided) => ({
      ...provided,
      svg: {
        fill: "#212529",
      },
    }),
    // option: (styles, { data, isDisabled, isFocused, isSelected }) => {
    //   return {
    //     ...styles,
    //     backgroundColor: isSelected ? "#f7f7f7" : "#fff",
    //     color: "#000",
    //   };
    // },
    option: (provided, state) => ({
      ...provided,
      backgroundColor: state.isFocused || state.isSelected ? '#19264f' : '#fff',
      color: state.isFocused || state.isSelected ? '#fff' : '#000',
      ":hover": {
              backgroundColor: "#19264f",
              color: "#fff"
            },
  }),
  };

  return (
    <div className="new-address-sec mt-4">
      <div className="login-form">
        <Formik
          initialValues={{
            name: "",
            contact_number: "",
            city: "",
            state: "",
            country: "",
            pincode: "",
            landmark: "",
            address: "",
          }}
          validationSchema={validationSchema}
          onSubmit={(values) => handleSubmit(values)}
          enableReinitialize={true}
        >
          {({ values, errors, touched, setFieldValue }) => (
            <FORM>
              <Row>
                <Col md={12} xl={6} lg={6}>
                  <Form.Group
                    className="mb-4 select-address-type"
                    controlId="exampleForm.ControlInput1"
                  >
                    <Form.Label>
                      {t("name")} <span>*</span>
                    </Form.Label>
                    <Field
                      type="text"
                      className="form-control"
                      name="name"
                      placeholder={t("address_choose")}
                    />
                    <ErrorMessage
                      component={"div"}
                      name="name"
                      className="text-danger"
                    />
                    <div className="select-address-type-btn">
                      <Button
                        className="text-btn"
                        type="button"
                        onClick={(e) => setFieldValue("name", "Home")}
                      >
                        {t("home")}
                      </Button>
                      <Button
                        className="text-btn"
                        type="button"
                        onClick={() => setFieldValue("name", "Work")}
                      >
                        {t("work")}
                      </Button>
                      <Button
                        className="text-btn"
                        type="button"
                        onClick={() => setFieldValue("name", "Others")}
                      >
                        {t("others")}
                      </Button>
                    </div>
                  </Form.Group>
                </Col>
                <Col md={12} xl={6} lg={6}>
                  <Form.Group
                    className="mb-4"
                    controlId="exampleForm.ControlInput1"
                  >
                    <Form.Label>
                      {t("contact_number")} <span>*</span>
                    </Form.Label>
                    <Field
                      type="number"
                      className="form-control"
                      name="contact_number"
                      placeholder={t("contact_placeholder")}
                      min="0"
                    />
                    <ErrorMessage
                      component={"div"}
                      name="contact_number"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
                <Col md={6}>
                  <Form.Group
                    className="mb-4"
                    controlId="exampleForm.ControlInput1"
                  >
                    <Form.Label>
                      {t("country")} <span>*</span>
                    </Form.Label>
                    <Select
                    styles={customStyles}
                      options={countriesList || []}
                      value={country}
                      onChange={(selected) => {
                        if (selected) {
                          setCountry(selected);
                          setFieldValue("country", selected.value);
                          setCurrentState(null);
                          setCurrentCity(null);
                          setCurrentPinCode(null);
                          setFieldValue("state", "");
                          setFieldValue("city", "");
                          setFieldValue("pincode", "");
                        } else {
                          setCountry(null);
                          setFieldValue("country", "");
                        }
                      }}
                      placeholder={t("country_placeholder")}
                      noOptionsMessage={() => t("no_countries")}
                    />
                    <ErrorMessage
                      component={"div"}
                      name="country"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
                <Col md={6}>
                  <Form.Group
                    className="mb-4"
                    controlId="exampleForm.ControlInput1"
                  >
                    <Form.Label>
                      {t("state")} <span>*</span>
                    </Form.Label>
                    <Select
                     styles={customStyles}
                      options={stateList || []}
                      value={currentState}
                      onChange={(selected) => {
                        if (selected) {
                          setCurrentState(selected);
                          setFieldValue("state", selected.value);
                          setCurrentCity(null);
                          setFieldValue("city", "");
                          setCurrentPinCode(null);
                          setFieldValue("pincode", "");
                        } else {
                          setCurrentState(null);
                          setFieldValue("state", "");
                        }
                      }}
                      placeholder={t("state_placeholder")}
                      noOptionsMessage={() => t("no_states")}
                    />
                    <ErrorMessage
                      component={"div"}
                      name="state"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
                <Col md={6}>
                  <Form.Group controlId="formBasicEmail">
                    <Form.Label>
                      {t("city")} <span>*</span>
                    </Form.Label>
                    <Select
                     styles={customStyles}
                      options={citiesList || []}
                      value={currentCity}
                      onChange={(selected) => {
                        if (selected) {
                          setCurrentCity(selected);
                          setFieldValue("city", selected.value);
                          setCurrentPinCode(null);
                          setFieldValue("pincode", "");
                        } else {
                          setCurrentCity(null);
                          setFieldValue("city", "");
                        }
                      }}
                      placeholder={t("city_placeholder")}
                      noOptionsMessage={() => t("no_city")}
                    />
                    <ErrorMessage
                      component={"div"}
                      name="city"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
                <Col md={6}>
                  <Form.Group
                    className="mb-4"
                    controlId="exampleForm.ControlInput1"
                  >
                   <div style={{display:"flex", justifyContent:"space-between", alignItems:"center", marginBottom:"0.5em"}}>
                   <Form.Label className="mb-0">
                      {t("pincode")} <span>*</span>
                    </Form.Label>
                    <Button className="manual-btn" onClick={()=> setManualPincode(!manualPincode)}>
                      {!manualPincode ? "Enter Manually" : "Select Pincode"}
                    </Button>
                   </div>
                    {!manualPincode ? <Select
                     styles={customStyles}
                      options={pincodeList}
                      value={currentPinCode}
                      onChange={(selected) => {
                        if (selected) {
                          setCurrentPinCode(selected);
                          setFieldValue("pincode", selected.value);
                        } else {
                          setCurrentPinCode(null);
                          setFieldValue("pincode", "");
                        }
                      }}
                      placeholder="Select your pincode"
                      noOptionsMessage={() => t("no_pincode")}
                    /> : 
                    <Field
                      type="text"
                      className="form-control"
                      name="pincode"
                      placeholder={t("pincode")}
                    />
                    }
                    <ErrorMessage
                      component={"div"}
                      name="pincode"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
                <Col md={12}>
                  <Form.Group
                    className="mb-4"
                    controlId="exampleForm.ControlInput1"
                  >
                    <Form.Label>
                      {t("landmark")} <span>*</span>
                    </Form.Label>
                    <Field
                      type="text"
                      className="form-control"
                      name="landmark"
                      placeholder={t("landmark_placeholder")}
                      min="0"
                    />
                    <ErrorMessage
                      component={"div"}
                      name="landmark"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
                <Col md={12}>
                  <Form.Group
                    className="mb-4"
                    controlId="exampleForm.ControlTextarea1"
                  >
                    <Form.Label>
                      {t("address_area")} <span>*</span>
                    </Form.Label>
                    <Field
                      as="textarea"
                      className="form-control"
                      name="address"
                      placeholder={t("address_placeholder")}
                      min="0"
                    />
                    <ErrorMessage
                      component={"div"}
                      name="address"
                      className="text-danger"
                    />
                  </Form.Group>
                </Col>
              </Row>
              <Form.Group
                className="mb-3 form-check-custom"
                controlId="formBasicCheckbox"
              >
                <Form.Check type="checkbox" label={t("use_as_default_add")} />
              </Form.Group>
              <div className="default-btn-sec">
                <Button
                  type="submit"
                  className="subscribe-btn"
                  disabled={props.deliveryAddressesSave.buttonDisable}
                >
                  {props.deliveryAddressesSave.loadingButtonContent
                    ? props.deliveryAddressesSave.loadingButtonContent
                    : t("save")}
                </Button>
              </div>
            </FORM>
          )}
        </Formik>
      </div>
    </div>
  );
};

const mapStateToPros = (state) => ({
  deliveryAddressesSave: state.delivery.deliveryAddressesSave,
  deliveryAddressesList: state.delivery.deliveryAddressesList,
  countries: state.delivery.countries,
  states: state.delivery.states,
});

function mapDispatchToProps(dispatch) {
  return { dispatch };
}

export default connect(
  mapStateToPros,
  mapDispatchToProps
)(withTranslation(NewAddressForm));
Back to Directory File Manager