[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/components/UserWidget.tsx from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { Fragment, useEffect, useState } from 'react'
import type { FunctionComponent } from 'react'
import { useQuery, useMutation } from 'react-apollo'
import { useIntl, FormattedMessage } from 'react-intl'
import {
  AutocompleteInput,
  Button,
  Input,
  Modal,
  Spinner,
  Tag,
} from 'vtex.styleguide'
import { useCssHandles } from 'vtex.css-handles'
import { useRuntime } from 'vtex.render-runtime'

import {
  organizationMessages as storeMessages,
  userWidgetMessages as messages,
} from './utils/messages'
import storageFactory from '../utils/storage'
import { useSessionResponse } from '../modules/session'
import USER_WIDGET_QUERY from '../graphql/userWidgetQuery.graphql'
import SET_CURRENT_ORGANIZATION from '../graphql/setCurrentOrganization.graphql'
import STOP_IMPERSONATION from '../graphql/impersonateUser.graphql'
import { B2B_CHECKOUT_SESSION_KEY } from '../utils/constants'
import '../css/user-widget.css'
import { sendStopImpersonateMetric } from '../utils/metrics/impersonate'
import type { ChangeTeamParams } from '../utils/metrics/changeTeam'
import { sendChangeTeamMetric } from '../utils/metrics/changeTeam'
import { UserWidgetTable } from './UserWidget/UserWidgetTable'
import { useDebounceValue } from '../hooks/useDebounce'

const CSS_HANDLES = [
  'userWidgetContainer',
  'userWidgetLoading',
  'userWidgetRow',
  'userWidgetItem',
  'userWidgetButton',
  'userWidgetImpersonationItem',
  'userWidgetImpersonationButton',
  'userWidgetImpersonationError',
  'userWidgetOrganizationError',
  'userWidgetModal',
  'userWidgetCompanyName',
  'userWidgetCostCenterName',
  'userWidgetRole',
  'col',
  'userWidgetModalRow',
  'userWidgetModalH1',
  'userWidgetModalH2',
  'userWidgetModalH3',
  'userWidgetModalH4',
  'userWidgetModalInput',
  'userWidgetModalJoinButton',
  'userWidgetModalTotal',
] as const

const SESSION_STORAGE_SHOW_MODAL = 'b2b-organizations-showModal'

const localStore = storageFactory(() => localStorage)
let isAuthenticated =
  JSON.parse(String(localStore.getItem('b2b-organizations_isAuthenticated'))) ??
  false

const CustomOrganizationOption = (props: any) => {
  const { roundedBottom, searchTerm, value, selected, onClick } = props
  const [highlightOption, setHighlightOption] = useState(false)

  const renderOptionHighlightedText = () => {
    const highlightableText = typeof value === 'string' ? value : value.label
    const index = highlightableText
      .toLowerCase()
      .indexOf(searchTerm.toLowerCase())

    if (index === -1) {
      return highlightableText
    }

    const prefix = highlightableText.substring(0, index)
    const match = highlightableText.substr(index, searchTerm.length)
    const suffix = highlightableText.substring(`${index}${match.length}`)

    return (

        {prefix}
        {match}
        {suffix}

    )
  }

  const buttonClasses = `bn w-100 tl pointer pa4 f6 ${
    roundedBottom ? 'br2 br--bottom' : ''
  } ${highlightOption || selected ? 'bg-muted-5' : 'bg-base'}`

  // --- This is a good practice. Use <button />.
  return (
    <button
      className={buttonClasses}
      onFocus={() => setHighlightOption(true)}
      onMouseEnter={() => setHighlightOption(true)}
      onMouseLeave={() => setHighlightOption(false)}
      onClick={onClick}
      disabled={value.status !== 'active'}
    >

        {renderOptionHighlightedText()}
        {typeof value !== 'string' &&
{value.caption}
}

    </button>
  )
}

interface VtexFunctionComponent<T = Record<string, unknown>>
  extends FunctionComponent<T> {
  schema?: {
    title?: string
    properties?: Record<string, unknown>
  }
}

interface UserWidgetProps {
  showDropdown?: boolean
  showLoadingIndicator?: boolean
}

const sortOrganizations = (a: any, b: any) =>
  a.organizationName < b.organizationName ? -1 : 1

const SEARCH_DELAY = 500

const UserWidget: VtexFunctionComponent<UserWidgetProps> = ({
  showDropdown = true,
  showLoadingIndicator = false,
}) => {
  const { navigate, rootPath } = useRuntime()
  const { formatMessage } = useIntl()
  const handles = useCssHandles(CSS_HANDLES)
  const [loadingState, setLoadingState] = useState(false)
  const [errorState, setErrorState] = useState(false)
  const [errorOrganization, setErrorOrganization] = useState(false)
  const [showModal, setShowModal] = useState(false)
  const [searchTerm, setSearchTerm] = useState('')
  const [radioValue, setRadioValue] = useState('')
  const [checkSession, setCheckSession] = useState(false)
  const searchTermDebounced = useDebounceValue(searchTerm, SEARCH_DELAY)

  const [organizationsState, setOrganizationsState] = useState({
    organizationOptions: [],
    costCenterOptions: [],
    organizationInput: '',
    costCenterInput: '',
    currentOrganization: '',
    currentRoleName: '',
    currentCostCenter: '',
    currentOrganizationStatus: '',
  })

  const sessionResponse: any = useSessionResponse()

  if (sessionResponse) {
    isAuthenticated =
      sessionResponse?.namespaces?.profile?.isAuthenticated?.value === 'true'

    localStore.setItem(
      'b2b-organizations_isAuthenticated',
      JSON.stringify(isAuthenticated)
    )

    if (!checkSession) {
      fetch('/api/sessions?items=public.facets,public.sc').then(response => {
        if (response.status === 200) {
          response.json().then(data => {
            if (window.__RUNTIME__) {
              const segmentToken = {
                ...JSON.parse(atob(window.__RUNTIME__.segmentToken)),
                ...(data?.namespaces?.public?.facets?.value
                  ? { facets: data?.namespaces?.public?.facets?.value }
                  : {}),
                ...(data?.namespaces?.public?.sc?.value
                  ? { sc: data?.namespaces?.public?.sc?.value }
                  : {}),
              }

              window.__RUNTIME__.segmentToken = btoa(
                JSON.stringify(segmentToken)
              )
              setCheckSession(true)
            }
          })
        }
      })
    }
  }

  const { data: userWidgetData, loading: userWidgetLoading } = useQuery(
    USER_WIDGET_QUERY,
    {
      ssr: false,
      skip: !isAuthenticated,
    }
  ) as any

  const [stopImpersonation] = useMutation(STOP_IMPERSONATION)
  const [setCurrentOrganization] = useMutation(SET_CURRENT_ORGANIZATION)

  const handleStopImpersonation = async () => {
    setLoadingState(true)
    setErrorState(false)

    stopImpersonation()
      .then(() => {
        if (sessionStorage.getItem(B2B_CHECKOUT_SESSION_KEY)) {
          sessionStorage.removeItem(B2B_CHECKOUT_SESSION_KEY)
        }

        const metricParams = {
          sessionResponse,
          email: userWidgetData?.checkImpersonation?.email,
          ...organizationsState,
        }

        sendStopImpersonateMetric(metricParams)
        window.location.reload()
      })
      .catch(error => {
        console.error(error)
        setErrorState(true)
        setLoadingState(false)
      })
  }

  const joinOrganization = async () => {
    const [orgId, costId] = radioValue.split(',')

    setLoadingState(true)
    try {
      await setCurrentOrganization({
        variables: {
          orgId,
          costId,
        },
      })
    } catch (error) {
      setErrorOrganization(true)
    } finally {
      setLoadingState(false)
    }

    window.location.reload()
  }

  const handleSetCurrentOrganization = async () => {
    setLoadingState(true)
    try {
      await setCurrentOrganization({
        variables: {
          orgId: organizationsState.currentOrganization,
          costId: organizationsState.currentCostCenter,
        },
      })

      const metricParams: ChangeTeamParams = {
        sessionResponse,
        ...organizationsState,
      }

      sendChangeTeamMetric(metricParams)
    } catch (error) {
      setErrorOrganization(true)
    } finally {
      setLoadingState(false)
    }

    window.location.reload()
  }

  const organizationAutoCompleteInput = {
    onChange: (text: string) => {
      setOrganizationsState({
        ...organizationsState,
        organizationInput: text,
        organizationOptions:
          userWidgetData?.getActiveOrganizationsByEmail
            ?.filter((organization: any) => {
              return organization?.organizationName
                ?.toLowerCase()
                .includes(text?.toLowerCase())
            })
            .map(
              (organization: {
                orgId: string
                organizationName: string
                organizationStatus: string
              }) => ({
                value: organization.orgId,
                label: organization.organizationName,
                status: organization.organizationStatus,
              })
            )
            .slice(0, 15) ?? [],
      })
    },
    placeholder: `${formatMessage(storeMessages.autocompleteSearching)}...`,
    value: organizationsState.organizationInput,
  }

  const costCenterAutoCompleteInput = {
    onChange: (text: string) => {
      setOrganizationsState({
        ...organizationsState,
        costCenterInput: text,
      })
    },
    placeholder: `${formatMessage(
      storeMessages.autocompleteSearchingCostCenter
    )}...`,
    value: organizationsState.costCenterInput,
  }

  useEffect(() => {
    if (!userWidgetData?.getActiveOrganizationsByEmail) {
      return
    }

    const uiSettings = userWidgetData?.getB2BSettings?.uiSettings

    if (uiSettings?.showModal) {
      const totalCompanies =
        userWidgetData?.getActiveOrganizationsByEmail?.length

      const storageShowModal = sessionStorage.getItem(
        SESSION_STORAGE_SHOW_MODAL
      )

      setShowModal(totalCompanies > 1 && !storageShowModal)

      sessionStorage.setItem(SESSION_STORAGE_SHOW_MODAL, 'true')
    }

    const currentOrganization =
      userWidgetData?.getOrganizationByIdStorefront?.id

    const currentCostCenter = userWidgetData?.getCostCenterByIdStorefront?.id

    setOrganizationsState({
      ...organizationsState,
      costCenterInput: userWidgetData?.getCostCenterByIdStorefront?.name,
      organizationInput: userWidgetData?.getOrganizationByIdStorefront?.name,
      organizationOptions: userWidgetData?.getActiveOrganizationsByEmail
        .slice(0, 15)
        .map((organization: { orgId: string; organizationName: string }) => ({
          value: organization.orgId,
          label: organization.organizationName,
        })),
      currentRoleName: userWidgetData?.getActiveOrganizationsByEmail?.find(
        (organizations: any) => organizations.costId === currentCostCenter
      )?.role?.name,
      costCenterOptions: userWidgetData?.getActiveOrganizationsByEmail
        .filter(
          (organization: { orgId: string }) =>
            organization.orgId === currentOrganization
        )
        .map((organization: { costId: string; costCenterName: string }) => ({
          value: organization.costId,
          label: organization.costCenterName,
        })),
      currentOrganization,
      currentCostCenter,
      currentOrganizationStatus:
        userWidgetData?.getOrganizationByIdStorefront?.status,
    })
  }, [userWidgetData])

  const handleStatusMessage = (status: string) => {
    switch (status) {
      case 'active':
        return (
          <Tag type="success" size="small">
            {formatMessage(messages.active)}
          </Tag>
        )

      case 'on-hold':
        return (
          <Tag type="warning" size="small">
            {formatMessage(messages.onHold)}
          </Tag>
        )

      case 'inactive':
        return (
          <Tag type="error" size="small">
            {formatMessage(messages.inactive)}
          </Tag>
        )

      default:
        return ''
    }
  }

  const autoCompleteOrganizationOptions = {
    value: organizationsState.organizationOptions,
    renderOption: (props: any) => <CustomOrganizationOption {...props} />,
    onSelect: (itemSelected: { value: string }) => {
      setOrganizationsState({
        ...organizationsState,
        costCenterInput: '',
        currentOrganization: itemSelected.value,
        costCenterOptions: userWidgetData?.getActiveOrganizationsByEmail
          .filter(
            (organization: { orgId: string }) =>
              organization.orgId === itemSelected.value
          )
          .map(
            (organization: {
              costId: string
              costCenterName: string
              organizationStatus: string
            }) => ({
              value: organization.costId,
              label: organization.costCenterName,
              status: organization.organizationStatus,
            })
          ) as [],
      })
    },
  }

  const autoCompleteCostCentersOptions = {
    value: organizationsState.costCenterOptions,
    onSelect: (itemSelected: { value: string }) => {
      setOrganizationsState({
        ...organizationsState,
        currentCostCenter: itemSelected.value,
      })
    },
  }

  if (showLoadingIndicator && userWidgetLoading) {
    return (

        <Spinner color="currentColor" />

    )
  }

  if (
    !isAuthenticated ||
    !userWidgetData?.checkUserPermission ||
    !userWidgetData?.getOrganizationByIdStorefront ||
    !userWidgetData?.getCostCenterByIdStorefront
  )
    return null

  const handleSearchOrganizations = (e: any) => setSearchTerm(e.target.value)

  const dataList =
    userWidgetData?.getActiveOrganizationsByEmail
      ?.sort(sortOrganizations)
      ?.filter((organization: any) => {
        if (!searchTermDebounced) return true

        const organizationName =
          organization.organizationName?.toLowerCase() ?? ''

        const costCenterName = organization.costCenterName?.toLowerCase() ?? ''

        const searchValue = searchTermDebounced.toLowerCase()

        return (
          organizationName.includes(searchValue) ||
          costCenterName.includes(searchValue)
        )
      }) ?? []

  return (
    <div
      className={`${handles.userWidgetContainer} w-100 flex flex-column mv3 bg-base--inverted`}
    >
      <Modal
        responsiveFullScreen={true}
        centered
        isOpen={showModal}
        onClose={() => setShowModal(false)}
      >
        <div className={`${handles.userWidgetModalRow} flex`}>
          <div className={`${handles.col}`}>

              <h1 className={`${handles.userWidgetModalH1} flex`}>
                {formatMessage(messages.selectCompany)}

              <div className={`${handles.userWidgetModalInput} flex`}>
                <Input
                  onChange={handleSearchOrganizations}
                  value={searchTerm}
                  placeholder={`${formatMessage(messages.search)}...`}
                />

                  <Button variation="primary">
                    {formatMessage(messages.search)}
                  </Button>

              <div className={`${handles.userWidgetModalTotal} pt4 mb4`}>
                {dataList.length} {formatMessage(messages.organizationsFound)}

              {showModal && (
                <UserWidgetTable
                  list={dataList}
                  radioValue={radioValue}
                  setRadioValue={setRadioValue}
                />
              )}

              <Button
                variation="primary"
                disabled={!radioValue || !radioValue.trim().length}
                onClick={() => joinOrganization()}
                isLoading={loadingState}
              >
                {formatMessage(messages.join)}
              </Button>

          <div className={`${handles.col}`}>
            <h2 className={`${handles.userWidgetModalH2} flex`}>
              {formatMessage(messages.currentOrganization)}

            <h3
              className={`${handles.userWidgetModalH3} flex`}
            >{`${userWidgetData?.getOrganizationByIdStorefront?.name}`}

            <h4
              className={`${handles.userWidgetModalH4} flex`}
            >{`${userWidgetData?.getCostCenterByIdStorefront?.name}`}

      </Modal>
      {userWidgetData?.getB2BSettings?.uiSettings?.showModal && (
        <Fragment>
          <div className={`${handles.userWidgetRow} flex pr4 pl4 items-center`}>

              <div className={`${handles.userWidgetCompanyName} mr4`}>
                {`${formatMessage(messages.organization)} ${
                  userWidgetData?.getOrganizationByIdStorefront?.name
                }`}

              <div className={`${handles.userWidgetCostCenterName} mr4`}>
                {`${formatMessage(messages.costCenter)} ${
                  userWidgetData?.getCostCenterByIdStorefront?.name
                }`}

              <div className={`${handles.userWidgetRole}`}>
                {`${formatMessage(messages.role)} ${
                  organizationsState.currentRoleName
                }`}

                {userWidgetData?.getActiveOrganizationsByEmail?.length > 1 && (
                  <Button variant="primary" onClick={() => setShowModal(true)}>
                    {formatMessage(messages.changeOrganization)}
                  </Button>
                )}

        </Fragment>
      )}
      {!userWidgetData?.getB2BSettings?.uiSettings?.showModal && (
        <Fragment>
          <div
            className={`${handles.userWidgetRow} flex justify-center items-center`}
          >
            <div
              className={`${handles.userWidgetItem} pa3 br2 bg-base--inverted hover-bg-base--inverted active-bg-base--inverted c-on-base--inverted hover-c-on-base--inverted active-c-on-base--inverted dib mr3`}
            >
              {((!userWidgetData?.checkImpersonation?.email ||
                userWidgetData?.getB2BSettings?.uiSettings
                  ?.fullImpersonation === true) &&
                showDropdown && (
                  <AutocompleteInput
                    input={organizationAutoCompleteInput}
                    options={autoCompleteOrganizationOptions}
                  />
                )) || (
                <Fragment>
                  {`${formatMessage(messages.organization)} ${
                    userWidgetData?.getOrganizationByIdStorefront?.name
                  }`}
                  {handleStatusMessage(
                    userWidgetData?.getOrganizationByIdStorefront?.status ?? ''
                  )}
                </Fragment>
              )}

            <div
              className={`${handles.userWidgetItem} pa3 br2 bg-base--inverted hover-bg-base--inverted active-bg-base--inverted c-on-base--inverted hover-c-on-base--inverted active-c-on-base--inverted dib mr3`}
            >
              {((!userWidgetData?.checkImpersonation?.email ||
                userWidgetData?.getB2BSettings?.uiSettings
                  ?.fullImpersonation === true) &&
                showDropdown && (
                  <AutocompleteInput
                    input={costCenterAutoCompleteInput}
                    options={autoCompleteCostCentersOptions}
                  />
                )) || (
                <Fragment>
                  {`${formatMessage(messages.costCenter)} ${
                    userWidgetData?.getCostCenterByIdStorefront?.name
                  }`}
                </Fragment>
              )}

            {(!userWidgetData?.checkImpersonation?.email ||
              userWidgetData?.getB2BSettings?.uiSettings?.fullImpersonation ===
                true) &&
              showDropdown && (
                <div
                  className={`${handles.userWidgetItem} pa3 br2 bg-base--inverted hover-bg-base--inverted active-bg-base--inverted c-on-base--inverted hover-c-on-base--inverted active-c-on-base--inverted dib mr3`}
                >
                  <Button
                    variation="primary"
                    size="small"
                    disabled={
                      organizationsState.currentCostCenter ===
                      userWidgetData?.getCostCenterByIdStorefront?.id
                    }
                    isLoading={loadingState}
                    onClick={() => handleSetCurrentOrganization()}
                  >
                    {formatMessage(messages.setCurrentOrganization)}
                  </Button>
                  {errorOrganization && (
                    <div
                      className={`${handles.userWidgetOrganizationError} error`}
                    >
                      <FormattedMessage id="store/b2b-organizations.set-organization-error" />

                  )}

              )}
            <div
              className={`${handles.userWidgetItem} pa3 br2 bg-base--inverted hover-bg-base--inverted active-bg-base--inverted c-on-base--inverted hover-c-on-base--inverted active-c-on-base--inverted dib mr3`}
            >
              {`${formatMessage(messages.role)} ${
                organizationsState.currentRoleName
              }`}

            <div className={`${handles.userWidgetButton} pa3`}>
              <Button
                variation="secondary"
                size="small"
                onClick={() =>
                  navigate({
                    to: `${rootPath ?? ''}/account#/organization`,
                  })
                }
              >
                {formatMessage(messages.manageOrganization)}
              </Button>

          {userWidgetData?.checkImpersonation?.email && (
            <div
              className={`${handles.userWidgetRow} flex justify-center items-center`}
            >
              <div
                className={`${handles.userWidgetImpersonationItem} pa3 br2 bg-base--inverted hover-bg-base--inverted active-bg-base--inverted c-on-base--inverted hover-c-on-base--inverted active-c-on-base--inverted dib mr3`}
              >
                {`${formatMessage(messages.impersonating)} ${
                  userWidgetData?.checkImpersonation.email
                }`}

              <div className={`${handles.userWidgetImpersonationButton} pa3`}>
                <Button
                  variation="danger"
                  size="small"
                  onClick={() => handleStopImpersonation()}
                  isLoading={loadingState}
                >
                  {formatMessage(messages.stopImpersonation)}
                </Button>
                {errorState && (
                  <div
                    className={`${handles.userWidgetImpersonationError} error`}
                  >
                    <FormattedMessage id="store/b2b-organizations.stop-impersonation-error" />

                )}

          )}
        </Fragment>
      )}

  )
}

UserWidget.schema = {
  title: 'userWidget',
  properties: {
    showDropdown: {
      title: 'showDropdown',
      type: 'boolean',
      default: true,
    },
    showLoadingIndicator: {
      title: 'showLoadingIndicator',
      type: 'boolean',
      default: false,
    },
  },
}

export default UserWidget

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/components/DeleteAddressModal.tsx from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import type { FunctionComponent } from 'react'
import { ModalDialog } from 'vtex.styleguide'
import { useIntl, FormattedMessage } from 'react-intl'

import { costCenterMessages as messages } from './utils/messages'

interface Props {
  loading: boolean
  isOpen: boolean
  handleDeleteAddress: () => void
  handleCloseModals: () => void
}

const DeleteAddressModal: FunctionComponent<Props> = ({
  loading,
  isOpen,
  handleDeleteAddress,
  handleCloseModals,
}) => {
  const { formatMessage } = useIntl()

  return (
    <ModalDialog
      centered
      confirmation={{
        onClick: () => handleDeleteAddress(),
        label: formatMessage(messages.deleteConfirm),
      }}
      cancelation={{
        onClick: () => handleCloseModals(),
        label: formatMessage(messages.cancel),
      }}
      loading={loading}
      isOpen={isOpen}
      onClose={() => handleCloseModals()}
      closeOnOverlayClick={false}
    >
      <p>
        <FormattedMessage id="store/b2b-organizations.costCenter-details.delete-address-confirmation" />
      </p>
    </ModalDialog>
  )
}

export default DeleteAddressModal

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/components/EditUserModal.tsx from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect } from 'react'
import type { FunctionComponent } from 'react'
import { Modal, Input, Button, Dropdown } from 'vtex.styleguide'
import { useIntl } from 'react-intl'
import { useQuery } from 'react-apollo'

import { organizationMessages as storeMessages } from './utils/messages'
import { organizationMessages as adminMessages } from '../admin/utils/messages'
import GET_ROLES from '../graphql/getRoles.graphql'
import GET_COST_CENTERS from '../graphql/getCostCentersByOrganizationIdStorefront.graphql'
import GET_COST_CENTERS_ADMIN from '../graphql/getCostCentersByOrganizationId.graphql'
import OrganizationsAutocomplete from './OrganizationsAutocomplete'

interface Props {
  loading: boolean
  isOpen: boolean
  user: UserDetails
  handleUpdateUser: (user: UserDetails) => void
  handleRemoveUser: () => void
  handleCloseModal: () => void
  organizationId: string
  isAdmin?: boolean
  canEdit?: boolean
  canEditSales?: boolean
  isSalesAdmin: boolean
  canManageOrg?: boolean
}

interface DropdownOption {
  value: string
  label: string
}

const EditUserModal: FunctionComponent<Props> = ({
  loading,
  isOpen,
  user,
  handleUpdateUser,
  handleRemoveUser,
  handleCloseModal,
  organizationId,
  isAdmin = false,
  canEdit,
  canEditSales,
  isSalesAdmin,
  canManageOrg,
}) => {
  const { formatMessage } = useIntl()
  const [userState, setUserState] = useState({} as UserDetails)
  const [costCenterOptions, setCostCenterOptions] = useState(
    [] as DropdownOption[]
  )

  const [organizationState, setOrganizationState] = useState(organizationId)
  const [roleOptions, setRoleOptions] = useState([] as DropdownOption[])

  const { data: rolesData } = useQuery(GET_ROLES, {
    ssr: false,
  })

  const {
    data: costCentersData,
    refetch,
    loading: costCenterLoading,
  } = useQuery(isAdmin ? GET_COST_CENTERS_ADMIN : GET_COST_CENTERS, {
    variables: {
      id: organizationId,
      pageSize: 100,
    },
    fetchPolicy: 'network-only',
    ssr: false,
  })

  useEffect(() => {
    if (!organizationState) {
      return
    }

    setUserState({
      ...userState,
      orgId: organizationState,
      costId: user.orgId !== organizationState ? '' : user.costId,
    })

    refetch({
      id: organizationState,
      pageSize: 100,
    })
  }, [organizationState])

  useEffect(() => {
    if (
      !costCentersData?.getCostCentersByOrganizationIdStorefront?.data
        ?.length &&
      !costCentersData?.getCostCentersByOrganizationId?.data?.length
    ) {
      return
    }

    const data = isAdmin
      ? costCentersData.getCostCentersByOrganizationId.data
      : costCentersData.getCostCentersByOrganizationIdStorefront.data

    const options = data.map((costCenter: any) => {
      return { label: costCenter.name, value: costCenter.id }
    })

    setCostCenterOptions([...options])
  }, [costCentersData])

  useEffect(() => {
    if (!rolesData?.listRoles?.length) {
      return
    }

    const filteredArray = rolesData.listRoles.filter((role: any) => {
      if (isAdmin) return true

      if (canManageOrg) {
        return true
      }

      if (role.slug.includes('customer') && canEdit) {
        return true
      }

      if (role.slug.includes('sales') && canEditSales) {
        return !(role.slug.includes('sales-admin') && !isSalesAdmin)
      }

      return false
    })

    const options = filteredArray.map((role: any) => {
      return { label: role.name, value: role.id }
    })

    setRoleOptions(options)
  }, [rolesData])

  useEffect(() => {
    if (!user?.id) return

    setUserState(user)
  }, [user])

  if (!costCenterOptions?.length || !roleOptions?.length) return null

  return (
    <Modal
      centered
      bottomBar={
        <div className="nowrap">
          <span className="mr4">
            <Button
              variation="tertiary"
              onClick={() => handleCloseModal()}
              disabled={loading}
            >
              {formatMessage(
                isAdmin ? adminMessages.cancel : storeMessages.cancel
              )}
            </Button>
          </span>
          <span className="mr4">
            <Button
              variation="danger"
              onClick={() => handleRemoveUser()}
              disabled={loading}
            >
              {formatMessage(
                isAdmin ? adminMessages.removeUser : storeMessages.removeUser
              )}
            </Button>
          </span>
          <span>
            <Button
              variation="primary"
              onClick={() => handleUpdateUser(userState)}
              isLoading={loading}
              disabled={
                !userState.orgId || !userState.costId || !userState.roleId
              }
            >
              {formatMessage(isAdmin ? adminMessages.save : storeMessages.save)}
            </Button>
          </span>
        </div>
      }
      isOpen={isOpen}
      onClose={() => handleCloseModal()}
      closeOnOverlayClick={false}
    >
      <p className="f3 f1-ns fw3 gray">
        {formatMessage(
          isAdmin ? adminMessages.editUser : storeMessages.editUser
        )}
      </p>
      <div className="w-100 mv6">
        <Input
          size="large"
          label={formatMessage(
            isAdmin ? adminMessages.email : storeMessages.email
          )}
          value={userState.email}
          disabled
        />
      </div>
      {isOpen && canEditSales && isSalesAdmin && (
        <div className="w-100 mv6">
          <p className="mb3">
            {formatMessage(
              isAdmin
                ? adminMessages.userOrganization
                : storeMessages.userOrganization
            )}
          </p>

          <OrganizationsAutocomplete
            isAdmin={isAdmin}
            organizationId={organizationId}
            onChange={event => setOrganizationState(event.value as string)}
          />
        </div>
      )}
      <div className="w-100 mv6">
        <Dropdown
          label={
            <h4 className="t-heading-5 mb0 pt3">
              {formatMessage(
                isAdmin
                  ? adminMessages.userCostCenter
                  : storeMessages.userCostCenter
              )}
            </h4>
          }
          placeholder={formatMessage(
            isAdmin ? adminMessages.costCenter : storeMessages.costCenter
          )}
          disabled={costCenterLoading || (canEditSales && !isSalesAdmin)}
          options={costCenterOptions}
          value={userState.costId}
          onChange={(_: any, v: string) =>
            setUserState({ ...userState, costId: v })
          }
        />
      </div>
      <div className="w-100 mv6">
        <Dropdown
          label={
            <h4 className="t-heading-5 mb0 pt3">
              {formatMessage(
                isAdmin ? adminMessages.userRole : storeMessages.userRole
              )}
            </h4>
          }
          placeholder={formatMessage(
            isAdmin ? adminMessages.role : storeMessages.role
          )}
          disabled={costCenterLoading}
          options={roleOptions}
          value={userState.roleId}
          onChange={(_: any, v: string) =>
            setUserState({ ...userState, roleId: v })
          }
        />
      </div>
    </Modal>
  )
}

export default EditUserModal

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/components/RemoveUserModal.tsx from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import type { FunctionComponent } from 'react'
import { ModalDialog } from 'vtex.styleguide'
import { useIntl } from 'react-intl'

import { organizationMessages as storeMessages } from './utils/messages'
import { organizationMessages as adminMessages } from '../admin/utils/messages'

interface Props {
  loading: boolean
  isOpen: boolean
  user: UserDetails
  handleRemoveUser: () => void
  handleCloseModal: () => void
  isAdmin?: boolean
}

const RemoveUserModal: FunctionComponent<Props> = ({
  loading,
  isOpen,
  user,
  handleRemoveUser,
  handleCloseModal,
  isAdmin = false,
}) => {
  const { formatMessage } = useIntl()

  return (
    <ModalDialog
      centered
      loading={loading}
      confirmation={{
        onClick: () => handleRemoveUser(),
        label: formatMessage(
          isAdmin
            ? adminMessages.removeUserConfirm
            : storeMessages.removeUserConfirm
        ),
        isDangerous: true,
      }}
      cancelation={{
        onClick: () => handleCloseModal(),
        label: formatMessage(
          isAdmin ? adminMessages.cancel : storeMessages.cancel
        ),
      }}
      isOpen={isOpen}
      onClose={() => handleCloseModal()}
    >
      <div className="">
        <p className="f3 f3-ns fw3 gray">
          {formatMessage(
            isAdmin ? adminMessages.removeUser : storeMessages.removeUser
          )}
        </p>
        <p>
          {formatMessage(
            isAdmin
              ? adminMessages.removeUserHelp
              : storeMessages.removeUserHelp,
            {
              email: user.email,
            }
          )}
        </p>
      </div>
    </ModalDialog>
  )
}

export default RemoveUserModal

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/components/DeleteCostCenterModal.tsx from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React from 'react'
import type { FunctionComponent } from 'react'
import { ModalDialog } from 'vtex.styleguide'
import { useIntl, FormattedMessage } from 'react-intl'

import { costCenterMessages as messages } from './utils/messages'

interface Props {
  loading: boolean
  isOpen: boolean
  handleDeleteCostCenter: () => void
  handleCloseModals: () => void
}

const DeleteCostCenterModal: FunctionComponent<Props> = ({
  loading,
  isOpen,
  handleDeleteCostCenter,
  handleCloseModals,
}) => {
  const { formatMessage } = useIntl()

  return (
    <ModalDialog
      centered
      confirmation={{
        onClick: () => handleDeleteCostCenter(),
        label: formatMessage(messages.deleteConfirm),
      }}
      cancelation={{
        onClick: () => handleCloseModals(),
        label: formatMessage(messages.cancel),
      }}
      loading={loading}
      isOpen={isOpen}
      onClose={() => handleCloseModals()}
      closeOnOverlayClick={false}
    >
      <p>
        <FormattedMessage id="store/b2b-organizations.costCenter-details.delete-costCenter-confirmation" />
      </p>
    </ModalDialog>
  )
}

export default DeleteCostCenterModal

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/components/NewCostCenterModal.tsx from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```tsx
import React, { useState, useEffect } from 'react'
import type { FunctionComponent } from 'react'
import { Modal, Input, Button, Spinner } from 'vtex.styleguide'
import { useIntl, FormattedMessage } from 'react-intl'
import { useQuery } from 'react-apollo'
import { useRuntime } from 'vtex.render-runtime'
import {
  AddressRules,
  AddressForm,
  AddressContainer,
  CountrySelector,
  PostalCodeGetter,
} from 'vtex.address-form'
import { StyleguideInput } from 'vtex.address-form/inputs'
import { addValidation } from 'vtex.address-form/helpers'
import 'vtex.country-codes/locales'
import { useCssHandles } from 'vtex.css-handles'

import { costCenterMessages as messages } from './utils/messages'
import { getEmptyAddress, isValidAddress } from '../utils/addresses'
import GET_LOGISTICS from '../graphql/getLogistics.graphql'
import { validatePhoneNumber } from '../modules/formValidators'
import GET_B2B_CUSTOM_FIELDS from '../graphql/getB2BCustomFields.graphql'
import CustomFieldInput from '../admin/OrganizationDetailsCustomField'

interface Props {
  loading: boolean
  isOpen: boolean
  handleAddNewCostCenter: ({
    name,
    address,
    phoneNumber,
    businessDocument,
    customFields,
  }: {
    name: string
    address: AddressFormFields
    phoneNumber: string
    businessDocument: string
    customFields: CustomField[]
  }) => void
  handleCloseModal: () => void
}

const CSS_HANDLES = ['businessDocument'] as const

const NewCostCenterModal: FunctionComponent<Props> = ({
  loading,
  isOpen,
  handleAddNewCostCenter,
  handleCloseModal,
}) => {
  const {
    culture: { country },
  } = useRuntime()

  const { formatMessage } = useIntl()
  const [newCostCenterName, setNewCostCenterName] = useState('')
  const [newCostCenterPhoneNumber, setNewCostCenterPhoneNumber] = useState('')
  const [
    newCostCenterBusinessDocument,
    setNewCostCenterBusinessDocument,
  ] = useState('')

  const handles = useCssHandles(CSS_HANDLES)

  const [newCostCenterAddressState, setNewCostCenterAddressState] = useState(
    addValidation(getEmptyAddress(country))
  )

  const { data: logisticsData } = useQuery(GET_LOGISTICS, { ssr: false })

  const translateCountries = () => {
    const { shipsTo = [] } = logisticsData?.logistics ?? {}

    return shipsTo.map((code: string) => ({
      label: formatMessage({ id: `country.${code}` }),
      value: code,
    }))
  }

  const handleNewCostCenterAddressChange = (
    changedAddress: AddressFormFields
  ) => {
    const curAddress = newCostCenterAddressState

    const newAddress = { ...curAddress, ...changedAddress }

    setNewCostCenterAddressState(newAddress)
  }

  //! CUSTOM FIELDS
  const {
    data: defaultCustomFieldsData,
    loading: defaultCustomFieldsDataLoading,
  } = useQuery(GET_B2B_CUSTOM_FIELDS, {
    ssr: false,
  })

  const [
    costCenterCustomFieldsState,
    setCostCenterCustomFieldsState,
  ] = useState<CustomField[]>([])

  useEffect(() => {
    if (defaultCustomFieldsDataLoading) return

    const costCenterFieldsToDisplay = defaultCustomFieldsData?.getB2BSettings.costCenterCustomFields.filter(
      (item: CustomField) => item.useOnRegistration
    )

    setCostCenterCustomFieldsState(costCenterFieldsToDisplay)
  }, [defaultCustomFieldsData])

  const handleCostCenterCustomFieldsUpdate = (
    index: number,
    customField: CustomField
  ) => {
    const newCustomFields = [...costCenterCustomFieldsState]

    newCustomFields[index] = customField
    setCostCenterCustomFieldsState(newCustomFields)
  }
  //! CUSTOM FIELDS

  return (
    <Modal
      centered
      bottomBar={
        <div className="nowrap">
          <span className="mr4">
            <Button
              variation="tertiary"
              onClick={() => handleCloseModal()}
              disabled={loading}
            >
              {formatMessage(messages.cancel)}
            </Button>
          </span>
          <span>
            <Button
              variation="primary"
              onClick={() =>
                handleAddNewCostCenter({
                  name: newCostCenterName,
                  address: newCostCenterAddressState,
                  phoneNumber: newCostCenterPhoneNumber,
                  businessDocument: newCostCenterBusinessDocument,
                  customFields: costCenterCustomFieldsState,
                })
              }
              isLoading={loading}
              disabled={
                !newCostCenterName ||
                !isValidAddress(newCostCenterAddressState) ||
                (newCostCenterPhoneNumber &&
                  !validatePhoneNumber(newCostCenterPhoneNumber))
              }
            >
              {formatMessage(messages.add)}
            </Button>
          </span>
        </div>
      }
      isOpen={isOpen}
      onClose={() => handleCloseModal()}
      closeOnOverlayClick={false}
    >
      <p className="f3 f1-ns fw3 gray">
        <FormattedMessage id="store/b2b-organizations.organization-details.add-costCenter" />
      </p>
      <div className="w-100 mv6">
        <Input
          autocomplete="off"
          size="large"
          label={formatMessage(messages.costCenterName)}
          value={newCostCenterName}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            setNewCostCenterName(e.target.value)
          }}
          required
        />
      </div>
      <div className="w-100 mv6">
        <Input
          autocomplete="off"
          size="large"
          label={formatMessage(messages.phoneNumber)}
          helpText={formatMessage(messages.phoneNumberHelp)}
          value={newCostCenterPhoneNumber}
          error={
            newCostCenterPhoneNumber &&
            !validatePhoneNumber(newCostCenterPhoneNumber)
          }
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            setNewCostCenterPhoneNumber(e.target.value)
          }}
        />
      </div>
      <div className={`${handles.businessDocument} w-100 mv6`}>
        <Input
          autocomplete="off"
          size="large"
          label={formatMessage(messages.businessDocument)}
          helpText={formatMessage(messages.businessDocumentHelp)}
          value={newCostCenterBusinessDocument}
          onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
            setNewCostCenterBusinessDocument(e.target.value)
          }}
        />
      </div>

      <div className="w-100 mv6">
        <FormattedMessage id="store/b2b-organizations.organization-details.add-costCenter.helpText" />
      </div>
      {/* //! Custom fields */}
      {defaultCustomFieldsDataLoading ? (
        <div className="mb5 flex flex-column">
          <Spinner />
        </div>
      ) : (
        <>
          {costCenterCustomFieldsState?.map(
            (customField: CustomField, index: number) => {
              return (
                <CustomFieldInput
                  key={`${customField.name}`}
                  index={index}
                  handleUpdate={handleCostCenterCustomFieldsUpdate}
                  customField={customField}
                />
              )
            }
          )}
        </>
      )}
      {/* //! Custom fields */}
      <AddressRules
        country={newCostCenterAddressState?.country?.value}
        shouldUseIOFetching
        useGeolocation={false}
      >
        <AddressContainer
          address={newCostCenterAddressState}
          Input={StyleguideInput}
          onChangeAddress={handleNewCostCenterAddressChange}
          autoCompletePostalCode
        >
          <CountrySelector shipsTo={translateCountries()} />

          <PostalCodeGetter />

          <AddressForm
            Input={StyleguideInput}
            omitAutoCompletedFields={false}
            omitPostalCodeFields
          />
        </AddressContainer>
      </AddressRules>
    </Modal>
  )
}

export default NewCostCenterModal

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getOrganizationRequest.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganizationRequest($id: ID!) {
  getOrganizationRequestById(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    name
    tradeName
    b2bCustomerAdmin {
      email
    }
    status
    created
    defaultCostCenter {
      name
      address {
        addressId
        addressType
        addressQuery
        postalCode
        country
        receiverName
        city
        state
        street
        number
        complement
        neighborhood
        geoCoordinates
        reference
      }
      phoneNumber
      businessDocument
      stateRegistration
      customFields {
        name
        type
        value
      }
    }
    customFields {
      name
      type
      value
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getB2BSettings.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetB2BSettings {
  getB2BSettings @context(provider: "vtex.b2b-organizations-graphql") {
    autoApprove
    businessReadOnly
    stateReadOnly
    defaultPaymentTerms {
      id
      name
    }
    defaultPriceTables
    uiSettings {
      showModal
      clearCart
      fullImpersonation
      topBar {
        name
        hexColor
      }
    }
    organizationCustomFields {
      name
      type
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
    costCenterCustomFields {
      name
      type
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/addUser.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation AddUser(
  $id: ID
  $roleId: ID!
  $userId: ID
  $orgId: ID
  $costId: ID
  $clId: ID
  $canImpersonate: Boolean = false
  $name: String!
  $email: String!
) {
  addUser(
    id: $id
    roleId: $roleId
    userId: $userId
    orgId: $orgId
    costId: $costId
    clId: $clId
    canImpersonate: $canImpersonate
    name: $name
    email: $email
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getOrganizationStorefront.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganizationStorefront($id: ID) {
  getOrganizationByIdStorefront(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    status
    paymentTerms {
      id
      name
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getOrganizationRequests.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganizationRequests(
  $status: [String]
  $search: String
  $page: Int
  $pageSize: Int
  $sortOrder: String
  $sortedBy: String
) {
  getOrganizationRequests(
    status: $status
    search: $search
    page: $page
    pageSize: $pageSize
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    pagination {
      total
    }
    data {
      id
      name
      b2bCustomerAdmin {
        email
      }
      status
      created
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getCostCenterStorefront.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetCostCenterStorefront($id: ID) {
  getCostCenterByIdStorefront(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    organization
    paymentTerms {
      id
      name
    }
    addresses {
      addressId
      addressType
      addressQuery
      postalCode
      country
      receiverName
      city
      state
      street
      number
      complement
      neighborhood
      geoCoordinates
      reference
    }
    phoneNumber
    businessDocument
    stateRegistration
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getRoles.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetRoles {
  listRoles @context(provider: "vtex.storefront-permissions") {
    id
    name
    slug
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/updateUser.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UpdateUser(
  $id: ID
  $roleId: ID!
  $userId: ID
  $orgId: ID
  $costId: ID
  $clId: ID
  $canImpersonate: Boolean = false
  $name: String
  $email: String
) {
  updateUser(
    id: $id
    roleId: $roleId
    userId: $userId
    orgId: $orgId
    costId: $costId
    clId: $clId
    canImpersonate: $canImpersonate
    name: $name
    email: $email
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/setMarketingTags.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation SetMarketingTags($costId: ID!, $tags: [String]!) {
  setMarketingTags(costId: $costId, tags: $tags)
    @context(provider: "vtex.b2b-organizations-graphql") {
    message
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getSellersPaginated.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetSellersPaginated($page: Int, $pageSize: Int) {
  getSellersPaginated(page: $page, pageSize: $pageSize) {
    pagination {
      page
      pageSize
      total
    }
    items {
      id
      name
      email
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/deleteCostCenter.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation DeleteCostCenter($id: ID!) {
  deleteCostCenter(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getOrganizationsWithoutSalesManager.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganizationsWithoutSalesManager {
  getOrganizationsWithoutSalesManager
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/setCurrentOrganization.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation CurrentOrganization($orgId: ID!, $costId: ID!) {
  setCurrentOrganization(orgId: $orgId, costId: $costId)
    @context(provider: "vtex.storefront-permissions") {
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/impersonateUser.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation ImpersonateUser($clId: ID, $userId: ID) {
  impersonateUser(clId: $clId, userId: $userId)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/updateCostCenter.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UpdateCostCenter($id: ID!, $input: CostCenterInput!) {
  updateCostCenter(id: $id, input: $input)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getPaymentTerms.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetPaymentTerms {
  getPaymentTerms
    @context(provider: "vtex.b2b-organizations-graphql") {
      id
      name
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/removeUser.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation RemoveUser($id: ID!, $userId: ID, $email: String!, $clId: ID!) {
  removeUser(id: $id, userId: $userId, email: $email, clId: $clId)
    @context(provider: "vtex.b2b-organizations-graphql") {
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/updateOrganizationRequest.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UpdateOrganizationRequest($id: ID!, $status: String!, $notes: String) {
  updateOrganizationRequest(id: $id, status: $status, notes: $notes)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getOrganizations.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganizations(
  $status: [String]
  $search: String
  $page: Int
  $pageSize: Int
  $sortOrder: String
  $sortedBy: String
) {
  getOrganizations(
    status: $status
    search: $search
    page: $page
    pageSize: $pageSize
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    pagination {
      total
    }
    data {
      id
      name
      status
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getCostCenter.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetCostCenter($id: ID!) {
  getCostCenterById(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    name
    organization
    paymentTerms {
      id
      name
    }
    addresses {
      addressId
      addressType
      addressQuery
      postalCode
      country
      receiverName
      city
      state
      street
      number
      complement
      neighborhood
      geoCoordinates
      reference
    }
    phoneNumber
    businessDocument
    customFields {
      name
      type
      value
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
    stateRegistration
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/checkCustomerSchema.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query CheckCustomerSchema {
  checkCustomerSchema @context(provider: "vtex.storefront-permissions")
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getPermissions.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetPermissions {
  checkUserPermission @context(provider: "vtex.storefront-permissions") {
    role {
      id
      name
      slug
    }
    permissions
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/saveUser.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation SaveUser(
  $id: ID
  $roleId: ID!
  $userId: ID
  $orgId: ID
  $costId: ID
  $clId: ID
  $canImpersonate: Boolean = false
  $name: String!
  $email: String!
) {
  saveUser(
    id: $id
    roleId: $roleId
    userId: $userId
    orgId: $orgId
    costId: $costId
    clId: $clId
    canImpersonate: $canImpersonate
    name: $name
    email: $email
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/updateB2BSettings.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation saveB2BSettings($input: B2BSettingsInput) {
  saveB2BSettings(input: $input)
    @context(provider: "vtex.b2b-organizations-graphql") {
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getCostCentersByOrganizationId.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetCostCentersByOrganizationId(
  $id: ID
  $search: String
  $page: Int
  $pageSize: Int
  $sortOrder: String
  $sortedBy: String
) {
  getCostCentersByOrganizationId(
    id: $id
    search: $search
    page: $page
    pageSize: $pageSize
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    pagination {
      total
    }
    data {
      id
      name
      addresses {
        country
      }
      customFields {
        name
        type
        value
        dropdownValues {
          value
          label
        }
        useOnRegistration
      }
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getSellers.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetSellers {
  getSellers @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    email
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getCostCentersByOrganizationIdStorefront.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetCostCentersByOrganizationIdStorefront(
  $id: ID
  $search: String
  $page: Int
  $pageSize: Int
  $sortOrder: String
  $sortedBy: String
) {
  getCostCentersByOrganizationIdStorefront(
    id: $id
    search: $search
    page: $page
    pageSize: $pageSize
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    pagination {
      total
    }
    data {
      id
      name
      addresses {
        country
      }
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getCollections.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetCollections(
  $searchKey: String
  $page: Int
  $pageSize: Int
  $ascending: Boolean
) {
  collections(
    searchKey: $searchKey
    page: $page
    pageSize: $pageSize
    ascending: $ascending
  ) @context(provider: "vtex.catalog-graphql") {
    items {
      id
      name
    }
    paging {
      total
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getUsers.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetUsers(
  $organizationId: ID
  $costCenterId: ID
  $page: Int
  $pageSize: Int
  $search: String
  $sortOrder: String
  $sortedBy: String
) {
  getUsersPaginated(
    organizationId: $organizationId
    costCenterId: $costCenterId
    page: $page
    pageSize: $pageSize
    search: $search
    sortOrder: $sortOrder
    sortedBy: $sortedBy
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    data {
      id
      roleId
      userId
      clId
      orgId
      costId
      name
      email
      canImpersonate
      role {
        name
        slug
      }
      organizationName
      costCenterName
    }
    pagination {
      total
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getB2BCustomFields.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetB2BCustomFields {
  getB2BSettings @context(provider: "vtex.b2b-organizations-graphql") {
    organizationCustomFields {
      name
      type
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
    costCenterCustomFields {
      name
      type
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getOrganization.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetOrganization($id: ID) {
  getOrganizationById(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    tradeName
    status
    created
    collections {
      id
      name
    }
    paymentTerms {
      id
      name
    }
    priceTables
    salesChannel
    costCenters
    sellers {
      id
      name
    }
    customFields {
      name
      value
      type
      dropdownValues {
        value
        label
      }
      useOnRegistration
    }
    permissions {
      createQuote
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/updateSalesChannels.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UpdateSalesChannels($channels: [SalesChannelsInput]!) {
  saveSalesChannels(channels: $channels)
    @context(provider: "vtex.b2b-organizations-graphql") {
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getMarketingTags.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetMarketingTags($costId: ID!) {
  getMarketingTags(costId: $costId)
    @context(provider: "vtex.b2b-organizations-graphql") {
    tags
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/createCostCenter.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation CreateCostCenter($organizationId: ID, $input: CostCenterInput!) {
  createCostCenter(organizationId: $organizationId, input: $input)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/updateOrganization.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation UpdateOrganization(
  $id: ID!
  $name: String!
  $tradeName: String
  $status: String!
  $collections: [CollectionInput]
  $paymentTerms: [PaymentTermInput]
  $priceTables: [String]
  $salesChannel: String
  $sellers: [SellerInput]
  $customFields: [CustomFieldInput]
) {
  updateOrganization(
    id: $id
    name: $name
    tradeName: $tradeName
    status: $status
    collections: $collections
    paymentTerms: $paymentTerms
    priceTables: $priceTables
    salesChannel: $salesChannel
    sellers: $sellers
    customFields: $customFields
  ) @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/createOrganizationRequest.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation CreateOrganizationRequest($input: OrganizationInput!) {
  createOrganizationRequest(input: $input)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getAccount.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetAccount {
  getAccount {
    id
    name
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getPriceTables.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetPriceTables {
  priceTables @context(provider: "vtex.admin-graphql")
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getBinding.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetBinding($email: String!) {
  getBinding(email: $email) @context(provider: "vtex.b2b-organizations-graphql")
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/impersonateB2BUser.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation ImpersonateB2BUser($id: ID!) {
  impersonateB2BUser(id: $id)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    status
    message
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getLogistics.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query Logistics {
  logistics @context(provider: "vtex.store-graphql") {
    shipsTo
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/userWidgetQuery.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query userWidgetQuery($orgId: ID) {
  getActiveOrganizationsByEmail
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    costCenterName
    costId
    organizationName
    organizationStatus
    orgId
    role {
      id
      name
    }
  }

  checkUserPermission @context(provider: "vtex.storefront-permissions") {
    role {
      id
      name
      slug
    }
    permissions
  }

  getOrganizationByIdStorefront(id: $orgId)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    status
    paymentTerms {
      id
      name
    }
  }

  getCostCenterByIdStorefront(id: $orgId)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
    organization
    paymentTerms {
      id
      name
    }
    addresses {
      addressId
      addressType
      addressQuery
      postalCode
      country
      receiverName
      city
      state
      street
      number
      complement
      neighborhood
      geoCoordinates
      reference
    }
    phoneNumber
    businessDocument
    stateRegistration
  }

  checkImpersonation @context(provider: "vtex.storefront-permissions") {
    email
  }

  getB2BSettings @context(provider: "vtex.b2b-organizations-graphql") {
    uiSettings {
      showModal
      fullImpersonation
    }
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getSalesChannels.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetSalesChannels {
  salesChannels @context(provider: "vtex.admin-graphql") {
    id
    name
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/getSelectedChannels.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query GetSelectedChannels {
  getSalesChannels @context(provider: "vtex.b2b-organizations-graphql") {
    id
    name
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/createOrganization.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
mutation CreateOrganization($input: OrganizationInput!) {
  createOrganization(input: $input)
    @context(provider: "vtex.b2b-organizations-graphql") {
    id
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/graphql/checkImpersonation.graphql from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```graphql
query CheckImpersonation {
  checkImpersonation @context(provider: "vtex.storefront-permissions") {
    email
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useClosedAlerts.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import useLocalStorage from './useLocalStorage'

const useClosedAlerts = () => {
  const [closedAlerts, setClosedAlerts] = useLocalStorage(
    'bulk-import-closed-alerts',
    [] as string[]
  )

  const addClosedAlert = (importId: string) => {
    if (closedAlerts.find(alertId => alertId === importId)) {
      return
    }

    setClosedAlerts([...closedAlerts, importId])
  }

  const removeClosedAlert = (importId: string) => {
    const filteredAlerts = closedAlerts.filter(alertId => alertId !== importId)

    setClosedAlerts(filteredAlerts)
  }

  return { closedAlerts, addClosedAlert, removeClosedAlert }
}

export default useClosedAlerts

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useOrgPermission.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import useSWR from 'swr'
import { useFullSession } from 'vtex.session-client'

import { checkUserAdminPermission } from '../services'
import type { ORGANIZATION_EDIT } from '../utils/constants'
import { ORGANIZATION_VIEW } from '../utils/constants'

interface UseOrgPermissionParams {
  resourceCode?: typeof ORGANIZATION_EDIT | typeof ORGANIZATION_VIEW
}

export function useOrgPermission({
  resourceCode = ORGANIZATION_VIEW,
}: UseOrgPermissionParams) {
  const fullSession = useFullSession({
    variables: {
      items: ['authentication.adminUserEmail', 'account.accountName'],
    },
  })

  const account =
    fullSession.data?.session?.namespaces?.account?.accountName?.value

  const userEmail =
    fullSession.data?.session?.namespaces?.authentication?.adminUserEmail?.value

  const { data, isLoading, isValidating, error } = useSWR<{ data: boolean }>(
    userEmail && account ? `/granted?${resourceCode}` : null,
    () =>
      checkUserAdminPermission({
        account,
        userEmail,
        resourceCode,
      }),
    {
      dedupingInterval: 0,
    }
  )

  return {
    data,
    error,
    isLoading,
    isValidating,
  }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useTranslate.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useIntl } from 'react-intl'
import type { ReactNode } from 'react'

import type { BulkImportMessageKey } from '../bulkImport/messages'
import { bulkUploadMessages, hasTranslation } from '../bulkImport/messages'

export type TranslateFunction = (
  key: BulkImportMessageKey,
  data?: Record<string, unknown>
) => ReactNode

const useTranslate = () => {
  const { formatMessage, ...intl } = useIntl()

  const translate: TranslateFunction = (descriptor, values) => {
    return hasTranslation(descriptor)
      ? formatMessage(
          bulkUploadMessages[descriptor],
          values as Record<string, string | number>
        )
      : null
  }

  return { translate, formatMessage, ...intl }
}

export default useTranslate

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useBulkImportsQuery.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import useSWR from 'swr'
import { useState } from 'react'

import type { Session } from '../modules/session'
import { useSessionResponse } from '../modules/session'
import { getBulkImportList } from '../services'

type UseBulkImportQueryProps = {
  shouldPoll?: boolean
}

const useBulkImportQuery = (
  { shouldPoll: initialShouldPoll }: UseBulkImportQueryProps = {
    shouldPoll: false,
  }
) => {
  const session = useSessionResponse() as Session

  const [shouldPoll, setShouldPoll] = useState(initialShouldPoll)

  const account = session?.namespaces?.account?.accountName?.value

  return useSWR(
    account ? '/buyer-orgs' : null,
    () => getBulkImportList(account),
    {
      refreshInterval: shouldPoll ? 30 * 1000 : 0, // 30 seconds
      onError: errorData => {
        const status = errorData?.response?.status ?? 0

        if (status >= 400 && status < 500) {
          setShouldPoll(false)
        }
      },
    }
  )
}

export default useBulkImportQuery

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useSelectSeller.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useProduct, useProductDispatch } from 'vtex.product-context'
import { useCallback, useMemo, useRef, useState } from 'react'
import type { Item } from 'vtex.product-context/react/ProductTypes'

import useSeller from './useSeller'

const SELECT_ITEM_EVENT = 'SET_SELECTED_ITEM'

export const useSelectSeller = () => {
  const { seller } = useSeller()
  const productContext = useProduct()
  const { product } = productContext ?? {}
  const latestItem = useRef((null as unknown) as Item)
  const [loading, setLoading] = useState(true)
  const productDispatch = useProductDispatch()

  const addSellerDefaultToItem = useCallback(
    itemSeller => ({
      ...itemSeller,
      sellerDefault: seller?.includes(itemSeller.sellerId),
    }),
    [seller]
  )

  const currentSelectedItem = useMemo(
    () =>
      product?.items?.find(item =>
        item.sellers?.find(
          itemSeller =>
            seller?.includes(itemSeller.sellerId) &&
            itemSeller.commertialOffer.AvailableQuantity > 0
        )
      ) ?? null,

    [seller, product]
  )

  const selectSeller = ({
    selectedItem,
  }: {
    selectedItem: Item | null | undefined
  }) => {
    if (!currentSelectedItem || !selectedItem) {
      return
    }

    // just to keep the dependency
    setLoading(true)
    const { sellers } = (currentSelectedItem as unknown) as Item
    const selectedItemWithSeller = {
      ...((currentSelectedItem as unknown) as Item),
      sellers: sellers.map(addSellerDefaultToItem),
    }

    if (
      JSON.stringify(latestItem.current) ===
      JSON.stringify(selectedItemWithSeller)
    ) {
      return
    }

    productDispatch?.({
      type: SELECT_ITEM_EVENT,
      args: {
        item: selectedItemWithSeller,
      },
    })
    setLoading(false)
    latestItem.current = selectedItemWithSeller
  }

  return { loading, seller, currentSelectedItem, selectSeller }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useScroll.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useCallback, useEffect, useRef } from 'react'

import { useDebounceFunction } from './useDebounce'

type UseScrollArgs = Readonly<{ onScrollEnd: () => void }>

const SCROLL_DELAY = 150
const SCROLL_END_TOLERANCE = 10

export function useScroll<T extends HTMLElement>({
  onScrollEnd,
}: UseScrollArgs) {
  const ref = useRef<T>(null)
  const onScrollEndDebounced = useDebounceFunction(onScrollEnd, SCROLL_DELAY)

  const handleScroll = useCallback(() => {
    if (!ref.current) return

    const scrollTop: number = Math.ceil(ref.current.scrollTop)
    const scrollHeight: number = Math.round(ref.current.scrollHeight)
    const clientHeight: number = Math.round(ref.current.clientHeight)

    const isScrollEnd =
      scrollTop + SCROLL_END_TOLERANCE >= scrollHeight - clientHeight

    if (isScrollEnd) {
      onScrollEndDebounced()
    }
  }, [onScrollEndDebounced])

  useEffect(() => {
    if (!ref.current) return

    ref.current.addEventListener('scroll', handleScroll)
  }, [handleScroll])

  useEffect(
    () => () => ref.current?.removeEventListener('scroll', handleScroll),
    []
  )

  return ref
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useErrorCount.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useCallback } from 'react'

import type { ValidationResult } from '../types/BulkImport'

const useErrorCount = () => {
  return useCallback((errorRowReportDataList: ValidationResult[] = []) => {
    return errorRowReportDataList.reduce(
      (acc, error) => acc + error.invalidRows,
      0
    )
  }, [])
}

export default useErrorCount

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useLocalStorage.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useState } from 'react'

const useLocalStorage = <T>(key: string, initialValue: T) => {
  const storedValue = localStorage.getItem(key)

  const [value, setValue] = useState(
    (storedValue ? JSON.parse(storedValue) : initialValue) as T
  )

  const setStoredValue = (newValue: T) => {
    setValue(newValue)
    localStorage.setItem(key, JSON.stringify(newValue))
  }

  return [value, setStoredValue] as const
}

export default useLocalStorage

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useSeller.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useEffect, useState } from 'react'
import { useProduct } from 'vtex.product-context'

const decode = (str: string): string =>
  Buffer.from(str, 'base64').toString('binary')

export default function useSeller() {
  const [seller, setSeller] = useState<string[] | null>(null)
  const productContext = useProduct()
  const { selectedItem, product } = productContext ?? {}

  useEffect(() => {
    try {
      const { facets } = JSON.parse(decode(window?.__RUNTIME__?.segmentToken))

      if (facets) {
        const facetsList = facets.split(';')
        const sellerFacet = facetsList.filter((facet: string) =>
          facet.includes('private-seller')
        )

        const sellers = sellerFacet.map((facet: string) => {
          const [, value] = facet?.split('=') ?? []

          return value
        })

        if (sellers?.length) {
          setSeller(sellers)
        }
      }
    } catch (e) {
      console.error(e)
    }
  }, [selectedItem, product])

  return { seller }
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useDebounce.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useCallback, useEffect, useRef, useState } from 'react'

export function useDebounceValue<T>(value: T, delay: number) {
  const [debounced, setDebounced] = useState(value)

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay)

    return () => clearTimeout(timer)
  }, [value, delay])

  return debounced
}

export const useDebounceFunction = <T extends unknown[]>(
  fn: (...args: T) => void,
  delay: number
) => {
  const timerRef = useRef<number>()
  const fnRef = useRef(fn)

  useEffect(() => {
    fnRef.current = fn
  }, [fn])

  const fnDebounced = useCallback(
    (...args: T) => {
      window.clearTimeout(timerRef.current)
      timerRef.current = window.setTimeout(() => fnRef.current(...args), delay)
    },
    [delay]
  )

  useEffect(() => () => window.clearTimeout(timerRef.current), [])

  return fnDebounced
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useStartBulkImport.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import useSWRMutation from 'swr/mutation'

import { startBulkImport } from '../services'

const useStartBulkImport = () => {
  const { trigger, ...data } = useSWRMutation(
    '/buyer-orgs',
    (_, { arg }: { arg: { importId: string } }) => startBulkImport(arg.importId)
  )

  return { startBulkImport: trigger, ...data }
}

export default useStartBulkImport

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useValidateBulkImport.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import useSWRMutation from 'swr/mutation'

import { validateBulkImport } from '../services'

const useValidateBulkImport = ({ onSuccess }: { onSuccess?: () => void }) => {
  const { trigger } = useSWRMutation(
    '/buyer-orgs/start',
    (_, { arg }: { arg: { importId: string } }) =>
      validateBulkImport(arg.importId),
    {
      onSuccess,
    }
  )

  return { startBulkImportValidation: trigger }
}

export default useValidateBulkImport

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/index.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
export { default as useTranslate } from './useTranslate'
export { default as useBulkImportsQuery } from './useBulkImportsQuery'

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/hooks/useBulkImportDetailsQuery.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import useSWR from 'swr'

import { getBulkImportDetails } from '../services'
import type { BulkImportDetails } from '../services/getBulkImportDetails'

export type UseBulkImportDetailsQueryProps = {
  importId?: string
  onSuccess?: (data: BulkImportDetails) => void
  refreshInterval?: number
}

const useBulkImportDetailsQuery = ({
  importId,
  onSuccess = () => {},
  refreshInterval = 0,
}: UseBulkImportDetailsQueryProps) => {
  return useSWR(
    importId ? `/buyer-orgs/${importId}` : null,
    () => getBulkImportDetails(importId),
    {
      refreshInterval,
      revalidateOnFocus: false,
      onSuccess,
    }
  )
}

export default useBulkImportDetailsQuery

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/modules/session.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import { useState, useEffect } from 'react'

interface KeyValue {
  value: string
}

export interface Session {
  type?: 'Session'
  id: string
  namespaces: {
    store: {
      channel: string
    }
    profile: {
      isAuthenticated: KeyValue
      email?: KeyValue
    }
    account: {
      accountName: KeyValue
    }
    authentication: {
      storeUserEmail: KeyValue
    }
  }
}

interface SessionUnauthorized {
  type: 'Unauthorized'
  message: string
}

interface SessionForbidden {
  type: 'Forbidden'
  message: string
}

interface SessionPromise {
  response: Session | SessionUnauthorized | SessionForbidden
}

export function getSession() {
  return window &&
    (window as any).__RENDER_8_SESSION__ &&
    (window as any).__RENDER_8_SESSION__.sessionPromise
    ? ((window as any).__RENDER_8_SESSION__.sessionPromise as Promise<
        SessionPromise
      >)
    : null
}

export const useSessionResponse = () => {
  const [session, setSession] = useState<
    Session | SessionUnauthorized | SessionForbidden
  >()

  const sessionPromise = getSession()

  useEffect(() => {
    if (!sessionPromise) {
      return
    }

    sessionPromise.then(sessionResponse => {
      const { response } = sessionResponse

      setSession(response)
    })
  }, [sessionPromise])

  return session
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/modules/formValidators.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
// https://regex101.com/r/926sxf/1
// If you change the regex, don't forget to go to the link above, update it there and save.
const EMAIL_REGEX = /^[A-z0-9"+_-]+(?:\.[A-z0-9+_-]+)*@(?:[A-z0-9](?:[A-z0-9-]*[A-z0-9])?\.)+[A-z0-9](?:[A-z0-9-]*[A-z0-9])?$/

// https://regex101.com/r/5dVM9R/1
// If you change the regex, don't forget to go to the link above, update it there and save.
// eslint-disable-next-line no-useless-escape
const PHONE_REGEX = /^([0-9]|\(|\)|\+|\ |\-)+$/

export function validateEmail(email: string) {
  return EMAIL_REGEX.test(email)
}

export function validatePhoneNumber(phone: string) {
  return PHONE_REGEX.test(phone)
}

export function validateUserName(name: string) {
  return name.length > 0
}

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/services/orgPermissionClient.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import axios from 'axios'

import { B2B_LM_PRODUCT_CODE } from '../utils/constants'

const LICENSE_MANAGER_BASE_URL = `/api/license-manager/pvt/accounts/`

const orgPermissionClient = axios.create()

orgPermissionClient.defaults.baseURL = LICENSE_MANAGER_BASE_URL

interface CheckUserAdminPermissionParams {
  account: string
  userEmail: string
  resourceCode: string
}

const checkUserAdminPermission = async ({
  account,
  userEmail,
  resourceCode,
}: CheckUserAdminPermissionParams) => {
  const checkOrgPermission = await orgPermissionClient.get(
    `${account}/products/${B2B_LM_PRODUCT_CODE}/logins/${userEmail}/resources/${resourceCode}/granted`
  )

  return checkOrgPermission.data
}

export default checkUserAdminPermission

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/services/uploadBulkImportFile.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { AxiosRequestConfig } from 'axios'

import bulkImportClient from '.'
import type {
  BulkImportUploadError,
  ImportDetails,
  UploadFileData,
} from '../types/BulkImport'

const uploadBulkImportFile = async (file: File): Promise<UploadFileData> => {
  const formData = new FormData()

  formData.append('file', file)

  try {
    const importListResponse = await bulkImportClient.post<ImportDetails>(
      `/buyer-orgs`,
      formData,
      {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      } as AxiosRequestConfig<FormData>
    )

    return {
      status: 'success',
      data: {
        fileData: importListResponse.data,
      },
    }
  } catch (error) {
    const errorData = error?.response?.data as BulkImportUploadError

    return {
      status: 'error',
      showReport: errorData?.error === 'FieldValidationError',
      data: { ...errorData, fileName: file.name },
    }
  }
}

export default uploadBulkImportFile

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/services/getBulkImportList.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import type { ImportDetails } from '../types/BulkImport'
import bulkImportClient from '.'

const statusMap = {
  InProgress: 'pending',
  Completed: 'success',
  CompletedWithError: 'error',
} as const

const getBulkImportList = async (account: string) => {
  const importListResponse = await bulkImportClient.get(
    `/buyer-orgs?an=${account}`
  )

  const importListData = importListResponse.data as ImportDetails[]

  return importListData
    .filter(item =>
      ['InProgress', 'Completed', 'CompletedWithError'].some(
        status => status === item.importState
      )
    )
    .map(item => ({
      importId: item.importId,
      progress: Number(item.percentage),
      status: statusMap[item.importState as keyof typeof statusMap],
      importedAt: new Date(item.importedAt),
      file: {
        name: item.fileName,
      },
    }))
    .sort(
      (currentImport, nextImport) =>
        nextImport.importedAt.getTime() - currentImport.importedAt.getTime()
    )
    .slice(0, 1)
}

export default getBulkImportList

```


[System] You are an expert VTEX IO developer. You specialize in building VTEX Store Framework apps, React components, GraphQL APIs, and Node.js services for e-commerce platforms.

[User] Show me the implementation of b2b-organizations/react/services/bulkImportClient.ts from the b2b-organizations VTEX app.

[Assistant]
Here's the implementation:

```typescript
import axios from 'axios'

export const BULK_IMPORT_BASE_URL = `/api/b2b/import`

const bulkImportClient = axios.create()

bulkImportClient.defaults.baseURL = BULK_IMPORT_BASE_URL

export default bulkImportClient

```