Skip to content

Commit f10230d

Browse files
Merge pull request #6677 from frappe/mergify/bp/master/pr-6676
fix(partner-onboarding): Add optimistic updates for better perf and ux (backport #6676)
2 parents 6684ebb + d904450 commit f10230d

2 files changed

Lines changed: 37 additions & 18 deletions

File tree

dashboard/src/onboarding/modal/PartnerRegistration.vue

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<script setup lang="ts">
2-
import { createResource, FormControl } from 'frappe-ui'
2+
import { createResource, FormControl, Tooltip } from 'frappe-ui'
33
import { computed, inject, onMounted, ref, useTemplateRef, watch } from 'vue'
44
import EmailInput from '@/components/EmailInput.vue'
55
import PhoneInput from '@/components/PhoneInput.vue'
66
import PostRegistrationMessage from '@/onboarding/modal/PostRegistrationMessage.vue'
77
import { usePartnerOnboarding } from '@/onboarding/usePartnerOnboarding'
8+
import LucideInfo from '~icons/lucide/info'
89
910
const emit = defineEmits(['registered'])
1011
@@ -101,9 +102,14 @@ const handleSubmit = async () => {
101102
102103
try {
103104
await onboarding.save()
104-
await onboarding.loadMRRStatus()
105105
registered.value = true
106106
emit('registered')
107+
// Fetch MRR in the background (fire-and-forget). It isn't shown on the
108+
// success screen, and the query can be slow against a large Invoice table,
109+
// so it must not block registration. We still trigger it here because the
110+
// modal can be opened from the partner-onboarding page itself — in which
111+
// case "Continue" doesn't re-navigate and the page's load() won't re-run.
112+
void onboarding.loadMRRStatus()
107113
} catch (error: any) {
108114
// Backend validation (e.g. the Phone field) wraps values in <strong>
109115
// tags via frappe.bold(); strip them so they don't render as literal
@@ -148,16 +154,25 @@ function stripHtmlTags(value: string) {
148154
{{ errors.company_name }}
149155
</p>
150156

151-
<FormControl
152-
v-model="onboarding.form.registered_country"
153-
label="Registered country"
154-
type="select"
155-
size="sm"
156-
variant="outline"
157-
placeholder="Select"
158-
:options="countryOptions"
159-
:class="{ 'has-error': errors.country }"
160-
/>
157+
<div class="flex flex-col gap-1.5">
158+
<div class="flex items-end gap-1">
159+
<label class="block text-xs text-ink-gray-5">Registered country</label>
160+
<Tooltip
161+
text="You'll be listed as a partner in this country, subject to approval and verification."
162+
>
163+
<LucideInfo class="h-3 w-3 text-ink-gray-5" />
164+
</Tooltip>
165+
</div>
166+
<FormControl
167+
v-model="onboarding.form.registered_country"
168+
type="select"
169+
size="sm"
170+
variant="outline"
171+
placeholder="Select"
172+
:options="countryOptions"
173+
:class="{ 'has-error': errors.country }"
174+
/>
175+
</div>
161176
<p v-if="errors.country" class="-mt-2 text-sm text-ink-red-4">
162177
{{ errors.country }}
163178
</p>

dashboard/src/onboarding/usePartnerOnboarding.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,13 @@ const savePartnerOnboarding = createResource({
259259
onSuccess: (nextDoc: PartnerOnboardingDoc) => {
260260
const wasRegistered = Boolean(doc.value?.name)
261261
applyDoc(nextDoc, activeTeam.value)
262-
// First registration creates the record — reload the team so the
263-
// sidebar surfaces the "Partnership" item (see NavList.vue / Sidebar.vue).
264-
if (!wasRegistered && nextDoc?.name) {
265-
void activeTeam.value?.reload?.()
262+
// First registration only needs the sidebar to surface the "Partnership"
263+
// item (see NavList.vue / Sidebar.vue). The backend doesn't mutate the
264+
// Team here — the sole delta is the computed `has_partner_onboarding`
265+
// flag — so set it optimistically instead of triggering a heavy full
266+
// Team reload (balance, billing, subscriptions, ...).
267+
if (!wasRegistered && nextDoc?.name && activeTeam.value?.doc) {
268+
activeTeam.value.doc.has_partner_onboarding = true
266269
}
267270
},
268271
})
@@ -335,8 +338,9 @@ export function usePartnerOnboarding(team?: TeamResource) {
335338
resetMRRStatus()
336339
return nextDoc
337340
}
338-
await loadCertificateStatus()
339-
await loadMRRStatus()
341+
// Certificate and MRR status are independent — fetch them concurrently so
342+
// the partner-onboarding page renders without waiting on a serial chain.
343+
await Promise.all([loadCertificateStatus(), loadMRRStatus()])
340344
return nextDoc
341345
}
342346

0 commit comments

Comments
 (0)