Repository: sunflower-farmers/sunflower-farmers
File: src/features/island/collectibles/components/pets/Pet.tsx (TypeScript)

Code before:
      });
      setShowXpPopup(true);
      window.setTimeout(() => setShowXpPopup(false), 1000);
    } else {
      setShowPetModal(true);
    }
  };

  return (
    <>
      <div className="absolute" style={{ ...PET_PIXEL_STYLES[name] }}>
        <img
          src={petImage}
          className={classNames("absolute w-full", {
            "cursor-pointer hover:img-highlight": !isVisiting,
          })}
          alt={name}
          onClick={handlePetClick}
        />
        <Transition
          appear={true}
          show={showXpPopup}
          enter="transition-opacity transition-transform duration-200"
          enterFrom="opacity-0 translate-y-4"
          enterTo="opacity-100 -translate-y-0"
          leave="transition-opacity duration-100"
          leaveFrom="opacity-100"
          leaveTo="opacity-0"
          className="flex -top-2 left-1/2 -translate-x-1/2 absolute z-40 pointer-events-none"
          as="div"
        >
          <span className="text-sm yield-text" style={{ color: "#71e358" }}>
            {"+10XP"}
          </span>
        </Transition>
        {isNapping ? (
          <img
            src={SUNNYSIDE.icons.sleeping}
            alt="sleeping"
            className="absolute w-6 top-[-0.5rem] left-[-0.5rem]"
          />
        ) : isNeglected ? (
          <img
            src={SUNNYSIDE.icons.expression_stress}
            alt="stress"
            className="absolute w-[18px] top-[-0.5rem] left-[-0.5rem]"
          />
        ) : null}
      </div>
      <PetModal
        show={showPetModal}

Review comment (refactor):
We now have a lot of branching logic in `Pet.tsx` - it can make flows hard to understand when there are lots of states a pet can be in.

Is it feasible to have a specific `VisitingPet.tsx` component that is used instead when visiting?

The purpose being to simplify the Pet in the normal use cases.

Code after:
  const [showHelped, setShowHelped] = useState(false);
  const { gameService } = useContext(Context);
  const { isVisiting } = useVisiting();

  const petData = useSelector(gameService, _petData(name));

  const isNeglected = isPetNeglected(petData);
  const isNapping = isPetNapping(petData);
  const petImage =
    PET_STATE_IMAGES[name][isNeglected || isNapping ? "asleep" : "happy"];

  // Visiting variables
  const visitorGameState = useSelector(
    gameService,
    (state) => state.context.visitorState,
  );
  const state = useSelector(gameService, (state) => state.context.state);
  const totalHelpedToday = useSelector(
    gameService,
    (state) => state.context.totalHelpedToday ?? 0,
  );
  const hasHelpedPet = useSelector(gameService, _hasHelpedPet(name));

  const handlePetClick = () => {
    if (isVisiting) {
      if (
        petData &&
        visitorGameState &&
        hasFeatureAccess(visitorGameState, "PETS") &&
        !hasHelpedPet
      ) {
        gameService.send("pet.visitingPets", { pet: name, totalHelpedToday });

        if (isHelpComplete({ game: gameService.getSnapshot().context.state })) {
          setShowHelped(true);
        }
      }
    } else if (isNapping) {
      gameService.send("pet.pet", {
        pet: name,
      });
      setShowXpPopup(true);
      window.setTimeout(() => setShowXpPopup(false), 1000);
    } else {
      setShowPetModal(true);
    }
  };

  return (
    <>
      <div className="absolute" style={{ ...PET_PIXEL_STYLES[name] }}>