All files / publisher tour.tsx

66.66% Statements 18/27
57.89% Branches 11/19
55.55% Functions 5/9
65.38% Lines 17/26

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                    40x   5x                               5x     5x       5x 5x                                                               5x       5x                                     5x 5x           5x   5x 5x                   5x 5x 5x       5x    
import { createRoot } from "react-dom/client";
 
import Tour from "./tour/tour";
 
import { toggleShadowWhenSticky } from "./market/stickyListingBar";
 
import type { Step } from "./listing/types";
 
// returns true if % of truthy values in the array is above the threshold
function isCompleted(fields: unknown[], threshold = 0.5): boolean {
  const completed = fields.filter((isCompleted) => isCompleted);
 
  return completed.length / fields.length >= threshold;
}
 
export function initTour({
  container,
  steps,
  onTourStarted,
  onTourClosed,
  startTour,
}: {
  container: HTMLElement;
  steps: Step[];
  onTourStarted: () => void;
  onTourClosed: () => void;
  startTour: boolean;
}) {
  Iif (!document.contains(container)) {
    throw Error("initTour container element not found in document.");
  }
  Iif (!steps || !steps.length) {
    throw Error("initTour expects steps array as an argument.");
  }
 
  const root = createRoot(container);
  root.render(
    <Tour
      steps={steps}
      onTourStarted={onTourStarted}
      onTourClosed={onTourClosed}
      startTour={startTour}
    />,
  );
}
 
export function initListingTour({
  snapName,
  container,
  steps,
  formFields,
}: {
  snapName: string;
  container: HTMLElement;
  steps: Step[];
  formFields: {
    title: string;
    snap_name: string;
    categories: string[];
    video_urls: string[];
    images: Array<{
      type: string;
    }>;
    summary: string;
    website: string[];
    contact: string[];
  };
}) {
  const storageKey = `listing-tour-finished-${snapName}`;
 
  // check form fields completed status
  // truthy value means field is considered completed
  const completedFields = [
    // title is completed if it is different from package name
    formFields.title !== formFields.snap_name,
    // category
    formFields.categories.length,
    // video
    formFields.video_urls.length,
    // icon
    formFields.images.filter((i) => i.type === "icon").length,
    // images
    formFields.images.filter((i) => i.type === "screenshot").length,
    // banner
    formFields.images.filter((i) => i.type === "banner").length,
    // summary is completed if it is different from the title
    formFields.summary !== formFields.title,
    // if one of website or contact is filled we consider it completed
    formFields.website || formFields.contact,
  ];
 
  const isFormCompleted = isCompleted(completedFields);
  const isTourFinished = !!(
    window.localStorage && window.localStorage.getItem(storageKey) === "true"
  );
 
  // start the tour automatically if form is not completed
  // (has less than 50% fields filled), and the tour wasn't closed before
  const startTour = !isFormCompleted && !isTourFinished;
 
  const stickyHeader = document.querySelector(".js-sticky-bar");
  const onTourClosed = (): void => {
    // save that tour was seen by user
    window.localStorage && window.localStorage.setItem(storageKey, "true");
    // make header sticky again
    if (stickyHeader) {
      stickyHeader.classList.remove("is-static");
    }
    toggleShadowWhenSticky(stickyHeader);
  };
 
  const onTourStarted = (): void => {
    Eif (stickyHeader) {
      stickyHeader.classList.add("is-static");
    }
  };
 
  initTour({ container, steps, onTourStarted, onTourClosed, startTour });
}