react-query#useQueryClient TypeScript Examples

The following examples show how to use react-query#useQueryClient. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useCreateAddress.ts    From wildduck-ui with MIT License 8 votes vote down vote up
useCreateAddress = () => {
	const queryClient = useQueryClient();

	return useMutation(
		({ userId, addressDetails }: IProp) => api.addressApi.createUserAddress(userId, addressDetails),
		{
			onError: () => {
				AppEvents.publish(Events.Error, 'Error');
			},
			onSuccess: ({ data }) => {
				handleError(data);
				queryClient.invalidateQueries('useAddress');
			},
		},
	);
}
Example #2
Source File: useRefetchQueries.ts    From anchor-web-app with Apache License 2.0 6 votes vote down vote up
export function useRefetchQueries(refetchMap?: TxRefetchMap) {
  const queryClient = useQueryClient();

  const { refetchMap: terraRefetchMap } = useApp();

  return useCallback(
    (txKey: string) => {
      const queryRefetches = (refetchMap ?? terraRefetchMap)[txKey];

      if (queryRefetches) {
        for (const queryRefetch of queryRefetches) {
          runRefetch(queryRefetch).then((queryKey) => {
            queryClient.invalidateQueries(queryKey, {
              refetchActive: true,
              refetchInactive: false,
            });
          });
        }
      }
    },
    [queryClient, refetchMap, terraRefetchMap],
  );
}
Example #3
Source File: mutation.ts    From RareCamp with Apache License 2.0 6 votes vote down vote up
useEditTaskMutation = (
  { taskId, projectId, programId },
  cb?: Function,
) => {
  const queryClient = useQueryClient()
  return useMutation(
    (task: any) => {
      return axios.put(`/projects/${projectId}/tasks/${taskId}`, {
        task,
      })
    },
    {
      onSuccess: async (resp: any) => {
        const { task } = resp.data
        queryClient.setQueryData(['task', task.taskId], {
          data: resp.data,
        })
        const programData: any = queryClient.getQueryData([
          'program',
          programId,
        ])
        if (programData) {
          updateProgramTask(programData.data.program, task)
          queryClient.setQueryData(['program', programId], {
            data: programData.data,
          })
        }

        if (cb) cb()
      },
      onError: (err: Error, variables) =>
        notification.error({
          duration: 2,
          message: `Task ${variables.name} was not updated`,
          description: err.message,
        }),
    },
  )
}
Example #4
Source File: useFetchResource.ts    From ke with MIT License 6 votes vote down vote up
useFetchResource = <ResourceData = unknown>(
  userConfigOrKey: ResourceOptionsOrKey<FetchResourceOptions<ResourceData>>
): ((requestOptions?: FetchOptions<ResourceData>) => Promise<ResourceData>) => {
  const userConfig = configResolver(userConfigOrKey)
  const {
    fetchResource: { fn },
  } = useDefaultResourceConfig<ResourceData>()

  const client = useQueryClient()

  return useCallback(
    (requestOptions: FetchOptions<ResourceData> = {}) => {
      const { key, ...config } = userConfig

      const { requestConfig = {}, ...queryOptions } = deepmerge(config, requestOptions)
      return client.fetchQuery(
        [key, requestConfig.lookupField, requestConfig.params],
        () => fn(key, requestConfig),
        queryOptions
      )
    },
    [client, fn, userConfig]
  )
}
Example #5
Source File: useBackgroundPaginatedRequest.ts    From apps with GNU Affero General Public License v3.0 6 votes vote down vote up
useBackgroundPaginatedRequest = <T extends InfiniteData<unknown>>(
  queryKey: QueryKey,
): T => {
  const client = useQueryClient();
  const data = client.getQueryData<T>(queryKey);
  useBackgroundRequest(queryKey, {
    callback: ({ res, req }) => {
      if (!res) {
        return;
      }

      const current = client.getQueryData(queryKey) as T;
      const updated = { ...current } as T;
      const index = updated.pages.length - 1;
      updated.pageParams[index] = req.variables.after;
      updated.pages[index] = res;
      client.setQueryData(queryKey, updated);
    },
  });

  return data;
}
Example #6
Source File: useUserSettings.ts    From tailchat with GNU General Public License v3.0 6 votes vote down vote up
/**
 * 用户设置hooks
 */
export function useUserSettings() {
  const client = useQueryClient();
  const { data: settings, isLoading } = useQuery(
    ['useUserSettings'],
    () => getUserSettings(),
    {
      staleTime: 1 * 60 * 1000, // 缓存1分钟
    }
  );

  const [{ loading: saveLoading }, setSettings] = useAsyncRequest(
    async (settings: UserSettings) => {
      const newSettings = await setUserSettings(settings);

      client.setQueryData(['useUserSettings'], () => newSettings);
    },
    [client]
  );

  return {
    settings: settings ?? {},
    setSettings,
    loading: isLoading || saveLoading,
  };
}
Example #7
Source File: Members.tsx    From Riakuto-StartingReact-ja3.1 with Apache License 2.0 6 votes vote down vote up
EnhancedMembers: VFC<{ enablePrefetch?: boolean }> = ({
  enablePrefetch = false,
}) => {
  const queryClient = useQueryClient();
  const prefetch = (orgCode: string): void => {
    const load = async (): Promise<void> => {
      try {
        await Promise.all([
          queryClient.prefetchQuery([orgCode, 'organization'], () =>
            getOrganization(orgCode),
          ),
          queryClient.prefetchQuery([orgCode, 'members'], () =>
            getMembers(orgCode),
          ),
        ]);
      } catch (error) {
        console.error(error); // eslint-disable-line no-console
      }
    };

    void load();
  };
  const membersProps = enablePrefetch
    ? { orgCodeList, prefetch }
    : { orgCodeList };

  // eslint-disable-next-line react/jsx-props-no-spreading
  return <Members {...membersProps} />;
}
Example #8
Source File: [id].tsx    From next-crud with MIT License 6 votes vote down vote up
UserCreate: NextPage<IProps> = ({ user }) => {
  const toast = useToast()
  const { replace } = useRouter()
  const queryClient = useQueryClient()

  const onSubmit = async (values: IFormValues) => {
    try {
      const userData = await fetch(`/api/users/${user.id}`, {
        method: 'PUT',
        body: JSON.stringify(values),
        headers: {
          'Content-Type': 'application/json',
        },
      }).then((res) => res.json())
      toast({
        status: 'success',
        description: 'User successfully updated',
        duration: 2000,
      })
      replace('/users')
      queryClient.setQueryData<
        InfiniteData<TPaginationResult<User>> | undefined
      >('users', (data) => {
        const page = data?.pages.find((page) =>
          page.data.some((userElem) => userElem.id === user.id)
        )
        if (page) {
          const elemIdx = page.data.findIndex((data) => data.id === user.id)
          page.data[elemIdx] = userData
        }

        return data
      })
    } catch (e) {
      toast({
        status: 'error',
        description: 'Failed to update user',
        duration: 2000,
      })
    }
  }

  return (
    <Layout title={user.username} backRoute="/users">
      <VStack spacing={4} width="100%">
        <Heading>User edition</Heading>
        <UserForm
          initialValues={{ username: user.username }}
          onSubmit={onSubmit}
        />
      </VStack>
    </Layout>
  )
}
Example #9
Source File: logout.tsx    From rcvr-app with GNU Affero General Public License v3.0 6 votes vote down vote up
export default function BusinessIndexPage() {
  const { t } = usePageLocale('business/logout')

  const router = useRouter()
  const queryClient = useQueryClient()
  React.useEffect(() => {
    localStorage.removeItem('rcvr_olt')
    queryClient.clear()
    router.replace('/business')
  }, [router, queryClient])

  return (
    <MobileApp pageTitle={t('title')} logoVariant="big">
      <Text as="h2" variant="h2">
        {t('title')}
      </Text>
      <Loading show />
    </MobileApp>
  )
}
Example #10
Source File: useCreateAllowedDomain.ts    From wildduck-ui with MIT License 6 votes vote down vote up
useCreateAllowedDomain = () => {
	const queryClient = useQueryClient();

	return useMutation(
		(domain: { tag: string; domain: string }) =>
			api.domainAccessApi.createAllowedDomain(domain.tag, { domain: domain.domain }),
		{
			onSuccess: () => {
				AppEvents.publish(Events.Success, 'Success');
				queryClient.invalidateQueries('query-allowList');
				queryClient.invalidateQueries('query-blockList');
			},
			onError: () => {
				AppEvents.publish(Events.Error, 'Error');
			},
		},
	);
}
Example #11
Source File: FusePoolPage.tsx    From rari-dApp with GNU Affero General Public License v3.0 5 votes vote down vote up
PendingAdminAlert = ({ comptroller }: { comptroller?: string }) => {
  const { address, fuse } = useRari();

  const toast = useToast();
  const queryClient = useQueryClient();

  const [isAccepting, setIsAccepting] = useState(false);

  const isPendingAdmin = useIsComptrollerPendingAdmin(comptroller);

  const acceptAdmin = async () => {
    if (!comptroller) return;
    const unitroller = createUnitroller(comptroller, fuse);
    setIsAccepting(true);

    try {
      await testForComptrollerErrorAndSend(
        unitroller.methods._acceptAdmin(),
        address,
        ""
      );

      LogRocket.track("Fuse-AcceptAdmin");

      queryClient.refetchQueries();
      setIsAccepting(false);
    } catch (e) {
      setIsAccepting(false);

      handleGenericError(e, toast);
    }
  };

  return (
    <>
      {isPendingAdmin && (
        <AdminAlert
          isAdmin={isPendingAdmin}
          isAdminText="You are the pending admin of this Fuse Pool! Click to Accept Admin"
          rightAdornment={
            <Button
              h="100%"
              p={3}
              ml="auto"
              color="black"
              onClick={acceptAdmin}
              disabled={isAccepting}
            >
              <HStack>
                <Text fontWeight="bold">
                  {isAccepting} ? Accepting... : Accept Admin{" "}
                </Text>
              </HStack>
            </Button>
          }
        />
      )}
    </>
  );
}
Example #12
Source File: index.tsx    From strapi-plugin-comments with MIT License 5 votes vote down vote up
DiscussionThreadItemApprovalFlowActions = ({
  id,
  allowedActions: { canModerate },
  queryToInvalidate,
}) => {
  const toggleNotification = useNotification();
  const queryClient = useQueryClient();
  const { lockApp, unlockApp } = useOverlayBlocker();

  const onSuccess = (message) => async () => {
    if (queryToInvalidate) {
      await queryClient.invalidateQueries(queryToInvalidate);
    }
    toggleNotification({
      type: "success",
      message: `${pluginId}.${message}`,
    });
    unlockApp();
  };

  const onError = (err) => {
    handleAPIError(err, toggleNotification);
  };

  const approveItemMutation = useMutation(approveItem, {
    onSuccess: onSuccess(
      "page.details.actions.comment.approve.confirmation.success"
    ),
    onError,
    refetchActive: false,
  });
  const rejectItemMutation = useMutation(rejectItem, {
    onSuccess: onSuccess(
      "page.details.actions.comment.reject.confirmation.success"
    ),
    onError,
    refetchActive: false,
  });

  const handleApproveClick = () => {
    if (canModerate) {
      lockApp();
      approveItemMutation.mutate(id);
    }
  };

  const handleRejectClick = () => {
    if (canModerate) {
      lockApp();
      rejectItemMutation.mutate(id);
    }
  };

  if (canModerate) {
    return (
      <>
        <IconButton
          icon={<Check />}
          label={getMessage("page.details.actions.comment.approve", "Approve")}
          onClick={handleApproveClick}
        />
        <IconButton
          icon={<Cross />}
          label={getMessage("page.details.actions.comment.reject", "Reject")}
          onClick={handleRejectClick}
        />
      </>
    );
  }
  return null;
}
Example #13
Source File: useTezos.ts    From homebase-app with MIT License 5 votes vote down vote up
useTezos = (): WalletConnectReturn => {
  const {
    state: { tezos, network, account, wallet },
    dispatch,
  } = useContext(TezosContext);

  const queryClient = useQueryClient()

  const connect = useCallback(async (newNetwork?: Network) => {
    const { wallet } = await connectWithBeacon(newNetwork || network);

    const newTezos = new TezosToolkit(rpcNodes[newNetwork || network]);
    newTezos.setPackerProvider(new MichelCodecPacker());
    newTezos.addExtension(new Tzip16Module());

    newTezos.setProvider({ wallet });
    const account = await newTezos.wallet.pkh();

    dispatch({
      type: TezosActionType.UPDATE_TEZOS,
      payload: {
        network: newNetwork || network,
        tezos: newTezos,
        account,
        wallet
      },
    });

    mixpanel.identify(account)

    return newTezos;
  }, [dispatch, network]);

  return {
    tezos,
    connect,
    reset: useCallback(async () => {
      if(!wallet) {
        throw new Error("No Wallet Connected")
      }
      
      await wallet.disconnect()

      dispatch({
        type: TezosActionType.RESET_TEZOS,
      });
    }, [dispatch, wallet]),
    changeNetwork: async (newNetwork: Network) => {
      mixpanel.register({'Network': newNetwork});

      localStorage.setItem("homebase:network", newNetwork);

      
      if (!("_pkh" in tezos.wallet)) {
        const Tezos = new TezosToolkit(rpcNodes[newNetwork]);
        Tezos.setPackerProvider(new MichelCodecPacker());
        Tezos.addExtension(new Tzip16Module());
  
        dispatch({
          type: TezosActionType.UPDATE_TEZOS,
          payload: {
            network: newNetwork,
            tezos: Tezos,
            account,
            wallet: undefined
          },
        });
      } else {
        await connect(newNetwork);
      }
      queryClient.resetQueries()
    },
    account,
    network,
  };
}
Example #14
Source File: CompanionEngagements.tsx    From apps with GNU Affero General Public License v3.0 5 votes vote down vote up
export function CompanionEngagements({
  post,
  commentsNum,
  isCommentsOpen,
  onCommentsClick,
  onUpvotesClick,
}: CompanionEngagementsProps): ReactElement {
  if (!post) {
    return null;
  }

  const client = useQueryClient();
  useRawBackgroundRequest(({ res, key }) => {
    if (!Array.isArray(key)) {
      return;
    }

    if (key[0] !== 'readingRank') {
      return;
    }

    client.setQueryData(key, res);
  });

  return (
    <div
      className="flex gap-x-4 justify-between items-center text-theme-label-tertiary typo-callout"
      data-testid="statsBar"
    >
      {post.numUpvotes <= 0 && <span>Be the first to upvote</span>}
      {post.numUpvotes > 0 && (
        <ClickableText onClick={onUpvotesClick}>
          {post.numUpvotes} Upvote{post.numUpvotes > 1 ? 's' : ''}
        </ClickableText>
      )}
      <Button
        buttonSize="small"
        className={isCommentsOpen ? 'btn-secondary' : 'btn-primary'}
        rightIcon={
          <ArrowIcon
            className={classNames(
              'ml-2 w-6 h-6 transition-transform',
              !isCommentsOpen && 'rotate-180',
            )}
          />
        }
        onClick={onCommentsClick}
      >
        {commentsNum.toLocaleString()}
        {` Comment${commentsNum === 1 ? '' : 's'}`}
      </Button>
    </div>
  );
}
Example #15
Source File: index.tsx    From interbtc-ui with Apache License 2.0 5 votes vote down vote up
ClaimRewardsButton = ({
  className,
  claimableRewardAmount,
  ...rest
}: CustomProps & InterlayDenimOrKintsugiMidnightContainedButtonProps): JSX.Element => {
  const { address } = useSelector((state: StoreType) => state.general);

  const queryClient = useQueryClient();

  const claimRewardsMutation = useMutation<void, Error, void>(
    () => {
      return window.bridge.escrow.withdrawRewards();
    },
    {
      onSuccess: () => {
        queryClient.invalidateQueries([GENERIC_FETCHER, 'escrow', 'getRewardEstimate', address]);
        queryClient.invalidateQueries([GENERIC_FETCHER, 'escrow', 'getRewards', address]);
      }
    }
  );

  const handleClaimRewards = () => {
    claimRewardsMutation.mutate();
  };

  return (
    <>
      <InterlayDenimOrKintsugiSupernovaContainedButton
        className={clsx('w-full', 'px-6', 'py-3', 'text-base', 'rounded-md', className)}
        onClick={handleClaimRewards}
        pending={claimRewardsMutation.isLoading}
        {...rest}
      >
        Claim {claimableRewardAmount} {GOVERNANCE_TOKEN_SYMBOL} Rewards
      </InterlayDenimOrKintsugiSupernovaContainedButton>
      {claimRewardsMutation.isError && (
        <ErrorModal
          open={claimRewardsMutation.isError}
          onClose={() => {
            claimRewardsMutation.reset();
          }}
          title='Error'
          description={claimRewardsMutation.error?.message || ''}
        />
      )}
    </>
  );
}
Example #16
Source File: index.tsx    From livepeer-com with MIT License 5 votes vote down vote up
useTableState = <T extends Record<string, unknown>>({
  tableId,
  pageSize = 20,
}: {
  tableId: string;
  pageSize?: number;
}) => {
  const [order, setOrder] = useState("");
  const [cursor, setCursor] = useState("");
  const [prevCursors, setPrevCursors] = useState<string[]>([]);
  const [nextCursor, setNextCursor] = useState("default");
  const [filters, setFilters] = useState<TFilter[]>([]);
  const [selectedRows, setSelectedRows] = useState<Row<T>[]>([]);
  const queryClient = useQueryClient();

  const stringifiedFilters = useMemo(() => {
    const formatted = formatFiltersForApiRequest(filters);
    return JSON.stringify(formatted);
  }, [filters]);

  const stateSetter: StateSetter<T> = useMemo(
    () => ({
      setOrder,
      setCursor,
      setPrevCursors,
      setNextCursor,
      setFilters,
      setSelectedRows,
    }),
    []
  );

  const state: State<T> = useMemo(
    () => ({
      tableId,
      order,
      cursor,
      prevCursors,
      nextCursor,
      filters,
      stringifiedFilters,
      selectedRows,
      pageSize,
      invalidate: () => queryClient.invalidateQueries(tableId),
    }),
    [
      order,
      cursor,
      prevCursors,
      nextCursor,
      filters,
      stringifiedFilters,
      selectedRows,
      pageSize,
      queryClient,
      tableId,
    ]
  );

  return { state, stateSetter };
}
Example #17
Source File: delete-device-modal.tsx    From homebridge-zigbee-nt with Apache License 2.0 5 votes vote down vote up
export function DeleteDeviceModal(props: Props) {
  const queryClient = useQueryClient();
  const [state, setState] = useState<State>({
    isDeletingDevice: false,
    error: null,
  });

  const { selectedDevice } = props;

  return (
    <Dialog
      isShown={props.isDeleteConfirmationShown}
      title="Unpair confirmation"
      onConfirm={async () => {
        setState({ ...state, isDeletingDevice: true });
        const response = await DevicesService.deleteDevice(selectedDevice.ieeeAddr);
        if (response.result === 'success') {
          await queryClient.invalidateQueries(DEVICES_QUERY_KEY);
          setState({ ...state, isDeletingDevice: false });
          props.onSuccess();
        } else {
          setState({ ...state, isDeletingDevice: false, error: response.error });
        }
      }}
      isConfirmLoading={state.isDeletingDevice}
      onCancel={props.onCancel}
      cancelLabel="Cancel"
      confirmLabel={state.isDeletingDevice ? 'Unpairing...' : 'Unpair'}
    >
      {selectedDevice && !!state.error && (
        <Paragraph size={300}>
          Are you sure you want to unpair device {selectedDevice.modelID} ({selectedDevice.ieeeAddr}
          )?
        </Paragraph>
      )}
      {state.error && (
        <Paragraph size={300}>
          An error occurred: {state.error}
        </Paragraph>
      )}
      {state.isDeletingDevice && renderSpinner()}
    </Dialog>
  );

}
Example #18
Source File: DeleteModal.tsx    From frontend with MIT License 5 votes vote down vote up
export default function DeleteModal({ id, onClose, onDelete }: Props) {
  const queryClient = useQueryClient()
  const router = useRouter()
  const { t } = useTranslation()

  const mutationFn = useDeleteCampaignById(id)

  const deleteMutation = useMutation<AxiosResponse<null>, AxiosError<ApiErrors>, string>({
    mutationFn,
    onError: () => AlertStore.show(t('campaigns:alerts:error'), 'error'),
    onSuccess: () => {
      AlertStore.show(t('Кампанията беше преместена в кошчето.'), 'warning')
      queryClient.removeQueries(endpoints.campaign.viewCampaignById(id).url)
      onDelete()
      router.push(routes.admin.campaigns.index)
    },
  })

  function deleteHandler() {
    deleteMutation.mutate(id)
  }

  return (
    <Dialog open onClose={onClose} sx={{ top: '-35%' }}>
      <DialogTitle>{t('campaigns:deleteTitle')}</DialogTitle>
      <Card>
        <CardContent>
          <Typography variant="body1" sx={{ marginBottom: '16px', textAlign: 'center' }}>
            {t('campaigns:deleteContent')}
          </Typography>
          <Box sx={{ display: 'flex', justifyContent: 'center' }}>
            <Button color="error" onClick={deleteHandler}>
              {t('campaigns:cta:delete')}
            </Button>
            <Button onClick={onClose}>{t('campaigns:cta:cancel')}</Button>
          </Box>
        </CardContent>
      </Card>
    </Dialog>
  )
}
Example #19
Source File: success.tsx    From rcvr-app with GNU Affero General Public License v3.0 5 votes vote down vote up
SetupSuccessPage: React.FC<WithOwnerProps> = ({ owner }) => {
  const { t } = usePageLocale('business/setup/success')
  const router = useRouter()
  const queryClient = useQueryClient()

  const generateKey = async (redirectTarget: string) => {
    if (!owner) return

    let { publicKey, privateKey } = owner
    if (!publicKey || !privateKey) {
      const keys = generateKeys()
      privateKey = keys.privateKey
      publicKey = keys.publicKey

      // the backend will receive the publicKey when the onboarding
      // process has been done completely.
      // meanwhile we store it in the frontend as setupPublicKey.
      // so when a user freshly logs in (or reloads or whatever)
      // and doesn't have a public_key assigned in the backend
      // the frontend needs to restart the onboarding process!
      await updateOwner(queryClient, {
        ...owner,
        privateKey,
        setupPublicKey: publicKey,
      })
    }
    router.push(redirectTarget)
  }

  return (
    <MobileApp pageTitle={t('title')} logoVariant="big">
      <Text as="h3" variant="h3">
        {t('title')} (2/3)
      </Text>
      <Box height={6} />
      <Row justifyContent="center">
        <KeyPaper />
      </Row>
      <Box height={4} />
      <Card variant="form" mx={-4}>
        <Text as="h2" variant="h2">
          2.
          {t('headline')}
        </Text>
        <Box height={4} />
        <Text>
          <PrivateKeyExplanation />
        </Text>
        <Box height={6} />
        <Text>
          <ContactInformation />
        </Text>
        <Box height={6} />
        <Button
          onClick={() => {
            generateKey('/business/setup/verify-key')
          }}
          right={<ArrowsRight color="green" />}
        >
          {t('downloadKeyButtonText')}
        </Button>
        <Box height={6} />
        <Button
          onClick={() => {
            generateKey('/business/setup/keys')
          }}
          right={<ArrowsRight color="green" />}
          css={{ textAlign: 'center' }}
        >
          {t('printKeyButtonText')}
        </Button>
      </Card>
    </MobileApp>
  )
}
Example #20
Source File: index.tsx    From RareCamp with Apache License 2.0 4 votes vote down vote up
export default function EditProgram({ program }) {
  const [isEditProgramVisible, setIsEditProgramVisible] =
    useState(false)
  const deleteProgram = () =>
    confirm({
      okButtonProps: {
        style: { backgroundColor: '#e53935', borderColor: '#e53935' },
      },
      title: 'Are you sure you want to delete this program?',
      centered: true,
      icon: <ExclamationCircleOutlined />,
      content:
        'Program will be immediately deleted. You cannot undo this action.',
      okText: 'Delete',
      onOk: deleteProgramMutation.mutateAsync,
      onCancel() {},
    })
  const menu = (
    <Menu>
      <Menu.Item>
        <Button
          onClick={() => setIsEditProgramVisible(true)}
          type="text"
        >
          Edit Program Details
        </Button>
      </Menu.Item>
      <Menu.Item>
        <Button onClick={deleteProgram} type="text">
          <Text type="danger">Delete Program</Text>
        </Button>
      </Menu.Item>
    </Menu>
  )
  const router = useRouter()
  const queryClient = useQueryClient()
  const deleteProgramMutation = useMutation(
    () =>
      axios.delete(
        `/workspaces/${program.workspaceId}/programs/${program.programId}`,
      ),
    {
      onSuccess: async () => {
        notification.success({
          duration: 2,
          message: `Program ${program.name} has been deleted successfully`,
        })
        const { data } = queryClient.getQueryData<any>(
          'defaultWorkspace',
        )
        queryClient.invalidateQueries('defaultWorkspace')
        if (data.workspace?.programs?.length) {
          await router.push('/workspace/intro')
        } else {
          await router.push('/')
        }
      },
      onError: (err: Error) =>
        notification.error({
          duration: 2,
          message: `Program ${program.name} was not deleted`,
          description: err.message,
        }),
    },
  )
  const editProgramMutation = useMutation(
    (values: { name: string; description: string }) => {
      const data = { ...program, ...values }
      return axios.put(
        `/workspaces/${program.workspaceId}/programs/${program.programId}`,
        {
          program: { name: data.name, description: data.description },
        },
      )
    },
    {
      onSuccess: async (resp) => {
        queryClient.setQueryData(['program', program.programId], {
          data: resp.data,
        })
        await queryClient.invalidateQueries('defaultWorkspace')
        notification.success({
          duration: 2,
          message: `Program ${program.name} has been updated successfully`,
        })
        setIsEditProgramVisible(false)
      },
      onError: (err: Error) =>
        notification.error({
          duration: 2,
          message: `Program ${program.name} was not updated`,
          description: err.message,
        }),
    },
  )
  const [editProgramForm] = Form.useForm()

  return (
    <EditProgramDropdown>
      <Dropdown overlay={menu}>
        <MoreOutlined />
      </Dropdown>
      <Modal
        centered
        title="Edit Program Details"
        visible={isEditProgramVisible}
        okText="Save"
        onOk={() => {
          editProgramForm.validateFields().then((values) => {
            // editProgramForm.resetFields()
            editProgramMutation.mutate(values)
          })
        }}
        confirmLoading={editProgramMutation.isLoading}
        onCancel={() => setIsEditProgramVisible(false)}
      >
        <Form
          name="editProgram"
          initialValues={{
            name: program.name,
            description: program.description,
          }}
          form={editProgramForm}
          layout="vertical"
        >
          <Form.Item
            label="Program Name"
            name="name"
            rules={[
              {
                required: true,
                message: 'Please input program name',
              },
            ]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            label="Description"
            name="description"
            rules={[{ message: 'Please input program description' }]}
          >
            <Input.TextArea rows={4} />
          </Form.Item>
        </Form>
      </Modal>
    </EditProgramDropdown>
  )
}
Example #21
Source File: FusePoolPage.tsx    From rari-dApp with GNU Affero General Public License v3.0 4 votes vote down vote up
AssetSupplyRow = ({
  assets,
  index,
  comptrollerAddress,
  supplyIncentives,
  rewardTokensData,
  isPaused,
}: {
  assets: USDPricedFuseAsset[];
  index: number;
  comptrollerAddress: string;
  supplyIncentives: CTokenRewardsDistributorIncentivesWithRates[];
  rewardTokensData: TokensDataMap;
  isPaused: boolean;
}) => {
  const {
    isOpen: isModalOpen,
    onOpen: openModal,
    onClose: closeModal,
  } = useDisclosure();

  const authedOpenModal = useAuthedCallback(openModal);

  const asset = assets[index];

  const { fuse, address } = useRari();

  const tokenData = useTokenData(asset.underlyingToken);

  const supplyAPY = convertMantissaToAPY(asset.supplyRatePerBlock, 365);

  const queryClient = useQueryClient();

  const toast = useToast();

  const onToggleCollateral = async () => {
    const comptroller = createComptroller(comptrollerAddress, fuse);

    let call;
    if (asset.membership) {
      call = comptroller.methods.exitMarket(asset.cToken);
    } else {
      call = comptroller.methods.enterMarkets([asset.cToken]);
    }

    let response = await call.call({ from: address });
    // For some reason `response` will be `["0"]` if no error but otherwise it will return a string number.
    if (response[0] !== "0") {
      if (asset.membership) {
        toast({
          title: "Error! Code: " + response,
          description:
            "You cannot disable this asset as collateral as you would not have enough collateral posted to keep your borrow. Try adding more collateral of another type or paying back some of your debt.",
          status: "error",
          duration: 9000,
          isClosable: true,
          position: "top-right",
        });
      } else {
        toast({
          title: "Error! Code: " + response,
          description:
            "You cannot enable this asset as collateral at this time.",
          status: "error",
          duration: 9000,
          isClosable: true,
          position: "top-right",
        });
      }

      return;
    }

    await call.send({ from: address });

    LogRocket.track("Fuse-ToggleCollateral");

    queryClient.refetchQueries();
  };

  const isStakedOHM =
    asset.underlyingToken.toLowerCase() ===
    "0x04F2694C8fcee23e8Fd0dfEA1d4f5Bb8c352111F".toLowerCase();

  const { data: stakedOHMApyData } = useQuery("sOHM_APY", async () => {
    const data = (
      await fetch("https://api.rari.capital/fuse/pools/18/apy")
    ).json();

    return data as Promise<{ supplyApy: number; supplyWpy: number }>;
  });

  const isMobile = useIsMobile();

  const { t } = useTranslation();

  const hasSupplyIncentives = !!supplyIncentives.length;
  const totalSupplyAPR =
    supplyIncentives?.reduce((prev, incentive) => {
      const apr = incentive.supplyAPR;
      return prev + apr;
    }, 0) ?? 0;

  const [hovered, setHovered] = useState<number>(-1);

  const handleMouseEnter = (index: number) => setHovered(index);
  const handleMouseLeave = () => setHovered(-1);

  const displayedSupplyAPR =
    hovered >= 0 ? supplyIncentives[hovered].supplyAPR : totalSupplyAPR;

  const displayedSupplyAPRLabel =
    hovered >= 0
      ? `${supplyIncentives[hovered].supplyAPR.toFixed(2)} % APR in ${
          rewardTokensData[supplyIncentives[hovered].rewardToken].symbol
        } distributions.`
      : `${displayedSupplyAPR.toFixed(
          2
        )}% total APR distributed in ${supplyIncentives
          .map((incentive) => rewardTokensData[incentive.rewardToken].symbol)
          .join(", ")}
         `;

  const _hovered = hovered > 0 ? hovered : 0;

  const color =
    rewardTokensData[supplyIncentives?.[_hovered]?.rewardToken]?.color ??
    "white";

  const symbol = getSymbol(tokenData, asset);

  return (
    <>
      <PoolModal
        defaultMode={Mode.SUPPLY}
        comptrollerAddress={comptrollerAddress}
        assets={assets}
        index={index}
        isOpen={isModalOpen}
        onClose={closeModal}
        isBorrowPaused={asset.isPaused}
      />

      <Row
        mainAxisAlignment="flex-start"
        crossAxisAlignment="flex-start"
        width="100%"
        px={4}
        py={1.5}
        className="hover-row"
      >
        {/* Underlying Token Data */}
        <Column
          mainAxisAlignment="flex-start"
          crossAxisAlignment="flex-start"
          width="27%"
        >
          <Row
            mainAxisAlignment="flex-start"
            crossAxisAlignment="center"
            width="100%"
            as="button"
            onClick={authedOpenModal}
          >
            <Avatar
              bg="#FFF"
              boxSize="37px"
              name={symbol}
              src={
                tokenData?.logoURL ??
                "https://raw.githubusercontent.com/feathericons/feather/master/icons/help-circle.svg"
              }
            />
            <Text fontWeight="bold" fontSize="lg" ml={2} flexShrink={0}>
              {symbol}
            </Text>
          </Row>
          {/* <Row
            mainAxisAlignment="flex-start"
            crossAxisAlignment="center"
            width="100%"
          >
            <Text fontSize="sm" ml={2} flexShrink={0}>
            {shortUsdFormatter(asset.liquidityUSD)}
            </Text>
          </Row> */}
        </Column>

        {/* APY */}
        {isMobile ? null : (
          <Column
            mainAxisAlignment="flex-start"
            crossAxisAlignment="flex-end"
            width="27%"
            as="button"
            onClick={authedOpenModal}
          >
            <Text
              color={tokenData?.color ?? "#FF"}
              fontWeight="bold"
              fontSize="17px"
            >
              {isStakedOHM
                ? stakedOHMApyData
                  ? (stakedOHMApyData.supplyApy * 100).toFixed(2)
                  : "?"
                : supplyAPY.toFixed(2)}
              %
            </Text>

            {/* Demo Supply Incentives */}
            {hasSupplyIncentives && (
              <Row
                // ml={1}
                // mb={.5}
                crossAxisAlignment="center"
                mainAxisAlignment="flex-end"
                py={2}
              >
                <Text fontWeight="bold" mr={1}>
                  +
                </Text>
                <AvatarGroup size="xs" max={30} ml={2} mr={1} spacing={1}>
                  {supplyIncentives?.map((supplyIncentive, i) => {
                    return (
                      <SimpleTooltip label={displayedSupplyAPRLabel}>
                        <CTokenIcon
                          address={supplyIncentive.rewardToken}
                          boxSize="20px"
                          onMouseEnter={() => handleMouseEnter(i)}
                          onMouseLeave={() => handleMouseLeave()}
                          _hover={{
                            zIndex: 9,
                            border: ".5px solid white",
                            transform: "scale(1.3);",
                          }}
                        />
                      </SimpleTooltip>
                    );
                  })}
                </AvatarGroup>
                <SimpleTooltip label={displayedSupplyAPRLabel}>
                  <Text color={color} fontWeight="bold" pl={1} fontSize="sm">
                    {/* {(supplyIncentive.supplySpeed / 1e18).toString()}%  */}
                    {displayedSupplyAPR.toFixed(2)}% APR
                  </Text>
                </SimpleTooltip>
              </Row>
            )}

            {/* Incentives */}
            {/* {hasSupplyIncentives && (
              <Column
                mainAxisAlignment="flex-start"
                crossAxisAlignment="flex-end"
                py={1}
              >
                {supplyIncentives?.map((supplyIncentive) => {
                  return (
                    <Row
                      ml={1}
                      py={0.5}
                      // mb={.5}
                      crossAxisAlignment="center"
                      mainAxisAlignment="flex-end"
                    >
                      <Text fontWeight="bold" mr={2}>
                        +
                      </Text>
                      <CTokenIcon
                        address={supplyIncentive.rewardToken}
                        boxSize="20px"
                      />
                      <Text fontWeight="bold" mr={2}></Text>
                      <Text
                        color={
                          rewardTokensData[supplyIncentive.rewardToken].color ??
                          "white"
                        }
                        fontWeight="bold"
                      >
                        {(supplyIncentive.supplySpeed / 1e18).toString()}%
                      </Text>
                    </Row>
                  );
                })}
              </Column>
            )} */}

            <SimpleTooltip
              label={t(
                "The Collateral Factor (CF) ratio defines the maximum amount of tokens in the pool that can be borrowed with a specific collateral. It’s expressed in percentage: if in a pool ETH has 75% LTV, for every 1 ETH worth of collateral, borrowers will be able to borrow 0.75 ETH worth of other tokens in the pool."
              )}
            >
              <Text fontSize="sm">{asset.collateralFactor / 1e16}% CF</Text>
            </SimpleTooltip>

            {/* Incentives under APY
            <Column
              mainAxisAlignment="flex-start"
              crossAxisAlignment="flex-end"
              my={1}
            >
              {supplyIncentives?.map((supplyIncentive) => {
                return (
                  <Row
                    mainAxisAlignment="space-between"
                    crossAxisAlignment="center"
                    w="100%"
                  >
                    <Avatar
                      src={
                        rewardTokensData[supplyIncentive.rewardToken].logoURL ?? ""
                      }
                      boxSize="20px"
                    />
                    <Text
                      ml={2}
                      fontWeight="bold"
                      color={
                        rewardTokensData[supplyIncentive.rewardToken].color ?? ""
                      }
                    >
                      {(supplyIncentive.supplySpeed / 1e18).toString()}%
                    </Text>
                  </Row>
                );
              })}
            </Column>
             */}
          </Column>
        )}

        {/* Incentives */}
        {/* <Column mainAxisAlignment="flex-start" crossAxisAlignment="flex-start">
          {supplyIncentives?.map((supplyIncentive) => {
            return (
              <Row mainAxisAlignment="flex-start" crossAxisAlignment="center">
                <Avatar
                  src={rewardTokensData[supplyIncentive.rewardToken].logoURL}
                  boxSize="15px"
                />
                <Box>
                  {(supplyIncentive.supplySpeed / 1e18).toString()}% APY
                </Box>
              </Row>
            );
          })}
        </Column> */}

        <Column
          mainAxisAlignment="flex-start"
          crossAxisAlignment="flex-end"
          width={isMobile ? "40%" : "27%"}
          as="button"
          onClick={authedOpenModal}
        >
          <Text
            color={tokenData?.color ?? "#FFF"}
            fontWeight="bold"
            fontSize="17px"
          >
            {smallUsdFormatter(asset.supplyBalanceUSD)}
          </Text>

          <Text fontSize="sm">
            {smallUsdFormatter(
              asset.supplyBalance / 10 ** asset.underlyingDecimals
            ).replace("$", "")}{" "}
            {symbol}
          </Text>
        </Column>

        {/* Set As Collateral  */}
        <Row
          width={isMobile ? "34%" : "20%"}
          mainAxisAlignment="flex-end"
          crossAxisAlignment="center"
        >
          <SwitchCSS symbol={symbol} color={tokenData?.color} />
          <Switch
            isChecked={asset.membership}
            className={symbol + "-switch"}
            onChange={onToggleCollateral}
            size="md"
            mt={1}
            mr={5}
          />
        </Row>
      </Row>
    </>
  );
}
Example #22
Source File: index.tsx    From strapi-plugin-comments with MIT License 4 votes vote down vote up
DiscussionThreadItemActions = ({
  allowedActions: { canModerate, canAccessReports, canReviewReports },
  ...item
}) => {
  const {
    id,
    blocked,
    removed,
    blockedThread,
    gotThread,
    threadItemsCount,
    threadFirstItemId,
    pinned,
    preview,
    reports = [],
    approvalStatus,
  } = item;

  const [blockConfirmationVisible, setBlockConfirmationVisible] =
    useState(false);
  const [blockThreadConfirmationVisible, setBlockThreadConfirmationVisible] =
    useState(false);
  const [blockButtonsDisabled, setBlockButtonsDisabled] =
    useState(blockedThread);

  const { push } = useHistory();
  const toggleNotification = useNotification();
  const queryClient = useQueryClient();
  const { lockApp, unlockApp } = useOverlayBlocker();

  const onSuccess =
    (message, stateAction = () => {}) =>
    async () => {
      await queryClient.invalidateQueries("get-details-data");
      toggleNotification({
        type: "success",
        message: `${pluginId}.${message}`,
      });
      stateAction(false);
      unlockApp();
    };

  const onError = (err) => {
    handleAPIError(err, toggleNotification);
  };

  const blockItemMutation = useMutation(blockItem, {
    onSuccess: onSuccess(
      "page.details.actions.comment.block.confirmation.success",
      setBlockConfirmationVisible
    ),
    onError,
    refetchActive: false,
  });
  const unblockItemMutation = useMutation(unblockItem, {
    onSuccess: onSuccess(
      "page.details.actions.comment.unblock.confirmation.success"
    ),
    onError,
    refetchActive: false,
  });
  const blockItemThreadMutation = useMutation(blockItemThread, {
    onSuccess: onSuccess(
      "page.details.actions.thread.block.confirmation.success",
      setBlockThreadConfirmationVisible
    ),
    onError,
    refetchActive: false,
  });
  const unblockItemThreadMutation = useMutation(unblockItemThread, {
    onSuccess: onSuccess(
      "page.details.actions.thread.unblock.confirmation.success"
    ),
    onError,
    refetchActive: false,
  });

  const gotApprovalFlow = !isNil(approvalStatus);
  const needsApproval = gotApprovalFlow && approvalStatus === "PENDING";
  const isBlocked = blocked || blockedThread;
  const isRejected = gotApprovalFlow && approvalStatus === "REJECTED";
  const openReports = reports?.filter((_) => !_.resolved);
  const hasReports = !isEmpty(openReports);
  const reviewFlowEnabled =
    (canAccessReports || canReviewReports) && hasReports;
  const hasActiveThread =
    gotThread && !(removed || preview || pinned || blockedThread);
  const isStatusBadgeVisible = isBlocked || reviewFlowEnabled;

  const renderStatus = (props) => {
    const status = resolveCommentStatus({ ...props, reviewFlowEnabled });
    const color = resolveCommentStatusColor(status);

    return (
      <StatusBadge
        backgroundColor={`${color}100`}
        textColor={`${color}700`}
        color={color}
      >
        {getMessage(
          {
            id: `page.common.item.status.${status}`,
            props: {
              count: openReports.length,
            },
          },
          status
        )}
      </StatusBadge>
    );
  };

  const handleBlockClick = () => setBlockConfirmationVisible(true);
  const handleBlockConfirm = async () => {
    if (canModerate) {
      lockApp();
      blockItemMutation.mutate(id);
    }
  };
  const handleBlockCancel = () => {
    setBlockConfirmationVisible(false);
  };
  const handleUnblockClick = async () => {
    if (canModerate) {
      lockApp();
      unblockItemMutation.mutate(id);
    }
  };

  const handleBlockThreadClick = () => setBlockThreadConfirmationVisible(true);
  const handleBlockThreadConfirm = async () => {
    if (canModerate) {
      lockApp();
      blockItemThreadMutation.mutate(id);
    }
  };
  const handleBlockThreadCancel = () => {
    setBlockThreadConfirmationVisible(false);
  };
  const handleUnblockThreadClick = async () => {
    if (canModerate) {
      lockApp();
      unblockItemThreadMutation.mutate(id);
    }
  };

  const handleDrilldownClick = () => {
    if (hasActiveThread) {
      push(getUrl(`discover/${threadFirstItemId}`));
    }
  };

  const handleBlockActionClick = async (mutation, onCallback) => {
    lockApp();
    await mutation.mutateAsync(id);
    onCallback();
  };

  const handleBlockButtonsStateChange = (disabled) =>
    setBlockButtonsDisabled(disabled);

  const anyGroupButtonsVisible =
    needsApproval || reviewFlowEnabled || !blockedThread;
  const isLoading =
    unblockItemMutation.isLoading ||
    blockItemMutation.isLoading ||
    blockItemThreadMutation.isLoading ||
    unblockItemThreadMutation.isLoading;

  if (removed || isRejected || !canModerate) {
    return (
      <DiscussionThreadItemActionsWrapper as={Flex} direction="row">
        {renderStatus(item)}
      </DiscussionThreadItemActionsWrapper>
    );
  }

  return (
    <>
      <DiscussionThreadItemActionsWrapper as={Flex} direction="row">
        {isStatusBadgeVisible && renderStatus(item)}
        {!blockedThread && (gotThread || pinned) && (
          <ActionButton
            onClick={handleBlockThreadClick}
            startIcon={<LockIcon />}
            loading={blockItemThreadMutation.isLoading}
            variant="danger"
          >
            {getMessage("page.details.actions.thread.block", "Block thread")}
          </ActionButton>
        )}
        {blockedThread && (gotThread || pinned) && (
          <ActionButton
            onClick={handleUnblockThreadClick}
            startIcon={<UnlockIcon />}
            loading={unblockItemThreadMutation.isLoading}
            variant="success"
          >
            {getMessage(
              "page.details.actions.thread.unblock",
              "Unblock thread"
            )}
          </ActionButton>
        )}
        {anyGroupButtonsVisible && (
          <IconButtonGroupStyled isSingle withMargin>
            {!blockedThread && !(blocked || needsApproval) && (
              <IconButton
                onClick={handleBlockClick}
                loading={blockItemMutation.isLoading}
                icon={<LockIcon />}
                label={getMessage(
                  "page.details.actions.comment.block",
                  "Block"
                )}
              />
            )}
            {!blockedThread && blocked && (
              <IconButton
                onClick={handleUnblockClick}
                loading={unblockItemMutation.isLoading}
                icon={<UnlockIcon />}
                label={getMessage(
                  "page.details.actions.comment.unblock",
                  "Unblock"
                )}
              />
            )}
            {needsApproval && (
              <DiscussionThreadItemApprovalFlowActions
                id={id}
                allowedActions={{ canModerate }}
                queryToInvalidate="get-details-data"
              />
            )}
            <DiscussionThreadItemReviewAction
              item={item}
              queryToInvalidate="get-details-data"
              areBlockButtonsDisabled={blockButtonsDisabled}
              isLoading={isLoading}
              allowedActions={{
                canModerate,
                canAccessReports,
                canReviewReports,
              }}
              blockItemMutation={blockItemMutation}
              blockItemThreadMutation={blockItemThreadMutation}
              onBlockButtonsStateChange={handleBlockButtonsStateChange}
              onBlockActionClick={handleBlockActionClick}
            />
          </IconButtonGroupStyled>
        )}
        {hasActiveThread && (
          <IconButtonGroupStyled isSingle withMargin>
            <IconButton
              onClick={handleDrilldownClick}
              icon={<Eye />}
              label={getMessage(
                "page.details.panel.discussion.nav.drilldown",
                "Drilldown thread"
              )}
              style={
                blocked && !blockedThread
                  ? { marginTop: "1px", marginRight: ".5rem" }
                  : {}
              }
            />
          </IconButtonGroupStyled>
        )}
      </DiscussionThreadItemActionsWrapper>
      {!blocked && (
        <ConfirmationDialog
          isVisible={blockConfirmationVisible}
          isActionAsync={blockItemMutation.isLoading}
          header={getMessage(
            "page.details.actions.comment.block.confirmation.header"
          )}
          labelConfirm={getMessage(
            "page.details.actions.comment.block.confirmation.button.confirm"
          )}
          iconConfirm={<LockIcon />}
          onConfirm={handleBlockConfirm}
          onCancel={handleBlockCancel}
        >
          {getMessage(
            "page.details.actions.comment.block.confirmation.description"
          )}
        </ConfirmationDialog>
      )}
      {!blockedThread && (
        <ConfirmationDialog
          isVisible={blockThreadConfirmationVisible}
          isActionAsync={blockItemThreadMutation.isLoading}
          header={getMessage(
            "page.details.actions.thread.block.confirmation.header"
          )}
          labelConfirm={getMessage(
            "page.details.actions.thread.block.confirmation.button.confirm"
          )}
          iconConfirm={<LockIcon />}
          onConfirm={handleBlockThreadConfirm}
          onCancel={handleBlockThreadCancel}
        >
          {getMessage(
            "page.details.actions.thread.block.confirmation.description"
          )}
        </ConfirmationDialog>
      )}
    </>
  );
}
Example #23
Source File: index.tsx    From react-query-auth with MIT License 4 votes vote down vote up
export function initReactQueryAuth<
  User = unknown,
  Error = unknown,
  LoginCredentials = unknown,
  RegisterCredentials = unknown
>(config: AuthProviderConfig<User, Error>) {
  const AuthContext = React.createContext<AuthContextValue<
    User,
    Error,
    LoginCredentials,
    RegisterCredentials
  > | null>(null);
  AuthContext.displayName = 'AuthContext';

  const {
    loadUser,
    loginFn,
    registerFn,
    logoutFn,
    key = 'auth-user',
    waitInitial = true,
    LoaderComponent = () => <div>Loading...</div>,
    ErrorComponent = (error: any) => (
      <div style={{ color: 'tomato' }}>{JSON.stringify(error, null, 2)}</div>
    ),
  } = config;

  function AuthProvider({ children }: AuthProviderProps): JSX.Element {
    const queryClient = useQueryClient();

    const {
      data: user,
      error,
      status,
      isLoading,
      isIdle,
      isSuccess,
      refetch,
    } = useQuery<User, Error>({
      queryKey: key,
      queryFn: loadUser,
    });

    const setUser = React.useCallback(
      (data: User) => queryClient.setQueryData(key, data),
      [queryClient]
    );

    const loginMutation = useMutation({
      mutationFn: loginFn,
      onSuccess: user => {
        setUser(user);
      },
    });

    const registerMutation = useMutation({
      mutationFn: registerFn,
      onSuccess: user => {
        setUser(user);
      },
    });

    const logoutMutation = useMutation({
      mutationFn: logoutFn,
      onSuccess: () => {
        queryClient.clear();
      },
    });

    const value = React.useMemo(
      () => ({
        user,
        error,
        refetchUser: refetch,
        login: loginMutation.mutateAsync,
        isLoggingIn: loginMutation.isLoading,
        logout: logoutMutation.mutateAsync,
        isLoggingOut: logoutMutation.isLoading,
        register: registerMutation.mutateAsync,
        isRegistering: registerMutation.isLoading,
      }),
      [
        user,
        error,
        refetch,
        loginMutation.mutateAsync,
        loginMutation.isLoading,
        logoutMutation.mutateAsync,
        logoutMutation.isLoading,
        registerMutation.mutateAsync,
        registerMutation.isLoading,
      ]
    );

    if (isSuccess || !waitInitial) {
      return (
        <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
      );
    }

    if (isLoading || isIdle) {
      return <LoaderComponent />;
    }

    if (error) {
      return <ErrorComponent error={error} />;
    }

    return <div>Unhandled status: {status}</div>;
  }

  function useAuth() {
    const context = React.useContext(AuthContext);
    if (!context) {
      throw new Error(`useAuth must be used within an AuthProvider`);
    }
    return context;
  }

  return { AuthProvider, AuthConsumer: AuthContext.Consumer, useAuth };
}
Example #24
Source File: useOriginate.ts    From homebase-app with MIT License 4 votes vote down vote up
useOriginate = (template: DAOTemplate) => {
  const queryClient = useQueryClient();
  const [states, setStates] = useState(INITIAL_STATES);

  const [activeState, setActiveState] = useState<number>();
  const { tezos, connect, network, account } = useTezos();

  const result = useMutation<
    ContractAbstraction<ContractProvider | Wallet>,
    Error,
    OriginateParams
  >(
    async ({ metadataParams, params }) => {
      const updatedStates = INITIAL_STATES;

      updatedStates[0] = {
        activeText: "Deploying Metadata Carrier Contract",
        completedText: "",
      };

      setActiveState(0);
      setStates(updatedStates);

      let tezosToolkit = tezos;

      if (!account) {
        tezosToolkit = await connect();
      }

      mixpanel.track("Started DAO origination", {
        contract: "MetadataCarrier",
        daoName: params.orgSettings.name,
        daoType: params.template
      })

      const metadata = await deployMetadataCarrier({
        ...metadataParams,
        tezos: tezosToolkit,
        connect,
      });

      if (!metadata) {
        throw new Error(
          `Could not deploy ${template}DAO because MetadataCarrier contract deployment failed`
        );
      }

      updatedStates[0] = {
        ...updatedStates[0],
        completedText: `Deployed Metadata Carrier with address "${metadata.deployAddress}" and key "${metadata.keyName}"`,
      };

      updatedStates[1] = {
        activeText: `Deploying ${template} DAO Contract`,
        completedText: "",
      };

      setActiveState(1);
      setStates(updatedStates);

      mixpanel.track("Started DAO origination", {
        contract: "BaseDAO",
        daoName: params.orgSettings.name
      })

      console.log(params, network, metadata)

      const contract = await BaseDAO.baseDeploy(template, {
        tezos: tezosToolkit,
        metadata,
        params,
        network,
      });

      if (!contract) {
        throw new Error(`Error deploying ${template}DAO`);
      }

      updatedStates[1] = {
        ...updatedStates[1],
        completedText: `Deployed ${template} DAO contract with address "${contract.address}"`,
      };

      updatedStates[2] = {
        activeText: `Waiting for DAO to be indexed`,
        completedText: "",
      };

      setActiveState(2);
      setStates(updatedStates);

      mixpanel.track("Completed DAO creation", {
        daoName: params.orgSettings.name,
        daoType: params.template
      })

      mixpanel.track("Waiting for DAO indexation", {
        daoName: params.orgSettings.name,
        daoType: params.template
      })

      const indexed = await waitForIndexation(contract.address);

      updatedStates[2] = {
        ...updatedStates[2],
        completedText: indexed
          ? `Deployed ${metadataParams.metadata.unfrozenToken.name} successfully`
          : `Deployed ${metadataParams.metadata.unfrozenToken.name} successfully, but metadata has not been indexed yet. This usually takes a few minutes, your DAO page may not be available yet.`,
      };

      setActiveState(3);
      setStates(updatedStates);

      mixpanel.track("Completed DAO indexation", {
        daoName: params.orgSettings.name,
        daoType: params.template
      })

      return contract;
    },
    {
      onSuccess: () => {
        queryClient.resetQueries();
      },
    }
  );

  console.log(result)

  return { mutation: result, states, activeState };
}
Example #25
Source File: Companion.tsx    From apps with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function Companion({
  postData,
  companionHelper,
  companionExpanded,
  onOptOut,
}: CompanionProps): ReactElement {
  const client = useQueryClient();
  const containerRef = useRef<HTMLDivElement>();
  const [isCommentsOpen, setIsCommentsOpen] = useState(false);
  const [assetsLoaded, setAssetsLoaded] = useState(isTesting);
  const [post, setPost] = useState<PostBootData>(postData);
  const [companionState, setCompanionState] =
    useState<boolean>(companionExpanded);
  const { user, closeLogin, loadingUser, shouldShowLogin, loginState } =
    useContext(AuthContext);

  const routeChangedCallbackRef = useTrackPageView();

  useEffect(() => {
    if (!assetsLoaded) {
      return;
    }

    client.setQueryData(REQUEST_PROTOCOL_KEY, {
      requestMethod: companionRequest,
      fetchMethod: companionFetch,
    });
  }, [assetsLoaded]);

  useEffect(() => {
    if (routeChangedCallbackRef.current) {
      routeChangedCallbackRef.current();
    }
  }, [routeChangedCallbackRef]);

  useEffect(() => {
    if (!containerRef?.current || assetsLoaded) {
      return;
    }

    const checkAssets = () => {
      if (containerRef?.current?.offsetLeft === 0) {
        return setTimeout(checkAssets, 10);
      }

      return setTimeout(() => setAssetsLoaded(true), 10);
    };

    checkAssets();
    routeChangedCallbackRef.current();
  }, [containerRef]);

  const onOpenComments = (value: boolean) => {
    if (value && !companionState) {
      setCompanionState(true);
    }

    setIsCommentsOpen(value);
  };

  return (
    <Container
      containerRef={containerRef}
      companionExpanded={companionState}
      shouldLoad={assetsLoaded}
    >
      {!user && !loadingUser && shouldShowLogin && (
        <LoginModal
          parentSelector={getCompanionWrapper}
          isOpen
          onRequestClose={closeLogin}
          contentLabel="Login Modal"
          {...loginState}
        />
      )}

      <CompanionMenu
        post={post}
        companionHelper={companionHelper}
        setPost={setPost}
        onOptOut={onOptOut}
        companionState={companionState}
        setCompanionState={setCompanionState}
        onOpenComments={() => onOpenComments(true)}
      />
      <CompanionContent
        post={post}
        viewComments={isCommentsOpen}
        onViewComments={onOpenComments}
      />
    </Container>
  );
}