diff --git a/packages/desktop-client/src/components/HelpMenu.tsx b/packages/desktop-client/src/components/HelpMenu.tsx index 73aed99ef4c..5d69fe0b8d3 100644 --- a/packages/desktop-client/src/components/HelpMenu.tsx +++ b/packages/desktop-client/src/components/HelpMenu.tsx @@ -8,6 +8,7 @@ import { useToggle } from 'usehooks-ts'; import { pushModal } from 'loot-core/client/actions/modals'; +import { useFeatureFlag } from '../hooks/useFeatureFlag'; import { SvgHelp } from '../icons/v2/Help'; import { openUrl } from '../util/router-tools'; @@ -16,7 +17,7 @@ import { Menu } from './common/Menu'; import { Popover } from './common/Popover'; import { SpaceBetween } from './common/SpaceBetween'; -type HelpMenuItem = 'docs' | 'keyboard-shortcuts'; +type HelpMenuItem = 'docs' | 'keyboard-shortcuts' | 'goal-templates'; type HelpButtonProps = { onPress?: () => void; @@ -66,6 +67,7 @@ const getPageDocs = (page: string) => { }; export const HelpMenu = () => { + const showGoalTemplates = useFeatureFlag('goalTemplatesEnabled'); const { t } = useTranslation(); const [isMenuOpen, toggleMenuOpen, setMenuOpen] = useToggle(); const menuButtonRef = useRef(null); @@ -81,6 +83,9 @@ export const HelpMenu = () => { case 'keyboard-shortcuts': dispatch(pushModal('keyboard-shortcuts')); break; + case 'goal-templates': + dispatch(pushModal('goal-templates')); + break; } }; @@ -98,7 +103,7 @@ export const HelpMenu = () => { onOpenChange={() => setMenuOpen(false)} > { + onMenuSelect={(item: HelpMenuItem) => { setMenuOpen(false); handleItemSelect(item); }} @@ -108,6 +113,9 @@ export const HelpMenu = () => { text: t('Documentation'), }, { name: 'keyboard-shortcuts', text: t('Keyboard shortcuts') }, + ...(showGoalTemplates && page === '/budget' + ? [{ name: 'goal-templates', text: t('Goal templates') }] + : []), ]} /> diff --git a/packages/desktop-client/src/components/Modals.tsx b/packages/desktop-client/src/components/Modals.tsx index f5e3dec9408..ef458ef87b4 100644 --- a/packages/desktop-client/src/components/Modals.tsx +++ b/packages/desktop-client/src/components/Modals.tsx @@ -35,6 +35,7 @@ import { EnvelopeBudgetMonthMenuModal } from './modals/EnvelopeBudgetMonthMenuMo import { EnvelopeBudgetSummaryModal } from './modals/EnvelopeBudgetSummaryModal'; import { EnvelopeToBudgetMenuModal } from './modals/EnvelopeToBudgetMenuModal'; import { FixEncryptionKeyModal } from './modals/FixEncryptionKeyModal'; +import { GoalTemplateModal } from './modals/GoalTemplateModal'; import { GoCardlessExternalMsgModal } from './modals/GoCardlessExternalMsgModal'; import { GoCardlessInitialiseModal } from './modals/GoCardlessInitialiseModal'; import { HoldBufferModal } from './modals/HoldBufferModal'; @@ -83,6 +84,9 @@ export function Modals() { const modals = modalStack .map(({ name, options }) => { switch (name) { + case 'goal-templates': + return budgetId ? : null; + case 'keyboard-shortcuts': // don't show the hotkey help modal when a budget is not open return budgetId ? : null; diff --git a/packages/desktop-client/src/components/modals/GoalTemplateModal.tsx b/packages/desktop-client/src/components/modals/GoalTemplateModal.tsx new file mode 100644 index 00000000000..4892d81ac66 --- /dev/null +++ b/packages/desktop-client/src/components/modals/GoalTemplateModal.tsx @@ -0,0 +1,179 @@ +import { Trans, useTranslation } from 'react-i18next'; + +import { theme } from '../../style'; +import { Link } from '../common/Link'; +import { Modal, ModalCloseButton, ModalHeader } from '../common/Modal'; +import { Text } from '../common/Text'; +import { View } from '../common/View'; +import { TableHeader, Row, Field } from '../table'; + +export function GoalTemplateModal() { + const { t } = useTranslation(); + return ( + + {({ state: { close } }) => ( + <> + } + /> + + + + Weekly Templates + + + Description + + + + + {t('#template $10 repeat every week starting 2025-01-03')} + + {t('$10 a week')} + + + + {t( + '#template $10 repeat every week starting 2025-01-03 up to $80', + )} + + + {t('$10 a week, up to a maximum of $80')} + + + +
+
+ + + Monthly Templates + + + Description + + + + {t('#template $50')} + {t('$50 each month')} + + + {t('#template up to $150')} + + {t('Up to $150 each month, and remove extra funds over $150')} + + + + {t('#template up to $150 hold')} + + {t('Up to $150 each month, but retain any funds over $150')} + + + +
+
+ + + Multi-month Templates + + + Description + + + + + {t('#template $500 by 2025-03 repeat every 6 months')} + + + {t('Break down less-frequent expenses into monthly expenses')} + + + + + {t('#template $500 by 2025-03 repeat every year')} + + + {t('Break down less-frequent expenses into monthly expenses')} + + + + + {t('#template $500 by 2025-03 repeat every 2 years')} + + + {t('Break down less-frequent expenses into monthly expenses')} + + + +
+
+ + + Schedule Templates + + + Description + + + + + {t('#template schedule SCHEDULE_NAME')} + + + {t('Fund upcoming scheduled transactions over time')} + + + + + {t('#template schedule full SCHEDULE_NAME')} + + + {t('Fund upcoming scheduled transaction only on needed month')} + + + +
+
+ + + Goal Tempaltes + + + Description + + + + {t('#goal 1000')} + + {t('Set a long-term goal instead of a monthly goal')} + + +
+ +
+
+ + {t('See')}{' '} + + {t('Goal Templates')} + {' '} + {t('for more information.')} + +
+
+ + )} +
+ ); +} diff --git a/packages/loot-core/src/client/state-types/modals.d.ts b/packages/loot-core/src/client/state-types/modals.d.ts index 484467285e8..11450cf4775 100644 --- a/packages/loot-core/src/client/state-types/modals.d.ts +++ b/packages/loot-core/src/client/state-types/modals.d.ts @@ -286,6 +286,7 @@ type FinanceModals = { onUnlink: () => void; }; 'keyboard-shortcuts': EmptyObject; + 'goal-templates': EmptyObject; }; export type PushModalAction = { diff --git a/upcoming-release-notes/3691.md b/upcoming-release-notes/3691.md new file mode 100644 index 00000000000..00d9058ee42 --- /dev/null +++ b/upcoming-release-notes/3691.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [deathblade666] +--- + +Add goal template reference guide to help menu \ No newline at end of file