mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-23 02:29:30 -05:00
team initial commit
This commit is contained in:
@@ -15,7 +15,7 @@ export const TabPassword = () => {
|
||||
const { resolver, defaults } = usePasswordForm();
|
||||
const { patch, loading } = usePatch<FormData, void>();
|
||||
|
||||
const { control, handleSubmit, reset, setError } = useForm<PasswordFormData>({
|
||||
const { control, handleSubmit, reset } = useForm<PasswordFormData>({
|
||||
resolver,
|
||||
defaultValues: defaults,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
import { Box } from "@mui/material";
|
||||
import { Stack } from "@mui/material";
|
||||
import { useTheme } from "@mui/material";
|
||||
import { useState, useMemo } from "react";
|
||||
import { HeaderTeamControls } from "./components/HeaderTeamControls";
|
||||
import { TeamTable } from "./components/TeamTable";
|
||||
import { useGet } from "@/Hooks/UseApi";
|
||||
import type { User, UserRole } from "@/Types/User";
|
||||
|
||||
export const TabTeam = () => {
|
||||
return <Box>{/* TODO: Implement TabTeam */}</Box>;
|
||||
const theme = useTheme();
|
||||
const [filter, setFilter] = useState<UserRole | "">("");
|
||||
|
||||
const { data: users } = useGet<User[]>("/auth/users");
|
||||
|
||||
const filteredUsers = useMemo(() => {
|
||||
if (!users) return [];
|
||||
if (!filter) return users;
|
||||
|
||||
return users.filter((u) => u.role.includes(filter));
|
||||
}, [users, filter]);
|
||||
|
||||
return (
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<HeaderTeamControls
|
||||
filter={filter}
|
||||
onFilterChange={setFilter}
|
||||
/>
|
||||
<TeamTable users={filteredUsers} />
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import Stack from "@mui/material/Stack";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { Button, Select } from "@/Components/v2/inputs";
|
||||
import { Icon } from "@/Components/v2/design-elements";
|
||||
import { UserPlus, Mail } from "lucide-react";
|
||||
|
||||
import { UserRoles } from "@/Types/User";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import type { UserRole } from "@/Types/User";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useIsAdmin, useIsSuperAdmin } from "@/Hooks/useIsAdmin";
|
||||
|
||||
interface HeaderTeamControlsProps {
|
||||
filter: UserRole | "";
|
||||
onFilterChange: (value: UserRole | "") => void;
|
||||
}
|
||||
|
||||
export const HeaderTeamControls = ({
|
||||
filter,
|
||||
onFilterChange,
|
||||
}: HeaderTeamControlsProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const isAdmin = useIsAdmin();
|
||||
const isSuperAdmin = useIsSuperAdmin();
|
||||
|
||||
const handleFilterChange = (event: { target: { value: unknown } }) => {
|
||||
onFilterChange(event.target.value as UserRole | "");
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="flex-end"
|
||||
gap={theme.spacing(4)}
|
||||
>
|
||||
<Select
|
||||
value={filter}
|
||||
onChange={handleFilterChange}
|
||||
placeholder={t("pages.account.team.filter.placeholder")}
|
||||
sx={{ minWidth: 150 }}
|
||||
>
|
||||
<MenuItem value="">{t("pages.account.team.filter.all")}</MenuItem>
|
||||
{UserRoles.map((role) => (
|
||||
<MenuItem
|
||||
key={role}
|
||||
value={role}
|
||||
>
|
||||
{t(`common.auth.roles.${role}`)}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<Icon icon={Mail} />}
|
||||
>
|
||||
{t("pages.account.team.inviteMember")}
|
||||
</Button>
|
||||
)}
|
||||
{isSuperAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
startIcon={<Icon icon={UserPlus} />}
|
||||
>
|
||||
{t("pages.account.team.addMember")}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
@@ -15,13 +15,6 @@ import { useGetInviteToken } from "../../../Hooks/inviteHooks.js";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useIsSuperAdmin } from "@/Hooks/useIsAdmin.js";
|
||||
import AddMemberMenu from "./AddMemberMenu/index.jsx";
|
||||
/**
|
||||
* TeamPanel component manages the organization and team members,
|
||||
* providing functionalities like renaming the organization, managing team members,
|
||||
* and inviting new members.
|
||||
*
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
|
||||
const TeamPanel = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Table } from "@/Components/v2/design-elements";
|
||||
import type { Header } from "@/Components/v2/design-elements/Table";
|
||||
import { useIsSuperAdmin } from "@/Hooks/useIsAdmin";
|
||||
import type { User } from "@/Types/User";
|
||||
|
||||
interface TeamTableProps {
|
||||
users: User[];
|
||||
}
|
||||
|
||||
export const TeamTable = ({ users }: TeamTableProps) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const isSuperAdmin = useIsSuperAdmin();
|
||||
|
||||
const headers: Header<User>[] = [
|
||||
{
|
||||
id: "name",
|
||||
content: t("common.table.headers.name"),
|
||||
render: (row) => <Typography>{`${row.firstName} ${row.lastName}`}</Typography>,
|
||||
},
|
||||
{
|
||||
id: "email",
|
||||
content: t("pages.account.team.table.headers.email"),
|
||||
render: (row) => <Typography>{row.email}</Typography>,
|
||||
},
|
||||
{
|
||||
id: "role",
|
||||
content: t("pages.account.team.table.headers.role"),
|
||||
render: (row) => (
|
||||
<Typography>
|
||||
{row.role.map((r) => t(`common.auth.roles.${r}`)).join(", ")}
|
||||
</Typography>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const handleRowClick = (row: User) => {
|
||||
if (isSuperAdmin) {
|
||||
navigate(`/account/team/${row.id}`);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Table
|
||||
headers={headers}
|
||||
data={users}
|
||||
onRowClick={isSuperAdmin ? handleRowClick : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -176,6 +176,14 @@
|
||||
"ClickUpload": "Click to upload",
|
||||
"close": "Close",
|
||||
"common": {
|
||||
"auth": {
|
||||
"roles": {
|
||||
"admin": "Admin",
|
||||
"demo": "Demo",
|
||||
"superadmin": "Super admin",
|
||||
"user": "User"
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"pageSpeedApiKey": {
|
||||
"content": "Warning: You haven't added a Google PageSpeed API key yet. Visit <settingsLink>Settings</settingsLink> to add one. Without it, the PageSpeed monitor won't function."
|
||||
@@ -549,6 +557,22 @@
|
||||
"title": "Delete account",
|
||||
"description": "This action is permanent and cannot be undone"
|
||||
}
|
||||
},
|
||||
"team": {
|
||||
"addMember": "Add member",
|
||||
"inviteMember": "Invite member",
|
||||
"filter": {
|
||||
"placeholder": "Filter by role",
|
||||
"all": "All roles",
|
||||
"admin": "Admin",
|
||||
"member": "Member"
|
||||
},
|
||||
"table": {
|
||||
"headers": {
|
||||
"email": "Email",
|
||||
"role": "Role"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth": {
|
||||
|
||||
Reference in New Issue
Block a user