Hubspot Contact Dropdown

/**
 * Questmate Custom Component - Hubspot Contact Dropdown (Questscript)
 *
 * Permissions:
 * @UseApp {HUBSPOT}
 *
 * Changelog:
 * v0.1 Initial release
 * v0.2 Converted to Custom V2 item
 */

return defineCustomItem((Questmate) => {
  Questmate.registerView('ITEM_RUN_VIEW', ({useRunData}) => {
    const [selectedContact, setSelectedContact] = useRunData('selectedContactId', null);

    return {
      components: [
        {
          id: "contact",
          type: "dropdown",
          icon: "person",
          value: selectedContact,
          onSelect: setSelectedContact,
          getOptions: async () => {
            const contacts = await contactsDataSource.retrieve()
            return contacts
            .map(({properties, id}) => ({
              label: `${properties.firstname || ""} ${properties.lastname || ""}`,
              value: id,
            }))
            .filter((entry) => entry.label.trimStart().trimEnd())
            .sort((a, b) =>
              a.label.localeCompare(b.label, undefined, {
                numeric: true,
                sensitivity: "base",
              })
            )
          },
          optionNoun: "Contact",
          optionPluralNoun: "Contacts",
        },
      ]
    }
  })

  const contactsDataSource = Questmate.registerDataSource({
    id: 'hubspot-contacts',
    aggregator: ({results, staleResults}) => {
      return [...results, ...staleResults]
          .flatMap((result) => result.data)
          // filter out duplicate row data
          .filter(
            (row, index, self) =>
              self.findIndex(({ id }) => id === row.id) === index
          )
    },
    fetcher: ({nextPageMarker}) => async () => {
      const response = await fetch(
        `https://api.hubapi.com/crm/v3/objects/contacts?limit=100&archived=false${
          nextPageMarker ? `&after=${nextPageMarker}` : ""
        }`
      );
      const responseData = await response.json();
      if (!responseData.results) {
        console.log("responseData: ", JSON.stringify(responseData));
        return {
          error: {
            message: "Failed to hubspot contacts",
            details: {response: responseData}
          }
        }
      }

      return {
        data: responseData.results,
        nextPageMarker: responseData.paging?.next?.after
      }
    }
  })
});