Fix some type errors
This commit is contained in:
commit
20488b35c8
|
@ -1341,5 +1341,7 @@
|
||||||
"yearly": "Yearly",
|
"yearly": "Yearly",
|
||||||
"checkout": "Checkout",
|
"checkout": "Checkout",
|
||||||
"your_team_disbanded_successfully": "Your team has been disbanded successfully",
|
"your_team_disbanded_successfully": "Your team has been disbanded successfully",
|
||||||
"error_creating_team": "Error creating team"
|
"error_creating_team": "Error creating team",
|
||||||
|
"you": "You",
|
||||||
|
"send_email": "Send email"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import { NewTeamFormValues, PendingMember } from "../lib/types";
|
||||||
|
|
||||||
type MemberInvitationModalProps = {
|
type MemberInvitationModalProps = {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
currentMember?: MembershipRole;
|
|
||||||
onExit: () => void;
|
onExit: () => void;
|
||||||
onSubmit: (values: NewMemberForm) => void;
|
onSubmit: (values: NewMemberForm) => void;
|
||||||
};
|
};
|
||||||
|
@ -31,55 +30,17 @@ export interface NewMemberForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MemberInvitationModal(props: MemberInvitationModalProps) {
|
export default function MemberInvitationModal(props: MemberInvitationModalProps) {
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
const { t } = useLocale();
|
||||||
const { t, i18n } = useLocale();
|
|
||||||
const utils = trpc.useContext();
|
|
||||||
|
|
||||||
const _options: MembershipRoleOption[] = [
|
const options: MembershipRoleOption[] = useMemo(() => {
|
||||||
{ value: "MEMBER", label: t("member") },
|
return [
|
||||||
{ value: "ADMIN", label: t("admin") },
|
{ value: "MEMBER", label: t("member") },
|
||||||
{ value: "OWNER", label: t("owner") },
|
{ value: "ADMIN", label: t("admin") },
|
||||||
];
|
{ value: "OWNER", label: t("owner") },
|
||||||
|
];
|
||||||
const newMemberFormMethods = useForm<NewMemberForm>();
|
|
||||||
|
|
||||||
const options = useMemo(() => {
|
|
||||||
_options.forEach((option, i) => {
|
|
||||||
_options[i].label = t(option.value.toLowerCase());
|
|
||||||
});
|
|
||||||
return _options;
|
|
||||||
}, [t]);
|
}, [t]);
|
||||||
|
|
||||||
const inviteMemberMutation = trpc.useMutation("viewer.teams.inviteMember", {
|
const newMemberFormMethods = useForm<NewMemberForm>();
|
||||||
async onSuccess() {
|
|
||||||
await utils.invalidateQueries(["viewer.teams.get"]);
|
|
||||||
props.onExit();
|
|
||||||
},
|
|
||||||
async onError(err) {
|
|
||||||
setErrorMessage(err.message);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function inviteMember(e: SyntheticEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
if (!props.team) return;
|
|
||||||
|
|
||||||
const target = e.target as typeof e.target & {
|
|
||||||
elements: {
|
|
||||||
role: { value: MembershipRole };
|
|
||||||
inviteUser: { value: string };
|
|
||||||
sendInviteEmail: { checked: boolean };
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
inviteMemberMutation.mutate({
|
|
||||||
teamId: props.team.id,
|
|
||||||
language: i18n.language,
|
|
||||||
role: target.elements["role"].value,
|
|
||||||
usernameOrEmail: target.elements["inviteUser"].value,
|
|
||||||
sendEmailInvitation: target.elements["sendInviteEmail"].checked,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={props.isOpen} onOpenChange={props.onExit}>
|
<Dialog open={props.isOpen} onOpenChange={props.onExit}>
|
||||||
|
@ -93,11 +54,12 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
your subscription once this member accepts your invite.
|
your subscription once this member accepts your invite.
|
||||||
</span>
|
</span>
|
||||||
}>
|
}>
|
||||||
<form>
|
<Form form={newMemberFormMethods} handleSubmit={(values) => props.onSubmit(values)}>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Controller
|
<Controller
|
||||||
name="emailOrUsername"
|
name="emailOrUsername"
|
||||||
control={newMemberFormMethods.control}
|
control={newMemberFormMethods.control}
|
||||||
|
rules={{ required: true, minLength: 1 }}
|
||||||
render={({ field: { onChange } }) => (
|
render={({ field: { onChange } }) => (
|
||||||
<TextField
|
<TextField
|
||||||
label={t("email_or_username")}
|
label={t("email_or_username")}
|
||||||
|
@ -112,6 +74,7 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
<Controller
|
<Controller
|
||||||
name="role"
|
name="role"
|
||||||
control={newMemberFormMethods.control}
|
control={newMemberFormMethods.control}
|
||||||
|
defaultValue={options[0]}
|
||||||
render={({ field: { onChange } }) => (
|
render={({ field: { onChange } }) => (
|
||||||
<div>
|
<div>
|
||||||
<label
|
<label
|
||||||
|
@ -121,7 +84,7 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
</label>
|
</label>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={options[0]}
|
defaultValue={options[0]}
|
||||||
options={props.currentMember !== MembershipRole.OWNER ? options.slice(0, 2) : options}
|
options={options.slice(0, 2)}
|
||||||
id="role"
|
id="role"
|
||||||
name="role"
|
name="role"
|
||||||
className="mt-1 block w-full rounded-sm border-gray-300 text-sm"
|
className="mt-1 block w-full rounded-sm border-gray-300 text-sm"
|
||||||
|
@ -133,6 +96,7 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
<Controller
|
<Controller
|
||||||
name="sendInviteEmail"
|
name="sendInviteEmail"
|
||||||
control={newMemberFormMethods.control}
|
control={newMemberFormMethods.control}
|
||||||
|
defaultValue={false}
|
||||||
render={() => (
|
render={() => (
|
||||||
<div className="relative flex items-start">
|
<div className="relative flex items-start">
|
||||||
<CheckboxField
|
<CheckboxField
|
||||||
|
@ -143,25 +107,20 @@ export default function MemberInvitationModal(props: MemberInvitationModalProps)
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{errorMessage && (
|
|
||||||
<p className="text-sm text-red-700">
|
|
||||||
<span className="font-bold">Error: </span>
|
|
||||||
{errorMessage}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button type="button" color="secondary" onClick={props.onExit}>
|
<Button type="button" color="secondary" onClick={props.onExit}>
|
||||||
{t("cancel")}
|
{t("cancel")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => props.onSubmit(newMemberFormMethods.getValues())}
|
// onClick={() => props.onSubmit(newMemberFormMethods.getValues())}
|
||||||
|
type="submit"
|
||||||
color="primary"
|
color="primary"
|
||||||
className="ltr:ml-2 rtl:mr-2"
|
className="ltr:ml-2 rtl:mr-2"
|
||||||
data-testid="invite-new-member-button">
|
data-testid="invite-new-member-button">
|
||||||
{t("invite")}
|
{t("invite")}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</form>
|
</Form>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -39,6 +39,7 @@ const AddNewTeamMembers = () => {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
onSuccess: (newMember: PendingMember) => {
|
onSuccess: (newMember: PendingMember) => {
|
||||||
membersFieldArray.append(newMember);
|
membersFieldArray.append(newMember);
|
||||||
|
setSkeletonMember(false);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -72,6 +73,11 @@ const AddNewTeamMembers = () => {
|
||||||
setSkeletonMember(true);
|
setSkeletonMember(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteMember = (email: string) => {
|
||||||
|
const memberIndex = formMethods.getValues("members").findIndex((member) => member.email === email);
|
||||||
|
membersFieldArray.remove(memberIndex);
|
||||||
|
};
|
||||||
|
|
||||||
// if (isLoading) return <AddNewTeamMemberSkeleton />;
|
// if (isLoading) return <AddNewTeamMemberSkeleton />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -107,12 +113,13 @@ const AddNewTeamMembers = () => {
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex space-x-1">
|
<div className="flex space-x-1">
|
||||||
<p>{member?.name || t("team_member")}</p>
|
<p>{member?.name || member?.email || t("team_member")}</p>
|
||||||
{/* Assume that the first member of the team is the creator */}
|
{/* Assume that the first member of the team is the creator */}
|
||||||
{index === 0 && <Badge variant="green">{t("you")}</Badge>}{" "}
|
{index === 0 && <Badge variant="green">{t("you")}</Badge>}
|
||||||
{member.role !== "OWNER" && <Badge variant="orange">{t("pending")}</Badge>}
|
{member.role !== "OWNER" && <Badge variant="orange">{t("pending")}</Badge>}
|
||||||
{member.role === "MEMBER" && <Badge variant="gray">{t("member")}</Badge>}
|
{member.role === "MEMBER" && <Badge variant="gray">{t("member")}</Badge>}
|
||||||
{member.role === "ADMIN" && <Badge variant="default">{t("admin")}</Badge>}
|
{member.role === "ADMIN" && <Badge variant="default">{t("admin")}</Badge>}
|
||||||
|
{member.sendInviteEmail && <Badge variant="blue">{t("send_email")}</Badge>}
|
||||||
</div>
|
</div>
|
||||||
{member.username ? (
|
{member.username ? (
|
||||||
<p className="text-gray-600">{`${WEBAPP_URL}/${member?.username}`}</p>
|
<p className="text-gray-600">{`${WEBAPP_URL}/${member?.username}`}</p>
|
||||||
|
@ -127,7 +134,7 @@ const AddNewTeamMembers = () => {
|
||||||
size="icon"
|
size="icon"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
className="h-[36px] w-[36px]"
|
className="h-[36px] w-[36px]"
|
||||||
onClick={() => removeMemberMutation.mutate({ teamId, memberId: member.id })}
|
onClick={() => handleDeleteMember(member.email)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
export interface NewTeamFormValues {
|
export interface NewTeamMembersFieldArray {
|
||||||
|
members: PendingMember[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NewTeamFormValues extends NewTeamMembersFieldArray {
|
||||||
name: string;
|
name: string;
|
||||||
slug: string;
|
slug: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NewTeamMembersFieldArray {
|
|
||||||
members: PendingMember[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PendingMember {
|
export interface PendingMember {
|
||||||
name: string | null;
|
name: string | null;
|
||||||
email: string;
|
email: string;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user