bugfix: invitation link copy option disapearing fixed. route problem for unauthorizrd users opening invitation link fixed.

This commit is contained in:
2026-05-17 00:02:13 +03:30
parent 627219df58
commit 2d43254af2
14 changed files with 561 additions and 205 deletions

View File

@@ -0,0 +1,107 @@
'use client';
import { useCallback, useEffect, useState } from 'react';
import {
organizationApi,
type OrganizationInvitationHistoryItemDto,
} from '@/lib/api/organization';
import {
canShareOrganizationInviteLink,
readOrganizationInviteLinks,
type StoredOrganizationInviteLink,
writeOrganizationInviteLinks,
} from '@/components/invitations/organizationInviteLinks';
export function useOrganizationInviteLinkCopy(organizationId: string | undefined) {
const [pendingInviteLinks, setPendingInviteLinks] = useState<
Record<string, StoredOrganizationInviteLink>
>({});
const [copiedId, setCopiedId] = useState<string | null>(null);
const [copyingInvitationId, setCopyingInvitationId] = useState<string | null>(null);
useEffect(() => {
if (!organizationId) return;
setPendingInviteLinks(readOrganizationInviteLinks(organizationId));
}, [organizationId]);
const storeInviteLink = useCallback(
(invitationId: string, ownerEmail: string, invitationUrl: string) => {
if (!organizationId) return;
setPendingInviteLinks((prev) => {
const next = {
...prev,
[invitationId]: {
invitationId,
ownerEmail: ownerEmail.trim().toLowerCase(),
invitationUrl,
},
};
writeOrganizationInviteLinks(organizationId, next);
return next;
});
},
[organizationId],
);
const pruneAcceptedLinks = useCallback(
(items: OrganizationInvitationHistoryItemDto[]) => {
if (!organizationId) return;
const acceptedIds = new Set(
items.filter((item) => item.acceptedAt || item.status === 'ACTIVE').map((item) => item.id),
);
setPendingInviteLinks((prev) => {
let changed = false;
const next = { ...prev };
for (const id of Object.keys(next)) {
if (acceptedIds.has(id)) {
delete next[id];
changed = true;
}
}
if (changed) {
writeOrganizationInviteLinks(organizationId, next);
}
return changed ? next : prev;
});
},
[organizationId],
);
const copyInvitationLink = useCallback(
async (
invitation: OrganizationInvitationHistoryItemDto,
options?: { onRegenerated?: () => void | Promise<void> },
): Promise<string | null> => {
if (!canShareOrganizationInviteLink(invitation)) return null;
setCopyingInvitationId(invitation.id);
try {
let invitationUrl = pendingInviteLinks[invitation.id]?.invitationUrl;
if (!invitationUrl || invitation.status === 'EXPIRED') {
const res = await organizationApi.getInvitationLink(invitation.id);
invitationUrl = res.data.invitationUrl;
storeInviteLink(invitation.id, invitation.ownerEmail, invitationUrl);
await options?.onRegenerated?.();
}
await navigator.clipboard.writeText(invitationUrl);
setCopiedId(invitation.id);
setTimeout(() => setCopiedId(null), 1500);
return invitationUrl;
} finally {
setCopyingInvitationId(null);
}
},
[pendingInviteLinks, storeInviteLink],
);
return {
pendingInviteLinks,
copiedId,
copyingInvitationId,
storeInviteLink,
copyInvitationLink,
pruneAcceptedLinks,
};
}