mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-14 10:34:06 +02:00
Fix Teams and MCP settings pages (#6605)
# Description of Changes Remove the Pro guards from the Team settings page and also fix the styling of the MCP settings screen (the code sections were black text on black background in light mode)
This commit is contained in:
@@ -2761,7 +2761,6 @@ copy = "Copy"
|
|||||||
done = "Done"
|
done = "Done"
|
||||||
error = "Error"
|
error = "Error"
|
||||||
expand = "Expand"
|
expand = "Expand"
|
||||||
learnMore = "Learn more"
|
|
||||||
loading = "Loading..."
|
loading = "Loading..."
|
||||||
next = "Next"
|
next = "Next"
|
||||||
operation = "this operation"
|
operation = "this operation"
|
||||||
@@ -7503,28 +7502,6 @@ removeError = "Failed to remove member"
|
|||||||
renameError = "Failed to rename team"
|
renameError = "Failed to rename team"
|
||||||
renameSuccess = "Team renamed successfully"
|
renameSuccess = "Team renamed successfully"
|
||||||
|
|
||||||
[team.features]
|
|
||||||
badge = "Team Features"
|
|
||||||
subtitle = "Collaborate with your team"
|
|
||||||
title = "Team Collaboration"
|
|
||||||
viewPlans = "View Plans"
|
|
||||||
|
|
||||||
[team.features.billing]
|
|
||||||
description = "Manage billing and subscriptions"
|
|
||||||
title = "Billing Management"
|
|
||||||
|
|
||||||
[team.features.credits]
|
|
||||||
description = "Shared credit pool for all members"
|
|
||||||
title = "Shared Credits"
|
|
||||||
|
|
||||||
[team.features.dashboard]
|
|
||||||
description = "View team activity and usage"
|
|
||||||
title = "Team Dashboard"
|
|
||||||
|
|
||||||
[team.features.invite]
|
|
||||||
description = "Add members to your team"
|
|
||||||
title = "Invite Members"
|
|
||||||
|
|
||||||
[team.invitationBanner]
|
[team.invitationBanner]
|
||||||
acceptButton = "Accept"
|
acceptButton = "Accept"
|
||||||
message = "has invited you to join"
|
message = "has invited you to join"
|
||||||
@@ -7546,11 +7523,6 @@ remove = "Remove"
|
|||||||
roleColumn = "Role"
|
roleColumn = "Role"
|
||||||
title = "Team Members"
|
title = "Team Members"
|
||||||
|
|
||||||
[team.upgrade]
|
|
||||||
button = "Upgrade to Team"
|
|
||||||
description = "Unlock team collaboration features"
|
|
||||||
title = "Upgrade to Team Plan"
|
|
||||||
|
|
||||||
[textAlign]
|
[textAlign]
|
||||||
center = "Center"
|
center = "Center"
|
||||||
left = "Left"
|
left = "Left"
|
||||||
|
|||||||
@@ -150,6 +150,16 @@ export const mantineTheme = createTheme({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Code: {
|
||||||
|
styles: {
|
||||||
|
root: {
|
||||||
|
backgroundColor: "var(--color-gray-100)",
|
||||||
|
color: "var(--text-primary)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
Textarea: {
|
Textarea: {
|
||||||
styles: (_theme: MantineTheme) => ({
|
styles: (_theme: MantineTheme) => ({
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
+2
-169
@@ -10,15 +10,9 @@ import {
|
|||||||
Badge,
|
Badge,
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Menu,
|
Menu,
|
||||||
List,
|
|
||||||
ThemeIcon,
|
|
||||||
Modal,
|
|
||||||
CloseButton,
|
|
||||||
Anchor,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useSaaSTeam } from "@app/contexts/SaaSTeamContext";
|
import { useSaaSTeam } from "@app/contexts/SaaSTeamContext";
|
||||||
import { useSaaSBilling } from "@app/contexts/SaasBillingContext";
|
|
||||||
import LocalIcon from "@app/components/shared/LocalIcon";
|
import LocalIcon from "@app/components/shared/LocalIcon";
|
||||||
import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex";
|
import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex";
|
||||||
import apiClient from "@app/services/apiClient";
|
import apiClient from "@app/services/apiClient";
|
||||||
@@ -43,15 +37,10 @@ export function SaaSTeamsSection() {
|
|||||||
refreshTeams,
|
refreshTeams,
|
||||||
} = useSaaSTeam();
|
} = useSaaSTeam();
|
||||||
|
|
||||||
// Check Pro status via billing context
|
|
||||||
const { tier } = useSaaSBilling();
|
|
||||||
const isPro = tier !== "free";
|
|
||||||
|
|
||||||
const [inviteEmail, setInviteEmail] = useState("");
|
const [inviteEmail, setInviteEmail] = useState("");
|
||||||
const [inviting, setInviting] = useState(false);
|
const [inviting, setInviting] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [success, setSuccess] = useState<string | null>(null);
|
const [success, setSuccess] = useState<string | null>(null);
|
||||||
const [featuresModalOpened, setFeaturesModalOpened] = useState(false);
|
|
||||||
|
|
||||||
// Team rename state
|
// Team rename state
|
||||||
const [isEditingName, setIsEditingName] = useState(false);
|
const [isEditingName, setIsEditingName] = useState(false);
|
||||||
@@ -71,12 +60,6 @@ export function SaaSTeamsSection() {
|
|||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, []); // Only run on mount/unmount
|
}, []); // Only run on mount/unmount
|
||||||
|
|
||||||
const navigateToPlan = () => {
|
|
||||||
window.dispatchEvent(
|
|
||||||
new CustomEvent("appConfig:navigate", { detail: { key: "planBilling" } }),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInvite = async (e: React.FormEvent) => {
|
const handleInvite = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!inviteEmail.trim()) return;
|
if (!inviteEmail.trim()) return;
|
||||||
@@ -321,156 +304,6 @@ export function SaaSTeamsSection() {
|
|||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Upgrade Banner for Free Users */}
|
|
||||||
{isPersonalTeam && !isPro && (
|
|
||||||
<Alert
|
|
||||||
color="blue"
|
|
||||||
icon={<LocalIcon icon="info" width={16} height={16} />}
|
|
||||||
>
|
|
||||||
<Group justify="space-between" align="center">
|
|
||||||
<div>
|
|
||||||
<Text fw={500} size="sm">
|
|
||||||
{t(
|
|
||||||
"team.upgrade.title",
|
|
||||||
"Upgrade to Pro to unlock team features",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed" mt={2}>
|
|
||||||
{t(
|
|
||||||
"team.upgrade.description",
|
|
||||||
"Invite members, share credits, and more.",
|
|
||||||
)}{" "}
|
|
||||||
<Anchor
|
|
||||||
size="xs"
|
|
||||||
onClick={() => setFeaturesModalOpened(true)}
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
|
||||||
{t("common.learnMore", "Learn more")}
|
|
||||||
</Anchor>
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<Button size="sm" variant="light" onClick={navigateToPlan}>
|
|
||||||
{t("team.upgrade.button", "Upgrade to Pro")}
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Team Features Modal */}
|
|
||||||
<Modal
|
|
||||||
opened={featuresModalOpened}
|
|
||||||
onClose={() => setFeaturesModalOpened(false)}
|
|
||||||
size="md"
|
|
||||||
centered
|
|
||||||
padding="xl"
|
|
||||||
withCloseButton={false}
|
|
||||||
zIndex={Z_INDEX_OVER_CONFIG_MODAL}
|
|
||||||
>
|
|
||||||
<div style={{ position: "relative" }}>
|
|
||||||
<CloseButton
|
|
||||||
onClick={() => setFeaturesModalOpened(false)}
|
|
||||||
size="lg"
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top: -8,
|
|
||||||
right: -8,
|
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Stack gap="lg" pt="md">
|
|
||||||
{/* Header */}
|
|
||||||
<Stack gap="md" align="center">
|
|
||||||
<Badge size="lg" color="violet" variant="filled">
|
|
||||||
{t("team.features.badge", "PRO FEATURE")}
|
|
||||||
</Badge>
|
|
||||||
<Text size="xl" fw={700} ta="center">
|
|
||||||
{t("team.features.title", "Team Collaboration")}
|
|
||||||
</Text>
|
|
||||||
<Text size="sm" c="dimmed" ta="center">
|
|
||||||
{t(
|
|
||||||
"team.features.subtitle",
|
|
||||||
"Upgrade to Pro and unlock powerful team features",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{/* Features List */}
|
|
||||||
<List
|
|
||||||
spacing="md"
|
|
||||||
size="sm"
|
|
||||||
icon={
|
|
||||||
<ThemeIcon color="violet" size={24} radius="xl" variant="light">
|
|
||||||
<LocalIcon icon="check" width={14} height={14} />
|
|
||||||
</ThemeIcon>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t("team.features.invite.title", "Invite team members")}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.invite.description",
|
|
||||||
"Add unlimited users with additional seat purchases",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t(
|
|
||||||
"team.features.credits.title",
|
|
||||||
"Share credits across your team",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.credits.description",
|
|
||||||
"Pool resources for collaborative work",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t(
|
|
||||||
"team.features.dashboard.title",
|
|
||||||
"Team management dashboard",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.dashboard.description",
|
|
||||||
"Control permissions, monitor usage, and manage members",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t("team.features.billing.title", "Centralized billing")}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.billing.description",
|
|
||||||
"One invoice for all team seats and usage",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
</List>
|
|
||||||
|
|
||||||
{/* CTA Button */}
|
|
||||||
<Button
|
|
||||||
size="md"
|
|
||||||
fullWidth
|
|
||||||
onClick={() => {
|
|
||||||
setFeaturesModalOpened(false);
|
|
||||||
navigateToPlan();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("team.features.viewPlans", "View Pro Plans")}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
{/* Error/Success Messages */}
|
{/* Error/Success Messages */}
|
||||||
{error && (
|
{error && (
|
||||||
<Alert color="red" onClose={() => setError(null)} withCloseButton>
|
<Alert color="red" onClose={() => setError(null)} withCloseButton>
|
||||||
@@ -484,8 +317,8 @@ export function SaaSTeamsSection() {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Invite Members (Pro Users) */}
|
{/* Invite Members */}
|
||||||
{isTeamLeader && isPro && (
|
{isTeamLeader && (
|
||||||
<div>
|
<div>
|
||||||
<Text fw={600} size="md" mb="sm">
|
<Text fw={600} size="md" mb="sm">
|
||||||
{t("team.invite.title", "Invite Team Member")}
|
{t("team.invite.title", "Invite Team Member")}
|
||||||
|
|||||||
@@ -10,15 +10,9 @@ import {
|
|||||||
Badge,
|
Badge,
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Menu,
|
Menu,
|
||||||
List,
|
|
||||||
ThemeIcon,
|
|
||||||
Modal,
|
|
||||||
CloseButton,
|
|
||||||
Anchor,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useSaaSTeam } from "@app/contexts/SaaSTeamContext";
|
import { useSaaSTeam } from "@app/contexts/SaaSTeamContext";
|
||||||
import { useAuth } from "@app/auth/UseSession";
|
|
||||||
import LocalIcon from "@app/components/shared/LocalIcon";
|
import LocalIcon from "@app/components/shared/LocalIcon";
|
||||||
import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex";
|
import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex";
|
||||||
import apiClient from "@app/services/apiClient";
|
import apiClient from "@app/services/apiClient";
|
||||||
@@ -38,13 +32,10 @@ const TeamSection: React.FC = () => {
|
|||||||
refreshTeams,
|
refreshTeams,
|
||||||
} = useSaaSTeam();
|
} = useSaaSTeam();
|
||||||
|
|
||||||
const { isPro } = useAuth();
|
|
||||||
|
|
||||||
const [inviteEmail, setInviteEmail] = useState("");
|
const [inviteEmail, setInviteEmail] = useState("");
|
||||||
const [inviting, setInviting] = useState(false);
|
const [inviting, setInviting] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [success, setSuccess] = useState<string | null>(null);
|
const [success, setSuccess] = useState<string | null>(null);
|
||||||
const [featuresModalOpened, setFeaturesModalOpened] = useState(false);
|
|
||||||
|
|
||||||
// Team rename state
|
// Team rename state
|
||||||
const [isEditingName, setIsEditingName] = useState(false);
|
const [isEditingName, setIsEditingName] = useState(false);
|
||||||
@@ -64,12 +55,6 @@ const TeamSection: React.FC = () => {
|
|||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, []); // Only run on mount/unmount
|
}, []); // Only run on mount/unmount
|
||||||
|
|
||||||
const navigateToPlan = () => {
|
|
||||||
window.dispatchEvent(
|
|
||||||
new CustomEvent("appConfig:navigate", { detail: { key: "plan" } }),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInvite = async (e: React.FormEvent) => {
|
const handleInvite = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!inviteEmail.trim()) return;
|
if (!inviteEmail.trim()) return;
|
||||||
@@ -314,156 +299,6 @@ const TeamSection: React.FC = () => {
|
|||||||
</Group>
|
</Group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Upgrade Banner for Free Users */}
|
|
||||||
{isPersonalTeam && !isPro && (
|
|
||||||
<Alert
|
|
||||||
color="blue"
|
|
||||||
icon={<LocalIcon icon="info" width={16} height={16} />}
|
|
||||||
>
|
|
||||||
<Group justify="space-between" align="center">
|
|
||||||
<div>
|
|
||||||
<Text fw={500} size="sm">
|
|
||||||
{t(
|
|
||||||
"team.upgrade.title",
|
|
||||||
"Upgrade to Pro to unlock team features",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed" mt={2}>
|
|
||||||
{t(
|
|
||||||
"team.upgrade.description",
|
|
||||||
"Invite members, share credits, and more.",
|
|
||||||
)}{" "}
|
|
||||||
<Anchor
|
|
||||||
size="xs"
|
|
||||||
onClick={() => setFeaturesModalOpened(true)}
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
|
||||||
{t("common.learnMore", "Learn more")}
|
|
||||||
</Anchor>
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
<Button size="sm" variant="light" onClick={navigateToPlan}>
|
|
||||||
{t("team.upgrade.button", "Upgrade to Pro")}
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Alert>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Team Features Modal */}
|
|
||||||
<Modal
|
|
||||||
opened={featuresModalOpened}
|
|
||||||
onClose={() => setFeaturesModalOpened(false)}
|
|
||||||
size="md"
|
|
||||||
centered
|
|
||||||
padding="xl"
|
|
||||||
withCloseButton={false}
|
|
||||||
zIndex={Z_INDEX_OVER_CONFIG_MODAL}
|
|
||||||
>
|
|
||||||
<div style={{ position: "relative" }}>
|
|
||||||
<CloseButton
|
|
||||||
onClick={() => setFeaturesModalOpened(false)}
|
|
||||||
size="lg"
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top: -8,
|
|
||||||
right: -8,
|
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Stack gap="lg" pt="md">
|
|
||||||
{/* Header */}
|
|
||||||
<Stack gap="md" align="center">
|
|
||||||
<Badge size="lg" color="violet" variant="filled">
|
|
||||||
{t("team.features.badge", "PRO FEATURE")}
|
|
||||||
</Badge>
|
|
||||||
<Text size="xl" fw={700} ta="center">
|
|
||||||
{t("team.features.title", "Team Collaboration")}
|
|
||||||
</Text>
|
|
||||||
<Text size="sm" c="dimmed" ta="center">
|
|
||||||
{t(
|
|
||||||
"team.features.subtitle",
|
|
||||||
"Upgrade to Pro and unlock powerful team features",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
|
||||||
|
|
||||||
{/* Features List */}
|
|
||||||
<List
|
|
||||||
spacing="md"
|
|
||||||
size="sm"
|
|
||||||
icon={
|
|
||||||
<ThemeIcon color="violet" size={24} radius="xl" variant="light">
|
|
||||||
<LocalIcon icon="check" width={14} height={14} />
|
|
||||||
</ThemeIcon>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t("team.features.invite.title", "Invite team members")}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.invite.description",
|
|
||||||
"Add unlimited users with additional seat purchases",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t(
|
|
||||||
"team.features.credits.title",
|
|
||||||
"Share credits across your team",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.credits.description",
|
|
||||||
"Pool resources for collaborative work",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t(
|
|
||||||
"team.features.dashboard.title",
|
|
||||||
"Team management dashboard",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.dashboard.description",
|
|
||||||
"Control permissions, monitor usage, and manage members",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Text fw={500}>
|
|
||||||
{t("team.features.billing.title", "Centralized billing")}
|
|
||||||
</Text>
|
|
||||||
<Text size="xs" c="dimmed">
|
|
||||||
{t(
|
|
||||||
"team.features.billing.description",
|
|
||||||
"One invoice for all team seats and usage",
|
|
||||||
)}
|
|
||||||
</Text>
|
|
||||||
</List.Item>
|
|
||||||
</List>
|
|
||||||
|
|
||||||
{/* CTA Button */}
|
|
||||||
<Button
|
|
||||||
size="md"
|
|
||||||
fullWidth
|
|
||||||
onClick={() => {
|
|
||||||
setFeaturesModalOpened(false);
|
|
||||||
navigateToPlan();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("team.features.viewPlans", "View Pro Plans")}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
{/* Error/Success Messages */}
|
{/* Error/Success Messages */}
|
||||||
{error && (
|
{error && (
|
||||||
<Alert color="red" onClose={() => setError(null)} withCloseButton>
|
<Alert color="red" onClose={() => setError(null)} withCloseButton>
|
||||||
@@ -477,8 +312,8 @@ const TeamSection: React.FC = () => {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Invite Members (Pro Users) */}
|
{/* Invite Members */}
|
||||||
{isTeamLeader && isPro && (
|
{isTeamLeader && (
|
||||||
<div>
|
<div>
|
||||||
<Text fw={600} size="md" mb="sm">
|
<Text fw={600} size="md" mb="sm">
|
||||||
{t("team.invite.title", "Invite Team Member")}
|
{t("team.invite.title", "Invite Team Member")}
|
||||||
|
|||||||
Reference in New Issue
Block a user