Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
a82c7b1
add beta badge to workspace agents
s77rt Oct 22, 2026
ad9e8bf
Merge branch 'main' into company-agents-beta-label
s77rt Oct 22, 2026
6ad2a3a
move side effects out of useAgents hook
s77rt Oct 22, 2026
c8b3acb
clean up
s77rt Oct 22, 2026
6eb2512
add shouldOpenAgentsPage param
s77rt Oct 22, 2026
e91d02d
use useAgents hook to derive errors
s77rt Oct 22, 2026
1e8b902
add policy agents RBR
s77rt Oct 22, 2026
2fe4a2f
fix typo
s77rt Oct 22, 2026
360f97c
fix test
s77rt Oct 22, 2026
a3b1b74
add shouldOpenWorkspaceMembersPage param
s77rt Oct 22, 2026
2793193
Merge branch 'main' into company-agents-beta-label
s77rt Oct 25, 2026
adfe243
Revert "move side effects out of useAgents hook"
s77rt Oct 25, 2026
6516cdd
rename useAgents to useAgentsTable and useWorkspaceAgents to useWorks…
s77rt Oct 25, 2026
8e17ffc
add useAgents
s77rt Oct 25, 2026
0e95ed1
use useAgents
s77rt Oct 25, 2026
b128d2b
add useWorkspaceAgents
s77rt Oct 25, 2026
d145db7
remove side-effects from useWorkspaceMembers
s77rt Oct 25, 2026
9332fe9
remove api command effect from useAgentsTable
s77rt Oct 25, 2026
4e64720
remove api command effect from useWorkspaceAgentsTable
s77rt Oct 25, 2026
83536e9
update useWorkspaceAgentsTable to use useWorkspaceAgents
s77rt Oct 25, 2026
796f876
use useWorkspaceAgents when possible
s77rt Oct 25, 2026
5f163b6
add AgentUtils
s77rt Oct 25, 2026
f4fa16c
fix doesAgentHaveErrors logic
s77rt Oct 25, 2026
6aeb187
use useAgents when possible
s77rt Oct 25, 2026
3eecb43
remove unwanted space rendering
s77rt Oct 25, 2026
0b51ea6
add agents RBR in Accounts tab
s77rt Oct 25, 2026
dc30334
lint
s77rt Oct 25, 2026
9c540ac
add hasErrorsSelector
s77rt Oct 26, 2026
118b1d0
add filterDeletedAgents
s77rt Oct 26, 2026
9037216
add return type
s77rt Oct 26, 2026
19cba48
remove useAgents from useAccountIndicatorChecks
s77rt Oct 26, 2026
695dafc
remove useAgents from useAgentsTable
s77rt Oct 26, 2026
a2fb01d
remove useAgents from useWorkspaceAgents
s77rt Oct 26, 2026
863434e
remove useAgent from useInitialSettingsPageMenuData
s77rt Oct 26, 2026
950f7f5
remove useAgent from DynamicWorkspaceInvitePageContent
s77rt Oct 26, 2026
57dcd41
remove useAgent
s77rt Oct 26, 2026
df3ad22
lint
s77rt Oct 26, 2026
644ad7f
update selector to return array instead of Set
s77rt Oct 26, 2026
b0c5fb5
remove filterDeletedAgents and avoid heavy selector
s77rt Oct 26, 2026
2cdc81f
clear agent personal details optimistically
s77rt Oct 26, 2026
83598ec
Revert "clear agent personal details optimistically"
s77rt Oct 26, 2026
3d7cf2c
prevent inviting an agent that is being deleted
s77rt Oct 26, 2026
3aee3e0
rename for consistency
s77rt Oct 26, 2026
5daf9b6
clean up
s77rt Oct 26, 2026
feeee5f
use usePersonalDetailsByIDs
s77rt Oct 26, 2026
9085c4c
translate
s77rt Oct 26, 2026
4989c3e
lint
s77rt Oct 26, 2026
021f285
load agents same as we load members - consistency
s77rt Oct 26, 2026
310c979
better type and clean up
s77rt Oct 26, 2026
b084f26
push agentError to be last
s77rt Oct 26, 2026
561fa7a
merge main
s77rt Oct 27, 2026
cd1558f
restore .github unwanted changes
s77rt Oct 27, 2026
1d3a5dc
merge main
s77rt Oct 27, 2026
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/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9642,6 +9642,7 @@ const CONST = {
HAS_MERGE_HR_SETUP_NEEDED: 'hasMergeHRSetupNeeded',
HAS_HR_CONNECTION_ERROR: 'hasHRConnectionError',
HAS_APPROVAL_WORKFLOW_NON_MEMBER_APPROVER: 'hasApprovalWorkflowNonMemberApprover',
HAS_AGENT_ERRORS: 'hasAgentErrors',
},

DEBUG: {
Expand Down
4 changes: 4 additions & 0 deletions src/components/Navigation/DebugTabView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ function getSettingsMessage(status: IndicatorStatus | undefined): TranslationPat
return 'debug.indicatorStatus.completeHrSetup';
case CONST.INDICATOR_STATUS.HAS_HR_CONNECTION_ERROR:
return 'debug.indicatorStatus.theresAProblemWithAnHRConnection';
case CONST.INDICATOR_STATUS.HAS_AGENT_ERRORS:
return 'debug.indicatorStatus.theresAProblemWithYourAgent';
default:
return undefined;
}
Expand Down Expand Up @@ -139,6 +141,8 @@ function getSettingsRoute(status: IndicatorStatus | undefined, reimbursementAcco
case CONST.INDICATOR_STATUS.HAS_MERGE_HR_SETUP_NEEDED:
case CONST.INDICATOR_STATUS.HAS_HR_CONNECTION_ERROR:
return ROUTES.WORKSPACE_HR.getRoute(indicatorPolicyID);
case CONST.INDICATOR_STATUS.HAS_AGENT_ERRORS:
return ROUTES.SETTINGS_AGENTS;
default:
return undefined;
}
Expand Down
3 changes: 3 additions & 0 deletions src/hooks/useAccountIndicatorChecks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {hasPaymentMethodError} from '@libs/actions/PaymentMethods';
import {hasAgentErrorsSelector} from '@libs/AgentUtils';
import {hasPartiallySetupBankAccount, hasPersonalBankAccountMissingInfo} from '@libs/BankAccountUtils';
import {hasCardPendingDigitalWalletApproval, hasPendingExpensifyCardAction} from '@libs/CardUtils';
import {hasSubscriptionGreenDotInfo, hasSubscriptionRedDotError} from '@libs/SubscriptionUtils';
Expand Down Expand Up @@ -39,6 +40,7 @@ function useAccountIndicatorChecks(): AccountIndicatorChecksResult {
const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const [hasDeviceManagementErrorValue] = useOnyx(ONYXKEYS.LOGINS, {selector: hasDeviceManagementError});
const [hasAgentError] = useOnyx(ONYXKEYS.COLLECTION.AGENT, {selector: hasAgentErrorsSelector});

const {
companyCards: {shouldShowRBR: hasCompanyCardFeedErrors},
Expand Down Expand Up @@ -68,6 +70,7 @@ function useAccountIndicatorChecks(): AccountIndicatorChecksResult {
[CONST.INDICATOR_STATUS.HAS_EMPLOYEE_CARD_FEED_ERRORS]: !isPolicyAdmin ? hasCompanyCardFeedErrors : false,
[CONST.INDICATOR_STATUS.HAS_LOCKED_BANK_ACCOUNT]: Object.values(bankAccountList ?? {}).some((bankAccount) => bankAccount?.accountData?.state === CONST.BANK_ACCOUNT.STATE.LOCKED),
[CONST.INDICATOR_STATUS.HAS_DEVICE_MANAGEMENT_ERROR]: hasDeviceManagementErrorValue,
[CONST.INDICATOR_STATUS.HAS_AGENT_ERRORS]: !!hasAgentError,
};

const infoChecks: Partial<Record<IndicatorStatus, boolean>> = {
Expand Down
26 changes: 8 additions & 18 deletions src/hooks/useAgents.ts → src/hooks/useAgentsTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {usePersonalDetails} from '@components/OnyxListItemProvider';
import type {TableHandle} from '@components/Table';
import type {AgentRowData, AgentsTableColumnKey} from '@components/Tables/AgentsTable';

import {clearAgentDeleteError, clearAgentError, clearAgentUpdateError, deleteAgent, openAgentsPage} from '@libs/actions/Agent';
import {clearAgentDeleteError, clearAgentError, clearAgentUpdateError, deleteAgent} from '@libs/actions/Agent';
import {getRuleBotEnforcedPolicy} from '@libs/AgentRulesUtils';
import {getLatestError} from '@libs/ErrorUtils';
import {getAgentErrors} from '@libs/AgentUtils';
import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
import Navigation from '@libs/Navigation/Navigation';

Expand Down Expand Up @@ -43,11 +43,7 @@ function handleErrorClose(pendingAction: PendingAction | null | undefined, accou
/**
* Hook that derives the current user's manageable agent rows from Onyx and exposes selection and bulk-delete helpers for the Agents table.
*/
function useAgents() {
useEffect(() => {
openAgentsPage();
}, []);

function useAgentsTable() {
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const [allAgents] = useOnyx(ONYXKEYS.COLLECTION.AGENT);
Expand All @@ -72,8 +68,7 @@ function useAgents() {
}
const pendingAction = agent.pendingAction;
const isPendingDeletion = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;

if (!isOffline && isPendingDeletion) {
if (isPendingDeletion && !isOffline) {
return [];
}

Expand All @@ -92,13 +87,7 @@ function useAgents() {
ownerDisplayName = domainNameSelector(domain) ?? (ownerDetails?.login ? Str.extractEmailDomain(ownerDetails.login) : undefined);
}

const mergedErrors = {
...getLatestError(agent.errors ?? undefined),
...getLatestError(agent.nameErrors ?? undefined),
...getLatestError(agent.promptErrors ?? undefined),
...getLatestError(agent.avatarErrors ?? undefined),
};
const rowErrors = getLatestError(mergedErrors);
const agentErrors = getAgentErrors(agent);

return [
{
Expand All @@ -111,7 +100,7 @@ function useAgents() {
ownerType: agent.ownerType,
ownerPolicyID,
pendingAction,
errors: Object.keys(rowErrors).length > 0 ? rowErrors : undefined,
errors: Object.keys(agentErrors ?? {}).length > 0 ? agentErrors : undefined,
disabled: isPendingDeletion,
canManage: true,
action: () => Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.AGENT_EDIT.getRoute(accountID))),
Expand Down Expand Up @@ -169,6 +158,7 @@ function useAgents() {
}
clearSelectedAgents();
};

const askForConfirmationToDelete = async () => {
const ruleBotEnforcedPolicy = selectedAgentKeys.map((accountIDString) => getRuleBotEnforcedPolicy(Number(accountIDString), allPolicies)).find(Boolean);
if (ruleBotEnforcedPolicy) {
Expand All @@ -194,4 +184,4 @@ function useAgents() {
return {agents, selectedAgentKeys, setSelectedAgents, clearSelectedAgents, askForConfirmationToDelete, tableRef};
}

export default useAgents;
export default useAgentsTable;
78 changes: 33 additions & 45 deletions src/hooks/useWorkspaceAgents.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,59 @@
import CONST from '@src/CONST';
import type {Policy} from '@src/types/onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Agent, Policy} from '@src/types/onyx';

import type {OnyxEntry} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';

import useAgents from './useAgents';
import useNetwork from './useNetwork';
import useOnyx from './useOnyx';
import useWorkspaceAccountID from './useWorkspaceAccountID';
import useWorkspaceMembers from './useWorkspaceMembers';

/**
* Hook that returns the agent rows for a workspace: agents the user can manage joined with their workspace role, plus read-only rows for custom-agent members the user cannot manage.
* Hook that derives the policy's agents, including both agents owned by the policy and member agents.
*/
function useWorkspaceAgents(policy: OnyxEntry<Policy>) {
const {isOffline} = useNetwork();
const [allAgents] = useOnyx(ONYXKEYS.COLLECTION.AGENT);
const policyID = policy?.id;
const workspaceAccountID = useWorkspaceAccountID(policyID);
const workspaceMembers = useWorkspaceMembers(policy);
const policyRoles = Object.values(CONST.POLICY.ROLE);

const {agents, ...rest} = useAgents();
const workspaceAgents = agents.flatMap((agent) => {
const agentMembership = workspaceMembers.find((member) => member.accountID === agent.accountID);
const isAgentOwnedByWorkspace = agent.ownerAccountID === workspaceAccountID;
const isAgentMemberOfWorkspace = !!agentMembership;
if (!isAgentOwnedByWorkspace && !isAgentMemberOfWorkspace) {
return [];
}
// Attach the workspace role to the agent row. The agent object is local to this flatMap and not shared
// eslint-disable-next-line no-param-reassign
agent.role = policyRoles.find((policyRole) => policyRole === agentMembership?.policyEmployee.role);
return [agent];
});
const manageableWorkspaceAgents: OnyxCollection<Agent> = Object.fromEntries(
Object.entries(allAgents ?? {}).filter(([key, agent]) => {
if (!agent) {
return false;
}
const isPendingDeletion = agent.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
if (isPendingDeletion && !isOffline) {
return false;
}
const accountID = Number(key.slice(ONYXKEYS.COLLECTION.AGENT.length));
const isAgentOwnedByWorkspace = agent.ownerAccountID === workspaceAccountID;
const isAgentMemberOfWorkspace = !!workspaceMembers.find((member) => member.accountID === accountID);
if (!isAgentOwnedByWorkspace && !isAgentMemberOfWorkspace) {
return false;
}
return true;
}),
);
const manageableWorkspaceAgentsIDs = new Set(Object.keys(manageableWorkspaceAgents).map((key) => Number(key.slice(ONYXKEYS.COLLECTION.AGENT.length))));

// The useAgents hook only includes agents that the user can manage
// We need to include other agents in the workspace too
const manageableAgentAccountIDs = new Set(workspaceAgents.map(({accountID}) => accountID));
for (const workspaceMember of workspaceMembers) {
const {policyEmployee, accountID, details} = workspaceMember;
const nonManageableWorkspaceAgentsIDs: number[] = [];
for (const {accountID, details} of workspaceMembers) {
if (!details.isCustomAgent) {
continue;
}
if (manageableAgentAccountIDs.has(accountID)) {
continue;
}
const pendingAction = policyEmployee.pendingAction;
const isPendingDeletion = pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;
if (!isOffline && isPendingDeletion) {
if (manageableWorkspaceAgentsIDs.has(accountID)) {
continue;
}
workspaceAgents.push({
keyForList: String(accountID),
accountID,
displayName: details.displayName ?? details.login ?? '',
login: details.login ?? '',
role: policyRoles.find((policyRole) => policyRole === policyEmployee.role),
pendingAction,
disabled: true,
isSelectionDisabled: true,
canManage: false,
action: () => {},
onChatPress: () => {},
onCopilotPress: () => {},
dismissError: () => {},
});
nonManageableWorkspaceAgentsIDs.push(accountID);
}

return {agents: workspaceAgents, ...rest};
return {
manageableWorkspaceAgents,
nonManageableWorkspaceAgentsIDs,
};
}

export default useWorkspaceAgents;
73 changes: 73 additions & 0 deletions src/hooks/useWorkspaceAgentsTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type {AgentRowData} from '@components/Tables/AgentsTable';

import Log from '@libs/Log';

import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Policy} from '@src/types/onyx';

import type {OnyxEntry} from 'react-native-onyx';

import useAgentsTable from './useAgentsTable';
import useWorkspaceAgents from './useWorkspaceAgents';
import useWorkspaceMembers from './useWorkspaceMembers';

/**
* Hook that returns the agent rows for a workspace: agents the user can manage joined with their workspace role, plus read-only rows for custom-agent members the user cannot manage.
*/
function useWorkspaceAgentsTable(policy: OnyxEntry<Policy>) {
const policyID = policy?.id;
const policyRoles = Object.values(CONST.POLICY.ROLE);
const workspaceMembers = useWorkspaceMembers(policy);

const {agents, ...rest} = useAgentsTable();
const {manageableWorkspaceAgents, nonManageableWorkspaceAgentsIDs} = useWorkspaceAgents(policy);

const workspaceAgents: AgentRowData[] = [];
for (const key of Object.keys(manageableWorkspaceAgents)) {
const accountID = Number(key.slice(ONYXKEYS.COLLECTION.AGENT.length));
const agent = agents.find((agentItem) => agentItem.accountID === accountID);

if (!agent) {
Log.warn('Manageable agent is not found in agents list', {accountID, policyID});
continue;
}

// Attach role if agent is a member of the policy
const agentMembership = workspaceMembers.find((member) => member.accountID === accountID);
if (agentMembership) {
const role = agentMembership.policyEmployee.role;
agent.role = policyRoles.find((policyRole) => policyRole === role);
}

workspaceAgents.push(agent);
}
for (const accountID of nonManageableWorkspaceAgentsIDs) {
const agentMembership = workspaceMembers.find((member) => member.accountID === accountID);

if (!agentMembership) {
Log.warn('Non-manageable agent is not found in members list', {accountID, policyID});
continue;
}

workspaceAgents.push({
keyForList: String(accountID),
accountID,
displayName: agentMembership.details.displayName ?? agentMembership.details.login ?? '',
login: agentMembership.details.login ?? '',
role: policyRoles.find((policyRole) => policyRole === agentMembership.policyEmployee.role),
pendingAction: agentMembership.policyEmployee.pendingAction,
disabled: true,
isSelectionDisabled: true,
canManage: false,
action: () => {},
onChatPress: () => {},
onCopilotPress: () => {},
dismissError: () => {},
});
}

return {agents: workspaceAgents, ...rest};
}

export default useWorkspaceAgentsTable;
31 changes: 5 additions & 26 deletions src/hooks/useWorkspaceMembers.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,31 @@
import {openWorkspaceMembersPage} from '@libs/actions/Policy/Member';
import {arePaymentsEnabled, shouldFilterExpensifyTeam, isDeletedPolicyEmployee, isExpensifyTeam, isPolicyAdmin, canMemberRead, getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils';
import {shouldFilterExpensifyTeam, isDeletedPolicyEmployee, isExpensifyTeam, getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils';
import {generateAccountID} from '@libs/UserUtils';

import CONST from '@src/CONST';
import type {PersonalDetails, Policy, PolicyEmployee} from '@src/types/onyx';
import {isEmptyValueObject} from '@src/types/utils/EmptyObject';

import type {OnyxEntry} from 'react-native-onyx';

import {useEffectEvent, useEffect} from 'react';

import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
import useLocalize from './useLocalize';
import useNetwork from './useNetwork';
import {usePersonalDetailsByLogins} from './usePersonalDetailByLogin';
import {useAllPersonalDetails} from './usePersonalDetails';
import {usePersonalDetailsByIDs} from './usePersonalDetails';

/**
* Hook that returns a workspace's members joined with personal details, filling in fallback identities when details haven't loaded and filtering out Expensify team members on Expensify-owned policies.
*/
function useWorkspaceMembers(policy: OnyxEntry<Policy>) {
const policyID = policy?.id;
const policyOwner = policy?.owner;

const {formatPhoneNumber} = useLocalize();
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const currentUserLogin = currentUserPersonalDetails.login;
const employeePersonalDetails = usePersonalDetailsByLogins(Object.keys(policy?.employeeList ?? {}));
const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(policy?.employeeList, employeePersonalDetails, true);
const policyMemberAccountIDs = Object.values(policyMemberEmailsToAccountIDs);
const shouldFilter = shouldFilterExpensifyTeam(policyOwner, currentUserLogin);
const [personalDetails] = useAllPersonalDetails();

const getWorkspaceMembers = () => {
if (!policyID) {
return;
}
if (!canMemberRead(policy, currentUserPersonalDetails.login ?? '', CONST.POLICY.POLICY_FEATURE.MEMBERS)) {
return;
}
const clientMemberEmails = Object.keys(getMemberAccountIDsForWorkspace(policy?.employeeList, employeePersonalDetails));
openWorkspaceMembersPage(policyID, clientMemberEmails);
};
const {isOffline} = useNetwork({onReconnect: getWorkspaceMembers});
const getWorkspaceMembersEvent = useEffectEvent(() => getWorkspaceMembers());
const shouldShowMemberBankAccounts = isPolicyAdmin(policy) && arePaymentsEnabled(policy);

// The bank accounts are only returned while the workspace shows them, so load the members again when that changes.
useEffect(() => getWorkspaceMembersEvent(), [shouldShowMemberBankAccounts]);
const [personalDetails] = usePersonalDetailsByIDs(policyMemberAccountIDs);
const {isOffline} = useNetwork();

const result: Array<{email: string; policyEmployee: PolicyEmployee; accountID: number; details: PersonalDetails}> = [];
for (const [email, policyEmployee] of Object.entries(policy?.employeeList ?? {})) {
Expand Down
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11939,6 +11939,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
aBankAccountIsLocked: 'Ein Bankkonto ist gesperrt',
completeHrSetup: 'HR-Einrichtung abschließen',
theresAProblemWithAnHRConnection: 'Es gibt ein Problem mit einer HR-Verbindung',
theresAProblemWithYourAgent: 'Es gibt ein Problem mit Ihrem/Ihren Agent(en)',
},
},
emptySearchView: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/el.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12155,6 +12155,7 @@ ${reportName}`,
aBankAccountIsLocked: 'Ένας τραπεζικός λογαριασμός είναι κλειδωμένος',
completeHrSetup: 'Ολοκληρώστε τη ρύθμιση HR',
theresAProblemWithAnHRConnection: 'Υπάρχει πρόβλημα με μια σύνδεση HR',
theresAProblemWithYourAgent: 'Υπάρχει πρόβλημα με τον/τους εκπρόσωπό σας',
},
},
emptySearchView: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12206,6 +12206,7 @@ const translations = {
aBankAccountIsLocked: 'A bank account is locked',
completeHrSetup: 'Complete HR setup',
theresAProblemWithAnHRConnection: "There's a problem with an HR connection",
theresAProblemWithYourAgent: "There's a problem with your agent(s)",
},
},
emptySearchView: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12122,6 +12122,7 @@ ${reportName}`,
aBankAccountIsLocked: 'Una cuenta bancaria está bloqueada',
completeHrSetup: 'Completa la configuración de RR. HH.',
theresAProblemWithAnHRConnection: 'Hay un problema con una conexión de RR. HH.',
theresAProblemWithYourAgent: 'Hay un problema con tu(s) agente(s)',
},
},
emptySearchView: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11965,6 +11965,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
aBankAccountIsLocked: 'Un compte bancaire est verrouillé',
completeHrSetup: 'Terminer la configuration RH',
theresAProblemWithAnHRConnection: 'Un problème est survenu avec une connexion RH',
theresAProblemWithYourAgent: 'Il y a un problème avec votre/vos agent(s)',
},
},
emptySearchView: {
Expand Down
Loading
Loading