From f252749d18b2e23b4aadba8de56400fdfe33882f Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Sun, 4 Oct 2026 10:38:16 +0330 Subject: [PATCH] feat(auth): referrer code at signup and agent code in profile Optional referrer agent code in registration with field validation UX. Show read-only agent referral code in profile edit and desktop overview. Co-authored-by: Cursor --- src/services/authService.ts | 11 ++- src/stores/auth.ts | 17 +++- src/utils/pendingRegister.ts | 3 + src/views/auth/OtpView.vue | 1 + src/views/auth/RegisterView.vue | 77 ++++++++++++++++++- src/views/profile/ProfileEditView.vue | 11 +++ .../profile/components/DesktopProfilePage.vue | 19 ++++- 7 files changed, 132 insertions(+), 7 deletions(-) diff --git a/src/services/authService.ts b/src/services/authService.ts index 8feb08d..ebfb863 100644 --- a/src/services/authService.ts +++ b/src/services/authService.ts @@ -10,6 +10,7 @@ type PendingOtp = { isRegister: boolean firstName?: string lastName?: string + referrerAgentCode?: string } let memoryPending: PendingOtp | null = null @@ -50,7 +51,12 @@ function setPendingOtp(value: PendingOtp | null) { export async function sendOtp( phone: string, - options: { firstName?: string; lastName?: string; isRegister: boolean }, + options: { + firstName?: string + lastName?: string + isRegister: boolean + referrerAgentCode?: string + }, ): Promise<{ success: boolean; message: string }> { const normalized = normalizePhone(phone) if (!/^09\d{9}$/.test(normalized)) { @@ -62,11 +68,13 @@ export async function sendOtp( } try { + const referrerAgentCode = options.referrerAgentCode?.trim() || undefined setPendingOtp({ phone: normalized, isRegister: options.isRegister, firstName: options.firstName, lastName: options.lastName, + referrerAgentCode, }) const res = await apiRequest<{ success: boolean; message: string; debugCode?: string }>( '/auth/otp/request', @@ -78,6 +86,7 @@ export async function sendOtp( firstName: options.firstName, lastName: options.lastName, isRegister: options.isRegister, + referrerAgentCode, }, }, ) diff --git a/src/stores/auth.ts b/src/stores/auth.ts index e303778..43d8926 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -50,7 +50,12 @@ export const useAuthStore = defineStore('auth', () => { async function requestOtp( phone: string, - options: { firstName?: string; lastName?: string; isRegister: boolean }, + options: { + firstName?: string + lastName?: string + isRegister: boolean + referrerAgentCode?: string + }, ) { loading.value = true error.value = null @@ -62,9 +67,16 @@ export const useAuthStore = defineStore('auth', () => { const firstName = options.firstName?.trim() || stored?.firstName const lastName = options.lastName?.trim() || stored?.lastName + const referrerAgentCode = + options.referrerAgentCode?.trim() || stored?.referrerAgentCode if (options.isRegister && firstName && lastName) { - pendingRegister.value = { firstName, lastName } + pendingRegister.value = { + firstName, + lastName, + jobCategory: stored?.jobCategory, + referrerAgentCode, + } setPendingRegister(pendingRegister.value) } @@ -72,6 +84,7 @@ export const useAuthStore = defineStore('auth', () => { isRegister: options.isRegister, firstName, lastName, + referrerAgentCode, }) if (!result.success) error.value = result.message return result diff --git a/src/utils/pendingRegister.ts b/src/utils/pendingRegister.ts index 886771d..075bd12 100644 --- a/src/utils/pendingRegister.ts +++ b/src/utils/pendingRegister.ts @@ -6,6 +6,7 @@ export type PendingRegister = { firstName: string lastName: string jobCategory?: JobCategory + referrerAgentCode?: string } export const JOB_CATEGORY_OPTIONS: Array<{ id: JobCategory; label: string }> = [ @@ -24,6 +25,7 @@ export function getPendingRegister(): PendingRegister | null { firstName: parsed.firstName.trim(), lastName: parsed.lastName.trim(), jobCategory: parsed.jobCategory, + referrerAgentCode: parsed.referrerAgentCode?.trim() || undefined, } } catch { return null @@ -38,6 +40,7 @@ export function setPendingRegister(value: PendingRegister | null) { firstName: value.firstName.trim(), lastName: value.lastName.trim(), jobCategory: value.jobCategory, + referrerAgentCode: value.referrerAgentCode?.trim() || undefined, }), ) return diff --git a/src/views/auth/OtpView.vue b/src/views/auth/OtpView.vue index a12ba52..917cdda 100644 --- a/src/views/auth/OtpView.vue +++ b/src/views/auth/OtpView.vue @@ -198,6 +198,7 @@ async function resend() { isRegister: isRegister.value, firstName: pending?.firstName, lastName: pending?.lastName, + referrerAgentCode: pending?.referrerAgentCode, }) if (result.success) { digits.value = Array.from({ length: OTP_LENGTH }, () => '') diff --git a/src/views/auth/RegisterView.vue b/src/views/auth/RegisterView.vue index 23b9e0b..486c125 100644 --- a/src/views/auth/RegisterView.vue +++ b/src/views/auth/RegisterView.vue @@ -36,6 +36,7 @@ const firstName = ref('') const lastName = ref('') const phone = ref('') const jobCategory = ref('garment_producer') +const referrerAgentCode = ref('') const acceptedTerms = ref(true) const fieldErrors = ref({}) const formError = ref('') @@ -80,6 +81,7 @@ async function submit() { firstName: firstName.value.trim(), lastName: lastName.value.trim(), jobCategory: jobCategory.value as JobCategory, + referrerAgentCode: referrerAgentCode.value.trim() || undefined, } setPendingRegister(names) @@ -87,11 +89,18 @@ async function submit() { isRegister: true, firstName: names.firstName, lastName: names.lastName, + referrerAgentCode: names.referrerAgentCode, }) if (result.success) { router.push({ name: 'otp', query: { phone: normalized, mode: 'register' } }) } else { - formError.value = result.message ?? 'خطا در ارسال کد تأیید.' + const msg = result.message ?? 'خطا در ارسال کد تأیید.' + if (msg.includes('کد واسطه معتبر نیست')) { + fieldErrors.value = { ...fieldErrors.value, referrerAgentCode: 'کد واسطه معتبر نیست' } + formError.value = '' + } else { + formError.value = msg + } } } @@ -143,6 +152,29 @@ async function submit() {

{{ fieldErrors.phone }}

+ +

+ اگر از طریق واسطه معرفی شده‌اید، کد واسطه را وارد کنید؛ در غیر این صورت این قسمت را خالی + بگذارید. +

+

+ {{ fieldErrors.referrerAgentCode }} +

+

دسته شغلی شما