Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drag drop not working on mobile #88

Closed
hinn254 opened this issue Jul 26, 2024 · 2 comments
Closed

Drag drop not working on mobile #88

hinn254 opened this issue Jul 26, 2024 · 2 comments

Comments

@hinn254
Copy link

hinn254 commented Jul 26, 2024

RPReplay_Final1721981473.2.mov

In this video, I start dragging as soon as I press start survey but nothing is happening, yet it works on desktop. I really need it to work on mobile as well.
Any suggestions

cc @sashamilenkovic

@hinn254
Copy link
Author

hinn254 commented Jul 26, 2024

Here is the code
import { SURVEY_UI_CONFIG } from "@/app/data";
import Prose from "@/components/prose";
import { FormContext } from "@/context/form-context";
import { FormField } from "@/types/form";
import type { ParentConfig } from "@formkit/drag-and-drop";
import { useDragAndDrop } from "@formkit/drag-and-drop/react";
import clsx from "clsx";
import React, { useContext, useEffect } from "react";
import { isMobile, useMobileOrientation } from "react-device-detect";

export default function MaxDiffPreferenceDragDrop({
  field,
  featureList = [""],
  currentIndex = 1,
  setCurrentStep,
  totalSteps = 1,
  task = 0,
}: {
  field: FormField;
  featureList: (string | undefined)[];
  currentIndex: number;
  setCurrentStep: (index: number) => void;
  totalSteps: number;
  task: any;
}) {
  const { handleMaxDiffAnswer, handleMaxDiffAnswerReset, surveyId } =
    useContext(FormContext);

  const [source, features, setFeatures] = useDragAndDrop<
    HTMLUListElement,
    string
  >(featureList as string[], {
    group: `maxDiff-${task}`,
    draggable: (el) => el.id !== "no-drag",
  });

  const config1: Partial<ParentConfig<string>> = {
    group: `maxDiff-${task}`,
  };

  const config2: Partial<ParentConfig<string>> = {
    group: `maxDiff-${task}`,
  };

  config1.accepts = (_parent, lastParent) => {
    if (lastParent.el === target2.current) {
      return false;
    }
    return mostLikedFeatures.length < 1;
  };

  config2.accepts = (_parent, lastParent) => {
    if (lastParent.el === target1.current) {
      return false;
    }
    return leastLikedFeatures.length < 1;
  };

  const [target1, mostLikedFeatures, setMostLikedFeatures] = useDragAndDrop(
    [],
    config1,
  );
  const [target2, leastLikedFeatures, setLeastLikedFeatures] = useDragAndDrop(
    [],
    config2,
  );

  const handleRemoveItem = (item: string, container: string) => {
    if (container === "mostLiked") {
      setMostLikedFeatures((prev) => prev.filter((i) => i !== item));
    } else if (container === "leastLiked") {
      setLeastLikedFeatures((prev) => prev.filter((i) => i !== item));
    }
    setFeatures((prev) => [...prev, item]);
  };

  const handleDragStart = (item: string, container: string) => {
    handleRemoveItem(item, container);
  };

  const handleTouchStart = (item: string, container: string) => {
    handleRemoveItem(item, container);
  };

  useEffect(() => {
    if (mostLikedFeatures.length > 0 && leastLikedFeatures.length > 0) {
      handleMaxDiffAnswer(
        field.id,
        mostLikedFeatures[0],
        leastLikedFeatures[0],
        task,
      );
    } else {
      handleMaxDiffAnswerReset(field.id, task);
    }
  }, [mostLikedFeatures, leastLikedFeatures]);

  const uiConfig = SURVEY_UI_CONFIG[parseInt(surveyId)];
  const { isPortrait } = useMobileOrientation();

  return (
    <div className="my-4 w-full">
      <ul ref={source} className="flex items-stretch justify-around gap-2 py-2">
        {features.map((file) => (
          <li
            key={file}
            onDragStart={(e) => {
              e.dataTransfer.setData("text/plain", file);
              handleDragStart(file, "features");
            }}
            onTouchStart={(e) => {
              handleTouchStart(file, "features");
            }}
            draggable
            className={clsx(
              "flex h-full max-w-52 flex-1 flex-col rounded-lg bg-bgSecondary p-2 px-4 text-center text-sm font-semibold",
              isMobile && isPortrait ? "min-h-16 p-1" : "min-h-32",
            )}
          >
            <Prose
              html={file ?? "Empty"}
              className={clsx(isMobile && isPortrait ? "!text-xs" : "text-sm")}
            />
          </li>
        ))}
      </ul>
      <div className="space-x- flex items-stretch justify-around gap-2 overflow-x-scroll pb-2 sm:justify-evenly md:space-x-4">
        <div
          ref={target1 as React.RefObject<HTMLDivElement>}
          className={clsx(
            "relative mt-4 flex flex-col items-center space-y-3 rounded-lg border border-borderSecondary sm:w-64",
            isMobile && isPortrait ? "min-h-10 p-0" : "min-h-48",
          )}
        >
          <p className="absolute -top-3 bg-white px-2 text-center text-normal font-semibold uppercase">
            Most Important
          </p>
          <ul
            ref={target1 as React.RefObject<HTMLUListElement>}
            className="flex flex-1"
          >
            {mostLikedFeatures.map((item) => (
              <li
                key={item}
                className={clsx(
                  "mb-2 flex w-full flex-col rounded-lg bg-bgInverseSecondary p-2 text-center text-white sm:w-40",
                  isMobile ? "text-normal" : "",
                )}
                style={{
                  backgroundColor: uiConfig?.colors
                    ? uiConfig.colors.primary
                    : "",
                }}
                draggable
                onDragStart={() => handleDragStart(item, "mostLiked")}
                onTouchStart={() => handleTouchStart(item, "mostLiked")}
              >
                {item}
              </li>
            ))}
          </ul>
        </div>
        <div
          ref={target2 as React.RefObject<HTMLDivElement>}
          className={clsx(
            "relative mt-4 flex flex-col items-center space-y-3 rounded-lg border border-borderSecondary sm:w-64",
            isMobile && isPortrait ? "min-h-10 p-0" : "min-h-48",
          )}
        >
          <p className="absolute -top-3 bg-white px-2 text-center text-normal font-semibold uppercase">
            Least Important
          </p>
          <ul
            ref={target2 as React.RefObject<HTMLUListElement>}
            className="flex flex-1"
          >
            {leastLikedFeatures.map((item) => (
              <li
                key={item}
                className={clsx(
                  "mb-2 flex w-full flex-col rounded-lg bg-bgInversePrimary p-2 text-center text-white sm:w-40",
                  isMobile ? "text-normal" : "",
                )}
                style={{
                  backgroundColor: uiConfig?.colors
                    ? uiConfig.colors.primary
                    : "",
                }}
                draggable
                onDragStart={() => handleDragStart(item, "leastLiked")}
                onTouchStart={() => handleTouchStart(item, "leastLiked")}
              >
                {item}
              </li>
            ))}
          </ul>
        </div>
      </div>
    </div>
  );
}

@sashamilenkovic
Copy link
Contributor

@hinn254 Overriding handleTouchstart is probably the issue. check out the new event listeners on the docs with the new release of v0.2.0. Closing this for now but feel free to reopen if you're still having issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants