All files / app/features/connections/friends AddFriendButton.tsx

90.9% Statements 40/44
50% Branches 2/4
80% Functions 8/10
90.9% Lines 40/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 1493x 3x 3x           3x 3x 3x 3x 3x 3x   3x 3x 3x 3x 3x 3x                 8x       25x 25x   25x 25x     25x   25x         3x   3x 3x   3x       3x       3x           3x       1x 1x           1x           25x 6x 1x   5x       25x 3x 3x                                                                     1x                                        
import { Link } from "@mui/material";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import Button from "components/Button";
import {
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
} from "components/Dialog";
import { PersonAddIcon } from "components/Icons";
import ProfileIncompleteDialog from "components/ProfileIncompleteDialog/ProfileIncompleteDialog";
import { doAntibot } from "features/antibot/antibot";
import useAccountInfo from "features/auth/useAccountInfo";
import { userKey } from "features/queryKeys";
import { Empty } from "google-protobuf/google/protobuf/empty_pb";
import { Trans, useTranslation } from "i18n";
import { CONNECTIONS, GLOBAL, PROFILE } from "i18n/namespaces";
import { User } from "proto/api_pb";
import React, { useState } from "react";
import { helpCenterFriendRequestsURL } from "routes";
import { service } from "service";
 
import { SetMutationError } from ".";
 
interface AddFriendButtonProps {
  setMutationError: SetMutationError;
  userId: number;
}
 
export default function AddFriendButton({
  setMutationError,
  userId,
}: AddFriendButtonProps) {
  const queryClient = useQueryClient();
  const { t } = useTranslation([PROFILE, CONNECTIONS, GLOBAL]);
  const [showCantFriendDialog, setShowCantFriendDialog] =
    useState<boolean>(false);
  const [showConfirmDialog, setShowConfirmDialog] = useState<boolean>(false);
 
  const { data: accountInfo, isLoading: isAccountInfoLoading } =
    useAccountInfo();
 
  const { isPending, mutate: sendFriendRequest } = useMutation<
    Empty,
    Error,
    AddFriendButtonProps
  >({
    mutationFn: ({ userId }) => service.api.sendFriendRequest(userId),
    onMutate: async ({ setMutationError }) => {
      setMutationError("");
      doAntibot("friend_request");
 
      await queryClient.cancelQueries({
        queryKey: userKey(userId),
      });
 
      const cachedUser = queryClient.getQueryData<User.AsObject>(
        userKey(userId),
      );
 
      Iif (cachedUser) {
        queryClient.setQueryData<User.AsObject>(userKey(userId), {
          ...cachedUser,
          friends: User.FriendshipStatus.PENDING,
        });
      }
      return cachedUser;
    },
 
    onError: (error, { setMutationError }, cachedUser) => {
      setMutationError(error.message);
      Iif (cachedUser) {
        queryClient.setQueryData(userKey(userId), cachedUser);
      }
    },
 
    onSuccess: (_, { userId }) => {
      queryClient.invalidateQueries({
        queryKey: userKey(userId),
      });
    },
  });
 
  const onClick = () => {
    if (!accountInfo?.profileComplete) {
      setShowCantFriendDialog(true);
    } else {
      setShowConfirmDialog(true);
    }
  };
 
  const onConfirm = () => {
    setShowConfirmDialog(false);
    sendFriendRequest({ setMutationError, userId });
  };
 
  return (
    <>
      <ProfileIncompleteDialog
        open={showCantFriendDialog}
        onClose={() => setShowCantFriendDialog(false)}
        attempted_action="send_friend_request"
      />
      <Dialog
        aria-labelledby="add-friend-confirm-dialog"
        open={showConfirmDialog}
        onClose={() => setShowConfirmDialog(false)}
      >
        <DialogTitle id="add-friend-confirm-dialog">
          {t("connections:add_friend_confirmation_dialog.title")}
        </DialogTitle>
        <DialogContent>
          <Trans
            i18nKey="connections:add_friend_confirmation_dialog.message"
            components={{
              helpCenterLink: (
                <Link
                  href={helpCenterFriendRequestsURL}
                  target="_blank"
                  rel="noopener noreferrer"
                />
              ),
            }}
          />
        </DialogContent>
        <DialogActions>
          <Button
            variant="outlined"
            onClick={() => setShowConfirmDialog(false)}
          >
            {t("global:cancel")}
          </Button>
          <Button variant="contained" loading={isPending} onClick={onConfirm}>
            {t("connections:add_friend_confirmation_dialog.confirm")}
          </Button>
        </DialogActions>
      </Dialog>
      <Button
        startIcon={<PersonAddIcon />}
        onClick={onClick}
        loading={isPending}
        disabled={isAccountInfoLoading}
      >
        {t("profile:actions.add_friend")}
      </Button>
    </>
  );
}