Skip to content
This repository has been archived by the owner on Jan 23, 2024. It is now read-only.

Commit

Permalink
feat: ability to reorder fields in multiple select in Routing Forms (c…
Browse files Browse the repository at this point in the history
…alcom#10927)

Co-authored-by: Udit Takkar <[email protected]>
  • Loading branch information
G3root and Udit-takkar authored Sep 27, 2023
1 parent ec4e2f5 commit 468da1f
Showing 1 changed file with 68 additions and 29 deletions.
97 changes: 68 additions & 29 deletions packages/app-store/routing-forms/pages/form-edit/[...appPages].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
Skeleton,
TextField,
} from "@calcom/ui";
import { Plus, FileText, X } from "@calcom/ui/components/icon";
import { Plus, FileText, X, ArrowUp, ArrowDown } from "@calcom/ui/components/icon";

import type { inferSSRProps } from "@lib/types/inferSSRProps";

Expand All @@ -29,7 +29,7 @@ import SingleForm, {

export { getServerSideProps };
type HookForm = UseFormReturn<RoutingFormWithResponseCount>;
type SelectOption = { placeholder: string; value: string };
type SelectOption = { placeholder: string; value: string; id: string };

export const FieldTypes = [
{
Expand Down Expand Up @@ -88,12 +88,13 @@ function Field({
appUrl: string;
}) {
const { t } = useLocale();
const [animationRef] = useAutoAnimate<HTMLUListElement>();

const [options, setOptions] = useState<SelectOption[]>([
{ placeholder: "< 10", value: "" },
{ placeholder: "10-100", value: "" },
{ placeholder: "100-500", value: "" },
{ placeholder: "> 500", value: "" },
{ placeholder: "< 10", value: "", id: uuidv4() },
{ placeholder: "10-100", value: "", id: uuidv4() },
{ placeholder: "100-500", value: "", id: uuidv4() },
{ placeholder: "> 500", value: "", id: uuidv4() },
]);

const handleRemoveOptions = (index: number) => {
Expand All @@ -108,6 +109,7 @@ function Field({
{
placeholder: "New Option",
value: "",
id: uuidv4(),
},
]);
};
Expand All @@ -118,6 +120,7 @@ function Field({
const values: SelectOption[] = originalValues.split("\n").map((fieldValue) => ({
value: fieldValue,
placeholder: "",
id: uuidv4(),
}));
setOptions(values);
}
Expand All @@ -132,6 +135,7 @@ function Field({
...opt,
...(index === optionIndex ? { value: e.target.value } : {}),
}));

setOptions(updatedOptions);
updateSelectText(updatedOptions);
};
Expand All @@ -156,6 +160,19 @@ function Field({
name: `${hookFieldNamespace}.identifier`,
});

function move(index: number, increment: 1 | -1) {
const newList = [...options];

const type = options[index];
const tmp = options[index + increment];
if (tmp) {
newList[index] = tmp;
newList[index + increment] = type;
}
setOptions(newList);
updateSelectText(newList);
}

return (
<div
data-testid="field"
Expand Down Expand Up @@ -242,29 +259,51 @@ function Field({
<Skeleton as={Label} loadingClassName="w-16" title={t("Options")}>
{t("options")}
</Skeleton>
{options.map((field, index) => (
<div key={`select-option-${index}`}>
<TextField
disabled={!!router}
containerClassName="[&>*:first-child]:border [&>*:first-child]:border-default hover:[&>*:first-child]:border-gray-400"
className="border-0 focus:ring-0 focus:ring-offset-0"
labelSrOnly
placeholder={field.placeholder.toString()}
value={field.value}
type="text"
addOnClassname="bg-transparent border-0"
onChange={(e) => handleChange(e, index)}
addOnSuffix={
<button
type="button"
onClick={() => handleRemoveOptions(index)}
aria-label={t("remove")}>
<X className="h-4 w-4" />
</button>
}
/>
</div>
))}
<ul ref={animationRef}>
{options.map((field, index) => (
<li key={`select-option-${field.id}`} className="group mt-2 flex items-center gap-2">
<div className="flex flex-col gap-2">
{options.length && index !== 0 ? (
<button
type="button"
onClick={() => move(index, -1)}
className="bg-default text-muted hover:text-emphasis invisible flex h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all hover:border-transparent hover:shadow group-hover:visible group-hover:scale-100 ">
<ArrowUp />
</button>
) : null}
{options.length && index !== options.length - 1 ? (
<button
type="button"
onClick={() => move(index, 1)}
className="bg-default text-muted hover:text-emphasis invisible flex h-6 w-6 scale-0 items-center justify-center rounded-md border p-1 transition-all hover:border-transparent hover:shadow group-hover:visible group-hover:scale-100 ">
<ArrowDown />
</button>
) : null}
</div>
<div className="w-full">
<TextField
disabled={!!router}
containerClassName="[&>*:first-child]:border [&>*:first-child]:border-default hover:[&>*:first-child]:border-gray-400"
className="border-0 focus:ring-0 focus:ring-offset-0"
labelSrOnly
placeholder={field.placeholder.toString()}
value={field.value}
type="text"
addOnClassname="bg-transparent border-0"
onChange={(e) => handleChange(e, index)}
addOnSuffix={
<button
type="button"
onClick={() => handleRemoveOptions(index)}
aria-label={t("remove")}>
<X className="h-4 w-4" />
</button>
}
/>
</div>
</li>
))}
</ul>
<div className={classNames("flex")}>
<Button
data-testid="add-attribute"
Expand Down

0 comments on commit 468da1f

Please sign in to comment.