From 07534df7fa596155fa3ec19d2369ccfdc7611c3e Mon Sep 17 00:00:00 2001 From: ShridharGoel <35566748+ShridharGoel@users.noreply.github.com> Date: Wed, 13 May 2026 20:10:15 +0530 Subject: [PATCH 1/8] Show Gusto sync results --- src/components/GustoSyncResultsModal.tsx | 125 +++++++++++++++++++ src/hooks/useGustoSyncResultsModal.ts | 50 ++++++++ src/languages/en.ts | 8 ++ src/languages/es.ts | 8 ++ src/pages/workspace/WorkspaceMembersPage.tsx | 3 + src/pages/workspace/hr/WorkspaceHRPage.tsx | 5 + 6 files changed, 199 insertions(+) create mode 100644 src/components/GustoSyncResultsModal.tsx create mode 100644 src/hooks/useGustoSyncResultsModal.ts diff --git a/src/components/GustoSyncResultsModal.tsx b/src/components/GustoSyncResultsModal.tsx new file mode 100644 index 000000000000..ed2cea58d1c0 --- /dev/null +++ b/src/components/GustoSyncResultsModal.tsx @@ -0,0 +1,125 @@ +import React, {useState} from 'react'; +import {View} from 'react-native'; +import Button from '@components/Button'; +import FixedFooter from '@components/FixedFooter'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import Icon from '@components/Icon'; +import Modal from '@components/Modal'; +import type {ModalProps} from '@components/Modal/Global/ModalContext'; +import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; +import ScreenWrapper from '@components/ScreenWrapper'; +import ScrollView from '@components/ScrollView'; +import Text from '@components/Text'; +import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import type {GustoSyncResult, GustoSyncResultUser} from '@libs/API/GustoSyncResult'; +import CONST from '@src/CONST'; + +type GustoSyncResultsModalProps = ModalProps & { + /** Sync result returned by the completed Gusto sync job */ + result: GustoSyncResult; +}; + +function getResultCount(users?: GustoSyncResultUser[]) { + return users?.length ?? 0; +} + +function GustoSyncResultsModal({result, closeModal}: GustoSyncResultsModalProps) { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const theme = useTheme(); + const icons = useMemoizedLazyExpensifyIcons(['DownArrow', 'Sync']); + const illustrations = useMemoizedLazyIllustrations(['NewUser']); + const [isSkippedSectionExpanded, setIsSkippedSectionExpanded] = useState(false); + + const addedCount = getResultCount(result.added); + const removedCount = getResultCount(result.removed); + const skippedCount = getResultCount(result.skipped); + const closeResultsModal = () => closeModal(); + + const renderResultSummary = (label: string, count: number) => ( + + {label} + {translate('workspace.hr.gusto.syncResults.employeeCount', {count})} + + ); + + return ( + + + + + + + + + + + {translate('workspace.hr.gusto.syncResults.successTitle')} + {renderResultSummary(translate('workspace.hr.gusto.syncResults.added'), addedCount)} + {renderResultSummary(translate('workspace.hr.gusto.syncResults.removed'), removedCount)} + setIsSkippedSectionExpanded((isExpanded) => !isExpanded)} + style={[styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter]} + > + + {translate('workspace.hr.gusto.syncResults.skipped')} + {translate('workspace.hr.gusto.syncResults.employeeCount', {count: skippedCount})} + + + + {isSkippedSectionExpanded && + result.skipped?.map((user) => ( + + {user.displayName ?? user.email} + {user.reason} + + ))} + + +