improvement: loading state added to buttons who interact with backend.
This commit is contained in:
@@ -597,39 +597,37 @@ export function StaffPage() {
|
||||
variant="outline"
|
||||
size="sm"
|
||||
isLoading={copyingInviteMembershipId === lastInviteInfo.membershipId}
|
||||
onClick={() => {
|
||||
onClick={async () => {
|
||||
const member = members.find((item) => item.id === lastInviteInfo.membershipId);
|
||||
if (member) {
|
||||
void copyStaffInviteLink(member);
|
||||
await copyStaffInviteLink(member);
|
||||
return;
|
||||
}
|
||||
void (async () => {
|
||||
setCopyingInviteMembershipId(lastInviteInfo.membershipId);
|
||||
toast.setError('');
|
||||
try {
|
||||
const res = await staffApi.getInvitationLink(lastInviteInfo.membershipId);
|
||||
if (currentOrganization?.id) {
|
||||
const nextLinks = {
|
||||
...pendingInviteLinks,
|
||||
[lastInviteInfo.membershipId]: {
|
||||
membershipId: lastInviteInfo.membershipId,
|
||||
email: lastInviteInfo.email,
|
||||
invitationUrl: res.data.invitationUrl,
|
||||
},
|
||||
};
|
||||
setPendingInviteLinks(nextLinks);
|
||||
writeStoredInviteLinks(currentOrganization.id, nextLinks);
|
||||
}
|
||||
setLastInviteInfo({ ...lastInviteInfo, invitationUrl: res.data.invitationUrl });
|
||||
await navigator.clipboard.writeText(res.data.invitationUrl);
|
||||
setCopiedInviteMembershipId(lastInviteInfo.membershipId);
|
||||
setTimeout(() => setCopiedInviteMembershipId(null), 1500);
|
||||
} catch (e) {
|
||||
toast.showError(getUserFacingError(e, tErrors, t('errorCopyInvite')));
|
||||
} finally {
|
||||
setCopyingInviteMembershipId(null);
|
||||
setCopyingInviteMembershipId(lastInviteInfo.membershipId);
|
||||
toast.setError('');
|
||||
try {
|
||||
const res = await staffApi.getInvitationLink(lastInviteInfo.membershipId);
|
||||
if (currentOrganization?.id) {
|
||||
const nextLinks = {
|
||||
...pendingInviteLinks,
|
||||
[lastInviteInfo.membershipId]: {
|
||||
membershipId: lastInviteInfo.membershipId,
|
||||
email: lastInviteInfo.email,
|
||||
invitationUrl: res.data.invitationUrl,
|
||||
},
|
||||
};
|
||||
setPendingInviteLinks(nextLinks);
|
||||
writeStoredInviteLinks(currentOrganization.id, nextLinks);
|
||||
}
|
||||
})();
|
||||
setLastInviteInfo({ ...lastInviteInfo, invitationUrl: res.data.invitationUrl });
|
||||
await navigator.clipboard.writeText(res.data.invitationUrl);
|
||||
setCopiedInviteMembershipId(lastInviteInfo.membershipId);
|
||||
setTimeout(() => setCopiedInviteMembershipId(null), 1500);
|
||||
} catch (e) {
|
||||
toast.showError(getUserFacingError(e, tErrors, t('errorCopyInvite')));
|
||||
} finally {
|
||||
setCopyingInviteMembershipId(null);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{copiedInviteMembershipId === lastInviteInfo.membershipId
|
||||
@@ -661,7 +659,7 @@ export function StaffPage() {
|
||||
canShareInviteLink={canShareStaffInviteLink}
|
||||
canEnable={canEnableStaff}
|
||||
canDisable={canDisableStaff}
|
||||
onCopyInviteLink={(member) => void copyStaffInviteLink(member)}
|
||||
onCopyInviteLink={(member) => copyStaffInviteLink(member)}
|
||||
onEnable={setEnableTarget}
|
||||
onDisable={setDisableTarget}
|
||||
onEdit={openEdit}
|
||||
@@ -747,7 +745,7 @@ export function StaffPage() {
|
||||
type="button"
|
||||
className="p-2 rounded-md text-text-secondary hover:bg-background-card/80 hover:text-text-primary disabled:opacity-50"
|
||||
disabled={copyingInviteMembershipId === m.id}
|
||||
onClick={() => void copyStaffInviteLink(m)}
|
||||
onClick={() => copyStaffInviteLink(m)}
|
||||
aria-label={t('copyInviteLink')}
|
||||
title={t('copyInviteLinkTitle')}
|
||||
>
|
||||
@@ -930,7 +928,7 @@ export function StaffPage() {
|
||||
type="button"
|
||||
isLoading={inviteLoading}
|
||||
disabled={!inviteEmail.trim() || !inviteName.trim()}
|
||||
onClick={() => void submitInvite(false)}
|
||||
onClick={() => submitInvite(false)}
|
||||
>
|
||||
{t('sendInvite')}
|
||||
</Button>
|
||||
@@ -941,7 +939,7 @@ export function StaffPage() {
|
||||
type="button"
|
||||
variant="outline"
|
||||
isLoading={inviteLoading}
|
||||
onClick={() => void submitInvite(false)}
|
||||
onClick={() => submitInvite(false)}
|
||||
>
|
||||
{t('skipForNow')}
|
||||
</Button>
|
||||
@@ -949,7 +947,7 @@ export function StaffPage() {
|
||||
type="button"
|
||||
isLoading={inviteLoading}
|
||||
disabled={Boolean(inviteHoursValidationError)}
|
||||
onClick={() => void submitInvite(true)}
|
||||
onClick={() => submitInvite(true)}
|
||||
>
|
||||
{t('sendInvite')}
|
||||
</Button>
|
||||
@@ -1004,7 +1002,7 @@ export function StaffPage() {
|
||||
variant="primary"
|
||||
isLoading={enablingMembershipId === enableTarget.id}
|
||||
disabled={Boolean(enablingMembershipId) || !hasAvailableSeat}
|
||||
onClick={() => void confirmEnableMember()}
|
||||
onClick={() => confirmEnableMember()}
|
||||
>
|
||||
{t('enableMemberButton')}
|
||||
</Button>
|
||||
@@ -1054,7 +1052,7 @@ export function StaffPage() {
|
||||
variant="danger"
|
||||
isLoading={disablingMembershipId === disableTarget.id}
|
||||
disabled={Boolean(disablingMembershipId)}
|
||||
onClick={() => void confirmDisableMember()}
|
||||
onClick={() => confirmDisableMember()}
|
||||
>
|
||||
{t('disableMemberButton')}
|
||||
</Button>
|
||||
@@ -1136,7 +1134,7 @@ export function StaffPage() {
|
||||
{tCommon('next')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button type="button" isLoading={editLoading} onClick={() => void submitEdit()}>
|
||||
<Button type="button" isLoading={editLoading} onClick={() => submitEdit()}>
|
||||
{tCommon('save')}
|
||||
</Button>
|
||||
)
|
||||
@@ -1145,7 +1143,7 @@ export function StaffPage() {
|
||||
type="button"
|
||||
isLoading={editLoading}
|
||||
disabled={Boolean(editHoursValidationError)}
|
||||
onClick={() => void submitEdit()}
|
||||
onClick={() => submitEdit()}
|
||||
>
|
||||
{tCommon('save')}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user