Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3011,6 +3011,7 @@ ${
whenClearStatus: 'ステータスをいつクリアしますか?',
vacationDelegate: '休暇代理人',
setVacationDelegate: `休暇中に代理承認者を設定して、不在の間にあなたの代わりにレポートを承認してもらいましょう。`,
cannotSetVacationDelegate: `現在、次のメンバーの代理人になっているため、休暇代理人を設定できません:`,
vacationDelegateError: '休暇代理人の更新中にエラーが発生しました。',
asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `${nameOrEmail} の休暇代理として`,
toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `${vacationDelegateName} の休暇代理人として ${submittedToName} に`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2973,6 +2973,7 @@ ${
whenClearStatus: '我们应何时清除你的状态?',
vacationDelegate: '休假代理',
setVacationDelegate: `设置一个休假代理,在你不在办公室时代你审批报销报告。`,
cannotSetVacationDelegate: `由于你目前是以下成员的代理人,因此无法设置休假代理人:`,
vacationDelegateError: '更新你的休假代理时出错。',
asVacationDelegate: ({nameOrEmail}: VacationDelegateParams) => `作为 ${nameOrEmail} 的休假代理`,
toAsVacationDelegate: ({submittedToName, vacationDelegateName}: SubmittedToVacationDelegateParams) => `作为 ${vacationDelegateName} 的休假代理,提交给 ${submittedToName}`,
Expand Down
93 changes: 65 additions & 28 deletions src/pages/settings/Profile/CustomStatus/StatusPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import InputWrapper from '@components/Form/InputWrapper';
import type {FormInputErrors, FormOnyxValues, FormRef} from '@components/Form/types';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';

Check warning on line 9 in src/pages/settings/Profile/CustomStatus/StatusPage.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'@components/Icon/Expensicons' import is restricted from being used by a pattern. Direct imports from Icon/Expensicons are deprecated. Please use lazy loading hooks instead. Use `useMemoizedLazyExpensifyIcons` from @hooks/useLazyAsset. See docs/LAZY_ICONS_AND_ILLUSTRATIONS.md for details

Check warning on line 9 in src/pages/settings/Profile/CustomStatus/StatusPage.tsx

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

'@components/Icon/Expensicons' import is restricted from being used. Direct imports from @components/Icon/Expensicons are deprecated. Please use lazy loading hooks instead. Use `useMemoizedLazyExpensifyIcons` from @hooks/useLazyAsset. See docs/LAZY_ICONS_AND_ILLUSTRATIONS.md for details
import MenuItem from '@components/MenuItem';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
Expand Down Expand Up @@ -58,6 +58,7 @@

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 ?? '');

Expand Down Expand Up @@ -190,6 +191,32 @@
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 (
<MenuItem
key={delegatorEmail}
title={delegatorDetails?.displayName ?? displayLogin}
description={displayLogin}
avatarID={delegatorDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID}
icon={delegatorDetails?.avatar ?? Expensicons.FallbackAvatar}
iconType={CONST.ICON_TYPE_AVATAR}
numberOfLinesDescription={1}
containerStyle={[styles.pr2, styles.mt1]}
interactive={false}
/>
);
});
};

return (
<ScreenWrapper
style={[StyleUtils.getBackgroundColorStyle(theme.PAGE_THEMES[SCREENS.SETTINGS.PROFILE.STATUS].backgroundColor)]}
Expand Down Expand Up @@ -264,35 +291,45 @@
)}
</View>
<View style={[styles.mb2, styles.mt6]}>
<Text style={[styles.mh5]}>{translate('statusPage.setVacationDelegate')}</Text>
{hasVacationDelegate && <Text style={[styles.mh5, styles.mt6, styles.mutedTextLabel]}>{translate('statusPage.vacationDelegate')}</Text>}
{hasVacationDelegate ? (
<OfflineWithFeedback
pendingAction={vacationDelegate?.pendingAction}
errors={vacationDelegate?.errors}
errorRowStyles={styles.mh5}
onClose={() => clearVacationDelegateError(vacationDelegate?.previousDelegate)}
>
<MenuItem
title={vacationDelegatePersonalDetails?.displayName ?? fallbackVacationDelegateLogin}
description={fallbackVacationDelegateLogin}
avatarID={vacationDelegatePersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID}
icon={vacationDelegatePersonalDetails?.avatar ?? Expensicons.FallbackAvatar}
iconType={CONST.ICON_TYPE_AVATAR}
numberOfLinesDescription={1}
shouldShowRightIcon
onPress={() => Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)}
containerStyle={styles.pr2}
/>
</OfflineWithFeedback>
<Text style={[styles.headerText, styles.mh5, styles.mb2]}>{translate('statusPage.vacationDelegate')}</Text>
{hasActiveDelegations ? (
<View>
<Text style={[styles.mh5, styles.mb4]}>{translate('statusPage.cannotSetVacationDelegate')}</Text>
{renderDelegatorList()}
</View>
) : (
<View style={[styles.mt1]}>
<MenuItem
description={translate('statusPage.vacationDelegate')}
shouldShowRightIcon
onPress={() => Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)}
containerStyle={styles.pr2}
/>
<View>
<Text style={[styles.mh5]}>{translate('statusPage.setVacationDelegate')}</Text>
{hasVacationDelegate && <Text style={[styles.mh5, styles.mt6, styles.mutedTextLabel]}>{translate('statusPage.vacationDelegate')}</Text>}
{hasVacationDelegate ? (
<OfflineWithFeedback
pendingAction={vacationDelegate?.pendingAction}
errors={vacationDelegate?.errors}
errorRowStyles={styles.mh5}
onClose={() => clearVacationDelegateError(vacationDelegate?.previousDelegate)}
>
<MenuItem
title={vacationDelegatePersonalDetails?.displayName ?? fallbackVacationDelegateLogin}
description={fallbackVacationDelegateLogin}
avatarID={vacationDelegatePersonalDetails?.accountID ?? CONST.DEFAULT_NUMBER_ID}
icon={vacationDelegatePersonalDetails?.avatar ?? Expensicons.FallbackAvatar}
iconType={CONST.ICON_TYPE_AVATAR}
numberOfLinesDescription={1}
shouldShowRightIcon
onPress={() => Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)}
containerStyle={styles.pr2}
/>
</OfflineWithFeedback>
) : (
<View style={[styles.mt1]}>
<MenuItem
description={translate('statusPage.vacationDelegate')}
shouldShowRightIcon
onPress={() => Navigation.navigate(ROUTES.SETTINGS_VACATION_DELEGATE)}
containerStyle={styles.pr2}
/>
</View>
)}
</View>
)}
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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(
Expand Down Expand Up @@ -164,6 +166,10 @@ function VacationDelegatePage() {
searchInServer(debouncedSearchTerm);
}, [debouncedSearchTerm]);

if (hasActiveDelegations) {
return <NotFoundPage />;
}

return (
<>
<ScreenWrapper
Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/VacationDelegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
Loading