fix: resend invite when invitation expired

This commit is contained in:
Ritvik Sardana
2026-05-27 12:04:41 +05:30
parent 15b9ba83b1
commit bbe713154b
4 changed files with 55 additions and 17 deletions
+10 -4
View File
@@ -16,8 +16,8 @@
<p class="font-medium text-ink-gray-8 text-xl">
{{ avatar.label }}
</p>
<Tooltip text="Invite sent. Waiting for the user to accept.">
<Badge v-if="props.badge" :label="props.badge" :theme="'orange'" />
<Tooltip v-if="badge" :text="badge.tooltip ?? ''">
<Badge :label="badge.label" :theme="badge.theme ?? 'orange'" />
</Tooltip>
</div>
<div v-if="!isMobileView" class="flex items-center gap-x-1.5">
@@ -64,15 +64,21 @@ interface DocInfoItem {
condition?: boolean;
}
interface BadgeInfo {
label: string;
theme?: "gray" | "blue" | "green" | "orange" | "red";
tooltip?: string;
}
const props = withDefaults(
defineProps<{
avatar: AvatarProps;
docInfo?: DocInfoItem[];
badge?: string;
badge?: BadgeInfo | null;
}>(),
{
docInfo: () => [],
badge: () => "",
badge: null,
}
);
+10 -2
View File
@@ -419,11 +419,19 @@ export function useContactInvite() {
const isLoading = ref(false);
// @ts-expect-error
const { updateOnboardingStep } = useOnboarding("helpdesk");
async function resendInvite(name: string): Promise<void> {
async function resendInvite(
invitationName: string,
status: string | undefined,
contactName: string,
email: string | undefined
): Promise<void> {
if (status === "Expired") {
return inviteAsUser(contactName, email);
}
try {
isLoading.value = true;
await call("frappe.core.api.user_invitation.resend_invitation", {
name,
name: invitationName,
app_name: "helpdesk",
});
toast.success(__("Invitation email resent successfully"));
+29 -8
View File
@@ -17,7 +17,7 @@
shape: 'circle',
}"
:doc-info="contactInfo"
:badge="invitationName && __('Invited')"
:badge="invitationBadge"
>
<template #actions>
<div class="flex gap-2 items-center">
@@ -212,15 +212,30 @@ const { resetPassword, isLoading: isResetPasswordLoading } =
const showEditDialog = ref(false);
const invitationName = computed(
() => contact.getInfo.data?.invitation_name || ""
);
const invitation = computed(() => contact.getInfo.data?.invitation);
const invitationBadge = computed(() => {
const inv = invitation.value;
if (!inv?.name) return null;
if (inv.status === "Expired") {
return {
label: __("Invitation Expired"),
theme: "red" as const,
tooltip: __("Invitation expired. Resend to invite again."),
};
}
return {
label: __("Invited"),
theme: "orange" as const,
tooltip: __("Invite sent. Waiting for the user to accept."),
};
});
const showDeleteDialog = ref(false);
const dropdownActions = computed(() => {
const baseActions = [];
if (!contact.doc?.user && !invitationName.value) {
if (!contact.doc?.user && !invitation.value?.name) {
baseActions.push({
label: __("Invite as User"),
icon: "user-plus",
@@ -230,12 +245,18 @@ const dropdownActions = computed(() => {
},
});
}
if (invitationName.value) {
if (invitation.value?.name) {
baseActions.push({
label: __("Resend Invite"),
icon: "mail",
onClick: () => {
resendInvite(invitationName.value);
onClick: async () => {
await resendInvite(
invitation.value!.name,
invitation.value!.status,
props.id,
contact.doc?.email_id
);
contact.getInfo.reload();
},
});
}
+6 -3
View File
@@ -11,20 +11,23 @@ class CustomContact(Contact):
rating = self.get_avg_rating()
customers = get_customers_with_image(self.name)
invitation_name = frappe.db.exists(
invitation = frappe.db.get_value(
"User Invitation",
{
"contact": self.name,
"status": "Pending",
"status": ["!=", "Accepted"],
"email": self.email_ids[0].email_id,
"app_name": "helpdesk",
},
["name", "status"],
as_dict=True,
order_by="creation desc",
)
result = {
"rating": rating,
"customers": customers,
"invitation_name": invitation_name,
"invitation": invitation,
}
if self.user: