diff --git a/.oxlintrc.json b/.oxlintrc.json index 6917f1bd55..7cdbfbaf1c 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -390,6 +390,12 @@ "typescript-paths/absolute-import": ["error", { "enableAlias": false }] } }, + { + "files": ["packages/desktop-client/src/style/themes/*"], + "rules": { + "eslint/no-restricted-imports": "off" + } + }, // TODO: enable these { "files": [ diff --git a/packages/component-library/src/styles.ts b/packages/component-library/src/styles.ts index 863194bd64..d3c00279ea 100644 --- a/packages/component-library/src/styles.ts +++ b/packages/component-library/src/styles.ts @@ -12,8 +12,7 @@ const shadowLarge = { boxShadow: '0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)', }; -// oxlint-disable-next-line typescript/no-explicit-any -export const styles: Record = { +export const styles: CSSProperties = { incomeHeaderHeight: 70, cardShadow: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)', monthRightPadding: 5, diff --git a/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx b/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx index 099c274c01..f55fc9a0f3 100644 --- a/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/CrossoverGraph.tsx @@ -20,6 +20,119 @@ import { Container } from '@desktop-client/components/reports/Container'; import { useFormat } from '@desktop-client/hooks/useFormat'; import { usePrivacyMode } from '@desktop-client/hooks/usePrivacyMode'; +type PayloadItem = { + payload: { + x: string; + investmentIncome: number | string; + expenses: number | string; + nestEgg: number | string; + adjustedExpenses?: number | string; + isProjection?: boolean; + }; +}; + +type CustomTooltipProps = { + active?: boolean; + payload?: PayloadItem[]; +}; + +function CustomTooltip({ active, payload }: CustomTooltipProps) { + const { t } = useTranslation(); + const format = useFormat(); + + if (active && payload && payload.length) { + return ( +
+
+
+ {payload[0].payload.x} + {payload[0].payload.isProjection ? ( + + {t('(projected)')} + + ) : null} +
+
+ +
+ Monthly investment income: +
+
+ + {format(payload[0].payload.investmentIncome, 'financial')} + +
+
+ +
+ Monthly expenses: +
+
+ + {format(payload[0].payload.expenses, 'financial')} + +
+
+ {payload[0].payload.adjustedExpenses != null && ( + +
+ Target income: +
+
+ + {format(payload[0].payload.adjustedExpenses, 'financial')} + +
+
+ )} + +
+ Life savings: +
+
+ + {format(payload[0].payload.nestEgg, 'financial')} + +
+
+
+
+
+ ); + } + return null; +} + type CrossoverGraphProps = { style?: CSSProperties; graphData: { @@ -45,7 +158,6 @@ export function CrossoverGraph({ compact = false, showTooltip = true, }: CrossoverGraphProps) { - const { t } = useTranslation(); const privacyMode = usePrivacyMode(); const format = useFormat(); const animationProps = useRechartsAnimation({ isAnimationActive: false }); @@ -57,116 +169,6 @@ export function CrossoverGraph({ return `${format(Math.round(tick), 'financial-no-decimals')}`; }; - type PayloadItem = { - payload: { - x: string; - investmentIncome: number | string; - expenses: number | string; - nestEgg: number | string; - adjustedExpenses?: number | string; - isProjection?: boolean; - }; - }; - - type CustomTooltipProps = { - active?: boolean; - payload?: PayloadItem[]; - }; - - // oxlint-disable-next-line react/no-unstable-nested-components - const CustomTooltip = ({ active, payload }: CustomTooltipProps) => { - if (active && payload && payload.length) { - return ( -
-
-
- {payload[0].payload.x} - {payload[0].payload.isProjection ? ( - - {t('(projected)')} - - ) : null} -
-
- -
- Monthly investment income: -
-
- - {format(payload[0].payload.investmentIncome, 'financial')} - -
-
- -
- Monthly expenses: -
-
- - {format(payload[0].payload.expenses, 'financial')} - -
-
- {payload[0].payload.adjustedExpenses != null && ( - -
- Target income: -
-
- - {format(payload[0].payload.adjustedExpenses, 'financial')} - -
-
- )} - -
- Life savings: -
-
- - {format(payload[0].payload.nestEgg, 'financial')} - -
-
-
-
-
- ); - } - }; - return ( ; +type TrendTooltipProps = TooltipContentProps & { + style?: CSSProperties; +}; + +function TrendTooltip({ active, payload, style }: TrendTooltipProps) { + const { t } = useTranslation(); + + if (active && payload && payload.length) { + return ( +
+
+
+ {payload[0].payload.date} +
+
+ {payload[0].payload.assets}} + /> + {payload[0].payload.debt}} + /> + + {payload[0].payload.networth} + + } + /> + {payload[0].payload.change}} + /> +
+
+
+ ); + } + return null; +} + +type StackedTooltipProps = TooltipContentProps & { + sortedAccounts: Array<{ id: string; name: string }>; + accounts: Array<{ id: string; name: string }>; + hoveredAccountId: string | null; + format: UseFormatResult; +}; + +function StackedTooltip({ + active, + payload, + sortedAccounts, + accounts, + hoveredAccountId, + format, +}: StackedTooltipProps) { + if (active && payload && payload.length) { + // Calculate total from payload (visible accounts) + const total = payload.reduce( + (acc: number, p) => acc + (Number(p.value) || 0), + 0, + ); + const sortedPayload = [...payload].sort((a, b) => { + const indexA = sortedAccounts.findIndex(acc => acc.id === a.dataKey); + const indexB = sortedAccounts.findIndex(acc => acc.id === b.dataKey); + return indexB - indexA; + }); + + const hasPositive = payload.some(p => (Number(p.value) || 0) > 0); + const hasNegative = payload.some(p => (Number(p.value) || 0) < 0); + const showPercentage = !(hasPositive && hasNegative); + + return ( +
+
+ {payload[0].payload.date} +
+ + + + + + {showPercentage && } + + + + {sortedPayload.map(entry => { + const accountId = entry.dataKey as string; + const accountName = + accounts.find(a => a.id === accountId)?.name || accountId; + const value = Number(entry.value); + const percent = total !== 0 ? (value / total) * 100 : 0; + + return ( + + + + {showPercentage && ( + + )} + + ); + })} + + + + {showPercentage && ( + + )} + + +
+ Account + + Value + %
+ {accountName} + + + + {format(value, 'financial')} + + + + + {percent.toFixed(1)}% + +
+ Total + + {format(total, 'financial')} + 100.0%
+
+ ); + } + return null; +} + type NetWorthGraphProps = { style?: CSSProperties; graphData: { @@ -64,7 +247,6 @@ export function NetWorthGraph({ interval = 'Monthly', mode = 'trend', }: NetWorthGraphProps) { - const { t } = useTranslation(); const privacyMode = usePrivacyMode(); const id = useId(); const format = useFormat(); @@ -151,184 +333,6 @@ export function NetWorthGraph({ .map(point => point.x); }, [interval, graphData.data]); - // Trend Tooltip - // oxlint-disable-next-line react/no-unstable-nested-components - const TrendTooltip = ({ - active, - payload, - }: TooltipContentProps) => { - if (active && payload && payload.length) { - return ( -
-
-
- {payload[0].payload.date} -
-
- {payload[0].payload.assets} - } - /> - {payload[0].payload.debt}} - /> - - {payload[0].payload.networth} - - } - /> - {payload[0].payload.change} - } - /> -
-
-
- ); - } - return null; - }; - - // Stacked Tooltip - // oxlint-disable-next-line react/no-unstable-nested-components - const StackedTooltip = ({ - active, - payload, - }: TooltipContentProps) => { - if (active && payload && payload.length) { - // Calculate total from payload (visible accounts) - const total = payload.reduce( - (acc: number, p) => acc + (Number(p.value) || 0), - 0, - ); - const sortedPayload = [...payload].sort((a, b) => { - const indexA = sortedAccounts.findIndex(acc => acc.id === a.dataKey); - const indexB = sortedAccounts.findIndex(acc => acc.id === b.dataKey); - return indexB - indexA; - }); - - const hasPositive = payload.some(p => (Number(p.value) || 0) > 0); - const hasNegative = payload.some(p => (Number(p.value) || 0) < 0); - const showPercentage = !(hasPositive && hasNegative); - - return ( -
-
- {payload[0].payload.date} -
- - - - - - {showPercentage && } - - - - {sortedPayload.map(entry => { - const accountId = entry.dataKey as string; - const accountName = - accounts.find(a => a.id === accountId)?.name || accountId; - const value = Number(entry.value); - const percent = total !== 0 ? (value / total) * 100 : 0; - - return ( - - - - {showPercentage && ( - - )} - - ); - })} - - - - {showPercentage && ( - - )} - - -
- Account - - Value - %
- {accountName} - - - - {format(value, 'financial')} - - - - - {percent.toFixed(1)}% - -
- Total - - {format(total, 'financial')} - 100.0%
-
- ); - } - return null; - }; - return ( {effectiveShowTooltip && mode === 'trend' && ( - content={props => } + content={props => } formatter={numberFormatterTooltip} isAnimationActive={false} /> )} {effectiveShowTooltip && mode === 'stacked' && ( - content={props => } + content={props => ( + + )} isAnimationActive={false} wrapperStyle={{ zIndex: 9999, pointerEvents: 'auto' }} /> diff --git a/packages/desktop-client/src/style/themes/dark.ts b/packages/desktop-client/src/style/themes/dark.ts index a45ab5e21b..9a8fb601d8 100644 --- a/packages/desktop-client/src/style/themes/dark.ts +++ b/packages/desktop-client/src/style/themes/dark.ts @@ -1,4 +1,3 @@ -// oxlint-disable-next-line eslint/no-restricted-imports import * as colorPalette from '@desktop-client/style/palette'; export const pageBackground = colorPalette.gray900; diff --git a/packages/desktop-client/src/style/themes/development.ts b/packages/desktop-client/src/style/themes/development.ts index 48fd175005..b81da66bb5 100644 --- a/packages/desktop-client/src/style/themes/development.ts +++ b/packages/desktop-client/src/style/themes/development.ts @@ -1,4 +1,3 @@ -// oxlint-disable-next-line eslint/no-restricted-imports import * as colorPalette from '@desktop-client/style/palette'; export const pageBackground = colorPalette.navy100; diff --git a/packages/desktop-client/src/style/themes/light.ts b/packages/desktop-client/src/style/themes/light.ts index a51af3ccfa..5846e4b1cb 100644 --- a/packages/desktop-client/src/style/themes/light.ts +++ b/packages/desktop-client/src/style/themes/light.ts @@ -1,4 +1,3 @@ -// oxlint-disable-next-line eslint/no-restricted-imports import * as colorPalette from '@desktop-client/style/palette'; export const pageBackground = colorPalette.navy100; diff --git a/packages/desktop-client/src/style/themes/midnight.ts b/packages/desktop-client/src/style/themes/midnight.ts index f7ff90e8f6..fcca782a10 100644 --- a/packages/desktop-client/src/style/themes/midnight.ts +++ b/packages/desktop-client/src/style/themes/midnight.ts @@ -1,4 +1,3 @@ -// oxlint-disable-next-line eslint/no-restricted-imports import * as colorPalette from '@desktop-client/style/palette'; export const pageBackground = colorPalette.gray600; diff --git a/upcoming-release-notes/6721.md b/upcoming-release-notes/6721.md new file mode 100644 index 0000000000..8f5ae84bc0 --- /dev/null +++ b/upcoming-release-notes/6721.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [MatissJanis] +--- + +lint: fix low-hanging fruit violations