Skip to content

Commit

Permalink
Merge pull request #855 from Promiseejiro/feat/settings-password-and-…
Browse files Browse the repository at this point in the history
…member-invite

Feat/settings password and member invite
  • Loading branch information
incredible-phoenix246 authored Aug 1, 2024
2 parents 39f9f27 + 2afeeee commit bfe967b
Show file tree
Hide file tree
Showing 9 changed files with 639 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar";
import { CardContent } from "~/components/ui/card";
import DeleteDropDown from "../deleteDropDown";
import RoleDropDown from "../roleDropDown";

interface MemberCardProperty {
name: string;
email: string;
image: string;
deleteHandle: () => void;
setRole: (role: string) => void;
}

const MemberCard = ({
name,
email,
image,
deleteHandle,
setRole,
}: MemberCardProperty) => {
return (
<div className="flex items-center justify-between border-b">
<div>
<CardContent className="m-0 px-0 py-4">
<div className="flex items-center space-x-4 rounded-md py-2">
<Avatar data-testid="avatar" className="h-10 w-10">
<AvatarImage src={image} />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
<div className="flex-1 space-y-1">
<p className="text-sm font-medium leading-none">{name}</p>
<p className="text-sm text-muted-foreground">{email}</p>
</div>
</div>
</CardContent>
</div>
<div>
<RoleDropDown
onChange={(data: string) => {
setRole(data);
}}
/>
</div>
<div>
<DeleteDropDown onDelete={deleteHandle} />
</div>
</div>
);
};

export default MemberCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"use client";

import React from "react";

import CustomButton from "~/components/common/common-button/common-button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogOverlay,
DialogTitle,
} from "~/components/ui/dialog";

interface ModalProperties {
show: boolean;
onClose: () => void;
// memberId?: string;
}

const DeleteSuccessModal: React.FC<ModalProperties> = ({
show,
onClose,
// memberId,
}) => {
return (
<Dialog open={show}>
<DialogOverlay
data-testid="overlay"
className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50"
/>
<DialogContent className="mx-10 rounded-md bg-white p-6 shadow-md">
<DialogTitle className="text-lg font-semibold">
Delete Member
</DialogTitle>
<DialogDescription className="text-sm font-normal text-muted-foreground">
Are you sure you want to delete Chad Bosewick ? All of your data will
be permanently removed. This action cannot be undone. All
</DialogDescription>
<div className="flex justify-end gap-4">
<div onClick={onClose}>
<CustomButton variant="outline">Cancel</CustomButton>
</div>
<div>
<CustomButton variant="destructive">Delete</CustomButton>
</div>
</div>
</DialogContent>
</Dialog>
);
};

export default DeleteSuccessModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"use client";

import { Link } from "lucide-react";
import React from "react";

import CustomButton from "~/components/common/common-button/common-button";
import CustomInput from "~/components/common/input/input";
import { Avatar, AvatarFallback } from "~/components/ui/avatar";
import {
Dialog,
DialogContent,
DialogOverlay,
DialogTitle,
} from "~/components/ui/dialog";
import SelectInput from "../SelectInput";

interface ModalProperties {
show: boolean;
onClose: () => void;
}

const InviteModal: React.FC<ModalProperties> = ({ show, onClose }) => {
return (
<Dialog open={show} onOpenChange={onClose}>
<DialogOverlay
data-testid="overlay"
className="fixed inset-0 z-50 flex items-center justify-center bg-gray-100 bg-opacity-50"
/>
<DialogContent className="max-w-[400px] rounded-md bg-white p-0 py-2 shadow-md">
<div className="flex items-center gap-4 border-b p-4">
<Avatar data-testid="avatar" className="h-10 w-10">
<AvatarFallback>CN</AvatarFallback>
</Avatar>{" "}
<DialogTitle className="text-[14px] font-normal">
Invite to your Organization
</DialogTitle>
</div>
<div className="px-4">
<CustomInput
label="Email"
variant="border"
placeholder="Input email"
/>
<SelectInput
label="Add to Organization (Optional)"
value="hello world"
onSelect={() => {}}
options={["Github", "Youtube"]}
placeHolder="Select Organization"
/>
<div className="flex items-center justify-end gap-10 py-6">
<CustomButton
variant="ghost"
icon={<Link color="hsl(25 95% 53%)" />}
isLeftIconVisible={true}
>
Invite with link
</CustomButton>
<CustomButton variant="primary">Send invites</CustomButton>
</div>
</div>
</DialogContent>
</Dialog>
);
};

export default InviteModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { SearchIcon } from "lucide-react";

interface SearcInputProperties {
onSearch: (data: string) => void;
placeholder: string;
}
const SearchInput = ({ onSearch, placeholder }: SearcInputProperties) => {
return (
<div className="flex h-10 items-center justify-between gap-2 rounded-[6px] border border-border bg-white px-3 text-sm font-normal placeholder:text-sm lg:max-w-[324px]">
<SearchIcon
data-testid="search"
className="h-4 w-4 text-neutral-dark-2"
/>
<input
className="placeholder:text-gray h-full w-full border-none text-neutral-dark-2 outline-none ring-0"
placeholder={placeholder}
data-testid="input"
onChange={() => {
onSearch("");
}}
/>
</div>
);
};

export default SearchInput;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ChevronDown } from "lucide-react";
import { useState } from "react";

interface SelectInputProperties {
placeHolder: string;
onSelect: (data: string) => void;
label: string;
value: string;
options: string[];
}
const SelectInput = ({
placeHolder,
onSelect,
label,
value,
options,
}: SelectInputProperties) => {
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false);
return (
<div className="relative mt-4">
<ChevronDown className="absolute right-4 top-[38px]" />
<label className="mb-2 flex border-0 text-sm font-medium text-foreground">
{label}
</label>
<input
className="w-full cursor-pointer rounded-md border border-border px-3 py-2 placeholder:text-sm placeholder:text-slate-400"
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
value={value}
placeholder={placeHolder}
/>

{isDropdownOpen && (
<div className="absolute left-0 top-full z-10 mt-1 w-full rounded-md border border-border bg-white">
{options.map((option) => (
<div
key={option}
className="cursor-pointer px-3 py-2 hover:bg-gray-100"
onClick={() => onSelect(option)}
>
{option}
</div>
))}
</div>
)}
</div>
);
};

export default SelectInput;
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@radix-ui/react-dropdown-menu";
import { Ellipsis } from "lucide-react";
import { useEffect, useRef, useState } from "react";

interface DeleteDropDownProperties {
onDelete: () => void;
}

const DeleteDropDown = ({ onDelete }: DeleteDropDownProperties) => {
const containerReference = useRef<HTMLDivElement>(null);
const [open, setOpen] = useState<boolean>(false);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
containerReference.current &&
!containerReference.current.contains(event.target as Node)
) {
setOpen(false);
}
};

if (open) {
document.addEventListener("click", handleClickOutside);
} else {
document.removeEventListener("click", handleClickOutside);
}

return () => {
document.removeEventListener("click", handleClickOutside);
};
}, [open]);

const options: string[] = ["Delete Member"];

return (
<div ref={containerReference}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<span
className="relative flex cursor-pointer items-center justify-center gap-1 rounded-[6px] bg-white px-5 text-sm font-normal placeholder:text-sm"
onClick={() => {
setOpen((previous) => !previous);
}}
>
<span>
<Ellipsis />
</span>
</span>
</DropdownMenuTrigger>
{open && (
<DropdownMenuContent className="translate-x-[-100px] rounded bg-white shadow">
<DropdownMenuSeparator />
{options.map((option, index) => (
<div key={index} onClick={onDelete}>
<DropdownMenuItem
onClick={onDelete}
className="right-0 cursor-pointer px-8 py-[6px] text-[14px] hover:border-none hover:bg-slate-50 hover:outline-none"
>
{option}
</DropdownMenuItem>
</div>
))}
</DropdownMenuContent>
)}
</DropdownMenu>
</div>
);
};

export default DeleteDropDown;
Loading

0 comments on commit bfe967b

Please sign in to comment.