diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-1-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-1-chromium-linux.png index 86e5a73abf870dac7c047883716cd2f24a17291a..5f2fd61f65a52d06f9ba22f26c1dffadff5c0786 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-1-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-2-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-2-chromium-linux.png index 282d42a1ae8008b5a8e096146a92bcbfac652890..456d02f3632f96decad666b8ead169f39ecbba21 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-2-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-2-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-3-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-3-chromium-linux.png index fb503d151e4fbfa268e400be3e46c9e06d8a73d9..002a17b784e0e874993b9d3700adf373deb50264 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-3-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-checks-that-settings-page-can-be-opened-3-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-1-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-1-chromium-linux.png index 81262d912b69024befb5ba25a7e2dcb2f450f7fb..22b15805aeab336d35226e9d26790b65b7277325 100644 Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-1-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-2-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-2-chromium-linux.png index 386edf7e87bd9b2e50712a08d4886e268428b4cb..36c63dae1016524c79c57ad24ef53126059724e4 100644 Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-2-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-2-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-3-chromium-linux.png b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-3-chromium-linux.png index ca122b1fc9f03e1207884f786453529b969f2b30..260b9ef0abd372352692bf10d111a96ab7a53c98 100644 Binary files a/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-3-chromium-linux.png and b/packages/desktop-client/e2e/reports.test.js-snapshots/Reports-loads-net-worth-and-cash-flow-reports-3-chromium-linux.png differ diff --git a/packages/desktop-client/src/components/FinancesApp.tsx b/packages/desktop-client/src/components/FinancesApp.tsx index 4718a93d46536fb3ad1ebd2b5219990f0581ee08..2950cf55fba5ddd927d67a19ef3ea0a1893d3c57 100644 --- a/packages/desktop-client/src/components/FinancesApp.tsx +++ b/packages/desktop-client/src/components/FinancesApp.tsx @@ -163,15 +163,7 @@ function FinancesAppWithoutContext() { <Routes> <Route path="/" element={<Navigate to="/budget" replace />} /> - <Route - path="/reports/*" - element={ - <NarrowNotSupported> - {/* Has its own lazy loading logic */} - <Reports /> - </NarrowNotSupported> - } - /> + <Route path="/reports/*" element={<Reports />} /> <Route path="/budget" @@ -239,6 +231,7 @@ function FinancesAppWithoutContext() { <Route path="/budget" element={<MobileNavTabs />} /> <Route path="/accounts" element={<MobileNavTabs />} /> <Route path="/settings" element={<MobileNavTabs />} /> + <Route path="/reports" element={<MobileNavTabs />} /> <Route path="*" element={null} /> </Routes> </View> diff --git a/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx b/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx index 725ad3e65a1911db318db80e3a121ae096f2cd81..4290d265813b9925a0a99296cf90151ef3bb8f58 100644 --- a/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx +++ b/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx @@ -14,6 +14,7 @@ import { SvgTuning, SvgWallet, } from '../../icons/v1'; +import { SvgReports } from '../../icons/v1/Reports'; import { SvgCalendar } from '../../icons/v2'; import { useResponsive } from '../../ResponsiveProvider'; import { theme, styles, type CSSProperties } from '../../style'; @@ -54,6 +55,12 @@ export function MobileNavTabs() { style: navTabStyle, Icon: SvgPiggyBank, }, + { + name: 'Reports', + path: '/reports', + style: navTabStyle, + Icon: SvgReports, + }, { name: 'Schedules (Soon)', path: '/schedules/soon', diff --git a/packages/desktop-client/src/components/reports/Header.jsx b/packages/desktop-client/src/components/reports/Header.jsx index d0648dfc84e458cfc6ebb2387d1c0830b4511d1d..3df44ca88e409e340ffa48b14ca426e4f208299d 100644 --- a/packages/desktop-client/src/components/reports/Header.jsx +++ b/packages/desktop-client/src/components/reports/Header.jsx @@ -3,6 +3,7 @@ import { useLocation } from 'react-router-dom'; import * as monthUtils from 'loot-core/src/shared/months'; import { SvgArrowLeft } from '../../icons/v1'; +import { useResponsive } from '../../ResponsiveProvider'; import { styles } from '../../style'; import { Button } from '../common/Button'; import { Link } from '../common/Link'; @@ -36,6 +37,7 @@ export function Header({ }) { const location = useLocation(); const path = location.pathname; + const { isNarrowWidth } = useResponsive(); return ( <View @@ -58,8 +60,8 @@ export function Header({ {path !== '/reports/custom' && ( <View style={{ - flexDirection: 'row', - alignItems: 'center', + flexDirection: isNarrowWidth ? 'column' : 'row', + alignItems: isNarrowWidth ? 'right' : 'center', marginTop: 15, gap: 15, }} @@ -103,45 +105,53 @@ export function Header({ /> </View> - {filters && <FilterButton onApply={onApply} type="accounts" />} - - {show1Month && ( + {!isNarrowWidth && filters && ( + <FilterButton onApply={onApply} type="accounts" /> + )} + <View + style={{ + flexDirection: 'row', + alignItems: 'center', + gap: 15, + }} + > + {show1Month && ( + <Button + type="bare" + onClick={() => onChangeDates(...getLatestRange(1))} + > + 1 month + </Button> + )} <Button type="bare" - onClick={() => onChangeDates(...getLatestRange(1))} + onClick={() => onChangeDates(...getLatestRange(2))} > - 1 month + 3 months </Button> - )} - <Button - type="bare" - onClick={() => onChangeDates(...getLatestRange(2))} - > - 3 months - </Button> - <Button - type="bare" - onClick={() => onChangeDates(...getLatestRange(5))} - > - 6 months - </Button> - <Button - type="bare" - onClick={() => onChangeDates(...getLatestRange(11))} - > - 1 Year - </Button> - <Button - type="bare" - onClick={() => - onChangeDates( - ...getFullRange(allMonths[allMonths.length - 1].name), - ) - } - > - All Time - </Button> - + <Button + type="bare" + onClick={() => onChangeDates(...getLatestRange(5))} + > + 6 months + </Button> + <Button + type="bare" + onClick={() => onChangeDates(...getLatestRange(11))} + > + 1 Year + </Button> + <Button + type="bare" + onClick={() => + onChangeDates( + ...getFullRange(allMonths[allMonths.length - 1].name), + ) + } + > + All Time + </Button> + </View> {children || <View style={{ flex: 1 }} />} </View> )} diff --git a/packages/desktop-client/src/components/reports/Overview.jsx b/packages/desktop-client/src/components/reports/Overview.jsx index e6a5e00d652b4f9cce67d6a109b1443900004d53..2cefe41a6603beb2afafa04f5311a2d0c14597e9 100644 --- a/packages/desktop-client/src/components/reports/Overview.jsx +++ b/packages/desktop-client/src/components/reports/Overview.jsx @@ -5,6 +5,7 @@ import { useReports } from 'loot-core/src/client/data-hooks/reports'; import { useAccounts } from '../../hooks/useAccounts'; import { useFeatureFlag } from '../../hooks/useFeatureFlag'; +import { useResponsive } from '../../ResponsiveProvider'; import { styles } from '../../style'; import { Button } from '../common/Button'; import { Link } from '../common/Link'; @@ -17,6 +18,7 @@ import { NetWorthCard } from './reports/NetWorthCard'; export function Overview() { const customReports = useReports(); + const { isNarrowWidth } = useResponsive(); const location = useLocation(); sessionStorage.setItem('url', location.pathname); @@ -28,10 +30,14 @@ export function Overview() { <View style={{ ...styles.page, - ...{ paddingLeft: 40, paddingRight: 40, minWidth: 700 }, + ...{ + padding: 15, + paddingTop: 0, + minWidth: isNarrowWidth ? null : 700, + }, }} > - {customReportsFeatureFlag && ( + {customReportsFeatureFlag && !isNarrowWidth && ( <View style={{ flex: '0 0 auto', @@ -49,7 +55,7 @@ export function Overview() { )} <View style={{ - flexDirection: 'row', + flexDirection: isNarrowWidth ? 'column' : 'row', flex: '0 0 auto', }} > diff --git a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx index 4918c92ce3959102473010eb53657a4ba9beb038..ed21a78200dacd4afbe25947dbd5151c316b684d 100644 --- a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx @@ -20,6 +20,7 @@ import { import { type GroupedEntity } from 'loot-core/src/types/models/reports'; import { usePrivacyMode } from '../../../hooks/usePrivacyMode'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import { AlignedText } from '../../common/AlignedText'; @@ -125,6 +126,7 @@ export function AreaGraph({ viewLabels, }: AreaGraphProps) { const privacyMode = usePrivacyMode(); + const { isNarrowWidth } = useResponsive(); const dataMax = Math.max(...data.intervalData.map(i => i[balanceTypeOp])); const dataMin = Math.min(...data.intervalData.map(i => i[balanceTypeOp])); @@ -211,11 +213,13 @@ export function AreaGraph({ tickSize={0} /> )} - <Tooltip - content={<CustomTooltip balanceTypeOp={balanceTypeOp} />} - formatter={numberFormatterTooltip} - isAnimationActive={false} - /> + {(!isNarrowWidth || !compact) && ( + <Tooltip + content={<CustomTooltip balanceTypeOp={balanceTypeOp} />} + formatter={numberFormatterTooltip} + isAnimationActive={false} + /> + )} <defs> <linearGradient id={`fill${balanceTypeOp}`} diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx index e420579bd22d516e5028d4661e3da9e2e1be0fc1..a01984afae5cd5046073afcec169685efc3e5b41 100644 --- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx @@ -26,6 +26,7 @@ import { useAccounts } from '../../../hooks/useAccounts'; import { useCategories } from '../../../hooks/useCategories'; import { useNavigate } from '../../../hooks/useNavigate'; import { usePrivacyMode } from '../../../hooks/usePrivacyMode'; +import { useResponsive } from '../../../ResponsiveProvider'; import { type CSSProperties } from '../../../style'; import { theme } from '../../../style/index'; import { AlignedText } from '../../common/AlignedText'; @@ -157,6 +158,7 @@ export function BarGraph({ const categories = useCategories(); const accounts = useAccounts(); const privacyMode = usePrivacyMode(); + const { isNarrowWidth } = useResponsive(); const [pointer, setPointer] = useState(''); const yAxis = groupBy === 'Interval' ? 'date' : 'name'; @@ -261,17 +263,19 @@ export function BarGraph({ bottom: 0, }} > - <Tooltip - cursor={{ fill: 'transparent' }} - content={ - <CustomTooltip - balanceTypeOp={balanceTypeOp} - yAxis={yAxis} - /> - } - formatter={numberFormatterTooltip} - isAnimationActive={false} - /> + {(!isNarrowWidth || !compact) && ( + <Tooltip + cursor={{ fill: 'transparent' }} + content={ + <CustomTooltip + balanceTypeOp={balanceTypeOp} + yAxis={yAxis} + /> + } + formatter={numberFormatterTooltip} + isAnimationActive={false} + /> + )} {!compact && ( <> <CartesianGrid strokeDasharray="3 3" /> @@ -306,7 +310,9 @@ export function BarGraph({ setPointer('pointer') } onClick={ - !['Group', 'Interval'].includes(groupBy) && onShowActivity + !isNarrowWidth && + !['Group', 'Interval'].includes(groupBy) && + onShowActivity } > {viewLabels && !compact && ( diff --git a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx index e7fe93c5c056b42f592f858b0b1d21220ff55ea4..e6cfeffa5ed6cceb56ba15cee53a1090dc2dfbae 100644 --- a/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/DonutGraph.tsx @@ -10,6 +10,7 @@ import { type RuleConditionEntity } from 'loot-core/types/models/rule'; import { useAccounts } from '../../../hooks/useAccounts'; import { useCategories } from '../../../hooks/useCategories'; import { useNavigate } from '../../../hooks/useNavigate'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme, type CSSProperties } from '../../../style'; import { PrivacyFilter } from '../../PrivacyFilter'; import { Container } from '../Container'; @@ -203,6 +204,7 @@ export function DonutGraph({ const navigate = useNavigate(); const categories = useCategories(); const accounts = useAccounts(); + const { isNarrowWidth } = useResponsive(); const [pointer, setPointer] = useState(''); const onShowActivity = item => { @@ -308,7 +310,9 @@ export function DonutGraph({ } }} onClick={ - !['Group', 'Interval'].includes(groupBy) && onShowActivity + !isNarrowWidth && + !['Group', 'Interval'].includes(groupBy) && + onShowActivity } > {data.legend.map((entry, index) => ( diff --git a/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx b/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx index 3b69d289411912204e9962ba24004347638cbca8..e7b1174246b3d637c3817b193976cb794203c7a0 100644 --- a/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/LineGraph.tsx @@ -23,6 +23,7 @@ import { useAccounts } from '../../../hooks/useAccounts'; import { useCategories } from '../../../hooks/useCategories'; import { useNavigate } from '../../../hooks/useNavigate'; import { usePrivacyMode } from '../../../hooks/usePrivacyMode'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import { AlignedText } from '../../common/AlignedText'; @@ -133,6 +134,7 @@ export function LineGraph({ const privacyMode = usePrivacyMode(); const [pointer, setPointer] = useState(''); const [tooltip, setTooltip] = useState(''); + const { isNarrowWidth } = useResponsive(); const largestValue = data.intervalData .map(c => c[balanceTypeOp]) @@ -206,13 +208,15 @@ export function LineGraph({ margin={{ top: 10, right: 10, left: leftMargin, bottom: 10 }} style={{ cursor: pointer }} > - <Tooltip - content={ - <CustomTooltip compact={compact} tooltip={tooltip} /> - } - formatter={numberFormatterTooltip} - isAnimationActive={false} - /> + {(!isNarrowWidth || !compact) && ( + <Tooltip + content={ + <CustomTooltip compact={compact} tooltip={tooltip} /> + } + formatter={numberFormatterTooltip} + isAnimationActive={false} + /> + )} {!compact && ( <> <CartesianGrid strokeDasharray="3 3" /> @@ -255,6 +259,7 @@ export function LineGraph({ setTooltip(''); }, onClick: (e, payload) => + !isNarrowWidth && !['Group', 'Interval'].includes(groupBy) && onShowActivity(e, entry.id, payload), }} diff --git a/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.tsx b/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.tsx index 825e1ade772a9d28cb504dbfb671a5e831bb113a..7a251f65facefbc5279e15d2e0ba8dd461ca0306 100644 --- a/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/NetWorthGraph.tsx @@ -13,6 +13,7 @@ import { } from 'recharts'; import { usePrivacyMode } from '../../../hooks/usePrivacyMode'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import { AlignedText } from '../../common/AlignedText'; @@ -31,6 +32,7 @@ export function NetWorthGraph({ compact, }: NetWorthGraphProps) { const privacyMode = usePrivacyMode(); + const { isNarrowWidth } = useResponsive(); const tickFormatter = tick => { return privacyMode ? '...' : `${Math.round(tick).toLocaleString()}`; // Formats the tick values as strings with commas @@ -139,11 +141,13 @@ export function NetWorthGraph({ tick={{ fill: theme.pageText }} tickLine={{ stroke: theme.pageText }} /> - <Tooltip - content={<CustomTooltip />} - formatter={numberFormatterTooltip} - isAnimationActive={false} - /> + {(!isNarrowWidth || !compact) && ( + <Tooltip + content={<CustomTooltip />} + formatter={numberFormatterTooltip} + isAnimationActive={false} + /> + )} <defs> <linearGradient id="splitColor" x1="0" y1="0" x2="0" y2="1"> <stop diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx index 227319d2deae74d3bb56ce7f72567be6ab9db932..3712c10a6ba50ddd9ea9f5b4dabfea42fcae8f66 100644 --- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx @@ -24,6 +24,7 @@ import { useAccounts } from '../../../hooks/useAccounts'; import { useCategories } from '../../../hooks/useCategories'; import { useNavigate } from '../../../hooks/useNavigate'; import { usePrivacyMode } from '../../../hooks/usePrivacyMode'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme } from '../../../style'; import { type CSSProperties } from '../../../style'; import { AlignedText } from '../../common/AlignedText'; @@ -162,6 +163,7 @@ export function StackedBarGraph({ const categories = useCategories(); const accounts = useAccounts(); const privacyMode = usePrivacyMode(); + const { isNarrowWidth } = useResponsive(); const [pointer, setPointer] = useState(''); const [tooltip, setTooltip] = useState(''); @@ -237,13 +239,20 @@ export function StackedBarGraph({ margin={{ top: 0, right: 0, left: leftMargin, bottom: 0 }} style={{ cursor: pointer }} > - <Tooltip - content={ - <CustomTooltip compact={compact} tooltip={tooltip} /> - } - formatter={numberFormatterTooltip} - isAnimationActive={false} - cursor={{ fill: 'transparent' }} + {(!isNarrowWidth || !compact) && ( + <Tooltip + content={ + <CustomTooltip compact={compact} tooltip={tooltip} /> + } + formatter={numberFormatterTooltip} + isAnimationActive={false} + cursor={{ fill: 'transparent' }} + /> + )} + <XAxis + dataKey="date" + tick={{ fill: theme.pageText }} + tickLine={{ stroke: theme.pageText }} /> {!compact && ( <> @@ -286,6 +295,7 @@ export function StackedBarGraph({ } }} onClick={e => + !isNarrowWidth && !['Group', 'Interval'].includes(groupBy) && onShowActivity(e, entry.id) } diff --git a/packages/desktop-client/src/components/reports/reports/CashFlow.tsx b/packages/desktop-client/src/components/reports/reports/CashFlow.tsx index a3ff9241efb4a276d9f996c7d3671c39e88e0f4c..68cbaec92e58eab006849e0a7b2be946e34f50ed 100644 --- a/packages/desktop-client/src/components/reports/reports/CashFlow.tsx +++ b/packages/desktop-client/src/components/reports/reports/CashFlow.tsx @@ -8,6 +8,7 @@ import { integerToCurrency } from 'loot-core/src/shared/util'; import { type RuleConditionEntity } from 'loot-core/types/models'; import { useFilters } from '../../../hooks/useFilters'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme, styles } from '../../../style'; import { AlignedText } from '../../common/AlignedText'; import { Block } from '../../common/Block'; @@ -23,6 +24,7 @@ import { cashFlowByDate } from '../spreadsheets/cash-flow-spreadsheet'; import { useReport } from '../useReport'; export function CashFlow() { + const { isNarrowWidth } = useResponsive(); const { filters, conditionsOp, @@ -100,7 +102,13 @@ export function CashFlow() { const { graphData, totalExpenses, totalIncome, totalTransfers } = data; return ( - <View style={{ ...styles.page, minWidth: 650, overflow: 'hidden' }}> + <View + style={{ + ...styles.page, + minWidth: isNarrowWidth ? undefined : 650, + overflow: 'hidden', + }} + > <Header title="Cash Flow" allMonths={allMonths} @@ -191,7 +199,7 @@ export function CashFlow() { showBalance={showBalance} /> - <View style={{ marginTop: 30 }}> + <View style={{ marginTop: 30, userSelect: 'none' }}> <Paragraph> <strong>How is cash flow calculated?</strong> </Paragraph> diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx index bdb9c74970ad855ce163ba3a97c8f88be5cc6741..b6cb2fa397d49ec25a24d14b5ade7ee5e02812b7 100644 --- a/packages/desktop-client/src/components/reports/reports/CustomReport.jsx +++ b/packages/desktop-client/src/components/reports/reports/CustomReport.jsx @@ -12,6 +12,7 @@ import { useCategories } from '../../../hooks/useCategories'; import { useFilters } from '../../../hooks/useFilters'; import { useLocalPref } from '../../../hooks/useLocalPref'; import { usePayees } from '../../../hooks/usePayees'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme, styles } from '../../../style'; import { AlignedText } from '../../common/AlignedText'; import { Block } from '../../common/Block'; @@ -37,6 +38,7 @@ import { fromDateRepr } from '../util'; export function CustomReport() { const categories = useCategories(); + const { isNarrowWidth } = useResponsive(); const [_firstDayOfWeekIdx] = useLocalPref('firstDayOfWeekIdx'); const firstDayOfWeekIdx = _firstDayOfWeekIdx || '0'; @@ -444,10 +446,16 @@ export function CustomReport() { }; return ( - <View style={{ ...styles.page, minWidth: 650, overflow: 'hidden' }}> + <View + style={{ + ...styles.page, + minWidth: isNarrowWidth ? undefined : 650, + overflow: 'hidden', + }} + > <View style={{ - flexDirection: 'row', + flexDirection: isNarrowWidth ? 'column' : 'row', flexShrink: 0, }} > @@ -455,7 +463,10 @@ export function CustomReport() { <Text style={{ ...styles.veryLargeText, - marginTop: 40, + marginTop: isNarrowWidth ? 0 : 40, + padding: isNarrowWidth ? 10 : 0, + paddingTop: 0, + flexShrink: 0, color: theme.pageTextPositive, }} > @@ -471,50 +482,54 @@ export function CustomReport() { flexGrow: 1, }} > - <ReportSidebar - customReportItems={customReportItems} - categories={categories} - dateRangeLine={dateRangeLine} - allIntervals={allIntervals} - setDateRange={setDateRange} - setGraphType={setGraphType} - setGroupBy={setGroupBy} - setInterval={setInterval} - setBalanceType={setBalanceType} - setMode={setMode} - setIsDateStatic={setIsDateStatic} - setShowEmpty={setShowEmpty} - setShowOffBudget={setShowOffBudget} - setShowHiddenCategories={setShowHiddenCategories} - setShowUncategorized={setShowUncategorized} - setSelectedCategories={setSelectedCategories} - onChangeDates={onChangeDates} - onReportChange={onReportChange} - disabledItems={disabledItems} - defaultItems={defaultItems} - defaultModeItems={defaultModeItems} - earliestTransaction={earliestTransaction} - firstDayOfWeekIdx={firstDayOfWeekIdx} - /> - <View - style={{ - flexGrow: 1, - }} - > - <ReportTopbar + {!isNarrowWidth && ( + <ReportSidebar customReportItems={customReportItems} - report={report} - savedStatus={savedStatus} + categories={categories} + dateRangeLine={dateRangeLine} + allIntervals={allIntervals} + setDateRange={setDateRange} setGraphType={setGraphType} - viewLegend={viewLegend} - viewSummary={viewSummary} - viewLabels={viewLabels} - onApplyFilter={onApplyFilter} - onChangeViews={onChangeViews} + setGroupBy={setGroupBy} + setInterval={setInterval} + setBalanceType={setBalanceType} + setMode={setMode} + setIsDateStatic={setIsDateStatic} + setShowEmpty={setShowEmpty} + setShowOffBudget={setShowOffBudget} + setShowHiddenCategories={setShowHiddenCategories} + setShowUncategorized={setShowUncategorized} + setSelectedCategories={setSelectedCategories} + onChangeDates={onChangeDates} onReportChange={onReportChange} disabledItems={disabledItems} defaultItems={defaultItems} + defaultModeItems={defaultModeItems} + earliestTransaction={earliestTransaction} + firstDayOfWeekIdx={firstDayOfWeekIdx} /> + )} + <View + style={{ + flexGrow: 1, + }} + > + {!isNarrowWidth && ( + <ReportTopbar + customReportItems={customReportItems} + report={report} + savedStatus={savedStatus} + setGraphType={setGraphType} + viewLegend={viewLegend} + viewSummary={viewSummary} + viewLabels={viewLabels} + onApplyFilter={onApplyFilter} + onChangeViews={onChangeViews} + onReportChange={onReportChange} + disabledItems={disabledItems} + defaultItems={defaultItems} + /> + )} {filters && filters.length > 0 && ( <View style={{ marginBottom: 10, marginLeft: 5, flexShrink: 0 }} @@ -618,7 +633,7 @@ export function CustomReport() { <LoadingIndicator message="Loading report..." /> )} </View> - {(viewLegend || viewSummary) && data && ( + {(viewLegend || viewSummary) && data && !isNarrowWidth && ( <View style={{ padding: 10, diff --git a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx index e66632295785d3e727e54bd8d718ab593c388758..d0423472cef38b8740c3f85f316c5009b2192f6b 100644 --- a/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx +++ b/packages/desktop-client/src/components/reports/reports/CustomReportListCards.tsx @@ -8,6 +8,7 @@ import { useAccounts } from '../../../hooks/useAccounts'; import { useCategories } from '../../../hooks/useCategories'; import { useLocalPref } from '../../../hooks/useLocalPref'; import { usePayees } from '../../../hooks/usePayees'; +import { useResponsive } from '../../../ResponsiveProvider'; import { styles } from '../../../style/index'; import { theme } from '../../../style/theme'; import { Block } from '../../common/Block'; @@ -79,6 +80,7 @@ export function CustomReportListCards({ const payees = usePayees(); const accounts = useAccounts(); const categories = useCategories(); + const { isNarrowWidth } = useResponsive(); const [_firstDayOfWeekIdx] = useLocalPref('firstDayOfWeekIdx'); const firstDayOfWeekIdx = _firstDayOfWeekIdx || '0'; @@ -171,12 +173,24 @@ export function CustomReportListCards({ key={i} style={{ flex: '0 0 auto', - flexDirection: 'row', + flexDirection: isNarrowWidth ? 'column' : 'row', }} > {group && group.map((report, id) => ( - <View key={id} style={{ position: 'relative', flex: '1' }}> + <View + key={id} + style={ + !isNarrowWidth + ? { + position: 'relative', + flex: '1', + } + : { + position: 'relative', + } + } + > <View style={{ width: '100%', height: '100%' }}> <ReportCard to="/reports/custom" report={report}> <View @@ -196,7 +210,6 @@ export function CustomReportListCards({ > <View style={{ - flexDirection: 'row', flexShrink: 0, paddingBottom: 5, }} @@ -311,6 +324,11 @@ export function CustomReportListCards({ ))} </View> ))} + <View + style={{ + paddingBottom: 75, + }} + /> </View> ); } diff --git a/packages/desktop-client/src/components/reports/reports/NetWorth.jsx b/packages/desktop-client/src/components/reports/reports/NetWorth.jsx index 4dbec9a8e056aa319976eb2b033b070c574b11eb..2d6bb7b12a61ac2928dab12629115d7b6bd30538 100644 --- a/packages/desktop-client/src/components/reports/reports/NetWorth.jsx +++ b/packages/desktop-client/src/components/reports/reports/NetWorth.jsx @@ -8,6 +8,7 @@ import { integerToCurrency } from 'loot-core/src/shared/util'; import { useAccounts } from '../../../hooks/useAccounts'; import { useFilters } from '../../../hooks/useFilters'; +import { useResponsive } from '../../../ResponsiveProvider'; import { theme, styles } from '../../../style'; import { Paragraph } from '../../common/Paragraph'; import { View } from '../../common/View'; @@ -21,6 +22,7 @@ import { fromDateRepr } from '../util'; export function NetWorth() { const accounts = useAccounts(); + const { isNarrowWidth } = useResponsive(); const { filters, saved, @@ -81,7 +83,13 @@ export function NetWorth() { } return ( - <View style={{ ...styles.page, minWidth: 650, overflow: 'hidden' }}> + <View + style={{ + ...styles.page, + minWidth: isNarrowWidth ? undefined : 650, + overflow: 'hidden', + }} + > <Header title="Net Worth" allMonths={allMonths} @@ -136,7 +144,7 @@ export function NetWorth() { }} /> - <View style={{ marginTop: 30 }}> + <View style={{ marginTop: 30, userSelect: 'none' }}> <Paragraph> <strong>How is net worth calculated?</strong> </Paragraph> diff --git a/upcoming-release-notes/2624.md b/upcoming-release-notes/2624.md new file mode 100644 index 0000000000000000000000000000000000000000..c5491742b0349fd2e98b25796fc73cae8c12226e --- /dev/null +++ b/upcoming-release-notes/2624.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [carkom] +--- + +Add mobile reports page.