From 000c059d3d8c138fb893d5961ab6041b9557a562 Mon Sep 17 00:00:00 2001 From: TaduJR Date: Wed, 26 Nov 2025 10:55:22 +0300 Subject: [PATCH] Revert "Merge pull request #72943 from TaduJR/feat-CFI-Add-group-by-report-layout-feature" This reverts commit 13420bc38d807793577661b3a577aa030aef9d14, reversing changes made to 5717a04357ec8d6ea5b2c22200b4ae3c55102d6f. --- src/CONST/index.ts | 7 - src/ONYXKEYS.ts | 4 - src/ROUTES.ts | 4 - src/SCREENS.ts | 1 - src/components/MoneyReportHeader.tsx | 12 -- .../MoneyRequestReportGroupHeader.tsx | 90 ------------- .../MoneyRequestReportTransactionList.tsx | 125 +++--------------- src/languages/de.ts | 12 -- src/languages/en.ts | 12 -- src/languages/es.ts | 12 -- src/languages/fr.ts | 12 -- src/languages/it.ts | 12 -- src/languages/ja.ts | 12 -- src/languages/nl.ts | 12 -- src/languages/pl.ts | 12 -- src/languages/pt-BR.ts | 12 -- src/languages/zh-hans.ts | 12 -- .../ModalStackNavigators/index.tsx | 1 - src/libs/Navigation/linkingConfig/config.ts | 3 - src/libs/Navigation/types.ts | 3 - src/libs/ReportLayoutUtils.ts | 120 ----------------- src/libs/ReportSecondaryActionUtils.ts | 21 +-- src/libs/actions/ReportLayout.ts | 51 ------- .../settings/Report/ReportLayoutPage.tsx | 82 ------------ src/styles/index.ts | 8 -- src/types/onyx/ReportLayout.ts | 26 ---- src/types/onyx/index.ts | 3 - 27 files changed, 22 insertions(+), 659 deletions(-) delete mode 100644 src/components/MoneyRequestReportView/MoneyRequestReportGroupHeader.tsx delete mode 100644 src/libs/ReportLayoutUtils.ts delete mode 100644 src/libs/actions/ReportLayout.ts delete mode 100644 src/pages/settings/Report/ReportLayoutPage.tsx delete mode 100644 src/types/onyx/ReportLayout.ts diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 3d4772128a2c..991e44940386 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1132,7 +1132,6 @@ const CONST = { EXPORT: 'export', PAY: 'pay', MERGE: 'merge', - REPORT_LAYOUT: 'reportLayout', }, PRIMARY_ACTIONS: { SUBMIT: 'submit', @@ -1682,12 +1681,6 @@ const CONST = { GSD: 'gsd', DEFAULT: 'default', }, - REPORT_LAYOUT: { - GROUP_BY: { - CATEGORY: 'mcc', - TAG: 'tag', - }, - }, THEME: { DEFAULT: 'system', FALLBACK: 'dark', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 9f140f97f6a1..657e76ba2b6f 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -149,9 +149,6 @@ const ONYXKEYS = { /** Contains the user preference for the LHN priority mode */ NVP_PRIORITY_MODE: 'nvp_priorityMode', - /** Contains the user preference for report layout group-by option */ - NVP_REPORT_LAYOUT_GROUP_BY: 'nvp_expensify_groupByOption', - /** Contains the users's block expiration (if they have one) */ NVP_BLOCKED_FROM_CONCIERGE: 'nvp_private_blockedFromConcierge', @@ -1147,7 +1144,6 @@ type OnyxValuesMapping = { [ONYXKEYS.BETA_CONFIGURATION]: OnyxTypes.BetaConfiguration; [ONYXKEYS.NVP_MUTED_PLATFORMS]: Partial>; [ONYXKEYS.NVP_PRIORITY_MODE]: ValueOf; - [ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY]: string; [ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE]: OnyxTypes.BlockedFromConcierge; [ONYXKEYS.QUEUE_FLUSHED_DATA]: OnyxUpdate[]; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index a9e8d82e7db1..f69d235c0700 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -616,10 +616,6 @@ const ROUTES = { // eslint-disable-next-line no-restricted-syntax -- Legacy route generation getRoute: (reportID: string, backTo?: string) => getUrlWithBackToParam(`r/${reportID}/settings/visibility` as const, backTo), }, - REPORT_SETTINGS_REPORT_LAYOUT: { - route: 'r/:reportID/settings/report-layout', - getRoute: (reportID: string) => `r/${reportID}/settings/report-layout` as const, - }, REPORT_CHANGE_APPROVER: { route: 'r/:reportID/change-approver', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index ef330e917af3..966881477b22 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -386,7 +386,6 @@ const SCREENS = { NOTIFICATION_PREFERENCES: 'Report_Settings_Notification_Preferences', WRITE_CAPABILITY: 'Report_Settings_Write_Capability', VISIBILITY: 'Report_Settings_Visibility', - REPORT_LAYOUT: 'Report_Settings_Report_Layout', }, NEW_TASK: { diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index c98e96747a31..e361f67d4c6b 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -226,7 +226,6 @@ function MoneyReportHeader({ 'Info', 'Export', 'Document', - 'Feed', ] as const); const [lastDistanceExpenseType] = useOnyx(ONYXKEYS.NVP_LAST_DISTANCE_EXPENSE_TYPE, {canBeMissing: true}); const {translate} = useLocalize(); @@ -1144,17 +1143,6 @@ function MoneyReportHeader({ Navigation.navigate(ROUTES.REPORT_CHANGE_APPROVER.getRoute(moneyRequestReport.reportID, Navigation.getActiveRoute())); }, }, - [CONST.REPORT.SECONDARY_ACTIONS.REPORT_LAYOUT]: { - text: translate('reportLayout.reportLayout'), - icon: expensifyIcons.Feed, - value: CONST.REPORT.SECONDARY_ACTIONS.REPORT_LAYOUT, - onSelected: () => { - if (!moneyRequestReport) { - return; - } - Navigation.navigate(ROUTES.REPORT_SETTINGS_REPORT_LAYOUT.getRoute(moneyRequestReport.reportID)); - }, - }, [CONST.REPORT.SECONDARY_ACTIONS.DELETE]: { text: translate('common.delete'), icon: expensifyIcons.Trashcan, diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportGroupHeader.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportGroupHeader.tsx deleted file mode 100644 index 0e9152d430e9..000000000000 --- a/src/components/MoneyRequestReportView/MoneyRequestReportGroupHeader.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import {View} from 'react-native'; -import type {StyleProp, ViewStyle} from 'react-native'; -import Checkbox from '@components/Checkbox'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {convertToDisplayString} from '@libs/CurrencyUtils'; -import variables from '@styles/variables'; -import type {GroupedTransactions} from '@src/types/onyx'; - -type MoneyRequestReportGroupHeaderProps = { - /** The grouped transaction data */ - group: GroupedTransactions; - - /** Currency code for amount formatting */ - currency: string; - - /** Whether grouping by tag (if false, grouping by category) */ - isGroupedByTag?: boolean; - - /** Whether selection mode is active (checkboxes should be visible) */ - isSelectionModeEnabled?: boolean; - - /** Whether all transactions in this group are selected */ - isSelected?: boolean; - - /** Whether some (but not all) transactions in this group are selected */ - isIndeterminate?: boolean; - - /** Callback when group checkbox is toggled */ - onToggleSelection?: () => void; - - /** Additional styles to apply */ - style?: StyleProp; -}; - -function MoneyRequestReportGroupHeader({ - group, - currency, - isGroupedByTag = false, - isSelectionModeEnabled = false, - isSelected = false, - isIndeterminate = false, - onToggleSelection, - style, -}: MoneyRequestReportGroupHeaderProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - - const displayName = group.groupName || translate(isGroupedByTag ? 'search.noTag' : 'search.noCategory'); - const formattedAmount = convertToDisplayString(Math.abs(group.totalAmount), currency); - - const shouldShowCheckbox = isSelectionModeEnabled || !shouldUseNarrowLayout; - - const DESKTOP_HEIGHT = 28; - const MOBILE_HEIGHT_WITH_CHECKBOX = 20; - const MOBILE_HEIGHT_WITHOUT_CHECKBOX = 16; - - const conditionalHeight = shouldUseNarrowLayout - ? {height: shouldShowCheckbox ? MOBILE_HEIGHT_WITH_CHECKBOX : MOBILE_HEIGHT_WITHOUT_CHECKBOX} - : {height: DESKTOP_HEIGHT, minHeight: DESKTOP_HEIGHT}; - - const textStyle = shouldUseNarrowLayout - ? {fontSize: variables.fontSizeLabel, lineHeight: shouldShowCheckbox ? MOBILE_HEIGHT_WITH_CHECKBOX : MOBILE_HEIGHT_WITHOUT_CHECKBOX} - : {fontSize: variables.fontSizeNormal, lineHeight: DESKTOP_HEIGHT}; - - return ( - - - {shouldShowCheckbox && ( - {})} - accessibilityLabel={translate('reportLayout.selectGroup', {groupName: displayName})} - style={styles.mr2} - /> - )} - {`${displayName} - ${formattedAmount}`} - - - ); -} - -MoneyRequestReportGroupHeader.displayName = 'MoneyRequestReportGroupHeader'; - -export default MoneyRequestReportGroupHeader; diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx index 97ee31171d5d..6713e7710e23 100644 --- a/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx +++ b/src/components/MoneyRequestReportView/MoneyRequestReportTransactionList.tsx @@ -26,14 +26,12 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import {turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; import {setOptimisticTransactionThread} from '@libs/actions/Report'; -import {getReportLayoutGroupBy} from '@libs/actions/ReportLayout'; import {setActiveTransactionIDs} from '@libs/actions/TransactionThreadNavigation'; import {convertToDisplayString} from '@libs/CurrencyUtils'; import FS from '@libs/Fullstory'; import {navigationRef} from '@libs/Navigation/Navigation'; import Parser from '@libs/Parser'; import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils'; -import {groupTransactionsByCategory, groupTransactionsByTag} from '@libs/ReportLayoutUtils'; import { canAddTransaction, getAddExpenseDropdownOptions, @@ -66,7 +64,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; -import MoneyRequestReportGroupHeader from './MoneyRequestReportGroupHeader'; import MoneyRequestReportTableHeader from './MoneyRequestReportTableHeader'; import MoneyRequestReportTotalSpend from './MoneyRequestReportTotalSpend'; import MoneyRequestReportTransactionItem from './MoneyRequestReportTransactionItem'; @@ -169,7 +166,6 @@ function MoneyRequestReportTransactionList({ const {markReportIDAsExpense} = useContext(WideRHPContext); const [isModalVisible, setIsModalVisible] = useState(false); const [selectedTransactionID, setSelectedTransactionID] = useState(''); - const [reportLayoutGroupBy] = useOnyx(ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY, {canBeMissing: true}); const {reportPendingAction} = getReportOfflinePendingActionAndErrors(report); const {totalDisplaySpend, nonReimbursableSpend, reimbursableSpend} = getMoneyRequestSpendBreakdown(report); @@ -234,51 +230,6 @@ function MoneyRequestReportTransactionList({ const isTransactionSelected = useCallback((transactionID: string) => selectedTransactionIDs.includes(transactionID), [selectedTransactionIDs]); - // Toggle all transactions in a group - const toggleGroupSelection = useCallback( - (groupTransactions: OnyxTypes.Transaction[]) => { - const groupTransactionIDs = groupTransactions.filter((t) => !isTransactionPendingDelete(t)).map((t) => t.transactionID); - const allSelected = groupTransactionIDs.every((id) => selectedTransactionIDs.includes(id)); - - let newSelectedTransactionIDs = selectedTransactionIDs; - if (allSelected) { - // Deselect all transactions in the group - newSelectedTransactionIDs = selectedTransactionIDs.filter((id) => !groupTransactionIDs.includes(id)); - } else { - // Select all transactions in the group - const idsToAdd = groupTransactionIDs.filter((id) => !selectedTransactionIDs.includes(id)); - newSelectedTransactionIDs = [...selectedTransactionIDs, ...idsToAdd]; - } - setSelectedTransactions(newSelectedTransactionIDs); - }, - [selectedTransactionIDs, setSelectedTransactions], - ); - - // Check if all transactions in a group are selected - const isGroupSelected = useCallback( - (groupTransactions: OnyxTypes.Transaction[]) => { - const groupTransactionIDs = groupTransactions.filter((t) => !isTransactionPendingDelete(t)).map((t) => t.transactionID); - if (groupTransactionIDs.length === 0) { - return false; - } - return groupTransactionIDs.every((id) => selectedTransactionIDs.includes(id)); - }, - [selectedTransactionIDs], - ); - - // Check if some (but not all) transactions in a group are selected - const isGroupIndeterminate = useCallback( - (groupTransactions: OnyxTypes.Transaction[]) => { - const groupTransactionIDs = groupTransactions.filter((t) => !isTransactionPendingDelete(t)).map((t) => t.transactionID); - if (groupTransactionIDs.length === 0) { - return false; - } - const selectedCount = groupTransactionIDs.filter((id) => selectedTransactionIDs.includes(id)).length; - return selectedCount > 0 && selectedCount < groupTransactionIDs.length; - }, - [selectedTransactionIDs], - ); - useFocusEffect( useCallback(() => { return () => { @@ -306,18 +257,6 @@ function MoneyRequestReportTransactionList({ })); }, [newTransactions, sortBy, sortOrder, transactions, localeCompare, report]); - // Get the current group-by preference - const currentGroupBy = getReportLayoutGroupBy(reportLayoutGroupBy); - - // Group transactions based on user preference - const groupedTransactions = useMemo(() => { - if (currentGroupBy === CONST.REPORT_LAYOUT.GROUP_BY.TAG) { - return groupTransactionsByTag(sortedTransactions, report, localeCompare); - } - // Default to grouping by category - return groupTransactionsByCategory(sortedTransactions, report, localeCompare); - }, [sortedTransactions, currentGroupBy, report, localeCompare]); - const columnsToShow = useMemo(() => { const columns = getColumnsToShow(currentUserDetails?.accountID, transactions, true); return (Object.keys(columns) as SearchColumnType[]).filter((column) => columns[column]); @@ -469,50 +408,28 @@ function MoneyRequestReportTransactionList({ )} )} - - {groupedTransactions.map((group) => { - const groupTransactionsWithHighlight = group.transactions.map((transaction) => { - const originalTransaction = sortedTransactions.find((t) => t.transactionID === transaction.transactionID); - return originalTransaction ?? transaction; - }); - + + {sortedTransactions.map((transaction) => { return ( - - toggleGroupSelection(group.transactions)} - /> - - {groupTransactionsWithHighlight.map((transaction) => { - return ( - - ); - })} - - + ); })} diff --git a/src/languages/de.ts b/src/languages/de.ts index beb00e7271ee..af00867d271d 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -7528,18 +7528,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name} hat dich eingeladen, Expensify auszuprobieren\nHey! Ich habe uns gerade *3 Monate kostenlos* gesichert, um Expensify auszuprobieren, den schnellsten Weg, um Ausgaben zu verwalten.\n\nHier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`, }, - reportLayout: { - reportLayout: 'Berichtslayout', - groupByLabel: 'Gruppieren nach:', - selectGroupByOption: 'Wählen Sie aus, wie Berichtsausgaben gruppiert werden sollen', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} diese Gruppe`, - selectGroup: ({groupName}: {groupName: string}) => `Alle Ausgaben in ${groupName} auswählen`, - groupBy: { - category: 'Kategorie', - tag: 'Schlagwort', - }, - }, export: { basicExport: 'Basis Export', reportLevelExport: 'Alle Daten - Berichtsebene', diff --git a/src/languages/en.ts b/src/languages/en.ts index 7730393a0eb8..7a0e36925ccd 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -6555,18 +6555,6 @@ const translations = { allMatchingItemsSelected: 'All matching items selected', }, }, - reportLayout: { - reportLayout: 'Report layout', - groupByLabel: 'Group by:', - selectGroupByOption: 'Select how to group report expenses', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} this group`, - selectGroup: ({groupName}: {groupName: string}) => `Select all expenses in ${groupName}`, - groupBy: { - category: 'Category', - tag: 'Tag', - }, - }, genericErrorPage: { title: 'Uh-oh, something went wrong!', body: { diff --git a/src/languages/es.ts b/src/languages/es.ts index a96118411658..018c5121e32d 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -6203,18 +6203,6 @@ ${amount} para ${merchant} - ${date}`, allMatchingItemsSelected: 'Todos los elementos coincidentes seleccionados', }, }, - reportLayout: { - reportLayout: 'Diseño del informe', - groupByLabel: 'Agrupar por:', - selectGroupByOption: 'Selecciona cómo agrupar los gastos del informe', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} este grupo`, - selectGroup: ({groupName}: {groupName: string}) => `Seleccionar todos los gastos en ${groupName}`, - groupBy: { - category: 'Categoría', - tag: 'Etiqueta', - }, - }, genericErrorPage: { title: '¡Oh-oh, algo salió mal!', body: { diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 084400b08332..92ccaaa5f979 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -7532,18 +7532,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name} vous a invité à essayer Expensify\nSalut ! Je viens de nous obtenir *3 mois gratuits* pour essayer Expensify, la façon la plus rapide de gérer les notes de frais.\n\nVoici un *reçu de test* pour vous montrer comment cela fonctionne :`, }, - reportLayout: { - reportLayout: 'Disposition du rapport', - groupByLabel: 'Grouper par :', - selectGroupByOption: 'Sélectionnez comment grouper les dépenses du rapport', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} ce groupe`, - selectGroup: ({groupName}: {groupName: string}) => `Sélectionner toutes les dépenses dans ${groupName}`, - groupBy: { - category: 'Catégorie', - tag: 'Étiquette', - }, - }, export: { basicExport: 'Exportation basique', reportLevelExport: 'Toutes les données - niveau rapport', diff --git a/src/languages/it.ts b/src/languages/it.ts index a2751fae92b1..afc4fafd1cb6 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -7511,18 +7511,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name} ti ha invitato a provare Expensify\nEhi! Ho appena ottenuto *3 mesi gratis* per provare Expensify, il modo più veloce per gestire le spese.\n\nEcco una *ricevuta di prova* per mostrarti come funziona:`, }, - reportLayout: { - reportLayout: 'Layout del report', - groupByLabel: 'Raggruppa per:', - selectGroupByOption: 'Seleziona come raggruppare le spese del report', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} questo gruppo`, - selectGroup: ({groupName}: {groupName: string}) => `Seleziona tutte le spese in ${groupName}`, - groupBy: { - category: 'Categoria', - tag: 'Tag', - }, - }, export: { basicExport: 'Esportazione basica', reportLevelExport: 'Tutti i dati - livello report', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index fbb85c55d56d..bfb6184850c5 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -7441,18 +7441,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name}がExpensifyの試用にあなたを招待しました\nこんにちは!私はExpensifyを試用するための*3ヶ月無料*を手に入れました。これは、経費を処理する最速の方法です。\n\nこちらがその仕組みを示す*テスト領収書*です:`, }, - reportLayout: { - reportLayout: 'レポートレイアウト', - groupByLabel: 'グループ化:', - selectGroupByOption: 'レポート経費のグループ化方法を選択', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `このグループを${action}`, - selectGroup: ({groupName}: {groupName: string}) => `${groupName}のすべての経費を選択`, - groupBy: { - category: 'カテゴリ', - tag: 'タグ', - }, - }, export: { basicExport: '基本エクスポート', reportLevelExport: 'すべてのデータ - レポートレベル', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 22dfbf45723b..4920a16d1afa 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -7490,18 +7490,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name} heeft je uitgenodigd om Expensify uit te proberen\nHey! Ik heb ons net *3 maanden gratis* gekregen om Expensify uit te proberen, de snelste manier om onkosten te beheren.\n\nHier is een *testbon* om je te laten zien hoe het werkt:`, }, - reportLayout: { - reportLayout: 'Rapportindeling', - groupByLabel: 'Groeperen op:', - selectGroupByOption: 'Selecteer hoe rapportuitgaven te groeperen', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} deze groep`, - selectGroup: ({groupName}: {groupName: string}) => `Selecteer alle uitgaven in ${groupName}`, - groupBy: { - category: 'Categorie', - tag: 'Tag', - }, - }, export: { basicExport: 'Basis export', reportLevelExport: 'Alle gegevens - rapportniveau', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 9370caf88602..30f3409223b8 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -7478,18 +7478,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name} zaprosił Cię do wypróbowania Expensify\nHej! Właśnie zdobyłem dla nas *3 miesiące za darmo*, aby wypróbować Expensify, najszybszy sposób na rozliczanie wydatków.\n\nOto *przykładowy paragon*, aby pokazać Ci, jak to działa:`, }, - reportLayout: { - reportLayout: 'Układ raportu', - groupByLabel: 'Grupuj według:', - selectGroupByOption: 'Wybierz sposób grupowania wydatków w raporcie', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} tę grupę`, - selectGroup: ({groupName}: {groupName: string}) => `Wybierz wszystkie wydatki w ${groupName}`, - groupBy: { - category: 'Kategoria', - tag: 'Tag', - }, - }, export: { basicExport: 'Eksport podstawowy', reportLevelExport: 'Wszystkie dane - poziom raportu', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 0560cddedd50..6c5b0b3e8dd5 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -7488,18 +7488,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name} convidou você para experimentar o Expensify\nEi! Acabei de conseguir *3 meses grátis* para testarmos o Expensify, a maneira mais rápida de lidar com despesas.\n\nAqui está um *recibo de teste* para mostrar como funciona:`, }, - reportLayout: { - reportLayout: 'Layout do relatório', - groupByLabel: 'Agrupar por:', - selectGroupByOption: 'Selecione como agrupar as despesas do relatório', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action} este grupo`, - selectGroup: ({groupName}: {groupName: string}) => `Selecionar todas as despesas em ${groupName}`, - groupBy: { - category: 'Categoria', - tag: 'Tag', - }, - }, export: { basicExport: 'Exportação básica', reportLevelExport: 'Todos os dados - nível de relatório', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 5e68bb9af746..721d9839c93e 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -7329,18 +7329,6 @@ ${ employeeInviteMessage: ({name}: EmployeeInviteMessageParams) => `# ${name}邀请你试用Expensify\n嘿!我刚为我们获得了*3个月免费*试用Expensify,这是处理费用的最快方式。\n\n这里有一个*测试收据*来向你展示它的工作原理:`, }, - reportLayout: { - reportLayout: '报告布局', - groupByLabel: '分组方式:', - selectGroupByOption: '选择如何对报告费用进行分组', - groupHeader: ({groupName}: {groupName: string}) => `${groupName}`, - groupHeaderHint: ({action}: {action: string}) => `${action}此组`, - selectGroup: ({groupName}: {groupName: string}) => `选择${groupName}中的所有费用`, - groupBy: { - category: '类别', - tag: '标签', - }, - }, export: { basicExport: '基本导出', reportLevelExport: '所有数据 - 报告级别', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 4a55d1406020..2b8a6bd45529 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -240,7 +240,6 @@ const ReportSettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/settings/Report/NotificationPreferencePage').default, [SCREENS.REPORT_SETTINGS.WRITE_CAPABILITY]: () => require('../../../../pages/settings/Report/WriteCapabilityPage').default, [SCREENS.REPORT_SETTINGS.VISIBILITY]: () => require('../../../../pages/settings/Report/VisibilityPage').default, - [SCREENS.REPORT_SETTINGS.REPORT_LAYOUT]: () => require('../../../../pages/settings/Report/ReportLayoutPage').default, }); const WorkspaceConfirmationModalStackNavigator = createModalStackNavigator({ diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index ac69a8f0df18..74662cbff8ef 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1157,9 +1157,6 @@ const config: LinkingOptions['config'] = { [SCREENS.REPORT_SETTINGS.VISIBILITY]: { path: ROUTES.REPORT_SETTINGS_VISIBILITY.route, }, - [SCREENS.REPORT_SETTINGS.REPORT_LAYOUT]: { - path: ROUTES.REPORT_SETTINGS_REPORT_LAYOUT.route, - }, }, }, [SCREENS.RIGHT_MODAL.SETTINGS_CATEGORIES]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 069714465ed1..7e824f63d55d 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1427,9 +1427,6 @@ type ReportSettingsNavigatorParamList = { // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md backTo?: Routes; }; - [SCREENS.REPORT_SETTINGS.REPORT_LAYOUT]: { - reportID: string; - }; }; type ReportDescriptionNavigatorParamList = { diff --git a/src/libs/ReportLayoutUtils.ts b/src/libs/ReportLayoutUtils.ts deleted file mode 100644 index b5319f9a5a90..000000000000 --- a/src/libs/ReportLayoutUtils.ts +++ /dev/null @@ -1,120 +0,0 @@ -import type {OnyxEntry} from 'react-native-onyx'; -import type {LocaleContextProps} from '@components/LocaleContextProvider'; -import type {GroupedTransactions} from '@src/types/onyx'; -import type Report from '@src/types/onyx/Report'; -import type Transaction from '@src/types/onyx/Transaction'; -import {getCategory, getTag} from './TransactionUtils'; - -/** - * Groups transactions by category - * @returns Array of grouped transactions with totals, sorted alphabetically (A→Z) - */ -function groupTransactionsByCategory(transactions: Transaction[], report: OnyxEntry, localeCompare: LocaleContextProps['localeCompare']): GroupedTransactions[] { - if (!report) { - return []; - } - - const groups = new Map(); - - for (const transaction of transactions) { - const category = getCategory(transaction); - const categoryKey = category || ''; - - if (!groups.has(categoryKey)) { - groups.set(categoryKey, []); - } - groups.get(categoryKey)?.push(transaction); - } - - const result: GroupedTransactions[] = []; - for (const [categoryKey, transactionList] of groups) { - // Translation handled at component level - const displayName = categoryKey; - - const totalAmount = transactionList.reduce((sum, transaction) => { - // Only include transactions with convertedAmount (already converted to report currency) - // Skip transactions without convertedAmount to avoid mixing currencies (e.g., offline created expenses) - if (!transaction.convertedAmount) { - return sum; - } - return sum + transaction.convertedAmount; - }, 0); - - result.push({ - groupName: displayName, - groupKey: categoryKey, - transactions: transactionList, - totalAmount, - isExpanded: true, - }); - } - - // Sort alphabetically (A→Z), empty keys (uncategorized) at the end - return result.sort((a, b) => { - if (a.groupKey === '' && b.groupKey !== '') { - return 1; - } - if (a.groupKey !== '' && b.groupKey === '') { - return -1; - } - return localeCompare(a.groupKey, b.groupKey); - }); -} - -/** - * Groups transactions by tag - * @returns Array of grouped transactions with totals, sorted alphabetically (A→Z) - */ -function groupTransactionsByTag(transactions: Transaction[], report: OnyxEntry, localeCompare: LocaleContextProps['localeCompare']): GroupedTransactions[] { - if (!report) { - return []; - } - - const groups = new Map(); - - for (const transaction of transactions) { - const tag = getTag(transaction); - const tagKey = tag || ''; - - if (!groups.has(tagKey)) { - groups.set(tagKey, []); - } - groups.get(tagKey)?.push(transaction); - } - - const result: GroupedTransactions[] = []; - for (const [tagKey, transactionList] of groups) { - // Translation handled at component level - const displayName = tagKey; - - const totalAmount = transactionList.reduce((sum, transaction) => { - // Only include transactions with convertedAmount (already converted to report currency) - // Skip transactions without convertedAmount to avoid mixing currencies (e.g., offline created expenses) - if (!transaction.convertedAmount) { - return sum; - } - return sum + transaction.convertedAmount; - }, 0); - - result.push({ - groupName: displayName, - groupKey: tagKey, - transactions: transactionList, - totalAmount, - isExpanded: true, - }); - } - - // Sort alphabetically (A→Z), empty keys (untagged) at the end - return result.sort((a, b) => { - if (a.groupKey === '' && b.groupKey !== '') { - return 1; - } - if (a.groupKey !== '' && b.groupKey === '') { - return -1; - } - return localeCompare(a.groupKey, b.groupKey); - }); -} - -export {groupTransactionsByCategory, groupTransactionsByTag}; diff --git a/src/libs/ReportSecondaryActionUtils.ts b/src/libs/ReportSecondaryActionUtils.ts index 863057afb56f..6ae1e461ee0e 100644 --- a/src/libs/ReportSecondaryActionUtils.ts +++ b/src/libs/ReportSecondaryActionUtils.ts @@ -594,21 +594,6 @@ function isRemoveHoldActionForTransaction(report: Report, reportTransaction: Tra return isOnHoldTransactionUtils(reportTransaction) && policy?.role === CONST.POLICY.ROLE.ADMIN && !isHoldCreator(reportTransaction, report.reportID); } -/** - * Checks if the report should show the "Report layout" option - * Only shows for expense reports with 2 or more transactions - */ -function isReportLayoutAction(report: Report, reportTransactions: Transaction[]): boolean { - const isExpenseReport = isExpenseReportUtils(report); - - if (!isExpenseReport) { - return false; - } - - // Only show if report has 2 or more transactions - return reportTransactions.length >= 2; -} - function getSecondaryReportActions({ currentUserEmail, report, @@ -703,10 +688,6 @@ function getSecondaryReportActions({ options.push(CONST.REPORT.SECONDARY_ACTIONS.EXPORT); - if (isReportLayoutAction(report, reportTransactions)) { - options.push(CONST.REPORT.SECONDARY_ACTIONS.REPORT_LAYOUT); - } - options.push(CONST.REPORT.SECONDARY_ACTIONS.DOWNLOAD_PDF); if (isChangeWorkspaceAction(report, policies, reportActions)) { @@ -784,4 +765,4 @@ function getSecondaryTransactionThreadActions( return options; } -export {getSecondaryReportActions, getSecondaryTransactionThreadActions, isMergeAction, getSecondaryExportReportActions, isSplitAction, isReportLayoutAction}; +export {getSecondaryReportActions, getSecondaryTransactionThreadActions, isMergeAction, getSecondaryExportReportActions, isSplitAction}; diff --git a/src/libs/actions/ReportLayout.ts b/src/libs/actions/ReportLayout.ts deleted file mode 100644 index 4a052a0cbd3e..000000000000 --- a/src/libs/actions/ReportLayout.ts +++ /dev/null @@ -1,51 +0,0 @@ -import Onyx from 'react-native-onyx'; -import type {OnyxUpdate} from 'react-native-onyx'; -import * as API from '@libs/API'; -import {WRITE_COMMANDS} from '@libs/API/types'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {ReportLayoutGroupBy} from '@src/types/onyx'; - -/** - * Set the user's report layout group-by preference - * Uses existing SetNameValuePair API command for backward compatibility with OldDot - * Implements Pattern A (Optimistic Without Feedback) - user gets instant visual feedback - * via transaction regrouping, doesn't need to know about server sync status - */ -function setReportLayoutGroupBy(groupBy: ReportLayoutGroupBy, previousValue?: string | null) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY, - value: groupBy, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY, - value: previousValue ?? null, - }, - ]; - - const parameters = { - name: 'expensify_groupByOption', - value: groupBy, - }; - - API.write(WRITE_COMMANDS.SET_NAME_VALUE_PAIR, parameters, {optimisticData, failureData}); -} - -/** - * Get the current group-by preference, defaulting to 'mcc' (Category) - * This matches OldDot behavior where no NVP set means Category grouping - */ -function getReportLayoutGroupBy(storedValue: string | null | undefined): ReportLayoutGroupBy { - if (!storedValue) { - return CONST.REPORT_LAYOUT.GROUP_BY.CATEGORY; - } - return storedValue as ReportLayoutGroupBy; -} - -export {setReportLayoutGroupBy, getReportLayoutGroupBy}; diff --git a/src/pages/settings/Report/ReportLayoutPage.tsx b/src/pages/settings/Report/ReportLayoutPage.tsx deleted file mode 100644 index 362f3fc93e4c..000000000000 --- a/src/pages/settings/Report/ReportLayoutPage.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import React, {useCallback} from 'react'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; -import SingleSelectListItem from '@components/SelectionList/ListItem/SingleSelectListItem'; -import type {ListItem} from '@components/SelectionList/types'; -import Text from '@components/Text'; -import useLocalize from '@hooks/useLocalize'; -import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {getReportLayoutGroupBy, setReportLayoutGroupBy} from '@libs/actions/ReportLayout'; -import Navigation from '@libs/Navigation/Navigation'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import type {ReportLayoutGroupBy} from '@src/types/onyx'; - -type ReportLayoutItem = ListItem & { - value: ReportLayoutGroupBy; -}; - -function ReportLayoutPage() { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const [reportLayoutGroupByNVP] = useOnyx(ONYXKEYS.NVP_REPORT_LAYOUT_GROUP_BY, {canBeMissing: true}); - const currentGroupBy = getReportLayoutGroupBy(reportLayoutGroupByNVP); - - const goBack = useCallback(() => { - Navigation.dismissModal(); - }, []); - - const onSelectGroupBy = useCallback( - (item: ReportLayoutItem) => { - if (item.value === currentGroupBy) { - goBack(); - return; - } - setReportLayoutGroupBy(item.value, reportLayoutGroupByNVP); - goBack(); - }, - [currentGroupBy, reportLayoutGroupByNVP, goBack], - ); - - const layoutOptions: ReportLayoutItem[] = [ - { - text: translate('reportLayout.groupBy.category'), - keyForList: CONST.REPORT_LAYOUT.GROUP_BY.CATEGORY, - value: CONST.REPORT_LAYOUT.GROUP_BY.CATEGORY, - isSelected: currentGroupBy === CONST.REPORT_LAYOUT.GROUP_BY.CATEGORY, - }, - { - text: translate('reportLayout.groupBy.tag'), - keyForList: CONST.REPORT_LAYOUT.GROUP_BY.TAG, - value: CONST.REPORT_LAYOUT.GROUP_BY.TAG, - isSelected: currentGroupBy === CONST.REPORT_LAYOUT.GROUP_BY.TAG, - }, - ]; - - return ( - - - {translate('reportLayout.groupByLabel')} - option.isSelected)?.keyForList} - /> - - ); -} - -ReportLayoutPage.displayName = 'ReportLayoutPage'; - -export default ReportLayoutPage; diff --git a/src/styles/index.ts b/src/styles/index.ts index b6fd5fe66b18..ffeb578b3192 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4235,14 +4235,6 @@ const staticStyles = (theme: ThemeColors) => alignItems: 'center', }, - reportLayoutGroupHeader: { - paddingHorizontal: 12, - marginTop: 16, - marginBottom: 8, - backgroundColor: theme.appBG, - justifyContent: 'center', - }, - reportActionItemImageBorder: { borderRightWidth: 4, borderColor: theme.cardBG, diff --git a/src/types/onyx/ReportLayout.ts b/src/types/onyx/ReportLayout.ts deleted file mode 100644 index 77e6a3f9469c..000000000000 --- a/src/types/onyx/ReportLayout.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type {ValueOf} from 'type-fest'; -import type CONST from '@src/CONST'; -import type Transaction from './Transaction'; - -/** User's report layout group-by preference */ -type ReportLayoutGroupBy = ValueOf; - -/** Grouped transactions for display */ -type GroupedTransactions = { - /** Display name of the group (category or tag name) */ - groupName: string; - - /** Key used for grouping (category or tag value) */ - groupKey: string; - - /** Transactions in this group */ - transactions: Transaction[]; - - /** Total amount for all transactions in this group */ - totalAmount: number; - - /** Whether the group is currently expanded */ - isExpanded: boolean; -}; - -export type {ReportLayoutGroupBy, GroupedTransactions}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index c683e220b8a8..4fd8c653057d 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -89,7 +89,6 @@ import type ReportAction from './ReportAction'; import type ReportActionReactions from './ReportActionReactions'; import type ReportActionsDraft from './ReportActionsDraft'; import type ReportActionsDrafts from './ReportActionsDrafts'; -import type {GroupedTransactions, ReportLayoutGroupBy} from './ReportLayout'; import type ReportMetadata from './ReportMetadata'; import type ReportNameValuePairs from './ReportNameValuePairs'; import type LastSearchParams from './ReportNavigation'; @@ -287,6 +286,4 @@ export type { BillingReceiptDetails, ExportTemplate, HybridApp, - ReportLayoutGroupBy, - GroupedTransactions, };