UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: корректный flow уведомлений Tasker

This commit is contained in:
DCCONSTRUCTIONS
2026-05-12 15:11:17 +03:00
parent 6737138ab7
commit fc59481703
17 changed files with 717 additions and 164 deletions
@@ -4,10 +4,11 @@
* See the LICENSE file for details.
*/
import type { ReactNode } from "react";
import { useEffect, useRef, type ReactNode } from "react";
import { observer } from "mobx-react";
import { useSearchParams, usePathname } from "next/navigation";
import useSWR from "swr";
import { TOAST_TYPE, setToast } from "@plane/propel/toast";
// components
import { LogoSpinner } from "@/components/common/logo-spinner";
// helpers
@@ -17,6 +18,10 @@ import { buildNodeDCOIDCLoginUrl, getCurrentRelativePath, shouldUseNodeDCOIDC }
import { useWorkspace } from "@/hooks/store/use-workspace";
import { useUser, useUserProfile, useUserSettings } from "@/hooks/store/user";
import { useAppRouter } from "@/hooks/use-app-router";
// services
import { WorkspaceService } from "@/services/workspace.service";
const workspaceService = new WorkspaceService();
type TPageType = EPageTypes;
@@ -35,6 +40,7 @@ export const AuthenticationWrapper = observer(function AuthenticationWrapper(pro
const router = useAppRouter();
const searchParams = useSearchParams();
const nextPath = searchParams.get("next_path");
const pendingInviteToastKey = useRef<string | undefined>(undefined);
// props
const { children, pageType = EPageTypes.AUTHENTICATED } = props;
// hooks
@@ -55,6 +61,47 @@ export const AuthenticationWrapper = observer(function AuthenticationWrapper(pro
currentUserProfile?.onboarding_step?.workspace_invite &&
currentUserProfile?.onboarding_step?.workspace_join) ||
false;
const shouldWatchPendingInvites =
pageType === EPageTypes.AUTHENTICATED && !!currentUser?.id && isUserOnboard && pathname !== "/invitations";
const { data: pendingWorkspaceInvitations } = useSWR(
shouldWatchPendingInvites ? "USER_WORKSPACE_INVITATIONS_NOTICE" : null,
() => workspaceService.userWorkspaceInvitations(),
{
refreshInterval: 15000,
revalidateOnFocus: true,
shouldRetryOnError: false,
}
);
useEffect(() => {
if (!shouldWatchPendingInvites || !pendingWorkspaceInvitations?.length) return;
const inviteKey = pendingWorkspaceInvitations
.map((invitation) => invitation.id)
.toSorted()
.join(":");
if (pendingInviteToastKey.current === inviteKey) return;
pendingInviteToastKey.current = inviteKey;
setToast({
type: TOAST_TYPE.INFO,
title: "Новое приглашение в Tasker",
message:
pendingWorkspaceInvitations.length === 1
? "Вам отправили доступ в workspace. Откройте приглашения, чтобы принять его."
: `У вас ${pendingWorkspaceInvitations.length} ожидающих приглашений. Откройте список, чтобы принять доступы.`,
actionItems: (
<button
type="button"
className="text-12 font-semibold text-[rgb(var(--nodedc-accent-rgb))] transition hover:opacity-80"
onClick={() => router.push("/invitations")}
>
Открыть приглашения
</button>
),
});
}, [pendingWorkspaceInvitations, router, shouldWatchPendingInvites]);
const getWorkspaceRedirectionUrl = (): string => {
let redirectionRoute = "/create-workspace";