Merge pull request #28 from dakshesh14/main

fix: mutation in project, issues page, feat: made redirection UX better
This commit is contained in:
Vamsi Kurama 2022-12-08 03:17:46 +05:30 committed by GitHub
commit 1368fb9164
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 170 additions and 56 deletions

View File

@ -1,14 +1,15 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect, useCallback } from "react";
// swr // swr
import { mutate } from "swr"; import useSWR, { mutate } from "swr";
// react hook form // react hook form
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
// headless // headless
import { Dialog, Transition } from "@headlessui/react"; import { Dialog, Transition } from "@headlessui/react";
// services // services
import projectServices from "lib/services/project.service"; import projectServices from "lib/services/project.service";
import workspaceService from "lib/services/workspace.service";
// fetch keys // fetch keys
import { PROJECTS_LIST } from "constants/fetch-keys"; import { PROJECTS_LIST, WORKSPACE_MEMBERS } from "constants/fetch-keys";
// hooks // hooks
import useUser from "lib/hooks/useUser"; import useUser from "lib/hooks/useUser";
import useToast from "lib/hooks/useToast"; import useToast from "lib/hooks/useToast";
@ -17,7 +18,7 @@ import { Button, Input, TextArea, Select } from "ui";
// common // common
import { debounce } from "constants/common"; import { debounce } from "constants/common";
// types // types
import { IProject } from "types"; import { IProject, WorkspaceMember } from "types";
type Props = { type Props = {
isOpen: boolean; isOpen: boolean;
@ -31,6 +32,23 @@ const defaultValues: Partial<IProject> = {
description: "", description: "",
}; };
const IsGuestCondition: React.FC<{
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
}> = ({ setIsOpen }) => {
const { setToastAlert } = useToast();
useEffect(() => {
setIsOpen(false);
setToastAlert({
title: "Error",
type: "error",
message: "You don't have permission to create project.",
});
}, []);
return null;
};
const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => { const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
const handleClose = () => { const handleClose = () => {
setIsOpen(false); setIsOpen(false);
@ -40,7 +58,12 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
}, 500); }, 500);
}; };
const { activeWorkspace } = useUser(); const { activeWorkspace, user } = useUser();
const { data: workspaceMembers } = useSWR<WorkspaceMember[]>(
activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
);
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
@ -56,6 +79,8 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
setValue, setValue,
} = useForm<IProject>({ } = useForm<IProject>({
defaultValues, defaultValues,
reValidateMode: "onChange",
mode: "all",
}); });
const onSubmit = async (formData: IProject) => { const onSubmit = async (formData: IProject) => {
@ -77,6 +102,15 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
handleClose(); handleClose();
}) })
.catch((err) => { .catch((err) => {
if (err.status === 403) {
setToastAlert({
title: "Error",
type: "error",
message: "You don't have permission to create project.",
});
handleClose();
return;
}
Object.keys(err).map((key) => { Object.keys(err).map((key) => {
const errorMessages = err[key]; const errorMessages = err[key];
setError(key as keyof IProject, { setError(key as keyof IProject, {
@ -105,6 +139,15 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
} }
}, [projectName, projectIdentifier, setValue, isChangeIdentifierRequired]); }, [projectName, projectIdentifier, setValue, isChangeIdentifierRequired]);
if (workspaceMembers) {
const isMember = workspaceMembers.find((member) => member.member.id === user?.id);
const isGuest = workspaceMembers.find(
(member) => member.member.id === user?.id && member.role === 5
);
if ((!isMember || isGuest) && isOpen) return <IsGuestCondition setIsOpen={setIsOpen} />;
}
return ( return (
<Transition.Root show={isOpen} as={React.Fragment}> <Transition.Root show={isOpen} as={React.Fragment}>
<Dialog as="div" className="relative z-10" onClose={handleClose}> <Dialog as="div" className="relative z-10" onClose={handleClose}>
@ -203,8 +246,8 @@ const CreateProjectModal: React.FC<Props> = ({ isOpen, setIsOpen }) => {
message: "Identifier must at least be of 1 character", message: "Identifier must at least be of 1 character",
}, },
maxLength: { maxLength: {
value: 9, value: 5,
message: "Identifier must at most be of 9 characters", message: "Identifier must at most be of 5 characters",
}, },
}} }}
/> />

View File

@ -50,8 +50,14 @@ const SendProjectInvitationModal: React.FC<Props> = ({ isOpen, setIsOpen, member
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const { data: people } = useSWR<WorkspaceMember[]>( const { data: people } = useSWR<WorkspaceMember[]>(
activeWorkspace ? WORKSPACE_MEMBERS : null, activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null,
{
onErrorRetry(err, _, __, revalidate, revalidateOpts) {
if (err?.status === 403) return;
setTimeout(() => revalidate(revalidateOpts), 5000);
},
}
); );
const { const {

View File

@ -42,8 +42,8 @@ type Props = {
> >
>; >;
bgColor?: string; bgColor?: string;
stateId?: string; stateId: string | null;
createdBy?: string; createdBy: string | null;
}; };
const SingleBoard: React.FC<Props> = ({ const SingleBoard: React.FC<Props> = ({
@ -109,7 +109,7 @@ const SingleBoard: React.FC<Props> = ({
<span <span
className={`w-3 h-3 block rounded-full ${!show ? "" : "mr-1"}`} className={`w-3 h-3 block rounded-full ${!show ? "" : "mr-1"}`}
style={{ style={{
backgroundColor: bgColor, backgroundColor: Boolean(bgColor) ? bgColor : undefined,
}} }}
/> />
<h2 <h2
@ -151,7 +151,7 @@ const SingleBoard: React.FC<Props> = ({
setIsIssueOpen(true); setIsIssueOpen(true);
if (selectedGroup !== null) if (selectedGroup !== null)
setPreloadedData({ setPreloadedData({
state: stateId, state: stateId !== null ? stateId : undefined,
[selectedGroup]: groupTitle, [selectedGroup]: groupTitle,
actionType: "createIssue", actionType: "createIssue",
}); });
@ -201,10 +201,12 @@ const SingleBoard: React.FC<Props> = ({
? "text-xs text-black" ? "text-xs text-black"
: key === "priority" : key === "priority"
? `text-xs bg-gray-200 px-2 py-1 mt-2 flex items-center gap-x-1 rounded w-min whitespace-nowrap capitalize font-medium ${ ? `text-xs bg-gray-200 px-2 py-1 mt-2 flex items-center gap-x-1 rounded w-min whitespace-nowrap capitalize font-medium ${
childIssue.priority === "high" childIssue.priority === "urgent"
? "bg-red-100 text-red-600" ? "bg-red-100 text-red-600"
: childIssue.priority === "high"
? "bg-orange-100 text-orange-600"
: childIssue.priority === "medium" : childIssue.priority === "medium"
? "bg-orange-100 text-orange-500" ? "bg-yellow-100 text-yellow-500"
: childIssue.priority === "low" : childIssue.priority === "low"
? "bg-green-100 text-green-500" ? "bg-green-100 text-green-500"
: "hidden" : "hidden"
@ -224,7 +226,7 @@ const SingleBoard: React.FC<Props> = ({
: "None"} : "None"}
</span> </span>
)} )}
{key === "target_date" && ( {key === "due_date" && (
<> <>
<span <span
className={`flex items-center gap-x-1 group ${ className={`flex items-center gap-x-1 group ${
@ -320,7 +322,7 @@ const SingleBoard: React.FC<Props> = ({
setIsIssueOpen(true); setIsIssueOpen(true);
if (selectedGroup !== null) { if (selectedGroup !== null) {
setPreloadedData({ setPreloadedData({
state: stateId, state: stateId !== null ? stateId : undefined,
[selectedGroup]: groupTitle, [selectedGroup]: groupTitle,
actionType: "createIssue", actionType: "createIssue",
}); });

View File

@ -197,9 +197,10 @@ const BoardView: React.FC<Props> = ({ properties, selectedGroup, groupedByIssues
selectedGroup={selectedGroup} selectedGroup={selectedGroup}
groupTitle={singleGroup} groupTitle={singleGroup}
createdBy={ createdBy={
members selectedGroup === "created_by"
? members?.find((m) => m.member.id === singleGroup)?.member.first_name ? members?.find((m) => m.member.id === singleGroup)?.member
: undefined .first_name ?? "loading..."
: null
} }
groupedByIssues={groupedByIssues} groupedByIssues={groupedByIssues}
index={index} index={index}
@ -208,8 +209,8 @@ const BoardView: React.FC<Props> = ({ properties, selectedGroup, groupedByIssues
setPreloadedData={setPreloadedData} setPreloadedData={setPreloadedData}
stateId={ stateId={
selectedGroup === "state_detail.name" selectedGroup === "state_detail.name"
? states?.find((s) => s.name === singleGroup)?.id ? states?.find((s) => s.name === singleGroup)?.id ?? null
: undefined : null
} }
bgColor={ bgColor={
selectedGroup === "state_detail.name" selectedGroup === "state_detail.name"

View File

@ -384,7 +384,7 @@ const ListView: React.FC<Props> = ({
)} )}
</Listbox> </Listbox>
</td> </td>
) : (key as keyof Properties) === "target_date" ? ( ) : (key as keyof Properties) === "due_date" ? (
<td className="px-3 py-4 text-sm font-medium text-gray-900 whitespace-nowrap"> <td className="px-3 py-4 text-sm font-medium text-gray-900 whitespace-nowrap">
{issue.target_date {issue.target_date
? renderShortNumericDateFormat(issue.target_date) ? renderShortNumericDateFormat(issue.target_date)
@ -440,4 +440,4 @@ const ListView: React.FC<Props> = ({
); );
}; };
export default ListView; export default ListView;

View File

@ -68,7 +68,7 @@ const IssueDetailSidebar: React.FC<Props> = ({ control, submitChanges, issueDeta
); );
const { data: people } = useSWR<WorkspaceMember[]>( const { data: people } = useSWR<WorkspaceMember[]>(
activeWorkspace ? WORKSPACE_MEMBERS : null, activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
); );

View File

@ -3,10 +3,14 @@ import React, { useState } from "react";
// next // next
import Link from "next/link"; import Link from "next/link";
import useSWR from "swr"; import useSWR from "swr";
import _ from "lodash"; // hooks
import useUser from "lib/hooks/useUser"; import useUser from "lib/hooks/useUser";
// Services // Services
import projectService from "lib/services/project.service"; import projectService from "lib/services/project.service";
// fetch keys
import { PROJECT_MEMBERS } from "constants/fetch-keys";
// commons
import { renderShortNumericDateFormat } from "constants/common";
// icons // icons
import { import {
CalendarDaysIcon, CalendarDaysIcon,
@ -17,25 +21,41 @@ import {
PlusIcon, PlusIcon,
TrashIcon, TrashIcon,
} from "@heroicons/react/24/outline"; } from "@heroicons/react/24/outline";
import { renderShortNumericDateFormat } from "constants/common"; // types
import type { IProject } from "types";
type Props = {
project: IProject;
slug: string;
invitationsRespond: string[];
handleInvitation: (project_invitation: any, action: "accepted" | "withdraw") => void;
setDeleteProject: React.Dispatch<React.SetStateAction<IProject | undefined>>;
};
const ProjectMemberInvitations = ({ const ProjectMemberInvitations: React.FC<Props> = ({
project, project,
slug, slug,
invitationsRespond, invitationsRespond,
handleInvitation, handleInvitation,
setDeleteProject, setDeleteProject,
}: any) => { }) => {
const { user } = useUser(); const { user } = useUser();
const { data: members } = useSWR("PROJECT_MEMBERS", () =>
const { data: members } = useSWR<any[]>(PROJECT_MEMBERS(project.id), () =>
projectService.projectMembers(slug, project.id) projectService.projectMembers(slug, project.id)
); );
const isMember = const isMember = members?.some((item: any) => item.member.id === (user as any)?.id);
_.filter(members, (item: any) => item.member.id === (user as any).id).length === 1;
const [selected, setSelected] = useState<any>(false); const [selected, setSelected] = useState<any>(false);
if (!members) {
return (
<div className="w-full h-36 flex flex-col px-4 py-3 rounded-md bg-white">
<div className="w-full h-full bg-gray-50 animate-pulse" />
</div>
);
}
return ( return (
<> <>
<div <div

View File

@ -2,7 +2,7 @@ export const CURRENT_USER = "CURRENT_USER";
export const USER_WORKSPACE_INVITATIONS = "USER_WORKSPACE_INVITATIONS"; export const USER_WORKSPACE_INVITATIONS = "USER_WORKSPACE_INVITATIONS";
export const USER_WORKSPACES = "USER_WORKSPACES"; export const USER_WORKSPACES = "USER_WORKSPACES";
export const WORKSPACE_MEMBERS = "WORKSPACE_MEMBERS"; export const WORKSPACE_MEMBERS = (workspaceSlug: string) => `WORKSPACE_MEMBERS_${workspaceSlug}`;
export const WORKSPACE_INVITATIONS = "WORKSPACE_INVITATIONS"; export const WORKSPACE_INVITATIONS = "WORKSPACE_INVITATIONS";
export const WORKSPACE_INVITATION = "WORKSPACE_INVITATION"; export const WORKSPACE_INVITATION = "WORKSPACE_INVITATION";

View File

@ -9,6 +9,7 @@ import authenticationService from "lib/services/authentication.service";
// hooks // hooks
import useUser from "lib/hooks/useUser"; import useUser from "lib/hooks/useUser";
import useTheme from "lib/hooks/useTheme"; import useTheme from "lib/hooks/useTheme";
import useToast from "lib/hooks/useToast";
// components // components
import CreateProjectModal from "components/project/CreateProjectModal"; import CreateProjectModal from "components/project/CreateProjectModal";
// headless ui // headless ui
@ -119,6 +120,8 @@ const Sidebar: React.FC = () => {
const { collapsed: sidebarCollapse, toggleCollapsed } = useTheme(); const { collapsed: sidebarCollapse, toggleCollapsed } = useTheme();
const { setToastAlert } = useToast();
return ( return (
<nav className="h-full"> <nav className="h-full">
<CreateProjectModal isOpen={isCreateProjectModal} setIsOpen={setCreateProjectModal} /> <CreateProjectModal isOpen={isCreateProjectModal} setIsOpen={setCreateProjectModal} />
@ -282,9 +285,11 @@ const Sidebar: React.FC = () => {
last_workspace_id: workspace?.id, last_workspace_id: workspace?.id,
}) })
.then((res) => { .then((res) => {
router.push("/workspace"); const isInProject =
router.pathname.includes("/[projectId]/");
if (isInProject) router.push("/workspace");
}) })
.catch((err) => console.log); .catch((err) => console.error(err));
}} }}
className={`${ className={`${
active ? "bg-theme text-white" : "text-gray-900" active ? "bg-theme text-white" : "text-gray-900"
@ -478,7 +483,13 @@ const Sidebar: React.FC = () => {
onClick={() => onClick={() =>
copyTextToClipboard( copyTextToClipboard(
`https://app.plane.so/projects/${project?.id}/issues/` `https://app.plane.so/projects/${project?.id}/issues/`
) ).then(() => {
setToastAlert({
title: "Link Copied",
message: "Link copied to clipboard",
type: "success",
});
})
} }
> >
<ClipboardDocumentIcon className="h-3 w-3" /> <ClipboardDocumentIcon className="h-3 w-3" />

View File

@ -4,7 +4,7 @@ import type { NextPage } from "next";
// redirect // redirect
import redirect from "lib/redirect"; import redirect from "lib/redirect";
const withAuth = (WrappedComponent: NextPage) => { const withAuth = (WrappedComponent: NextPage, getBackToSameRoute: boolean = true) => {
const Wrapper: NextPage<any> = (props) => { const Wrapper: NextPage<any> = (props) => {
return <WrappedComponent {...props} />; return <WrappedComponent {...props} />;
}; };
@ -17,7 +17,8 @@ const withAuth = (WrappedComponent: NextPage) => {
const token = cookies?.split("accessToken=")?.[1]?.split(";")?.[0]; const token = cookies?.split("accessToken=")?.[1]?.split(";")?.[0];
if (!token) { if (!token) {
redirect(ctx, "/signin"); if (getBackToSameRoute) redirect(ctx, "/signin?next=" + ctx?.asPath);
else redirect(ctx, "/signin");
} }
const pageProps = const pageProps =

View File

@ -78,6 +78,10 @@ const useIssuesFilter = (projectIssues?: IssueResponse) => {
} }
} }
if (groupByProperty === "priority" && orderBy === "priority") {
setOrderBy(null);
}
return { return {
groupedByIssues, groupedByIssues,
issueView, issueView,

View File

@ -16,7 +16,7 @@ const initialValues: Properties = {
assignee: true, assignee: true,
priority: false, priority: false,
start_date: false, start_date: false,
target_date: false, due_date: false,
cycle: false, cycle: false,
}; };

View File

@ -27,7 +27,7 @@ class ProjectServices extends APIService {
return response?.data; return response?.data;
}) })
.catch((error) => { .catch((error) => {
throw error?.response?.data; throw error?.response;
}); });
} }

View File

@ -87,10 +87,18 @@ const ProjectIssues: NextPage = () => {
); );
const { data: members } = useSWR<ProjectMember[]>( const { data: members } = useSWR<ProjectMember[]>(
activeWorkspace && activeProject ? PROJECT_MEMBERS : null, activeWorkspace && activeProject
? PROJECT_MEMBERS(activeWorkspace.slug, activeProject.id)
: null,
activeWorkspace && activeProject activeWorkspace && activeProject
? () => projectService.projectMembers(activeWorkspace.slug, activeProject.id) ? () => projectService.projectMembers(activeWorkspace.slug, activeProject.id)
: null : null,
{
onErrorRetry(err, _, __, revalidate, revalidateOpts) {
if (err?.status === 403) return;
setTimeout(() => revalidate(revalidateOpts), 5000);
},
}
); );
const { const {
@ -173,7 +181,7 @@ const ProjectIssues: NextPage = () => {
<Popover.Button <Popover.Button
className={classNames( className={classNames(
open ? "text-gray-900" : "text-gray-500", open ? "text-gray-900" : "text-gray-500",
"group inline-flex items-center rounded-md bg-transparent text-base font-medium hover:text-gray-900 focus:outline-none border border-gray-300 px-3 py-1" "group inline-flex items-center rounded-md bg-transparent text-xs font-medium hover:text-gray-900 focus:outline-none border border-gray-300 px-2 py-2"
)} )}
> >
<span>View</span> <span>View</span>
@ -195,7 +203,7 @@ const ProjectIssues: NextPage = () => {
leaveFrom="opacity-100 translate-y-0" leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1" leaveTo="opacity-0 translate-y-1"
> >
<Popover.Panel className="absolute mr-5 right-1/2 z-10 mt-3 w-screen max-w-xs translate-x-1/2 transform px-2 sm:px-0 bg-gray-0 backdrop-filter backdrop-blur-xl bg-opacity-100 rounded-lg shadow-lg overflow-hidden"> <Popover.Panel className="absolute mr-5 right-1/2 z-10 mt-3 w-screen max-w-xs translate-x-1/2 transform px-2 sm:px-0 bg-white rounded-lg shadow-lg overflow-hidden">
<div className="overflow-hidden py-8 px-4"> <div className="overflow-hidden py-8 px-4">
<div className="relative flex flex-col gap-1 gap-y-4"> <div className="relative flex flex-col gap-1 gap-y-4">
<div className="flex justify-between"> <div className="flex justify-between">

View File

@ -53,7 +53,13 @@ const ProjectMembers: NextPage = () => {
activeWorkspace && projectId ? PROJECT_MEMBERS(projectId as string) : null, activeWorkspace && projectId ? PROJECT_MEMBERS(projectId as string) : null,
activeWorkspace && projectId activeWorkspace && projectId
? () => projectService.projectMembers(activeWorkspace.slug, projectId as any) ? () => projectService.projectMembers(activeWorkspace.slug, projectId as any)
: null : null,
{
onErrorRetry(err, _, __, revalidate, revalidateOpts) {
if (err?.status === 403) return;
setTimeout(() => revalidate(revalidateOpts), 5000);
},
}
); );
const { data: projectInvitations, mutate: mutateInvitations } = useSWR( const { data: projectInvitations, mutate: mutateInvitations } = useSWR(
activeWorkspace && projectId ? PROJECT_INVITATIONS : null, activeWorkspace && projectId ? PROJECT_INVITATIONS : null,
@ -235,7 +241,7 @@ const ProjectMembers: NextPage = () => {
)} )}
</td> </td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500 sm:pl-6"> <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500 sm:pl-6">
{member.status ? ( {member.member ? (
<span className="p-0.5 px-2 text-sm bg-green-700 text-white rounded-full"> <span className="p-0.5 px-2 text-sm bg-green-700 text-white rounded-full">
Active Active
</span> </span>
@ -261,7 +267,7 @@ const ProjectMembers: NextPage = () => {
className="w-full text-left py-2 pl-2" className="w-full text-left py-2 pl-2"
type="button" type="button"
onClick={() => { onClick={() => {
if (!member.status) { if (!member.member) {
setToastAlert({ setToastAlert({
type: "error", type: "error",
message: "You can't edit a pending invitation.", message: "You can't edit a pending invitation.",
@ -282,7 +288,7 @@ const ProjectMembers: NextPage = () => {
className="w-full text-left py-2 pl-2" className="w-full text-left py-2 pl-2"
type="button" type="button"
onClick={() => { onClick={() => {
if (member.status) { if (member.member) {
setSelectedRemoveMember(member.id); setSelectedRemoveMember(member.id);
} else { } else {
setSelectedInviteRemoveMember(member.id); setSelectedInviteRemoveMember(member.id);

View File

@ -78,8 +78,14 @@ const ProjectSettings: NextPage = () => {
); );
const { data: people } = useSWR<WorkspaceMember[]>( const { data: people } = useSWR<WorkspaceMember[]>(
activeWorkspace ? WORKSPACE_MEMBERS : null, activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null,
{
onErrorRetry(err, _, __, revalidate, revalidateOpts) {
if (err?.status === 403) return;
setTimeout(() => revalidate(revalidateOpts), 5000);
},
}
); );
useEffect(() => { useEffect(() => {
@ -541,4 +547,4 @@ const ProjectSettings: NextPage = () => {
); );
}; };
export default ProjectSettings; export default ProjectSettings;

View File

@ -43,8 +43,14 @@ const SignIn: NextPage = () => {
async (res: any) => { async (res: any) => {
await mutateUser(); await mutateUser();
await mutateWorkspaces(); await mutateWorkspaces();
if (res.user.is_onboarded) router.push("/"); const nextLocation = router.asPath.split("?next=")[1];
else router.push("/invitations");
if (nextLocation) {
router.push(nextLocation as string);
} else {
if (res.user.is_onboarded) router.push("/");
else router.push("/invitations");
}
}, },
[mutateUser, mutateWorkspaces, router] [mutateUser, mutateWorkspaces, router]
); );

View File

@ -41,7 +41,7 @@ const WorkspaceInvite: NextPage = () => {
const { setToastAlert } = useToast(); const { setToastAlert } = useToast();
const { data: workspaceMembers, mutate: mutateMembers } = useSWR<any[]>( const { data: workspaceMembers, mutate: mutateMembers } = useSWR<any[]>(
activeWorkspace ? WORKSPACE_MEMBERS : null, activeWorkspace ? WORKSPACE_MEMBERS(activeWorkspace.slug) : null,
activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null activeWorkspace ? () => workspaceService.workspaceMembers(activeWorkspace.slug) : null
); );
const { data: workspaceInvitations, mutate: mutateInvitations } = useSWR<any[]>( const { data: workspaceInvitations, mutate: mutateInvitations } = useSWR<any[]>(
@ -229,7 +229,7 @@ const WorkspaceInvite: NextPage = () => {
)} )}
</td> </td>
<td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500 sm:pl-6"> <td className="whitespace-nowrap px-3 py-4 text-sm text-gray-500 sm:pl-6">
{member.status ? ( {member.member ? (
<span className="p-0.5 px-2 text-sm bg-green-700 text-white rounded-full"> <span className="p-0.5 px-2 text-sm bg-green-700 text-white rounded-full">
Active Active
</span> </span>
@ -277,7 +277,7 @@ const WorkspaceInvite: NextPage = () => {
className="w-full text-left py-2 pl-2" className="w-full text-left py-2 pl-2"
type="button" type="button"
onClick={() => { onClick={() => {
if (member.status) { if (member.member) {
setSelectedRemoveMember(member.id); setSelectedRemoveMember(member.id);
} else { } else {
setSelectedInviteRemoveMember(member.id); setSelectedInviteRemoveMember(member.id);

View File

@ -102,7 +102,7 @@ export type Properties = {
assignee: boolean; assignee: boolean;
priority: boolean; priority: boolean;
start_date: boolean; start_date: boolean;
target_date: boolean; due_date: boolean;
cycle: boolean; cycle: boolean;
}; };