returns error message from server when add new member fails

This commit is contained in:
Mantey
2025-02-04 08:51:01 +00:00
parent aaa87389d3
commit f43bb15275
@@ -1,36 +1,36 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { MembershipSchemas, type UtilitySchemas } from "@plunk/shared";
import type { Project, Role } from "@prisma/client";
import { motion } from "framer-motion";
import { useRouter } from "next/router";
import React, { useState } from "react";
import { useForm } from "react-hook-form";
import { toast } from "sonner";
import { Card, FullscreenLoader, Input, Modal, SettingTabs, Table } from "../../components";
import { Dashboard } from "../../layouts";
import { useActiveProject, useActiveProjectMemberships, useProjects } from "../../lib/hooks/projects";
import { useUser } from "../../lib/hooks/users";
import { network } from "../../lib/network";
import { zodResolver } from '@hookform/resolvers/zod'
import { MembershipSchemas, type UtilitySchemas } from '@plunk/shared'
import type { Project, Role } from '@prisma/client'
import { motion } from 'framer-motion'
import { useRouter } from 'next/router'
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { Card, FullscreenLoader, Input, Modal, SettingTabs, Table } from '../../components'
import { Dashboard } from '../../layouts'
import { useActiveProject, useActiveProjectMemberships, useProjects } from '../../lib/hooks/projects'
import { useUser } from '../../lib/hooks/users'
import { network } from '../../lib/network'
interface EmailValues {
email: string;
email: string
}
/**
*
*/
export default function Index() {
const [showInviteModal, setShowInviteModal] = useState(false);
const [showLeaveModal, setShowLeaveModal] = useState(false);
const [showInviteModal, setShowInviteModal] = useState(false)
const [showLeaveModal, setShowLeaveModal] = useState(false)
const [project, setProject] = useState<Project>();
const [project, setProject] = useState<Project>()
const router = useRouter();
const router = useRouter()
const activeProject = useActiveProject();
const { data: user } = useUser();
const { data: projects, mutate: projectMutate } = useProjects();
const { data: memberships, mutate: membershipMutate } = useActiveProjectMemberships();
const activeProject = useActiveProject()
const { data: user } = useUser()
const { data: projects, mutate: projectMutate } = useProjects()
const { data: memberships, mutate: membershipMutate } = useActiveProjectMemberships()
const {
register,
@@ -38,89 +38,91 @@ export default function Index() {
formState: { errors },
} = useForm<EmailValues>({
resolver: zodResolver(MembershipSchemas.invite.omit({ id: true, role: true })),
});
})
if (activeProject && !project) {
setProject(activeProject);
setProject(activeProject)
}
if (!project || !projects || !memberships || !user) {
return <FullscreenLoader />;
return <FullscreenLoader />
}
if (!activeProject) {
return <FullscreenLoader />;
return <FullscreenLoader />
}
const inviteAccount = (data: EmailValues) => {
toast.promise(
network.mock<
{
success: true;
success: true
members: {
userId: string;
email: string;
role: Role;
}[];
userId: string
email: string
role: Role
}[]
},
typeof MembershipSchemas.invite
>(project.secret, "POST", "/memberships/invite", {
>(project.secret, 'POST', '/memberships/invite', {
id: project.id,
email: data.email,
role: "ADMIN",
role: 'ADMIN',
}),
{
loading: "Adding new member",
loading: 'Adding new member',
success: async (result) => {
await membershipMutate(result.members);
setShowInviteModal(false);
await membershipMutate(result.members)
setShowInviteModal(false)
return "Added new member";
return 'Added new member'
},
error: "Could not add new member!",
},
);
};
error: (e) => {
return e.message
},
}
)
}
const kickAccount = (email: string) => {
void network
.fetch<
{
success: true;
success: true
members: {
userId: string;
email: string;
role: Role;
}[];
userId: string
email: string
role: Role
}[]
},
typeof MembershipSchemas.kick
>("POST", "/memberships/kick", {
>('POST', '/memberships/kick', {
id: project.id,
email,
})
.then(async (res) => {
await membershipMutate(res.members);
});
};
await membershipMutate(res.members)
})
}
const leaveProject = () => {
void network
.fetch<
{
success: true;
memberships: Project[];
success: true
memberships: Project[]
},
typeof UtilitySchemas.id
>("POST", "/memberships/leave", {
>('POST', '/memberships/leave', {
id: project.id,
})
.then(async (res) => {
await projectMutate(res.memberships);
localStorage.removeItem("project");
await router.push("/");
window.location.reload();
});
};
await projectMutate(res.memberships)
localStorage.removeItem('project')
await router.push('/')
window.location.reload()
})
}
return (
<>
@@ -128,29 +130,29 @@ export default function Index() {
isOpen={showLeaveModal}
onToggle={() => setShowLeaveModal(!showLeaveModal)}
onAction={leaveProject}
type={"danger"}
title={"Are you sure?"}
type={'danger'}
title={'Are you sure?'}
description={
memberships.length === 1
? "You are the last person in this project, if you leave it we will automatically delete it!"
: "Leaving a project is permanent, you will lose access to the data and will need to be reinvited again."
? 'You are the last person in this project, if you leave it we will automatically delete it!'
: 'Leaving a project is permanent, you will lose access to the data and will need to be reinvited again.'
}
/>
<Modal
isOpen={showInviteModal}
onToggle={() => setShowInviteModal(!showInviteModal)}
onAction={handleSubmit(inviteAccount)}
type={"info"}
title={"Invite a new member"}
type={'info'}
title={'Invite a new member'}
description={
"Enter the email of the account you want to invite to this project. The person you want to invite needs to have an account on Plunk."
'Enter the email of the account you want to invite to this project. The person you want to invite needs to have an account on Plunk.'
}
>
<Input register={register("email")} error={errors.email} label={"Email"} placeholder={"hello@example.com"} />
<Input register={register('email')} error={errors.email} label={'Email'} placeholder={'hello@example.com'} />
</Modal>
<Dashboard>
<SettingTabs />
<Card title={"Project members"}>
<Card title={'Project members'}>
<Table
values={memberships.map((membership) => {
return {
@@ -160,30 +162,30 @@ export default function Index() {
Manage:
membership.userId === user.id ? (
<button
className={"mb-2 text-sm text-neutral-400 underline transition ease-in-out hover:text-neutral-700"}
className={'mb-2 text-sm text-neutral-400 underline transition ease-in-out hover:text-neutral-700'}
onClick={() => setShowLeaveModal(true)}
>
Leave
</button>
) : memberships.find((membership) => membership.userId === user.id)?.role === "OWNER" ? (
) : memberships.find((membership) => membership.userId === user.id)?.role === 'OWNER' ? (
<button
className={"mb-2 text-sm text-neutral-400 underline transition ease-in-out hover:text-neutral-700"}
className={'mb-2 text-sm text-neutral-400 underline transition ease-in-out hover:text-neutral-700'}
onClick={() => kickAccount(membership.email)}
>
Kick
</button>
) : (
""
''
),
};
}
})}
/>
<div className={"mt-9 flex items-center"}>
<div className={"w-2/3"}>
<p className={"text-sm font-semibold text-neutral-800"}>Invite team</p>
<p className={"text-sm text-neutral-400"}>
By adding someone to your project you give them access to all data present in your project including emails and
your API key.
<div className={'mt-9 flex items-center'}>
<div className={'w-2/3'}>
<p className={'text-sm font-semibold text-neutral-800'}>Invite team</p>
<p className={'text-sm text-neutral-400'}>
By adding someone to your project you give them access to all data present in your project including emails and your API
key.
</p>
</div>
@@ -191,7 +193,7 @@ export default function Index() {
onClick={() => setShowInviteModal(true)}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.9 }}
className={"ml-auto mt-4 self-end rounded bg-neutral-800 px-8 py-2.5 text-sm font-medium text-white"}
className={'ml-auto mt-4 self-end rounded bg-neutral-800 px-8 py-2.5 text-sm font-medium text-white'}
>
Invite user
</motion.button>
@@ -199,5 +201,5 @@ export default function Index() {
</Card>
</Dashboard>
</>
);
)
}