feat: add brain management people page

This commit is contained in:
mamadoudicko 2023-07-24 17:14:37 +02:00
parent 37f904122c
commit cff94e3249
17 changed files with 144 additions and 30 deletions

View File

@ -1,14 +1,18 @@
import { Content, List, Root } from "@radix-ui/react-tabs";
import { BrainTabTrigger } from "./components";
import { BrainTabTrigger, PeopleTab } from "./components";
import { useBrainManagementTabs } from "./hooks/useBrainManagementTabs";
export const BrainManagementTabs = (): JSX.Element => {
const { selectedTab, setSelectedTab } = useBrainManagementTabs();
const { selectedTab, setSelectedTab, brainId } = useBrainManagementTabs();
if (brainId === undefined) {
return <div />;
}
return (
<Root
className="shadow-md min-h-[50%] dark:shadow-primary/25 hover:shadow-xl transition-shadow rounded-xl overflow-hidden bg-white dark:bg-black border border-black/10 dark:border-white/25 p-4"
className="shadow-md min-h-[50%] dark:shadow-primary/25 hover:shadow-xl transition-shadow rounded-xl overflow-hidden bg-white dark:bg-black border border-black/10 dark:border-white/25 p-4 pt-10"
defaultValue="settings"
>
<List className="flex justify-between" aria-label="Manage your brain">
@ -31,9 +35,15 @@ export const BrainManagementTabs = (): JSX.Element => {
onChange={setSelectedTab}
/>
</List>
<Content value="settings">
<p>coming soon</p>
</Content>
<div className="p-20 pt-5">
<Content value="settings">
<p>coming soon</p>
</Content>
<Content value="people">
<PeopleTab brainId={brainId} />
</Content>
</div>
</Root>
);
};

View File

@ -0,0 +1,93 @@
/* eslint-disable max-lines */
"use client";
import { UUID } from "crypto";
import { ImUserPlus } from "react-icons/im";
import { MdContentPaste, MdLink } from "react-icons/md";
import { BrainUsers } from "@/lib/components/BrainUsers/BrainUsers";
import { UserToInvite } from "@/lib/components/UserToInvite";
import Button from "@/lib/components/ui/Button";
import { useShareBrain } from "@/lib/hooks/useShareBrain";
type ShareBrainModalProps = {
brainId: UUID;
};
export const PeopleTab = ({ brainId }: ShareBrainModalProps): JSX.Element => {
const {
roleAssignations,
handleCopyInvitationLink,
updateRoleAssignation,
removeRoleAssignation,
inviteUsers,
addNewRoleAssignationRole,
sendingInvitation,
canAddNewRow,
} = useShareBrain(brainId);
return (
<>
<form
onSubmit={(event) => {
event.preventDefault();
void inviteUsers();
}}
>
<div>
<div className="flex flex-row align-center my-5">
<div
onClick={() => void handleCopyInvitationLink()}
className="cursor-pointer flex bg-gray-100 p-0 flex-1 flex-row border-gray-200 dark:border-gray-700 justify-space-between align-center rounded-md border-2"
>
<div className="px-8 py-3 text-sm disabled:opacity-80 text-center font-medium rounded-md focus:ring ring-primary/10 outline-none flex items-center justify-center gap-2 transition-opacity bg-transparent border-2 border-gray border-l-0 border-t-0 border-b-0 rounded-l-none">
<MdLink size="20" color="gray" />
</div>
<div className="flex flex-row flex-1 items-center justify-center">
<span className="color-gray">
Click to copy link to share your brain
</span>
</div>
<Button type="button">
<MdContentPaste />
</Button>
</div>
</div>
<div className="bg-gray-100 h-0.5 my-10 border-gray-200 dark:border-gray-700" />
<p className="text-lg font-bold">Add new users</p>
{roleAssignations.map((roleAssignation, index) => (
<UserToInvite
key={roleAssignation.id}
onChange={updateRoleAssignation(index)}
removeCurrentInvitation={removeRoleAssignation(index)}
roleAssignation={roleAssignation}
/>
))}
<Button
className="my-5"
onClick={addNewRoleAssignationRole}
disabled={sendingInvitation || !canAddNewRow}
data-testid="add-new-row-role-button"
>
<ImUserPlus />
</Button>
</div>
<div className="mb-3 flex flex-row justify-end">
<Button
isLoading={sendingInvitation}
disabled={roleAssignations.length === 0}
type="submit"
>
Share
</Button>
</div>
</form>
<div className="bg-gray-100 h-0.5 my-10 border-gray-200 dark:border-gray-700" />
<p className="text-lg font-bold">Users with access</p>
<BrainUsers brainId={brainId} />
</>
);
};

View File

@ -0,0 +1 @@
export * from "./PeopleTab";

View File

@ -1 +1,2 @@
export * from "./BrainTabTrigger";
export * from "./PeopleTab";

View File

@ -1,3 +1,5 @@
import { UUID } from "crypto";
import { useParams } from "next/navigation";
import { useState } from "react";
import { BrainManagementTab } from "../types";
@ -7,8 +9,13 @@ export const useBrainManagementTabs = () => {
const [selectedTab, setSelectedTab] =
useState<BrainManagementTab>("settings");
const params = useParams();
const brainId = params?.brainId as UUID | undefined;
return {
selectedTab,
setSelectedTab,
brainId,
};
};

View File

@ -1,3 +1,4 @@
export * from "./BrainListItem";
export * from "./BrainManagementTabs";
export * from "./BrainSearchBar";
export * from "./BrainsList";

View File

@ -3,7 +3,7 @@
import { UUID } from "crypto";
import { useParams } from "next/navigation";
import { BrainManagementTabs } from "./components/BrainManagementTabs/BrainManagementTabs";
import { BrainManagementTabs } from "./components";
const BrainsManagement = (): JSX.Element => {
const params = useParams();
@ -21,7 +21,7 @@ const BrainsManagement = (): JSX.Element => {
}
return (
<main className="flex flex-col w-full pt-20 px-20">
<main className="flex flex-col w-full pt-20 px-20 mb-10">
<BrainManagementTabs />
</main>
);

View File

@ -6,8 +6,8 @@ import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainConte
import { RemoveAccessIcon } from "./components/RemoveAccessIcon";
import { useBrainUser } from "./hooks/useBrainUser";
import { BrainRoleType } from "../../../../../../types";
import { availableRoles } from "../../../../types";
import { availableRoles } from "../../../NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/components/ShareBrain/types";
import { BrainRoleType } from "../../../NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/types";
type BrainUserProps = {
email: string;

View File

@ -5,7 +5,7 @@ import { useBrainApi } from "@/lib/api/brain/useBrainApi";
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
import { useToast } from "@/lib/hooks";
import { BrainRoleType } from "../../../../../../../types";
import { BrainRoleType } from "../../../../NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/types";
type UseBrainUserProps = {
fetchBrainUsers: () => Promise<void>;

View File

@ -5,12 +5,11 @@ import { UUID } from "crypto";
import { ImUserPlus } from "react-icons/im";
import { MdContentPaste, MdShare } from "react-icons/md";
import { BrainUsers } from "@/lib/components/BrainUsers/BrainUsers";
import { UserToInvite } from "@/lib/components/UserToInvite";
import Button from "@/lib/components/ui/Button";
import { Modal } from "@/lib/components/ui/Modal";
import { BrainUsers } from "./components/BrainUsers/BrainUsers";
import { UserToInvite } from "./components/UserToInvite";
import { useShareBrain } from "./hooks/useShareBrain";
import { useShareBrain } from "@/lib/hooks/useShareBrain";
type ShareBrainModalProps = {
brainId: UUID;
@ -32,13 +31,9 @@ export const ShareBrain = ({
sendingInvitation,
setIsShareModalOpen,
isShareModalOpen,
canAddNewRow,
} = useShareBrain(brainId);
const canAddNewRow =
roleAssignations.length === 0 ||
roleAssignations.filter((invitingUser) => invitingUser.email === "")
.length === 0;
return (
<Modal
Trigger={

View File

@ -1,2 +0,0 @@
export * from "./BrainUsers/components/BrainUser/BrainUser";
export * from "./UserToInvite";

View File

@ -5,8 +5,11 @@ import Field from "@/lib/components/ui/Field";
import { Select } from "@/lib/components/ui/Select";
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
import { BrainRoleAssignation, BrainRoleType } from "../../../types";
import { userRoleToAssignableRoles } from "../types";
import { userRoleToAssignableRoles } from "./NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/components/ShareBrain/types";
import {
BrainRoleAssignation,
BrainRoleType,
} from "./NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/types";
type UserToInviteProps = {
onChange: (newRole: BrainRoleAssignation) => void;
@ -25,10 +28,6 @@ export const UserToInvite = ({
const [email, setEmail] = useState(roleAssignation.email);
const { currentBrain } = useBrainContext();
if (currentBrain === undefined) {
throw new Error("Brain is undefined");
}
useEffect(() => {
onChange({
...roleAssignation,
@ -37,6 +36,10 @@ export const UserToInvite = ({
});
}, [email, selectedRole]);
if (currentBrain === undefined) {
return <div />;
}
return (
<div
data-testid="assignation-row"

View File

@ -6,8 +6,8 @@ import { Subscription } from "@/lib/api/brain/brain";
import { useBrainApi } from "@/lib/api/brain/useBrainApi";
import { useToast } from "@/lib/hooks";
import { BrainRoleAssignation } from "../../../types";
import { generateBrainAssignation } from "../utils/generateBrainAssignation";
import { generateBrainAssignation } from "../components/NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/components/ShareBrain/utils/generateBrainAssignation";
import { BrainRoleAssignation } from "../components/NavBar/components/NavItems/components/BrainsDropDown/components/BrainActions/types";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const useShareBrain = (brainId: string) => {
@ -102,6 +102,10 @@ export const useShareBrain = (brainId: string) => {
const addNewRoleAssignationRole = () => {
setRoleAssignation([...roleAssignations, generateBrainAssignation()]);
};
const canAddNewRow =
roleAssignations.length === 0 ||
roleAssignations.filter((invitingUser) => invitingUser.email === "")
.length === 0;
return {
roleAssignations,
@ -114,5 +118,6 @@ export const useShareBrain = (brainId: string) => {
sendingInvitation,
setIsShareModalOpen,
isShareModalOpen,
canAddNewRow,
};
};