Skip to content

Commit

Permalink
Merge pull request #406 from melpsh/38-Dec-31-inviting-a-new-user
Browse files Browse the repository at this point in the history
added a modal for sending invitation
  • Loading branch information
MuhammadKhalilzadeh authored Jan 6, 2025
2 parents 31ac9c7 + 84ca7f8 commit f2a4cb4
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 2 deletions.
158 changes: 158 additions & 0 deletions Clients/src/presentation/components/Modals/InviteUser/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/**
* A modal component that displays a form for inviting a user.
*
* @component
* @param {InviteUserModalProps} props - The properties for the InviteUserModal component.
* @param {boolean} props.isOpen - A boolean indicating whether the modal is open.
* @param {function} props.setIsOpen - A function to set the modal's open state.
* @param {function} props.onSendInvite - A function to handle sending the invite.
*
* @returns {JSX.Element} The rendered modal component.
*
* @example
* <InviteUserModal isOpen={isOpen} setIsOpen={setIsOpen} onSendInvite={handleSendInvite} />
*/

import {
Button,
MenuItem,
Modal,
Stack,
Typography,
useTheme,
} from "@mui/material";
import React, { useState } from "react";
import Field from "../../Inputs/Field";
import Select from "../../Inputs/Select";

interface InviteUserModalProps {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
onSendInvite: (email: string, role: string) => void;
}

const InviteUserModal: React.FC<InviteUserModalProps> = ({
isOpen,
setIsOpen,
onSendInvite,
}) => {
const theme = useTheme();

const [email, setEmail] = useState<string>("");
const [role, setRole] = useState<string>("");

const handleSendInvite = () => {
onSendInvite(email, role);
setIsOpen(false);
};

return (
<Modal open={isOpen} onClose={() => setIsOpen(false)}>
<Stack
gap={theme.spacing(2)}
color={theme.palette.text.secondary}
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 450,
bgcolor: theme.palette.background.paper,
border: 1,
borderColor: theme.palette.border.dark,
borderRadius: theme.shape.borderRadius,
boxShadow: 24,
p: theme.spacing(4),
padding: theme.spacing(12),
"&:focus": {
outline: "none",
},
}}
>
<Typography id="modal-invite-user" fontSize={16} fontWeight={600}>
Invite new team member
</Typography>
<Typography
id="invite-user-instructions"
fontSize={13}
textAlign={"justify"}
paddingBottom={theme.spacing(8)}
>
When you add a new team member, they will get access to all monitors.
</Typography>
<Field
placeholder="Email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
isRequired
sx={{
marginBottom: theme.spacing(4),
}}
/>
<Select
id="role-select"
value={role}
onChange={(e) => setRole(e.target.value as string)}
items={[
{ _id: "administrator", name: "Administrator" },
{ _id: "reviewer", name: "Reviewer" },
{ _id: "editor", name: "Editor" },
]}
sx={{ mt: theme.spacing(2) }}
/>
<Stack
direction="row"
gap={theme.spacing(4)}
mt={theme.spacing(4)}
justifyContent="flex-end"
paddingBottom={theme.spacing(4)}
>
<Button
disableRipple
disableFocusRipple
disableTouchRipple
variant="text"
color="inherit"
onClick={() => setIsOpen(false)}
sx={{
width: 100,
textTransform: "capitalize",
fontSize: 13,
borderRadius: "4px",
"&:hover": {
boxShadow: "none",
backgroundColor: "transparent",
},
}}
>
Cancel
</Button>
<Button
disableRipple
disableFocusRipple
disableTouchRipple
variant="contained"
color="primary"
disabled={!email || !role}
sx={{
width: 140,
textTransform: "capitalize",
fontSize: 13,
boxShadow: "none",
borderRadius: "4px",
"&:hover": {
boxShadow: "none",
},
}}
onClick={handleSendInvite}
>
Send Invite
</Button>
</Stack>
</Stack>
</Modal>
);
};

export default InviteUserModal;
21 changes: 19 additions & 2 deletions Clients/src/presentation/pages/SettingsPage/Team/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Field from "../../../components/Inputs/Field";
import { ReactComponent as SelectorVertical } from "../../../assets/icons/selector-vertical.svg";
import TablePaginationActions from "../../../components/TablePagination";
import { VerifyWiseContext } from "../../../../application/contexts/VerifyWise.context";
import InviteUserModal from "../../../components/Modals/InviteUser";

// Enum for roles
enum Role {
Expand Down Expand Up @@ -77,8 +78,9 @@ const TeamManagement: React.FC = (): JSX.Element => {
]);

const [page, setPage] = useState(0); // Current page
const { dashboardValues, setDashboardValues } = useContext(VerifyWiseContext);
const { dashboardValues} = useContext(VerifyWiseContext);
const [rowsPerPage, setRowsPerPage] = useState(5); // Rows per page
const [inviteUserModalOpen, setInviteUserModalOpen] = useState(false);

// Handle saving organization name
const handleSaveOrgName = useCallback(() => {
Expand Down Expand Up @@ -143,6 +145,11 @@ const TeamManagement: React.FC = (): JSX.Element => {
// return filteredMembers.slice(startIndex, startIndex + rowsPerPage);
// }, [filteredMembers, page, rowsPerPage]);

const inviteTeamMember = () => {
console.log("Inviting team member");
setInviteUserModalOpen(true);
};

return (
<Stack sx={{ pt: theme.spacing(10) }}>
<Box sx={{ mb: 4 }}>
Expand Down Expand Up @@ -237,7 +244,7 @@ const TeamManagement: React.FC = (): JSX.Element => {
</Box>

<Box sx={{ mt: 10 }}>
<Button variant="contained" disableRipple>
<Button variant="contained" disableRipple onClick={() => inviteTeamMember()}>
Invite team member
</Button>
</Box>
Expand Down Expand Up @@ -353,6 +360,16 @@ const TeamManagement: React.FC = (): JSX.Element => {
</Box>
</Stack>
</Box>
{inviteUserModalOpen && (
<InviteUserModal
isOpen={inviteUserModalOpen}
setIsOpen={setInviteUserModalOpen}
onSendInvite={(data) => {
console.log('Invite sent:', data);
setInviteUserModalOpen(false);
}}
/>
)}
</Stack>
);
};
Expand Down

0 comments on commit f2a4cb4

Please sign in to comment.