Untitled

 avatar
unknown
plain_text
a year ago
63 kB
4
Indexable
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useState } from "react";
import axios from "axios";
import { z } from "zod";
import {
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalFooter,
  Badge,
  ModalBody,
  ModalCloseButton,
  Input,
  Button,
  VStack,
  FormControl,
  FormLabel,
  Select,
  SimpleGrid,
  GridItem,
  Box,
  List,
  ListItem,
  useToast,
  Tag,
  Divider,
  Textarea,
  Text,
  TagLabel,
  TagCloseButton,
  Avatar,
  Flex,
  HStack,
  Tooltip,
  FormErrorMessage,
  useTabPanel,
} from "@chakra-ui/react";
import {
  Keyword,
  RecordInterface,
} from "@/interface/due-diligence/RecordInterface";
import { Niche } from "@/interface/due-diligence/NicheInterface";
import {
  useCreateNicheMutation,
  useSearchNicheQuery,
  useGetOneNicheQuery,
  useGetAllNichesQuery,
} from "@/redux/api/niche.api";
import {
  useCreateKeywordMutation,
  useSearchKeywordQuery,
  useGetOneKeywordQuery,
} from "@/redux/api/keyword.api";
import { useGetOneRecordQuery } from "@/redux/api/due-diligence.api";
import { Comment } from "@/interface/due-diligence/RecordInterface";
import { useDeleteCommentMutation } from "@/redux/api/due-diligence.api";
import Image from "next/image";
import { AiFillCaretDown } from "react-icons/ai";
import { useAppSelector } from "@/redux/hooks";
import validationScripts from "@/util/validation";
import { Formik, Field, useFormik } from "formik";
import * as yup from "yup";

// constants
import countries from "@/constants/datasets/countries.json";
import states from "@/constants/datasets/states.json";
import TooltipCustom from "../tooltipCustom/tooltipCustom";

const formValidationSchema = z.object({
  availableDomain: z
    .string()
    .regex(/^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/)
    .min(1),
  competitiveBusiness1: z
    .string()
    .regex(
      /^(?!https?:\/\/|www\.)([A-Za-z0-9-]+\.){1}[A-Za-z]{2,6}(?:\/[^\/]*)?$/
    )
    .min(1),
  competitiveBusiness2: z
    .string()
    .regex(
      /^(?!https?:\/\/|www\.)([A-Za-z0-9-]+\.){1}[A-Za-z]{2,6}(?:\/[^\/]*)?$/
    )
    .min(1),
  competitiveBusiness3: z
    .string()
    .regex(
      /^(?!https?:\/\/|www\.)([A-Za-z0-9-]+\.){1}[A-Za-z]{2,6}(?:\/[^\/]*)?$/
    )
    .min(1),
});

interface CustomModalProps {
  isOpen: boolean;
  onClose: () => void;
  _id?: string;
  record: RecordInterface | undefined;
  onSave: (editedRecord: RecordInterface) => void;
}

const AddRecordModal: React.FC<CustomModalProps> = ({
  isOpen,
  onClose,
  record,
  _id,
  onSave,
}) => {
  const toast = useToast();

  const [country, setCountry] = useState<string>("United States");
  const [domainAvailable, setDomainAvailable] = useState("");
  const [searchNiche, setSearchNiche] = useState("");
  const [nicheRef, setNicheRef] = useState(record?.nicheRef || "");
  const [selectedNiche, setSelectedNiche] = useState("");
  const [population, setPopulation] = useState<number>(0);
  const [searchKeyword, setSearchKeyword] = useState("");
  const [selectedKeyword, setSelectedKeyword] = useState("");
  const [keywordRef, setKeywordRef] = useState(record?.keywordRef || "");

  const [searchSecondaryKeyword, setSearchSecondaryKeyword] = useState("");
  const [secondaryKeyword, setSecondaryKeyword] = useState({
    value: "",
    _id: "",
  });
  const [secondaryKeywordsArr, setSecondaryKeywordsArr] = useState<Niche[]>([]);

  const [location, setLocation] = useState(record?.cityName || "us");
  const [cityName, setCityName] = useState(record?.cityName || "");

  const [competitiveBusinesses, setCompetitiveBusinesses] = useState([
    "",
    "",
    "",
  ]);
  const [isGo, setIsGo] = useState<string>(record?.isGo || "TBD");
  const [activeBusiness, setActiveBusiness] = useState("NONE");
  const [isLowHangingFruit, setIsLowHangingFruit] = useState<string>(
    record?.isLowHangingFruit || "UNSURE"
  );
  const [callDrivenNiche, setCallDrivenNiche] = useState<string>(
    record?.callDrivenNiche || "NO"
  );

  const [comment, setComment] = useState<string>("");
  const [comments, setComments] = useState<Comment[]>([]);

  const [createNiche] = useCreateNicheMutation();
  const [createKeyword] = useCreateKeywordMutation();
  const { data: searchPrimaryKeywordData } =
    useSearchKeywordQuery(searchKeyword);
  const { data: getAllNiches } = useGetAllNichesQuery();

  const { data: nicheRes } = useGetOneNicheQuery(searchNiche);
  const { data: keywordRes } = useGetOneKeywordQuery(searchKeyword);
  const { data: keywordRess } = useGetOneKeywordQuery(searchSecondaryKeyword);
  const { data: recordData }: any = useGetOneRecordQuery(_id || "");
  const { data } = useSearchNicheQuery(searchNiche);
  const { data: keywordsData } = useSearchKeywordQuery(searchSecondaryKeyword);
  const [deleteComment, { isSuccess: CommentDeletionResponseStatus }] =
    useDeleteCommentMutation();

  const [isStateFieldInFocus, setStateFieldFocusState] =
    useState<boolean>(false);

  const [isCityFieldInFocus, setCityFieldFocusState] = useState<boolean>(false);

  const [isNicheFieldInFocus, setNicheFieldFocusState] =
    useState<boolean>(false);

  const [isPrimaryKeyFieldInFocus, setPrimaryKeyFieldFocusState] =
    useState<boolean>(false);

  const [isSecondaryFieldInFocus, setSecondaryFieldFocusState] =
    useState<boolean>(false);

  const [countryData, setcountryData] = useState<string>("US");
  const [statesData, setStatesData] = useState<any>();

  const [selState, setSelState] = useState<any>({});

  const [citiesData, setCitiesData] = useState<any>();

  const [selCity, setSelCity] = useState<any>("");

  const [validationErrors, setValidationErrors] = useState({
    domainAvailable: "",
    selectedKeyword: "",
    location: "",
    competitiveBusinesses: ["", "", ""],
  });
  const { isOpen: isMenuBarOpen } = useAppSelector(
    (state) => state.SideBarState
  );
  useEffect(() => {
    if (isOpen) {
      resetForm();
    }

    if (_id && recordData) {
      setDomainAvailable(recordData?.data[0]?.domainAvailable || "");
      setSearchNiche(recordData.data[0]?.nicheRef.primaryNiche.value || "");
      setSelectedNiche(recordData.data[0]?.nicheRef.primaryNiche.value || "");
      setNicheRef(recordData.data[0]?.nicheRef.primaryNiche._id || "");

      setSearchKeyword(
        recordData.data[0]?.keywordRefs?.primaryKeyword?.value || ""
      );
      setSelectedKeyword(
        recordData.data[0]?.keywordRefs?.primaryKeyword?.value || ""
      );
      setKeywordRef(recordData.data[0]?.keywordRefs?.primaryKeyword?._id || "");

      const competitiveBusinessLinks = Array.from(
        { length: 3 },
        (_, index) =>
          recordData?.data[0]?.competitiveBusinesses?.[index]?.businessLink ||
          ""
      );

      const [business1, business2, business3] = competitiveBusinessLinks;
      setCompetitiveBusinesses([business1, business2, business3]);
      setIsGo(String(recordData?.data[0]?.isGo));
      setActiveBusiness(recordData?.data[0]?.activeBusiness || "MANY");
      setIsLowHangingFruit(recordData?.data[0]?.isLowHangingFruit);
      setCallDrivenNiche(recordData?.data[0]?.callDrivenNiche);
      setComments(recordData?.data[0]?.comments || []);
      const secondaryKeywordsArr =
        recordData?.data[0]?.keywordRefs.secondaryKeywords || [];
      const extractedSecondaryKeywords = secondaryKeywordsArr.map(
        (keyword: any) => ({
          value: keyword?.value || "",
          _id: keyword?._id || "",
        })
      );
      setSecondaryKeywordsArr(extractedSecondaryKeywords);
    }
  }, [recordData, _id, isOpen]);

  const handleNicheClick = (nicheValue: string, nicheRef: string) => {
    setSearchNiche(nicheValue);
    setSelectedNiche(nicheValue);
    setNicheRef(nicheRef);
  };

  const handlePrimaryKeywordClick = (value: string, _id: string) => {
    if (!location) {
      setLocation("us");
    }
    setSearchKeyword(value);
    setSelectedKeyword(value);
    setKeywordRef(_id);
  };

  const isSecondaryKeywordAlreadyPresent = (id: string): boolean => {
    return (
      secondaryKeywordsArr.filter((val: any) => val._id === id).length === 0
    );
  };

  useEffect(() => {
    if (
      secondaryKeyword.value &&
      secondaryKeyword.value.trim() !== "" &&
      isSecondaryKeywordAlreadyPresent(secondaryKeyword._id)
    ) {
      if (secondaryKeywordsArr.length > 5) {
        toast({
          description: "Secondary keyword limit exceeded!",
          status: "error",
          isClosable: true,
          duration: 4500,
        });
        return;
      }
      setSecondaryKeywordsArr([...secondaryKeywordsArr, secondaryKeyword]);
      setSecondaryKeyword({ value: "", _id: "" });
    }
  }, [secondaryKeyword, secondaryKeywordsArr]);

  const handleMultipleKeywordsClick: (
    value: string,
    _id: string
  ) => void = async (value, _id) => {
    if (secondaryKeywordsArr.length > 6) {
      toast({
        description: "Secondary keyword limit exceeded!",
        isClosable: true,
        duration: 4500,
        status: "error",
      });
      return;
    }
    setSecondaryKeyword({ value, _id });
  };

  const sortStateData = () => {
    setStatesData(
      states.filter((item: any) => item.country_code === countryData)
    );
  };

  const fetchPopulationData = async (cityId: string) => {
    try {
      const {
        data: { data },
      } = await axios.get(
        `https://wft-geo-db.p.rapidapi.com/v1/geo/cities/${cityId}`,
        {
          headers: {
            "X-RapidAPI-Key": process.env.NEXT_PUBLIC_RAPID_API_KEY,
            "X-RapidAPI-Host": process.env.NEXT_PUBLIC_RAPID_API_HOST,
          },
        }
      );
      setPopulation(data.population);
    } catch (err: any) {
      toast({
        description: "Population Api failed!",
        status: "error",
      });
    }
  };

  useEffect(() => {
    sortStateData();
  }, [countryData]);

  useEffect(() => {
    if (selState) {
      sortCitiesData();
    }
  }, [selState]);

  useEffect(() => {
    if (selCity) {
      const data = citiesData.filter((item: any) => item.id == selCity.id);
      fetchPopulationData(data[0].wikiDataId);
    }
  }, [selCity]);

  const toastNicheCreated = (value: string) => {
    toast({
      title: `${value} created`,
      status: "success",
      duration: 3000,
      isClosable: true,
    });
  };

  const toastNicheError = () => {
    toast({
      title: "Error",
      description: "An error occurred while creating.",
      status: "error",
      duration: 3000,
      isClosable: true,
    });
  };

  const handleCommentDeletion = async (commentId: string) => {
    try {
      if (_id && commentId) {
        await deleteComment({ id: _id, commentId });
      }
      if (CommentDeletionResponseStatus) {
        toast({
          title: "Comment Deleted Successfully!",
          status: "success",
          duration: 9000,
          isClosable: true,
        });
      }
    } catch (err: any) {
      toast({
        description: "Failed to delete comment!",
        status: "error",
        duration: 9000,
        isClosable: true,
      });
    }
  };

  const validateForm = () => {
    let isValid = true;
    const errors = {
      domainAvailable: "",
      selectedKeyword: "",
      cityName: "",
      competitiveBusinesses: ["", "", ""],
    };

    // Validate domainAvailable
    if (!domainAvailable) {
      isValid = false;
      errors.domainAvailable = "Domain is required";
    }

    // Validate keyword
    if (!selectedKeyword) {
      isValid = false;
      errors.selectedKeyword = "Keyword is required";
    }

    // Validate location
    if (!cityName) {
      isValid = false;
      errors.cityName = "Location is required";
    }

    setValidationErrors(errors as any);
    return isValid;
  };

  const resetForm = () => {
    setDomainAvailable("");
    setNicheRef("");
    setSelectedNiche("");
    setSearchKeyword("");
    setKeywordRef("");
    setLocation("us");
    setCompetitiveBusinesses(["", "", ""]);
    setIsGo("TBD");
    setActiveBusiness("NONE");
    setIsLowHangingFruit("UNSURE");
    setCallDrivenNiche("NO");
    setSearchNiche("");
    setComment("");
    setComments([]);
    setSelectedKeyword("");
    setSecondaryKeyword({ value: "", _id: "" });
    setSecondaryKeywordsArr([]);
    setStateSearchText("");
    setCityData([]);
  };

  const [cityData, setCityData] = useState<any[]>([]);
  const [stateSearchText, setStateSearchText] = useState<string>("");
  const [citySearchText, setCitySearchText] = useState<string>("");

  const fetchCities = async () => {
    try {
      const {
        data: { results },
      } = await axios.get(
        `https://public.opendatasoft.com//api/explore/v2.1/catalog/datasets/geonames-all-cities-with-a-population-1000/records?limit=100&refine=cou_name_en%3A%22${country
          .split(" ")
          .join("%20")}%22`
      );
      setCityData(results);
      setCityName(results[0].name);
      setPopulation(results[0].population);
    } catch (err: any) {
      toast({
        description:
          "Data for cities with population over 1000 failed to be collected!",
        duration: 4500,
        isClosable: true,
        status: "error",
      });
    }
  };

  useEffect(() => {
    if (isOpen) {
      fetchCities();
    }
  }, [country, isOpen]);

  type DomainValidationErrors = {
    availableDomain: string;
    competitiveBusiness1: string;
    competitiveBusiness2: string;
    competitiveBusiness3: string;
  };

  const [domainValidationErrors, setDomainValidationErrors] =
    useState<DomainValidationErrors>({
      availableDomain: "",
      competitiveBusiness1: "",
      competitiveBusiness2: "",
      competitiveBusiness3: "",
    });

  type domainValidationErrorKeys = keyof typeof domainValidationErrors;

  const handleBusinessChange = (index: number, value: string) => {
    //add validation
    // Additional validation to check for URL prefixes
    const urlPrefixes = ["http://", "https://", "www."];
    const startsWithPrefix = urlPrefixes.some((prefix) =>
      value.toLowerCase().startsWith(prefix)
    );

    if (startsWithPrefix) {
      // Display error message for URL prefixes
      setDomainValidationErrors((prevErrors: DomainValidationErrors) => ({
        ...prevErrors,
        [`competitiveBusiness${index + 1}`]:
          "Invalid URL prefix. Please enter only the root domain.",
      }));
    } else {
      // Update the state and clear any previous error message
      setDomainValidationErrors((prevErrors: DomainValidationErrors) => ({
        ...prevErrors,
        [`competitiveBusiness${index + 1}`]: "",
      }));

      const updatedBusinesses = [...competitiveBusinesses];
      updatedBusinesses[index] = value;

      setCompetitiveBusinesses(updatedBusinesses);
    }
  };

  useEffect(() => {
    try {
      const d = formValidationSchema.parse({
        availableDomain: domainAvailable,
        competitiveBusiness1: competitiveBusinesses[0],
        competitiveBusiness2: competitiveBusinesses[1],
        competitiveBusiness3: competitiveBusinesses[2],
      });
    } catch (err: any) {
      if (err instanceof z.ZodError) {
        const issues = err.issues;
        issues.map((trace: any) => {
          switch (trace.path[0]) {
            case "availableDomain":
              if (
                trace.validation === "regex" &&
                domainAvailable.length !== 0
              ) {
                setDomainValidationErrors({
                  ...domainValidationErrors,
                  availableDomain: "Invalid Domain",
                });
              }
              break;
            case "competitiveBusiness1":
              if (
                trace.validation === "regex" &&
                competitiveBusinesses[0].length !== 0
              ) {
                setDomainValidationErrors({
                  ...domainValidationErrors,
                  competitiveBusiness1: "Invalid Domain",
                });
              }
              break;
            case "competitiveBusiness2":
              if (
                trace.validation === "regex" &&
                competitiveBusinesses[1].length !== 0
              ) {
                setDomainValidationErrors({
                  ...domainValidationErrors,
                  competitiveBusiness2: "Invalid Domain",
                });
              }
              break;
            case "competitiveBusiness3":
              if (
                trace.validation === "regex" &&
                competitiveBusinesses[2].length !== 0
              ) {
                setDomainValidationErrors({
                  ...domainValidationErrors,
                  competitiveBusiness3: "Invalid Domain",
                });
              }
              break;
            default:
              break;
          }
        });
      }
    }
  }, [domainAvailable, competitiveBusinesses]);
  const formik = useFormik({
    initialValues: {
      Comments: "",
      AvailableDomain: "",
      GoOrNoGo: "",
      LowHangingFruit: "",
      NumberOfActiveBusinesses: "",
      CompetitorBusiness1: "",
      CompetitorBusiness2: "",
      CompetitorBusiness3: "",
      SecondaryBusiness: "",
      PrimaryKeyword: "",
      SecondaryKeyword: "",
      CallDrivenNiche: "",
      Niche: "",
      City: "",
      // from use state
      State: "",
    },
    onSubmit: async (values, actions) => {
      try {
        const editedRecord = {
          population,
          cityName: selCity.name,
          location: countryData,
          domainAvailable: values.AvailableDomain,
          nicheRef: values.Niche,
          keywordRef: values.PrimaryKeyword,
          secondaryKeywordsArr: values.SecondaryKeyword,
          competitiveBusinesses: [
            values.CompetitorBusiness1,
            values.CompetitorBusiness2,
            values.CompetitorBusiness3,
          ],
          isGo: values.GoOrNoGo,
          activeBusiness: values.NumberOfActiveBusinesses,
          isLowHangingFruit: values.LowHangingFruit,
          callDrivenNiche: values.CallDrivenNiche,
          comment: values.Comments,
        };

        onSave({
          ...editedRecord,
          secondaryKeywordsArr: secondaryKeywordsArr,
          keywordRef: selectedKeyword,
        } as any);
      } catch (error: any) {
        toast({
          description: error.data.message,
          duration: 4500,
          isClosable: true,
          status: "error",
        });
      }
    },

    validationSchema: yup.object({
      CompetitorBusiness1: yup
        .string()
        .test(
          "is-valid-domain",
          "The entered URL is invalid! Please enter only the root domain and remove URL prefixes such as https, www, etc",
          (value) => !/^(https?:\/\/|www\.)/.test(value || "")
        )
        .required("This field is required"),
      CompetitorBusiness2: yup
        .string()
        .test(
          "is-valid-domain",
          "The entered URL is invalid! Please enter only the root domain and remove URL prefixes such as https, www, etc",
          (value) => !/^(https?:\/\/|www\.)/.test(value || "")
        )
        .required("This field is required"),
      CompetitorBusiness3: yup
        .string()
        .test(
          "is-valid-domain",
          "The entered URL is invalid! Please enter only the root domain and remove URL prefixes such as https, www, etc",
          (value) => !/^(https?:\/\/|www\.)/.test(value || "")
        )
        .required("This field is required"),
      Niche: yup.string().required("Niche is required"),
      PrimaryKeyword: yup.string().required("Primary keyword is required"),
      GoOrNoGo: yup.string().required("Please select Go or No"),
      LowHangingFruit: yup.string().required("Please select low hanging fruit"),
      AvailableDomain: yup
        .string()
        .required("Please fill the Available domain"),
    }),
  });

  const sortCitiesData = () => {
    fetch("https://stgapi.rankandrentengine.com/api/utils/cities", {
      method: "POST",
      body: JSON.stringify({
        country_code: selState.country_code,
        state_code: selState.state_code,
      }),
      headers: { "Content-Type": "application/json" },
    })
      .then((data) => data.json())
      .then((item) => {
        if (item && item.cities) {
          setCitiesData(item.cities);
        }
      });
  };

  const handleCreatePrimaryKeyword = async ($event: any) => {
    if ($event.key === "Enter") {
      if (!location) {
        toast({
          description: "Please enter country inorder to add keywords!",
          status: "error",
        });
        return;
      }
      setSelectedKeyword(formik.values.PrimaryKeyword);
      formik.setValues({ ...formik.values, PrimaryKeyword: "" });
    }
  };
  const handleRemovePrimaryKeyword = () => {
    formik.setValues({ ...formik.values, PrimaryKeyword: "" });
    setSelectedKeyword("");
  };
  const handleRemoveNicheForNicheArr = (index: number) => {
    const updatedValues = secondaryKeywordsArr.filter((_, i) => i !== index);
    setSecondaryKeywordsArr(updatedValues);
  };
  const handleKeyDownSecondaryKeyword = async (
    event: React.KeyboardEvent<HTMLInputElement>
  ) => {
    if (event.key !== "Enter") {
      return;
    }
    if (secondaryKeywordsArr.length > 5) {
      toast({
        description: "Secondary keyword limit exceeded!",
        status: "error",
        isClosable: true,
        duration: 4500,
      });
      return;
    }

    event.preventDefault();

    try {
      if (!location) {
        toast({
          description: "Please enter country before proceeding",
          status: "error",
        });
        return;
      }

      setSecondaryKeywordsArr((prev) => [
        ...prev,
        {
          value: formik.values.SecondaryKeyword || "",
          _id: formik.values.SecondaryKeyword || "",
        },
      ]);
      formik.setValues({ ...formik.values, SecondaryKeyword: "" });
    } catch (error) {
      toastNicheError();
    }
  };
  const handleCreateNiche = async (niche: any) => {
    formik.setValues({ ...formik.values, Niche: niche.value });
  };
  const handleRemovePrimaryNiche = () => {
    formik.setValues({ ...formik.values, Niche: "" });
    setSelectedNiche("");
  };
  const handleStateChange = (event: any) => {
    setStateSearchText(event.target.value);
    sortCitiesData();
  };
  const handleCityChange = (event: any) => {
    setCitySearchText(event.target.value);
    fetchPopulationData(selCity.wikiDataId);
  };

  return (
    <Modal size={"5xl"} isOpen={isOpen} onClose={onClose}>
      <ModalOverlay
        bg={"rgba(255, 255, 255, 0.6)"}
        backdropFilter="blur(4.5px)"
      />

      <ModalContent
        bg={"#E1EDEE"}
        padding={"20px"}
        pt={"40px"}
        h={"85vh"}
        w={"75vw"}
        overflowX={"hidden"}
        overflowY={"auto"}
      >
        <ModalHeader
          color={"#022B3A"}
          fontSize={"2.1rem"}
          display={"flex"}
          alignItems={"center"}
          gap={"30px"}
        >
          <Text>Add Location</Text>
          <Tag
            p={"9px 16px"}
            color={"#fff"}
            size="lg"
            bg={"#022B3A"}
            borderRadius="18px"
          >
            <Avatar
              src="/assets/icons/tag_icon.svg"
              size="xs"
              name="Segun Adebayo"
              ml={-1}
              mr={2}
            />
            <TagLabel fontSize={"1.5rem"} fontWeight={"700"}>
              #4854333
            </TagLabel>
          </Tag>
        </ModalHeader>
        <ModalCloseButton />

        <ModalBody w={"100%"} pt={"20px"} color={"#022B3A"}>
          <VStack gap={"0"}>
            <HStack
              bg={"#E1EDEE"}
              pt={"10px"}
              width={"100%"}
              justifyContent={"space-between"}
              borderRadius={"15px 15px 0 0"}
              border={"3px solid rgba(174, 214, 220, 0.36)"}
              alignItems={"flex-end"}
            >
              <Text
                pl={"15px"}
                pr={"40px"}
                borderBottom={"4px solid"}
                fontSize={"1.5rem"}
                fontWeight={"700"}
              >
                {_id ? "Update" : "Create "} Record
              </Text>
            </HStack>

            <Box
              border={"2px"}
              w={"100%"}
              pr={"40px"}
              bgColor={"rgba(255, 255, 255, 0.45)"}
            >
              <form onSubmit={formik.handleSubmit}>
                <HStack pb={"30px"} w={"100%"} alignItems={"start"} gap={"5vw"}>
                  <Box pl={"15px"} w="20vw">
                    <Text fontSize={"22px"} fontWeight={"600"}>
                      {" "}
                      General Info
                    </Text>
                    <Text color={"#7A7A7A"}>
                      Add details about your market, niche, and core keywords.
                    </Text>
                  </Box>
                  <VStack
                    w={"100%"}
                    mt={"10px"}
                    pb={"20px"}
                    borderBottom={"1px solid rgba(2, 43, 58, 0.3)"}
                  >
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>Country</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="Select the country for your prospective market."
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <Select
                        textTransform={"capitalize"}
                        icon={<AiFillCaretDown />}
                        bg={"#fff"}
                        onChange={(e) => {
                          setcountryData(e.target.value);
                        }}
                      >
                        {countries?.map((item, index) => {
                          return (
                            <option
                              key={index}
                              value={item.iso2}
                              selected={item.name === "United States"}
                              disabled={item.name !== "United States"}
                            >
                              {item.name}
                            </option>
                          );
                        })}
                      </Select>
                      <FormErrorMessage>
                        {validationErrors.location}
                      </FormErrorMessage>
                    </FormControl>

                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>State</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="Enter a state for your prospective market."
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <VStack>
                        <Input
                          bg={"#fff"}
                          name="State"
                          placeholder="Search for State"
                          value={
                            stateSearchText === ""
                              ? selState.name
                              : stateSearchText
                          }
                          onChange={(e) => handleStateChange(e)}
                          _placeholder={{
                            color: "#7A7A7A",
                          }}
                          onFocus={() => setStateFieldFocusState(true)}
                          onBlur={() =>
                            setTimeout(
                              () => setStateFieldFocusState(false),
                              500
                            )
                          }
                        />
                        {isStateFieldInFocus && (
                          <Box
                            w={"100%"}
                            position={"absolute"}
                            bg={"#fff"}
                            zIndex={100}
                            top={"74px"}
                            h={"15vh"}
                            overflow="scroll"
                          >
                            {statesData &&
                              statesData
                                ?.filter(
                                  (state: any) =>
                                    state.name.toLowerCase() !==
                                    stateSearchText.toLowerCase()
                                )
                                .map((state: any, index: number) => (
                                  <Text
                                    p={2}
                                    cursor="pointer"
                                    _hover={{
                                      backgroundColor: "teal.500",
                                      color: "#fff",
                                    }}
                                    key={index}
                                    onClick={() => {
                                      setSelState(state);
                                      setStateSearchText("");
                                    }}
                                  >
                                    {state.name}
                                  </Text>
                                ))}
                          </Box>
                        )}
                      </VStack>
                      <FormErrorMessage>
                        {validationErrors.location}
                      </FormErrorMessage>
                    </FormControl>
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>City</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="Enter a city for your prospective market."
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <VStack>
                        <Input
                          bg={"#fff"}
                          placeholder="Search for City"
                          name="City"
                          value={selCity.name}
                          onChange={(e) => handleCityChange(e)}
                          _placeholder={{
                            color: "#7A7A7A",
                          }}
                          onFocus={() => setCityFieldFocusState(true)}
                          onBlur={() =>
                            setTimeout(() => setCityFieldFocusState(false), 500)
                          }
                        />
                        {isCityFieldInFocus && (
                          <Box
                            w={"100%"}
                            position={"absolute"}
                            bg={"#fff"}
                            zIndex={100}
                            top={"74px"}
                            h={"15vh"}
                            overflow="scroll"
                          >
                            {citiesData &&
                              citiesData
                                .filter(
                                  (city: any) =>
                                    city.name.toLowerCase() !==
                                    stateSearchText.toLowerCase()
                                )
                                .map((city: any, index: number) => (
                                  <Text
                                    p={2}
                                    _hover={{
                                      backgroundColor: "teal.500",
                                      color: "#fff",
                                    }}
                                    key={index}
                                    onClick={() => setSelCity(city)}
                                  >
                                    {city.name}
                                  </Text>
                                ))}
                          </Box>
                        )}
                      </VStack>
                      <FormErrorMessage>
                        {validationErrors.location}
                      </FormErrorMessage>
                    </FormControl>
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>Niche</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="Enter a niche for your prospective market."
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <Box>
                        <Input
                          bgColor="#fff"
                          name="Niche"
                          value={formik.values.Niche}
                          onChange={formik.handleChange}
                          placeholder="Search or create a niche"
                          _placeholder={{
                            color: "#7A7A7A",
                          }}
                          onFocus={() => setNicheFieldFocusState(true)}
                          onBlur={() =>
                            setTimeout(
                              () => setNicheFieldFocusState(false),
                              500
                            )
                          }
                        />
                        {isNicheFieldInFocus &&
                          getAllNiches &&
                          getAllNiches.data
                            .filter(
                              (niche: any) =>
                                niche.value.toLowerCase() !==
                                formik.values.Niche.toLowerCase()
                            )
                            .map((niche: any, index: number) => (
                              <Text
                                p={2}
                                _hover={{
                                  backgroundColor: "teal.500",
                                  color: "#fff",
                                }}
                                key={index}
                                onClick={() => handleCreateNiche(niche)}
                              >
                                {niche.value}
                              </Text>
                            ))}

                        {formik.errors.Niche && formik.touched.Niche && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.Niche}
                          </Text>
                        )}
                      </Box>
                    </FormControl>
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>Call Driven Niche?</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="Some niches rely almost exclusively on phone calls rather than a walk-in client. Call-driven niches usually work best for rank and rent, but there are exceptions. Whether the niche is call driven is an important factor in due diligence."
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <Select
                        textTransform={"capitalize"}
                        icon={<AiFillCaretDown />}
                        bg={"#fff"}
                        name="CallDrivenNiche"
                        value={formik.values.CallDrivenNiche}
                        onChange={formik.handleChange}
                      >
                        <option value={""}>Select</option>

                        <option value={"YES"}>Yes </option>
                        <option value={"NO"}>No</option>
                      </Select>
                    </FormControl>
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>Primary Keyword</Text>
                        <TooltipCustom tooltipText="Enter the primary keyword you want to rank for in your prospective market and press enter. This is usually the same keyword as for your landing page." />
                      </FormLabel>
                      <Box>
                        <Input
                          bgColor="#fff"
                          value={formik.values.PrimaryKeyword}
                          name="PrimaryKeyword"
                          onChange={formik.handleChange}
                          placeholder="Search or create a keyword and press enter"
                          onFocus={() => setPrimaryKeyFieldFocusState(true)}
                          onBlur={() =>
                            setTimeout(
                              () => setPrimaryKeyFieldFocusState(false),
                              500
                            )
                          }
                          onKeyDown={handleCreatePrimaryKeyword}
                          _placeholder={{
                            color: "#7A7A7A",
                          }}
                        />
                        {selectedKeyword && (
                          <Tag mt={2} variant="solid" colorScheme="teal">
                            {selectedKeyword}
                            <Button
                              size="sm"
                              variant="unstyled"
                              onClick={handleRemovePrimaryKeyword}
                            >
                              X
                            </Button>
                          </Tag>
                        )}

                        {formik.errors.PrimaryKeyword && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.PrimaryKeyword}
                          </Text>
                        )}
                      </Box>
                    </FormControl>
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>Secondary Keywords</Text>
                        <TooltipCustom tooltipText="Enter up to 6 additional secondary keywords for your prospective market.These are usually the same keywords used for your service pages" />
                      </FormLabel>
                      <Input
                        bg={"#fff"}
                        type="text"
                        name="SecondaryKeyword"
                        placeholder="Enter secondary keywords and press enter to add"
                        value={formik.values.SecondaryKeyword}
                        onChange={formik.handleChange}
                        onKeyDown={handleKeyDownSecondaryKeyword}
                        onFocus={() => setSecondaryFieldFocusState(true)}
                        onBlur={() =>
                          setTimeout(
                            () => setSecondaryFieldFocusState(false),
                            500
                          )
                        }
                        _placeholder={{
                          color: "#7A7A7A",
                        }}
                      />
                      <Box mt="2">
                        {secondaryKeywordsArr.map((secondaryKeyword, index) => (
                          <Tag
                            key={index}
                            size="md"
                            variant="subtle"
                            colorScheme="blue"
                            mr="2"
                            mb="2"
                          >
                            <TagLabel>{secondaryKeyword.value}</TagLabel>
                            <TagCloseButton
                              onClick={() =>
                                handleRemoveNicheForNicheArr(index)
                              }
                            />
                          </Tag>
                        ))}
                      </Box>

                      {formik.errors.SecondaryKeyword &&
                        formik.touched.SecondaryKeyword && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.SecondaryKeyword}
                          </Text>
                        )}
                    </FormControl>
                  </VStack>
                </HStack>
                <HStack w={"100%"} alignItems={"start"} gap={"5vw"}>
                  <Box w={"20vw"} pl={"15px"}>
                    <Text fontSize={"22px"} fontWeight={"600"}>
                      {" "}
                      Competitor Analysis
                    </Text>
                    <Text color={"#7A7A7A"}>
                      Add the domains for your top 3 competitors in your
                      prospective market to assess your ranking difficulty.
                    </Text>
                  </Box>
                  <VStack
                    w={"100%"}
                    pb={"30px"}
                    borderBottom={"1px solid rgba(2, 43, 58, 0.3)"}
                  >
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>How Many Active Businesses?</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="A market should have enough active businesses to prospect for a client. Assess how many businesses exist in this market and assign a choice here,"
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <Select
                        textTransform={"capitalize"}
                        icon={<AiFillCaretDown />}
                        bg={"#fff"}
                        name="NumberOfActiveBusinesses"
                        value={formik.values.NumberOfActiveBusinesses}
                        onChange={formik.handleChange}
                      >
                        <option value="MANY">Many</option>
                        <option value="FEW">Few</option>
                        <option value="NONE">None</option>
                      </Select>
                    </FormControl>
                    <FormControl w={"100%"}>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>{`Competitor Domain `}</Text>
                        <TooltipCustom
                          tooltipText={`Enter the domain for the  of the three top competitors in your market for competitive analysis.`}
                        />
                      </FormLabel>
                      <Input
                        bg={"#fff"}
                        placeholder={`Business 1`}
                        name="CompetitorBusiness1"
                        value={formik.values.CompetitorBusiness1}
                        pattern="[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@%_\+.~#?&//=]*)"
                        onChange={formik.handleChange}
                        _placeholder={{
                          color: "#7A7A7A",
                        }}
                      />
                      {formik.errors.CompetitorBusiness1 &&
                        formik.touched.CompetitorBusiness1 && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.CompetitorBusiness1}
                          </Text>
                        )}
                    </FormControl>
                    <FormControl w={"100%"}>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>{`Competitor Domain `}</Text>
                        <TooltipCustom
                          tooltipText={`Enter the domain for the  of the three top competitors in your market for competitive analysis.`}
                        />
                      </FormLabel>
                      <Input
                        bg={"#fff"}
                        placeholder={`Business 2`}
                        name="CompetitorBusiness2"
                        value={formik.values.CompetitorBusiness2}
                        pattern="[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@%_\+.~#?&//=]*)"
                        onChange={formik.handleChange}
                        _placeholder={{
                          color: "#7A7A7A",
                        }}
                      />
                      {formik.errors.CompetitorBusiness2 &&
                        formik.touched.CompetitorBusiness2 && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.CompetitorBusiness2}
                          </Text>
                        )}
                    </FormControl>
                    <FormControl w={"100%"}>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>{`Competitor Domain `}</Text>
                        <TooltipCustom
                          tooltipText={`Enter the domain for the  of the three top competitors in your market for competitive analysis.`}
                        />
                      </FormLabel>
                      <Input
                        bg={"#fff"}
                        placeholder={`Business 3`}
                        name="CompetitorBusiness3"
                        value={formik.values.CompetitorBusiness3}
                        pattern="[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@%_\+.~#?&//=]*)"
                        onChange={formik.handleChange}
                        _placeholder={{
                          color: "#7A7A7A",
                        }}
                      />
                      {formik.errors.CompetitorBusiness3 &&
                        formik.touched.CompetitorBusiness3 && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.CompetitorBusiness3}
                          </Text>
                        )}
                    </FormControl>
                  </VStack>
                </HStack>
                <HStack pt={"30px"} w={"100%"} alignItems={"start"} gap={"5vw"}>
                  <Box w={"20vw"} pl={"15px"}>
                    <Text fontSize={"22px"} fontWeight={"600"}>
                      {" "}
                      Market Analysis
                    </Text>
                    <Text color={"#7A7A7A"}>
                      Enter details about your decision for this market.
                    </Text>
                  </Box>

                  <VStack
                    w={"100%"}
                    pb={"30px"}
                    borderBottom={"1px solid rgba(2, 43, 58, 0.3)"}
                  >
                    <FormControl>
                      <FormLabel
                        display={"flex"}
                        justifyContent={"space-between"}
                      >
                        <Text>Available Domain</Text>
                        <Tooltip
                          bg={"#fff"}
                          color={"#5F7F9E"}
                          placement="top"
                          hasArrow
                          label="Look up whether your preferred domain is available here for this market and add it here."
                        >
                          <Image
                            src={"/assets/icons/qus_icon.svg"}
                            alt="qus icon"
                            height={21}
                            width={21}
                          />
                        </Tooltip>
                      </FormLabel>
                      <Input
                        bg={"#fff"}
                        placeholder="Enter company domain"
                        onChange={formik.handleChange}
                        value={formik.values.AvailableDomain}
                        name="AvailableDomain"
                        disabled={_id ? true : false}
                        _placeholder={{
                          color: "#7A7A7A",
                        }}
                      />
                      {formik.errors.AvailableDomain &&
                        formik.touched.AvailableDomain && (
                          <Text fontWeight={500} fontSize="sm" color="tomato">
                            {formik.errors.AvailableDomain}
                          </Text>
                        )}
                    </FormControl>
                    <SimpleGrid
                      w={"100%"}
                      templateColumns="repeat(2 , 1fr)"
                      columns={2}
                      columnGap={4}
                      rowGap={4}
                    >
                      <GridItem colSpan={1} alignSelf={"end"}>
                        <FormControl>
                          <FormLabel
                            display={"flex"}
                            justifyContent={"space-between"}
                          >
                            <Text>Go or No Go?</Text>
                            <Tooltip
                              bg={"#fff"}
                              color={"#5F7F9E"}
                              placement="top"
                              hasArrow
                              label="Go status means you've decided to enter this market. No Go means you concluded this is not a viable market. TBD means this market's status is to be determined. This decision is made after due diligence for this market is complete."
                            >
                              <Image
                                src={"/assets/icons/qus_icon.svg"}
                                alt="qus icon"
                                height={21}
                                width={21}
                              />
                            </Tooltip>
                          </FormLabel>
                          <Select
                            textTransform={"capitalize"}
                            icon={<AiFillCaretDown />}
                            bg={"#fff"}
                            name="GoOrNoGo"
                            value={formik.values.GoOrNoGo}
                            onChange={formik.handleChange}
                          >
                            <option value="">Select</option>

                            <option value={"GO"}>Go</option>
                            <option value={"NOGO"}>No Go</option>
                            <option value={"TBD"}>TBD</option>
                          </Select>
                          {formik.errors.GoOrNoGo &&
                            formik.touched.GoOrNoGo && (
                              <Text
                                fontWeight={500}
                                fontSize="sm"
                                color="tomato"
                              >
                                {formik.errors.GoOrNoGo}
                              </Text>
                            )}
                        </FormControl>
                      </GridItem>
                      <GridItem colSpan={1}>
                        <FormControl>
                          <FormLabel
                            display={"flex"}
                            justifyContent={"space-between"}
                          >
                            <Text>Low Hanging Fruit?</Text>
                            <Tooltip
                              bg={"#fff"}
                              color={"#5F7F9E"}
                              placement="top"
                              hasArrow
                              label="Low hanging fruit is a market where there is low to no competition and are ideal for ranking quickly. A market is not required to be low hanging fruit, but it is often helpful."
                            >
                              <Image
                                src={"/assets/icons/qus_icon.svg"}
                                alt="qus icon"
                                height={21}
                                width={21}
                              />
                            </Tooltip>
                          </FormLabel>
                          <Select
                            textTransform={"capitalize"}
                            icon={<AiFillCaretDown />}
                            bg={"#fff"}
                            onChange={formik.handleChange}
                            name="LowHangingFruit"
                            value={formik.values.LowHangingFruit}
                          >
                            <option value={""}>Select</option>

                            <option value={"YES"}>Yes</option>
                            <option value={"NO"}>No </option>
                            <option value={"UNSURE"}>Unsure</option>
                          </Select>
                          {formik.errors.LowHangingFruit &&
                            formik.touched.LowHangingFruit && (
                              <Text
                                fontWeight={500}
                                fontSize="sm"
                                color="tomato"
                              >
                                {formik.errors.LowHangingFruit}
                              </Text>
                            )}
                        </FormControl>
                      </GridItem>
                    </SimpleGrid>
                  </VStack>
                </HStack>
                <HStack
                  pt={"20px"}
                  bgColor={"rgba(255, 255, 255, 0.45)"}
                  pr={"40px"}
                >
                  <HStack
                    pb={"30px"}
                    w={"100%"}
                    alignItems={"start"}
                    gap={"5vw"}
                  >
                    <Box pl={"15px"} w={"20vw"}>
                      <Text fontSize={"22px"} fontWeight={"600"}>
                        Comments
                      </Text>
                      <Text color={"#7A7A7A"}>
                        Add comments about this market that offer additional
                        insights into your due diligence.
                      </Text>
                    </Box>
                    <Box w={"100%"}>
                      <FormControl>
                        <FormLabel>Add comments</FormLabel>
                        <Textarea
                          name="Comments"
                          value={formik.values.Comments}
                          onChange={formik.handleChange}
                          onBlur={formik.handleBlur}
                          placeholder="Add a comment..."
                          color="gray.700"
                          bg={"#fff"}
                          width="100%"
                          _placeholder={{
                            color: "#7A7A7A",
                          }}
                        />
                      </FormControl>
                      <Box mt={"12px"} w={"100%"} textAlign={"center"}>
                        {comments.length > 0 &&
                          comments.map(
                            (
                              comment: {
                                userRef: string;
                                comment: string;
                                _id: string;
                              },
                              index
                            ) => (
                              <React.Fragment key={index}>
                                <Text>{comment.comment}</Text>
                                <Button
                                  mt={"16px"}
                                  h={"32px"}
                                  w="70px"
                                  bg="button.100"
                                  color={"#fff"}
                                  onClick={() =>
                                    handleCommentDeletion(comment._id)
                                  }
                                >
                                  Delete
                                </Button>
                              </React.Fragment>
                            )
                          )}
                      </Box>
                    </Box>
                  </HStack>
                </HStack>
                <HStack
                  bg={"#E1EDEE"}
                  py={"10px"}
                  width={"100%"}
                  justifyContent={"space-between"}
                  borderRadius={"0 15px 15px 15px "}
                  border={"3px solid rgba(174, 214, 220, 0.36)"}
                  alignItems={"flex-end"}
                >
                  <Flex justifyContent={"left"} align={"center"} gap={"15px"}>
                    <Box>
                      <Button
                        borderRadius={"18px"}
                        padding={"9px 16px"}
                        variant={"solid"}
                        color={"#fff"}
                        bgColor={"button.100"}
                        fontSize={"1.4rem"}
                        fontWeight={"600"}
                        type="submit"
                      >
                        {_id ? "Update" : "Save Location"}
                      </Button>
                    </Box>
                    <Box>
                      <Button
                        borderRadius={"18px"}
                        padding={"9px 16px"}
                        fontSize={"1.2rem"}
                        fontWeight={"700"}
                        colorScheme="button.100"
                        mr={3}
                        variant={"outline"}
                        onClick={onClose}
                      >
                        Close
                      </Button>
                    </Box>
                  </Flex>
                </HStack>
              </form>
            </Box>
          </VStack>
        </ModalBody>
      </ModalContent>
    </Modal>
  );
};
export default AddRecordModal;
Editor is loading...
Leave a Comment