-
+}) => {
+ const [isMenuActive, setIsMenuActive] = useState(false);
+ const actionSectionRef = useRef
(null);
+
+ useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false));
+
+ return (
+
= ({
/>
{label.name}
-
-
-
-
-
- }
+
+ setIsMenuActive(!isMenuActive)}>
+
+
+ }
+ >
+
addLabelToGroup(label)}>
+
+
+ Convert to group
+
+
+
editLabel(label)}>
+
+
+ Edit label
+
+
+
+
+
-
-
-
-
-);
+ );
+};
diff --git a/web/components/onboarding/invite-members.tsx b/web/components/onboarding/invite-members.tsx
index fee1cb252..8f1b1fa41 100644
--- a/web/components/onboarding/invite-members.tsx
+++ b/web/components/onboarding/invite-members.tsx
@@ -1,15 +1,27 @@
-import React, { useEffect } from "react";
+import React, { useEffect, useRef, useState } from "react";
+// headless ui
+import { Listbox, Transition } from "@headlessui/react";
// react-hook-form
-import { Controller, useFieldArray, useForm } from "react-hook-form";
+import {
+ Control,
+ Controller,
+ FieldArrayWithId,
+ UseFieldArrayRemove,
+ useFieldArray,
+ useForm,
+} from "react-hook-form";
// services
import workspaceService from "services/workspace.service";
// hooks
import useToast from "hooks/use-toast";
// ui
-import { CustomSelect, Input, PrimaryButton, SecondaryButton } from "components/ui";
+import { Input, PrimaryButton, SecondaryButton } from "components/ui";
+// hooks
+import useDynamicDropdownPosition from "hooks/use-dynamic-dropdown";
// icons
-import { PlusIcon, XMarkIcon } from "@heroicons/react/24/outline";
+import { ChevronDownIcon } from "@heroicons/react/20/solid";
+import { PlusIcon, XMarkIcon, CheckIcon } from "@heroicons/react/24/outline";
// types
import { ICurrentUserResponse, IWorkspace, TOnboardingSteps } from "types";
// constants
@@ -31,12 +43,136 @@ type FormValues = {
emails: EmailRole[];
};
-export const InviteMembers: React.FC
= ({
- finishOnboarding,
- stepChange,
- user,
- workspace,
-}) => {
+type InviteMemberFormProps = {
+ index: number;
+ remove: UseFieldArrayRemove;
+ control: Control;
+ field: FieldArrayWithId;
+ fields: FieldArrayWithId[];
+ errors: any;
+};
+
+const InviteMemberForm: React.FC = (props) => {
+ const { control, index, fields, remove, errors } = props;
+
+ const buttonRef = useRef(null);
+ const dropdownRef = useRef(null);
+
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
+
+ useDynamicDropdownPosition(
+ isDropdownOpen,
+ () => setIsDropdownOpen(false),
+ buttonRef,
+ dropdownRef
+ );
+
+ return (
+
+
+ (
+ <>
+
+ {errors.emails?.[index]?.email && (
+
+ {errors.emails?.[index]?.email?.message}
+
+ )}
+ >
+ )}
+ />
+
+
+
(
+ {
+ onChange(val);
+ setIsDropdownOpen(false);
+ }}
+ className="flex-shrink-0 text-left w-full"
+ >
+ setIsDropdownOpen((prev) => !prev)}
+ className="flex items-center px-2.5 py-2 text-xs justify-between gap-1 w-full rounded-md border border-custom-border-300 shadow-sm duration-300 focus:outline-none"
+ >
+ {ROLE[value]}
+
+
+
+
+
+
+ {Object.entries(ROLE).map(([key, value]) => (
+
+ `cursor-pointer select-none truncate rounded px-1 py-1.5 ${
+ active || selected ? "bg-custom-background-80" : ""
+ } ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
+ }
+ >
+ {({ selected }) => (
+
+
{value}
+ {selected &&
}
+
+ )}
+
+ ))}
+
+
+
+
+ )}
+ />
+
+ {fields.length > 1 && (
+
+ )}
+
+ );
+};
+
+export const InviteMembers: React.FC = (props) => {
+ const { finishOnboarding, stepChange, user, workspace } = props;
+
const { setToastAlert } = useToast();
const {
@@ -109,66 +245,15 @@ export const InviteMembers: React.FC = ({
{fields.map((field, index) => (
-
-
- (
- <>
-
- {errors.emails?.[index]?.email && (
-
- {errors.emails?.[index]?.email?.message}
-
- )}
- >
- )}
- />
-
-
- (
- {ROLE[value]}}
- onChange={onChange}
- width="w-full"
- input
- >
- {Object.entries(ROLE).map(([key, value]) => (
-
- {value}
-
- ))}
-
- )}
- />
-
- {fields.length > 1 && (
-
- )}
-
+
))}