import { AddressBookThirdPartyResultsProps, entityLookup, useAddressBook, useThirdPartyAPIEndpoints, } from "@tradetrust-tt/address-identity-resolver"; import { debounce, isEmpty } from "lodash"; import React, { FunctionComponent, useCallback, useEffect, useState, } from "react"; import { Download, Search } from "react-feather"; import { useOverlayContext } from "../../common/context/OverlayContext"; import { LinkButton } from "../UI/Button"; import { Dropdown, DropdownItem } from "../UI/Dropdown"; import { OverlayContent, OverlayContentProps, } from "../UI/Overlay/OverlayContent"; import { Pagination } from "../UI/Pagination"; import { AddressBookLocal } from "./AddressBookLocal"; import { AddressBookThirdParty } from "./AddressBookThirdParty"; import { CsvUploadButton } from "./CsvUploadButton"; export enum AddressBookState { NONE = "NONE", PENDING = "PENDING", SUCCESS = "SUCCESS", EMPTY = "EMPTY", ERROR = "ERROR", } type onAddressSelectType = (address: string) => void; export interface AddressBookProps { network?: string; onAddressSelect?: onAddressSelectType; paginationOffset?: number; paginationLimit?: number; className?: string; } export const AddressBook: FunctionComponent = ({ network, onAddressSelect, paginationOffset = 0, paginationLimit = 10, ...props }) => { const { thirdPartyAPIEndpoints } = useThirdPartyAPIEndpoints(); const { handleLocalAddressBookCsv, addressBook } = useAddressBook(); const [searchTerm, setSearchTerm] = useState(""); const [isLocal, setIsLocal] = useState(true); const [remoteEndpointIndex, setRemoteEndpointIndex] = useState(0); const [thirdPartyPageResults, setThirdPartyPageResults] = useState< AddressBookThirdPartyResultsProps[] >([]); const { name, endpoint, apiHeader, apiKey, path } = thirdPartyAPIEndpoints[remoteEndpointIndex] ?? {}; const [thirdPartyTotalPages, setThirdPartyTotalPages] = useState(1); const [currentPage, setCurrentPage] = useState(1); const hasEntityLookupPath = !!path?.entityLookup; const filteredLocalAddresses = Object.keys(addressBook).filter((key) => { const identifier = addressBook[key]; return ( identifier.toLowerCase().includes(searchTerm.toLowerCase()) || key.toLowerCase().includes(searchTerm.toLowerCase()) ); }); const localTotalPages = Math.ceil( filteredLocalAddresses.length / paginationLimit ); const totalNoOfPages = isLocal ? localTotalPages : thirdPartyTotalPages; const offset = (currentPage - 1) * paginationLimit || paginationOffset; const localPageResults = filteredLocalAddresses.slice( offset, offset + paginationLimit ); const [addressBookThirdPartyStatus, setAddressBookThirdPartyStatus] = useState( hasEntityLookupPath ? AddressBookState.NONE : AddressBookState.ERROR ); const [addressBookLocalStatus, setAddressBookLocalStatus] = useState( AddressBookState.NONE ); const queryEndpoint = async ( search: string, pageOffset: number ): Promise => { if (!path.entityLookup) { throw "This endpoint does not have the entityLookup feature."; } setAddressBookThirdPartyStatus(AddressBookState.PENDING); try { const results = await entityLookup({ offset: pageOffset.toString(), limit: paginationLimit.toString(), query: search, endpoint, apiHeader, apiKey, path: path.entityLookup, }); setThirdPartyPageResults(results.identities); const numberOfResults = results.total > 0 ? results.total : paginationLimit; setThirdPartyTotalPages(Math.ceil(numberOfResults / paginationLimit)); if (isEmpty(results.identities)) { setAddressBookThirdPartyStatus(AddressBookState.EMPTY); } else { setAddressBookThirdPartyStatus(AddressBookState.SUCCESS); } } catch (e) { setThirdPartyPageResults([]); setThirdPartyTotalPages(1); setAddressBookThirdPartyStatus(AddressBookState.EMPTY); console.log(e); } }; const queryEndpointWithDebounce = useCallback( debounce(async (search, pageOffset = offset) => { queryEndpoint(search, pageOffset); }, 700), [] ); useEffect(() => { if (isLocal) return; const pageOffset = (currentPage - 1) * paginationLimit; queryEndpoint(searchTerm, pageOffset); }, [currentPage]); useEffect(() => { if (isEmpty(addressBook)) { setAddressBookLocalStatus(AddressBookState.NONE); } else if (isEmpty(localPageResults)) { setAddressBookLocalStatus(AddressBookState.EMPTY); } else { setAddressBookLocalStatus(AddressBookState.SUCCESS); } }, [addressBook, localPageResults]); const onSearchTermChanged = ( event: React.ChangeEvent ): void => { const inputText = event.target.value; setSearchTerm(inputText); setCurrentPage(1); if (!isLocal) queryEndpointWithDebounce(inputText); }; const resetThirdPartyAPIEndpointResult = (): void => { setSearchTerm(""); setCurrentPage(1); setThirdPartyPageResults([]); setThirdPartyTotalPages(1); }; return (
{ setIsLocal(true); resetThirdPartyAPIEndpointResult(); }} > Local {thirdPartyAPIEndpoints.map((item, index) => { return ( { setIsLocal(false); setRemoteEndpointIndex(index); resetThirdPartyAPIEndpointResult(); }} > {item.name} ); })}
Download Template
{isLocal ? ( ) : ( )}
); }; export interface OverlayAddressBookProps extends OverlayContentProps { network: string; onAddressSelected?: (newValue: string) => void; } export const OverlayAddressBook: FunctionComponent = ({ network, onAddressSelected, ...props }: OverlayAddressBookProps) => { const { setOverlayVisible } = useOverlayContext(); const onAddressSelect: onAddressSelectType = (address) => { if (onAddressSelected) { onAddressSelected(address); setOverlayVisible(false); } }; return ( ); };