From 570dcf69b483148d7cadf4d0a063560da55f4474 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Wed, 24 Dec 2025 23:26:59 +0500 Subject: [PATCH 1/6] Add vacation delegate handling to StatusPage with active delegations check --- .../Profile/CustomStatus/StatusPage.tsx | 83 ++++++++++++------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/src/pages/settings/Profile/CustomStatus/StatusPage.tsx b/src/pages/settings/Profile/CustomStatus/StatusPage.tsx index c741fd7ff3c7..243793bff6bd 100644 --- a/src/pages/settings/Profile/CustomStatus/StatusPage.tsx +++ b/src/pages/settings/Profile/CustomStatus/StatusPage.tsx @@ -58,6 +58,7 @@ function StatusPage() { const [vacationDelegate] = useOnyx(ONYXKEYS.NVP_PRIVATE_VACATION_DELEGATE, {canBeMissing: true}); const hasVacationDelegate = !!vacationDelegate?.delegate; + const hasActiveDelegations = (vacationDelegate?.delegatorFor?.length ?? 0) > 0; const vacationDelegatePersonalDetails = getPersonalDetailByEmail(vacationDelegate?.delegate ?? ''); const formattedDelegateLogin = formatPhoneNumber(vacationDelegatePersonalDetails?.login ?? ''); @@ -264,35 +265,61 @@ function StatusPage() { )} - {translate('statusPage.setVacationDelegate')} - {hasVacationDelegate && {translate('statusPage.vacationDelegate')}} - {hasVacationDelegate ? ( - clearVacationDelegateError(vacationDelegate?.previousDelegate)} - > - Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)} - containerStyle={styles.pr2} - /> - + {translate('statusPage.vacationDelegate')} + {hasActiveDelegations ? ( + + {translate('statusPage.cannotSetVacationDelegate')} + {vacationDelegate?.delegatorFor?.map((delegatorEmail) => { + const delegatorPersonalDetails = getPersonalDetailByEmail(delegatorEmail); + const formattedDelegatorLogin = formatPhoneNumber(delegatorPersonalDetails?.login ?? ''); + const delegatorDisplayText = formattedDelegatorLogin === '' ? delegatorEmail : formattedDelegatorLogin; + return ( + + ); + })} + ) : ( - - Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)} - containerStyle={styles.pr2} - /> + + {translate('statusPage.setVacationDelegate')} + {hasVacationDelegate && {translate('statusPage.vacationDelegate')}} + {hasVacationDelegate ? ( + clearVacationDelegateError(vacationDelegate?.previousDelegate)} + > + Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)} + containerStyle={styles.pr2} + /> + + ) : ( + + Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)} + containerStyle={styles.pr2} + /> + + )} )} From 888da9b6e87126de23e4cc44728f5461410dfe0a Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Wed, 24 Dec 2025 23:27:35 +0500 Subject: [PATCH 2/6] Add delegatorFor field to VacationDelegate type --- src/types/onyx/VacationDelegate.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/onyx/VacationDelegate.ts b/src/types/onyx/VacationDelegate.ts index 54870c8ebf23..0d3ac4b8d29d 100644 --- a/src/types/onyx/VacationDelegate.ts +++ b/src/types/onyx/VacationDelegate.ts @@ -8,6 +8,9 @@ type VacationDelegate = OnyxCommon.OnyxValueWithOfflineFeedback<{ /** Email of the vacation delegate */ delegate?: string; + /** Array of emails for users that the current user is delegating for */ + delegatorFor?: string[]; + /** Previous delegate for rollback on failure */ previousDelegate?: string; From 669b77d32061b35b62f9763cb1feca311c5f3c32 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Wed, 24 Dec 2025 23:28:38 +0500 Subject: [PATCH 3/6] add cannotSetVacationDelegate message in all locals --- src/languages/de.ts | 1 + src/languages/en.ts | 1 + src/languages/es.ts | 1 + src/languages/fr.ts | 1 + src/languages/it.ts | 1 + src/languages/ja.ts | 1 + src/languages/nl.ts | 1 + src/languages/pl.ts | 1 + src/languages/pt-BR.ts | 1 + src/languages/zh-hans.ts | 1 + 10 files changed, 10 insertions(+) diff --git a/src/languages/de.ts b/src/languages/de.ts index 0dbc0abb96a7..7038b5b1c683 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -3030,6 +3030,7 @@ ${ whenClearStatus: 'Wann sollen wir deinen Status löschen?', vacationDelegate: 'Urlaubsvertreter', setVacationDelegate: `Legen Sie eine Urlaubsvertretung fest, die Berichte in Ihrer Abwesenheit in Ihrem Namen genehmigt.`, + cannotSetVacationDelegate: `Du kannst keinen Urlaubsvertreter festlegen, da du derzeit der Vertreter für die folgenden Mitglieder bist:`, vacationDelegateError: 'Beim Aktualisieren deines Urlaubsvertreters ist ein Fehler aufgetreten.', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `als Urlaubsvertretung von ${nameOrEmail}`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `an ${submittedToName} als Urlaubsvertreter für ${vacationDelegateName}`, diff --git a/src/languages/en.ts b/src/languages/en.ts index 48bd86e513e2..2891d15c2485 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2988,6 +2988,7 @@ const translations = { whenClearStatus: 'When should we clear your status?', vacationDelegate: 'Vacation delegate', setVacationDelegate: `Set a vacation delegate to approve reports on your behalf while you're out of office.`, + cannotSetVacationDelegate: `You can't set a vacation delegate because you're currently the delegate for the following members:`, vacationDelegateError: 'There was an error updating your vacation delegate.', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `as ${nameOrEmail}'s vacation delegate`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `to ${submittedToName} as vacation delegate for ${vacationDelegateName}`, diff --git a/src/languages/es.ts b/src/languages/es.ts index 7c1b88d59db1..b543fdf4501e 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2676,6 +2676,7 @@ ${amount} para ${merchant} - ${date}`, whenClearStatus: '¿Cuándo deberíamos borrar tu estado?', vacationDelegate: 'Delegado de vacaciones', setVacationDelegate: 'Configura un delegado de vacaciones para aprobar informes en tu nombre mientras estás fuera de la oficina.', + cannotSetVacationDelegate: `No puedes establecer un delegado de vacaciones porque actualmente eres el delegado de los siguientes miembros:`, vacationDelegateError: 'Hubo un error al actualizar tu delegado de vacaciones.', asVacationDelegate: ({nameOrEmail: managerName}) => `como delegado de vacaciones de ${managerName}`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}) => `a ${submittedToName} como delegado de vacaciones de ${vacationDelegateName}`, diff --git a/src/languages/fr.ts b/src/languages/fr.ts index ae5ac067e1a2..8885986070ad 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -3034,6 +3034,7 @@ ${ whenClearStatus: 'Quand devons-nous effacer votre statut ?', vacationDelegate: 'Délégué de vacances', setVacationDelegate: `Définissez un délégué de vacances pour approuver les rapports en votre nom pendant que vous êtes absent du bureau.`, + cannotSetVacationDelegate: `Vous ne pouvez pas définir un délégué de vacances car vous êtes actuellement le délégué des membres suivants :`, vacationDelegateError: 'Une erreur s’est produite lors de la mise à jour de votre délégué de vacances.', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `en tant que délégué de vacances de ${nameOrEmail}`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => diff --git a/src/languages/it.ts b/src/languages/it.ts index b370b5ddebee..50d837adc8ac 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -3018,6 +3018,7 @@ ${ whenClearStatus: 'Quando dovremmo cancellare il tuo stato?', vacationDelegate: 'Delegato ferie', setVacationDelegate: `Imposta un delegato per le vacanze che approvi i report per tuo conto mentre sei fuori ufficio.`, + cannotSetVacationDelegate: `Non puoi impostare un delegato per le ferie perché al momento sei il delegato per i seguenti membri:`, vacationDelegateError: "Si è verificato un errore durante l'aggiornamento del tuo delegato per le ferie.", asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `come delegato per le vacanze di ${nameOrEmail}`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `a ${submittedToName} come delegato per le ferie di ${vacationDelegateName}`, diff --git a/src/languages/ja.ts b/src/languages/ja.ts index b04db3fc0ecd..3800c863e6d0 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -3011,6 +3011,7 @@ ${ whenClearStatus: 'ステータスをいつクリアしますか?', vacationDelegate: '休暇代理人', setVacationDelegate: `休暇中に代理承認者を設定して、不在の間にあなたの代わりにレポートを承認してもらいましょう。`, + cannotSetVacationDelegate: `現在、次のメンバーの代理人になっているため、休暇代理人を設定できません:`, vacationDelegateError: '休暇代理人の更新中にエラーが発生しました。', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `${nameOrEmail} の休暇代理として`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `${vacationDelegateName} の休暇代理人として ${submittedToName} に`, diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 975dcd6e1f67..c13e0cf1eb2a 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -3015,6 +3015,7 @@ ${ whenClearStatus: 'Wanneer moeten we je status wissen?', vacationDelegate: 'Vakantie-gemachtigde', setVacationDelegate: `Stel een vervangende goedkeurder in om rapporten namens jou te accorderen terwijl je afwezig bent.`, + cannotSetVacationDelegate: `Je kunt geen vakantiedelegaat instellen omdat je momenteel de delegaat bent voor de volgende leden:`, vacationDelegateError: 'Er is een fout opgetreden bij het bijwerken van je vervanger tijdens vakantie.', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `als ${nameOrEmail}'s plaatsvervanger tijdens vakantie`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `aan ${submittedToName} als vakantiemachtiging voor ${vacationDelegateName}`, diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 4a8bc42f3359..cc14141faf02 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -3012,6 +3012,7 @@ ${ whenClearStatus: 'Kiedy powinniśmy wyczyścić Twój status?', vacationDelegate: 'Zastępca urlopowy', setVacationDelegate: `Ustaw zastępcę na czas urlopu, aby zatwierdzał raporty w Twoim imieniu, gdy jesteś poza biurem.`, + cannotSetVacationDelegate: `Nie możesz ustawić delegata urlopowego, ponieważ obecnie jesteś delegatem dla następujących członków:`, vacationDelegateError: 'Wystąpił błąd podczas aktualizowania Twojego zastępcy urlopowego.', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `jako zastępca urlopowy ${nameOrEmail}`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `do ${submittedToName} jako zastępca urlopowy dla ${vacationDelegateName}`, diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 58c21f2b9120..980f42251be9 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -3012,6 +3012,7 @@ ${ whenClearStatus: 'Quando devemos limpar seu status?', vacationDelegate: 'Delegado de férias', setVacationDelegate: `Defina um delegado de férias para aprovar relatórios em seu nome enquanto você estiver fora do escritório.`, + cannotSetVacationDelegate: `Você não pode definir um delegado de férias porque atualmente é o delegado dos seguintes membros:`, vacationDelegateError: 'Ocorreu um erro ao atualizar o seu delegado de férias.', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `como representante de férias de ${nameOrEmail}`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index ae12b55b034d..88a94338b93e 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -2973,6 +2973,7 @@ ${ whenClearStatus: '我们应何时清除你的状态?', vacationDelegate: '休假代理', setVacationDelegate: `设置一个休假代理,在你不在办公室时代你审批报销报告。`, + cannotSetVacationDelegate: `由于你目前是以下成员的代理人,因此无法设置休假代理人:`, vacationDelegateError: '更新你的休假代理时出错。', asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `作为 ${nameOrEmail} 的休假代理`, toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `作为 ${vacationDelegateName} 的休假代理,提交给 ${submittedToName}`, From d5a8f71b68a0148cd8479b06b1c353044e5063bb Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Thu, 25 Dec 2025 00:33:02 +0500 Subject: [PATCH 4/6] fix: set interactive false for delegator MenuItem component in StatusPage --- src/pages/settings/Profile/CustomStatus/StatusPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Profile/CustomStatus/StatusPage.tsx b/src/pages/settings/Profile/CustomStatus/StatusPage.tsx index 243793bff6bd..de4b64187d85 100644 --- a/src/pages/settings/Profile/CustomStatus/StatusPage.tsx +++ b/src/pages/settings/Profile/CustomStatus/StatusPage.tsx @@ -283,6 +283,7 @@ function StatusPage() { iconType={CONST.ICON_TYPE_AVATAR} numberOfLinesDescription={1} containerStyle={[styles.pr2, styles.mt1]} + interactive={false} /> ); })} From 1dfe78c5dcd6bc2161ab30a458beae314eb9ba48 Mon Sep 17 00:00:00 2001 From: Samran Ahmed Date: Thu, 25 Dec 2025 00:39:52 +0500 Subject: [PATCH 5/6] add error page for users with active vacation delegations --- .../settings/Profile/CustomStatus/VacationDelegatePage.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pages/settings/Profile/CustomStatus/VacationDelegatePage.tsx b/src/pages/settings/Profile/CustomStatus/VacationDelegatePage.tsx index 2d09aa9960f7..6048000a9823 100644 --- a/src/pages/settings/Profile/CustomStatus/VacationDelegatePage.tsx +++ b/src/pages/settings/Profile/CustomStatus/VacationDelegatePage.tsx @@ -18,6 +18,7 @@ import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; import Navigation from '@libs/Navigation/Navigation'; import {getHeaderMessage} from '@libs/OptionsListUtils'; import {getPersonalDetailByEmail} from '@libs/PersonalDetailsUtils'; +import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -35,6 +36,7 @@ function VacationDelegatePage() { const [vacationDelegate] = useOnyx(ONYXKEYS.NVP_PRIVATE_VACATION_DELEGATE, {canBeMissing: true}); const currentVacationDelegate = vacationDelegate?.delegate; const delegatePersonalDetails = getPersonalDetailByEmail(currentVacationDelegate ?? ''); + const hasActiveDelegations = (vacationDelegate?.delegatorFor?.length ?? 0) > 0; const icons = useMemoizedLazyExpensifyIcons(['FallbackAvatar']); const excludeLogins = useMemo( @@ -164,6 +166,10 @@ function VacationDelegatePage() { searchInServer(debouncedSearchTerm); }, [debouncedSearchTerm]); + if (hasActiveDelegations) { + return ; + } + return ( <> Date: Fri, 26 Dec 2025 14:15:47 +0500 Subject: [PATCH 6/6] refactor: extract delegator list rendering into a separate function in StatusPage --- .../Profile/CustomStatus/StatusPage.tsx | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/pages/settings/Profile/CustomStatus/StatusPage.tsx b/src/pages/settings/Profile/CustomStatus/StatusPage.tsx index de4b64187d85..e4f2eee2771b 100644 --- a/src/pages/settings/Profile/CustomStatus/StatusPage.tsx +++ b/src/pages/settings/Profile/CustomStatus/StatusPage.tsx @@ -191,6 +191,32 @@ function StatusPage() { const {inputCallbackRef, inputRef} = useAutoFocusInput(); const fallbackVacationDelegateLogin = formattedDelegateLogin === '' ? vacationDelegate?.delegate : formattedDelegateLogin; + const renderDelegatorList = () => { + if (!vacationDelegate?.delegatorFor) { + return null; + } + + return vacationDelegate.delegatorFor.map((delegatorEmail) => { + const delegatorDetails = getPersonalDetailByEmail(delegatorEmail); + const formattedLogin = formatPhoneNumber(delegatorDetails?.login ?? ''); + const displayLogin = formattedLogin || delegatorEmail; + + return ( + + ); + }); + }; + return ( {translate('statusPage.cannotSetVacationDelegate')} - {vacationDelegate?.delegatorFor?.map((delegatorEmail) => { - const delegatorPersonalDetails = getPersonalDetailByEmail(delegatorEmail); - const formattedDelegatorLogin = formatPhoneNumber(delegatorPersonalDetails?.login ?? ''); - const delegatorDisplayText = formattedDelegatorLogin === '' ? delegatorEmail : formattedDelegatorLogin; - return ( - - ); - })} + {renderDelegatorList()} ) : (