diff --git a/src/CONST/index.ts b/src/CONST/index.ts index e13ba87a9aa9..ce29675f4df6 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -7455,6 +7455,8 @@ const CONST = { POLICY_NAME: this.TABLE_COLUMNS.POLICY_NAME, CARD: this.TABLE_COLUMNS.CARD, CATEGORY: this.TABLE_COLUMNS.CATEGORY, + ATTENDEES: this.TABLE_COLUMNS.ATTENDEES, + TOTAL_PER_ATTENDEE: this.TABLE_COLUMNS.TOTAL_PER_ATTENDEE, TAG: this.TABLE_COLUMNS.TAG, EXCHANGE_RATE: this.TABLE_COLUMNS.EXCHANGE_RATE, ORIGINAL_AMOUNT: this.TABLE_COLUMNS.ORIGINAL_AMOUNT, @@ -7578,6 +7580,8 @@ const CONST = { this.TABLE_COLUMNS.MERCHANT, this.TABLE_COLUMNS.FROM, this.TABLE_COLUMNS.CATEGORY, + this.TABLE_COLUMNS.ATTENDEES, + this.TABLE_COLUMNS.TOTAL_PER_ATTENDEE, this.TABLE_COLUMNS.TAG, this.TABLE_COLUMNS.TOTAL_AMOUNT, ], @@ -7679,6 +7683,8 @@ const CONST = { BILLABLE: 'billable', TAX_RATE: 'taxrate', TOTAL_AMOUNT: 'amount', + ATTENDEES: 'attendees', + TOTAL_PER_ATTENDEE: 'totalPerAttendee', TOTAL: 'total', TYPE: 'type', ACTION: 'action', diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index cdf0c718b078..be1f3efb319a 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -266,8 +266,9 @@ function MoneyRequestReportTransactionList({ shouldShowBillableColumn, shouldShowReimbursableColumn: hasNonReimbursableTransactions(transactions), reportCurrency: report?.currency, + policy, }); - }, [transactions, currentUserDetails?.accountID, isExpenseReportViewFromIOUReport, shouldShowBillableColumn, reportDetailsColumns, report?.currency]); + }, [currentUserDetails?.accountID, transactions, isExpenseReportViewFromIOUReport, reportDetailsColumns, shouldShowBillableColumn, report?.currency, policy]); const {windowWidth, windowHeight} = useWindowDimensions(); const minTableWidth = getTableMinWidth(columnsToShow); diff --git a/src/components/Search/SearchList/ListItem/AttendeesCell.tsx b/src/components/Search/SearchList/ListItem/AttendeesCell.tsx new file mode 100644 index 000000000000..ea45c07ee33d --- /dev/null +++ b/src/components/Search/SearchList/ListItem/AttendeesCell.tsx @@ -0,0 +1,136 @@ +import React from 'react'; +import {View} from 'react-native'; +import Avatar from '@components/Avatar'; +import Text from '@components/Text'; +import Tooltip from '@components/Tooltip'; +import UserDetailsTooltip from '@components/UserDetailsTooltip'; +import useDefaultAvatars from '@hooks/useDefaultAvatars'; +import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import useStyleUtils from '@hooks/useStyleUtils'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {getUserDetailTooltipText, sortIconsByName} from '@libs/ReportUtils'; +import {getDefaultAvatar} from '@libs/UserAvatarUtils'; +import colors from '@styles/theme/colors'; +import variables from '@styles/variables'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {Attendee} from '@src/types/onyx/IOU'; +import type {Icon as IconType} from '@src/types/onyx/OnyxCommon'; + +type AttendeesCellProps = { + attendees: Attendee[]; + isHovered: boolean; + isPressed: boolean; +}; + +function AttendeesCell({attendees, isHovered, isPressed}: AttendeesCellProps) { + const defaultAvatars = useDefaultAvatars(); + const attendeeIcons: IconType[] = attendees.map((attendee) => ({ + id: attendee.accountID ?? CONST.DEFAULT_NUMBER_ID, + name: attendee.displayName ?? attendee.email, + source: (attendee.avatarUrl || getDefaultAvatar({accountID: attendee.accountID, accountEmail: attendee.email, defaultAvatars})) ?? '', + type: CONST.ICON_TYPE_AVATAR, + })); + + const theme = useTheme(); + const styles = useThemeStyles(); + const StyleUtils = useStyleUtils(); + const {localeCompare, formatPhoneNumber} = useLocalize(); + + const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); + + const size = CONST.AVATAR_SIZE.SMALLER; + const maxAvatarsInRow = CONST.AVATAR_ROW_SIZE.DEFAULT; + const oneAvatarSize = StyleUtils.getAvatarStyle(size); + const oneAvatarBorderWidth = StyleUtils.getAvatarBorderWidth(size).borderWidth ?? 0; + const overlapSize = oneAvatarSize.width / 3 + 2 * oneAvatarBorderWidth; + const height = oneAvatarSize.height; + const avatarContainerStyles = StyleUtils.combineStyles([styles.alignItemsCenter, styles.flexRow, StyleUtils.getHeight(height), styles.overflowHidden]); + + const icons = sortIconsByName(attendeeIcons, personalDetails, localeCompare); + const tooltipTexts = icons.map((icon) => getUserDetailTooltipText(Number(icon.id), formatPhoneNumber, icon.name)); + + return ( + + {[...icons].splice(0, maxAvatarsInRow).map((icon, index) => ( + + + + + + ))} + {icons.length > maxAvatarsInRow && ( + + + + {`+${icons.length - maxAvatarsInRow}`} + + + + )} + + ); +} + +export default AttendeesCell; diff --git a/src/components/Search/SearchTableHeader.tsx b/src/components/Search/SearchTableHeader.tsx index 60931f20c28f..7ac9cc87beb3 100644 --- a/src/components/Search/SearchTableHeader.tsx +++ b/src/components/Search/SearchTableHeader.tsx @@ -82,6 +82,14 @@ const getExpenseHeaders = (groupBy?: SearchGroupBy): SearchColumnConfig[] => [ columnName: CONST.SEARCH.TABLE_COLUMNS.CATEGORY, translationKey: 'common.category', }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.ATTENDEES, + translationKey: 'iou.attendees', + }, + { + columnName: CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE, + translationKey: 'iou.totalPerAttendee', + }, { columnName: CONST.SEARCH.TABLE_COLUMNS.TAG, translationKey: 'common.tag', diff --git a/src/components/TransactionItemRow/index.tsx b/src/components/TransactionItemRow/index.tsx index ff78b83014fe..c4db37bd52b7 100644 --- a/src/components/TransactionItemRow/index.tsx +++ b/src/components/TransactionItemRow/index.tsx @@ -7,6 +7,7 @@ import type {TransactionWithOptionalHighlight} from '@components/MoneyRequestRep import {PressableWithFeedback} from '@components/Pressable'; import RadioButton from '@components/RadioButton'; import ActionCell from '@components/Search/SearchList/ListItem/ActionCell'; +import AttendeesCell from '@components/Search/SearchList/ListItem/AttendeesCell'; import DateCell from '@components/Search/SearchList/ListItem/DateCell'; import ExportedIconCell from '@components/Search/SearchList/ListItem/ExportedIconCell'; import StatusCell from '@components/Search/SearchList/ListItem/StatusCell'; @@ -16,6 +17,7 @@ import UserInfoCell from '@components/Search/SearchList/ListItem/UserInfoCell'; import WorkspaceCell from '@components/Search/SearchList/ListItem/WorkspaceCell'; import type {SearchColumnType, TableColumnSize} from '@components/Search/types'; import Text from '@components/Text'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; @@ -29,6 +31,9 @@ import {getReportName} from '@libs/ReportNameUtils'; import {isExpenseReport, isIOUReport, isSettled} from '@libs/ReportUtils'; import StringUtils from '@libs/StringUtils'; import { + getAmount, + getAttendees, + getCurrency, getDescription, getExchangeRate, getMerchant, @@ -43,6 +48,7 @@ import { isScanning, isTimeRequest, isUnreportedAndHasInvalidDistanceRateTransaction, + shouldShowAttendees as shouldShowAttendeesUtils, } from '@libs/TransactionUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; @@ -202,6 +208,7 @@ function TransactionItemRow({ const hasCategoryOrTag = !isCategoryMissing(transactionItem?.category) || !!transactionItem.tag; const createdAt = getTransactionCreated(transactionItem); const expensicons = useMemoizedLazyExpensifyIcons(['ArrowRight']); + const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const transactionThreadReportID = reportActions ? getIOUActionForTransactionID(reportActions, transactionItem.transactionID)?.childReportID : undefined; const isDateColumnWide = dateColumnSize === CONST.SEARCH.TABLE_COLUMN_SIZES.WIDE; @@ -267,6 +274,21 @@ function TransactionItemRow({ return transactionItem.cardName; }, [transactionItem.cardID, transactionItem.cardName, transactionItem.isCardFeedDeleted, customCardNames, translate]); + const transactionAttendees = useMemo(() => getAttendees(transactionItem, currentUserPersonalDetails), [transactionItem, currentUserPersonalDetails]); + + const shouldShowAttendees = shouldShowAttendeesUtils(CONST.IOU.TYPE.SUBMIT, policy) && transactionAttendees.length > 0; + + const totalPerAttendee = useMemo(() => { + const attendeesCount = transactionAttendees.length ?? 0; + const totalAmount = getAmount(transactionItem); + + if (!attendeesCount || totalAmount === undefined) { + return undefined; + } + + return totalAmount / attendeesCount; + }, [transactionAttendees.length, transactionItem]); + const renderColumn = (column: SearchColumnType): React.ReactNode => { switch (column) { case CONST.SEARCH.TABLE_COLUMNS.TYPE: @@ -495,6 +517,21 @@ function TransactionItemRow({ ); + case CONST.SEARCH.TABLE_COLUMNS.ATTENDEES: + return ( + + {shouldShowAttendees && ( + + )} + + ); case CONST.SEARCH.TABLE_COLUMNS.COMMENTS: return ( ); + case CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE: + return ( + + {shouldShowAttendees && ( + + )} + + ); case CONST.SEARCH.TABLE_COLUMNS.ORIGINAL_AMOUNT: return ( = { bookingArchived: 'Diese Buchung ist archiviert', bookingArchivedDescription: 'Diese Buchung ist archiviert, weil das Reisedatum verstrichen ist. Füge bei Bedarf eine Ausgabe für den endgültigen Betrag hinzu.', attendees: 'Teilnehmende', + totalPerAttendee: 'Pro Teilnehmendem', whoIsYourAccountant: 'Wer ist Ihre Steuerberaterin bzw. Ihr Steuerberater?', paymentComplete: 'Zahlung abgeschlossen', time: 'Zeit', diff --git a/src/languages/en.ts b/src/languages/en.ts index a88b7dc2cd64..24acd3ef3459 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1594,6 +1594,7 @@ const translations = { bookingArchived: 'This booking is archived', bookingArchivedDescription: 'This booking is archived because the trip date has passed. Add an expense for the final amount if needed.', attendees: 'Attendees', + totalPerAttendee: 'Per attendee', whoIsYourAccountant: 'Who is your accountant?', paymentComplete: 'Payment complete', time: 'Time', diff --git a/src/languages/es.ts b/src/languages/es.ts index 94ea3d6623bb..f15bfdb59752 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1462,6 +1462,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'Esta reserva está archivada', bookingArchivedDescription: 'Esta reserva está archivada porque la fecha del viaje ha pasado. Agregue un gasto por el monto final si es necesario.', attendees: 'Asistentes', + totalPerAttendee: 'Por asistente', whoIsYourAccountant: '¿Quién es tu contador?', paymentComplete: 'Pago completo', time: 'Tiempo', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 119438e3629f..a3224ff22aad 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -1545,6 +1545,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'Cette réservation est archivée', bookingArchivedDescription: 'Cette réservation est archivée car la date du voyage est passée. Ajoutez une dépense pour le montant final si nécessaire.', attendees: 'Participants', + totalPerAttendee: 'Par participant', whoIsYourAccountant: 'Qui est votre comptable ?', paymentComplete: 'Paiement terminé', time: 'Heure', diff --git a/src/languages/it.ts b/src/languages/it.ts index c9c8209d4063..244bb2670053 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -1543,6 +1543,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'Questa prenotazione è archiviata', bookingArchivedDescription: 'Questa prenotazione è archiviata perché la data del viaggio è passata. Aggiungi una spesa per l’importo finale, se necessario.', attendees: 'Partecipanti', + totalPerAttendee: 'Per partecipante', whoIsYourAccountant: 'Chi è il tuo commercialista?', paymentComplete: 'Pagamento completato', time: 'Ora', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 407a92f60fec..b01a5e7da7ae 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -1524,6 +1524,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'この予約はアーカイブされています', bookingArchivedDescription: 'この予約は旅行日が過ぎたためアーカイブされています。必要に応じて、最終金額の経費を追加してください。', attendees: '参加者', + totalPerAttendee: '参加者ごと', whoIsYourAccountant: 'あなたの会計士は誰ですか?', paymentComplete: '支払いが完了しました', time: '時間', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index dbe5744bc7fb..eaa391a667fb 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -1540,6 +1540,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'Deze boeking is gearchiveerd', bookingArchivedDescription: 'Deze boeking is gearchiveerd omdat de reisdatum is verstreken. Voeg indien nodig een uitgave toe voor het eindbedrag.', attendees: 'Deelnemers', + totalPerAttendee: 'Per deelnemer', whoIsYourAccountant: 'Wie is jouw accountant?', paymentComplete: 'Betaling voltooid', time: 'Tijd', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index d61887f0ed3e..75a83832ea73 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -1538,6 +1538,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'Ta rezerwacja jest zarchiwizowana', bookingArchivedDescription: 'Ta rezerwacja została zarchiwizowana, ponieważ data podróży już minęła. W razie potrzeby dodaj wydatek na ostateczną kwotę.', attendees: 'Uczestnicy', + totalPerAttendee: 'Na uczestnika', whoIsYourAccountant: 'Kim jest twój księgowy?', paymentComplete: 'Płatność zakończona', time: 'Czas', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index b335a965bae3..0106d0328629 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -1537,6 +1537,7 @@ const translations: TranslationDeepObject = { bookingArchived: 'Esta reserva está arquivada', bookingArchivedDescription: 'Esta reserva está arquivada porque a data da viagem já passou. Adicione uma despesa com o valor final, se necessário.', attendees: 'Participantes', + totalPerAttendee: 'Por participante', whoIsYourAccountant: 'Quem é seu contador?', paymentComplete: 'Pagamento concluído', time: 'Hora', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 91512e9023c0..dc4a7b881869 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -1490,6 +1490,7 @@ const translations: TranslationDeepObject = { bookingArchived: '此预订已归档', bookingArchivedDescription: '此预订已归档,因为行程日期已过。如有需要,请为最终金额添加一笔报销。', attendees: '参与者', + totalPerAttendee: '每位参与者', whoIsYourAccountant: '你的会计是谁?', paymentComplete: '付款完成', time: '时间', diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 0741324ed4f5..65e763540f27 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -168,6 +168,7 @@ import { isPending, isScanning, isViolationDismissed, + shouldShowAttendees, } from './TransactionUtils'; import {isInvalidMerchantValue} from './ValidationUtils'; import ViolationsUtils from './Violations/ViolationsUtils'; @@ -439,6 +440,8 @@ type TransactionKey = `${typeof ONYXKEYS.COLLECTION.TRANSACTION}${string}`; type ReportActionKey = `${typeof ONYXKEYS.COLLECTION.REPORT_ACTIONS}${string}`; +type PolicyKey = `${typeof ONYXKEYS.COLLECTION.POLICY}${string}`; + type ViolationKey = `${typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${string}`; type SearchGroupKey = `${typeof CONST.SEARCH.GROUP_PREFIX}${string}`; @@ -1196,6 +1199,13 @@ function isTransactionEntry(key: string): key is TransactionKey { return key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION); } +/** + * @private + */ +function isPolicyEntry(key: string): key is PolicyKey { + return key.startsWith(ONYXKEYS.COLLECTION.POLICY); +} + /** * Determines whether to display the merchant field based on the transactions in the search results. */ @@ -3578,6 +3588,10 @@ function getSearchColumnTranslationKey(column: SearchColumnType): TranslationPat return 'common.to'; case CONST.SEARCH.TABLE_COLUMNS.CATEGORY: return 'common.category'; + case CONST.SEARCH.TABLE_COLUMNS.ATTENDEES: + return 'iou.attendees'; + case CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE: + return 'iou.totalPerAttendee'; case CONST.SEARCH.TABLE_COLUMNS.RECEIPT: return 'common.receipt'; case CONST.SEARCH.TABLE_COLUMNS.TAG: @@ -4457,6 +4471,7 @@ function getColumnsToShow({ shouldShowReimbursableColumn = false, reportCurrency, shouldUseStrictDefaultExpenseColumns = false, + policy, }: { currentAccountID: number | undefined; data: OnyxTypes.SearchResults['data'] | OnyxTypes.Transaction[]; @@ -4467,8 +4482,9 @@ function getColumnsToShow({ isExpenseReportViewFromIOUReport?: boolean; shouldShowBillableColumn?: boolean; shouldShowReimbursableColumn?: boolean; - reportCurrency?: string; shouldUseStrictDefaultExpenseColumns?: boolean; + policy?: OnyxTypes.Policy; + reportCurrency?: string; }): SearchColumnType[] { if (type === CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT) { const defaultReportColumns: SearchColumnType[] = [ @@ -4577,6 +4593,8 @@ function getColumnsToShow({ [CONST.SEARCH.TABLE_COLUMNS.MERCHANT]: false, [CONST.SEARCH.TABLE_COLUMNS.DESCRIPTION]: false, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: false, + [CONST.SEARCH.TABLE_COLUMNS.ATTENDEES]: false, + [CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE]: false, [CONST.SEARCH.TABLE_COLUMNS.TAG]: false, [CONST.SEARCH.TABLE_COLUMNS.CARD]: false, [CONST.SEARCH.TABLE_COLUMNS.TAX_RATE]: false, @@ -4605,6 +4623,8 @@ function getColumnsToShow({ [CONST.SEARCH.TABLE_COLUMNS.POLICY_NAME]: false, [CONST.SEARCH.TABLE_COLUMNS.CARD]: false, [CONST.SEARCH.TABLE_COLUMNS.CATEGORY]: false, + [CONST.SEARCH.TABLE_COLUMNS.ATTENDEES]: false, + [CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE]: false, [CONST.SEARCH.TABLE_COLUMNS.TAG]: false, [CONST.SEARCH.TABLE_COLUMNS.REIMBURSABLE]: false, [CONST.SEARCH.TABLE_COLUMNS.BILLABLE]: false, @@ -4786,8 +4806,18 @@ function getColumnsToShow({ for (const item of data) { updateColumns(item); } + if (shouldShowAttendees(CONST.IOU.TYPE.SUBMIT, policy)) { + columns[CONST.SEARCH.TABLE_COLUMNS.ATTENDEES] = true; + columns[CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE] = true; + } } else { for (const key of Object.keys(data)) { + if (isPolicyEntry(key)) { + if (shouldShowAttendees(CONST.IOU.TYPE.SUBMIT, data[key])) { + columns[CONST.SEARCH.TABLE_COLUMNS.ATTENDEES] = true; + columns[CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE] = true; + } + } if (!isTransactionEntry(key)) { continue; } diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 32aced2e6338..e34689a6ea67 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -1177,7 +1177,7 @@ function getReportOwnerAsAttendee(transaction: OnyxInputOrEntry, cu accountID: creatorAccountID, text: creatorDisplayName, searchText: creatorDisplayName, - avatarUrl: creatorDetails?.avatarThumbnail ?? '', + avatarUrl: (creatorDetails?.avatarThumbnail ?? creatorDetails?.avatar ?? '') as string, selected: true, }; } diff --git a/src/styles/utils/index.ts b/src/styles/utils/index.ts index 1cac4503552e..06b0adaedc25 100644 --- a/src/styles/utils/index.ts +++ b/src/styles/utils/index.ts @@ -834,6 +834,7 @@ type AvatarBorderStyleParams = { isInReportAction: boolean; shouldUseCardBackground: boolean; isActive?: boolean; + customPressedBorderColor?: string; }; function getHorizontalStackedAvatarBorderStyle({ @@ -843,6 +844,7 @@ function getHorizontalStackedAvatarBorderStyle({ isInReportAction = false, shouldUseCardBackground = false, isActive = false, + customPressedBorderColor, }: AvatarBorderStyleParams): ViewStyle { let borderColor = shouldUseCardBackground ? theme.cardBG : theme.appBG; @@ -855,6 +857,9 @@ function getHorizontalStackedAvatarBorderStyle({ if (isPressed) { borderColor = isInReportAction ? theme.hoverComponentBG : theme.buttonPressedBG; + if (customPressedBorderColor) { + borderColor = customPressedBorderColor; + } } return {borderColor}; @@ -863,9 +868,9 @@ function getHorizontalStackedAvatarBorderStyle({ /** * Get computed avatar styles based on position and border size */ -function getHorizontalStackedAvatarStyle(index: number, overlapSize: number): ViewStyle { +function getHorizontalStackedAvatarStyle(index: number, overlapSize: number, firstAvatarMarginLeft = 0): ViewStyle { return { - marginLeft: index > 0 ? -overlapSize : 0, + marginLeft: index > 0 ? -overlapSize : firstAvatarMarginLeft, zIndex: index + 2, }; } @@ -1853,6 +1858,7 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ case CONST.SEARCH.TABLE_COLUMNS.ORIGINAL_AMOUNT: case CONST.SEARCH.TABLE_COLUMNS.TOTAL_AMOUNT: case CONST.SEARCH.TABLE_COLUMNS.GROUP_TOTAL: + case CONST.SEARCH.TABLE_COLUMNS.TOTAL_PER_ATTENDEE: case CONST.SEARCH.TABLE_COLUMNS.TOTAL: columnWidth = {...getWidthStyle(isAmountColumnWide ? variables.w130 : variables.w96), ...(!shouldRemoveTotalColumnFlex && styles.flex1), ...styles.alignItemsEnd}; break; @@ -1872,6 +1878,9 @@ const createStyleUtils = (theme: ThemeColors, styles: ThemeStyles) => ({ case CONST.SEARCH.TABLE_COLUMNS.EXPORTED_TO: columnWidth = {...getWidthStyle(variables.w72), ...styles.alignItemsCenter}; break; + case CONST.SEARCH.TABLE_COLUMNS.ATTENDEES: + columnWidth = {...getWidthStyle(variables.w72)}; + break; case CONST.SEARCH.TABLE_COLUMNS.GROUP_FEED: case CONST.SEARCH.TABLE_COLUMNS.GROUP_BANK_ACCOUNT: case CONST.SEARCH.TABLE_COLUMNS.GROUP_WITHDRAWAL_ID: