import { Invite, User } from "@medusajs/medusa" import copy from "copy-to-clipboard" import { useAdminStore } from "medusa-react" import React, { useEffect, useMemo, useState } from "react" import useNotification from "../../hooks/use-notification" import Medusa from "../../services/api" import ClipboardCopyIcon from "../fundamentals/icons/clipboard-copy-icon" import EditIcon from "../fundamentals/icons/edit-icon" import RefreshIcon from "../fundamentals/icons/refresh-icon" import TrashIcon from "../fundamentals/icons/trash-icon" import StatusIndicator from "../fundamentals/status-indicator" import SidebarTeamMember from "../molecules/sidebar-team-member" import Table from "../molecules/table" import DeletePrompt from "../organisms/delete-prompt" import EditUser from "../organisms/edit-user-modal" import { useTranslation } from "react-i18next" import { getFullAdminPath } from "../../utils/get-admin-path" type UserListElement = { entity: any entityType: string tableElement: JSX.Element } type UserTableProps = { users: any[] invites: any[] triggerRefetch: () => void } const getInviteStatus = (invite: Invite) => { return new Date(invite.expires_at) < new Date() ? "expired" : "pending" } const UserTable: React.FC = ({ users, invites, triggerRefetch, }) => { const [elements, setElements] = useState([]) const [shownElements, setShownElements] = useState([]) const [selectedUser, setSelectedUser] = useState(null) const [deleteUser, setDeleteUser] = useState(false) const [selectedInvite, setSelectedInvite] = useState(null) const notification = useNotification() const { store, isLoading } = useAdminStore() const { t } = useTranslation() useEffect(() => { setElements([ ...users.map((user, i) => ({ entity: user, entityType: "user", tableElement: getUserTableRow(user, i), })), ...invites.map((invite, i) => ({ entity: invite, entityType: "invite", tableElement: getInviteTableRow(invite, i), })), ]) }, [users, invites]) useEffect(() => { setShownElements(elements) }, [elements]) const handleClose = () => { setDeleteUser(false) setSelectedUser(null) setSelectedInvite(null) } const getUserTableRow = (user: User, index: number) => { return ( setSelectedUser(user), icon: , }, { label: t("templates-remove-user", "Remove User"), variant: "danger", onClick: () => { setDeleteUser(true) setSelectedUser(user) }, icon: , }, ]} > {user.email} {user.role.charAt(0).toUpperCase()} {user.role.slice(1)} ) } const inviteLink = useMemo(() => { if (store?.invite_link_template) { return store.invite_link_template } const adminPath = getFullAdminPath() return `${adminPath}invite?token={invite_token}` }, [store]) const getInviteTableRow = (invite: Invite, index: number) => { return ( { Medusa.invites .resend(invite.id) .then(() => { notification( t("templates-success", "Success"), t( "templates-invitiation-link-has-been-resent", "Invitiation link has been resent" ), "success" ) }) .then(() => triggerRefetch()) }, icon: , }, { label: t("templates-copy-invite-link", "Copy invite link"), disabled: isLoading, onClick: () => { copy(inviteLink.replace("{invite_token}", invite.token)) notification( t("templates-success", "Success"), t( "templates-invite-link-copied-to-clipboard", "Invite link copied to clipboard" ), "success" ) }, icon: , }, { label: t("templates-remove-invitation", "Remove Invitation"), variant: "danger", onClick: () => { setSelectedInvite(invite) }, icon: , }, ]} > {invite.user_email} {new Date(invite?.expires_at) < new Date() ? ( ) : ( )} ) } const filteringOptions = [ { title: "Team permissions", options: [ { title: t("templates-all", "All"), count: elements.length, onClick: () => setShownElements(elements), }, { title: t("templates-member", "Member"), count: elements.filter( (e) => e.entityType === "user" && e.entity.role === "member" ).length, onClick: () => setShownElements( elements.filter( (e) => e.entityType === "user" && e.entity.role === "member" ) ), }, { title: t("templates-admin", "Admin"), count: elements.filter( (e) => e.entityType === "user" && e.entity.role === "admin" ).length, onClick: () => setShownElements( elements.filter( (e) => e.entityType === "user" && e.entity.role === "admin" ) ), }, { title: t("templates-no-team-permissions", "No team permissions"), count: elements.filter((e) => e.entityType === "invite").length, onClick: () => setShownElements(elements.filter((e) => e.entityType === "invite")), }, ], }, { title: t("templates-status", "Status"), options: [ { title: t("templates-all", "All"), count: elements.length, onClick: () => setShownElements(elements), }, { title: t("templates-active", "Active"), count: elements.filter((e) => e.entityType === "user").length, onClick: () => setShownElements(elements.filter((e) => e.entityType === "user")), }, { title: t("templates-pending", "Pending"), count: elements.filter( (e) => e.entityType === "invite" && getInviteStatus(e.entity) === "pending" ).length, onClick: () => setShownElements( elements.filter( (e) => e.entityType === "invite" && getInviteStatus(e.entity) === "pending" ) ), }, { title: t("templates-expired", "Expired"), count: elements.filter( (e) => e.entityType === "invite" && getInviteStatus(e.entity) === "expired" ).length, onClick: () => setShownElements( elements.filter( (e) => e.entityType === "invite" && getInviteStatus(e.entity) === "expired" ) ), }, ], }, ] const handleUserSearch = (term: string) => { setShownElements( elements.filter( (e) => e.entity?.first_name?.includes(term) || e.entity?.last_name?.includes(term) || e.entity?.email?.includes(term) || e.entity?.user_email?.includes(term) ) ) } return (
{t("templates-name", "Name")} {t("templates-email", "Email")} {t("templates-team-permissions", "Team permissions")} Status {shownElements.map((e) => e.tableElement)}
{selectedUser && (deleteUser ? ( Medusa.users.delete(selectedUser.id).then(() => { notification( t("templates-success", "Success"), t("templates-user-has-been-removed", "User has been removed"), "success" ) triggerRefetch() }) } handleClose={handleClose} /> ) : ( triggerRefetch()} /> ))} {selectedInvite && ( Medusa.invites.delete(selectedInvite.id).then(() => { notification( t("templates-success", "Success"), t( "templates-invitiation-has-been-removed", "Invitiation has been removed" ), "success" ) triggerRefetch() }) } handleClose={handleClose} /> )}
) } export default UserTable