From 86ad035fbba8e350277dcf370529d7a865674c9f Mon Sep 17 00:00:00 2001 From: Jono M Date: Wed, 30 Aug 2023 10:08:31 +0100 Subject: [PATCH] Wired up AdminX Tips & Donations (#17846) refs https://github.com/TryGhost/Product/issues/3746 --- This pull request adds and improves features for the membership settings app, especially for the tips or donations feature. It introduces a new `CurrencyField` component and a `currency` module for handling currency input and display. It also refactors and enhances some existing components, hooks, and types for better user experience and code quality. It affects files such as `TierDetailModal.tsx`, `TipsOrDonations.tsx`, `useForm.ts`, and `currency.ts`. --- .../admin-x-ds/global/form/CurrencyField.tsx | 39 +++++++++ .../src/admin-x-ds/global/form/Select.tsx | 8 +- apps/admin-x-settings/src/api/settings.ts | 2 +- .../newsletters/NewsletterDetailModal.tsx | 4 +- .../settings/membership/TipsOrDonations.tsx | 78 +++++++++++++----- .../membership/tiers/TierDetailModal.tsx | 60 ++++++-------- .../membership/tiers/TierDetailPreview.tsx | 14 +--- apps/admin-x-settings/src/hooks/useForm.ts | 10 ++- .../src/hooks/useSettingGroup.tsx | 22 ++++-- apps/admin-x-settings/src/utils/currency.ts | 79 +++++++++++++++++++ .../test/e2e/membership/tiers.test.ts | 2 +- 11 files changed, 236 insertions(+), 82 deletions(-) create mode 100644 apps/admin-x-settings/src/admin-x-ds/global/form/CurrencyField.tsx diff --git a/apps/admin-x-settings/src/admin-x-ds/global/form/CurrencyField.tsx b/apps/admin-x-settings/src/admin-x-ds/global/form/CurrencyField.tsx new file mode 100644 index 0000000000..16a30256c1 --- /dev/null +++ b/apps/admin-x-settings/src/admin-x-ds/global/form/CurrencyField.tsx @@ -0,0 +1,39 @@ +import React, {useState} from 'react'; +import TextField, {TextFieldProps} from './TextField'; +import {currencyFromDecimal, currencyToDecimal} from '../../../utils/currency'; + +export type CurrencyFieldProps = Omit & { + currency?: string + onChange?: (value: number) => void +} + +const CurrencyField: React.FC = ({ + value, + onChange, + ...props +}) => { + const [localValue, setLocalValue] = useState(currencyToDecimal(parseInt(value || '0')).toString()); + + // While the user is editing we allow more lenient input, e.g. "1.32.566" to make it easier to type and change + const stripNonNumeric = (input: string) => input.replace(/[^\d.]+/g, ''); + + // The saved value is strictly a number with 2 decimal places + const forceCurrencyValue = (input: string) => { + return currencyFromDecimal(parseFloat(input.match(/[\d]+\.?[\d]{0,2}/)?.[0] || '0')); + }; + + return { + setLocalValue(currencyToDecimal(forceCurrencyValue(e.target.value)).toString()); + props.onBlur?.(e); + }} + onChange={(e) => { + setLocalValue(stripNonNumeric(e.target.value)); + onChange?.(forceCurrencyValue(e.target.value)); + }} + />; +}; + +export default CurrencyField; diff --git a/apps/admin-x-settings/src/admin-x-ds/global/form/Select.tsx b/apps/admin-x-settings/src/admin-x-ds/global/form/Select.tsx index 2623c909fe..06d7a33499 100644 --- a/apps/admin-x-settings/src/admin-x-ds/global/form/Select.tsx +++ b/apps/admin-x-settings/src/admin-x-ds/global/form/Select.tsx @@ -7,11 +7,13 @@ import clsx from 'clsx'; export interface SelectOption { value: string; label: string; + key?: string; className?: string; } export interface SelectOptionGroup { label: string; + key?: string; options: SelectOption[]; } @@ -100,10 +102,10 @@ const Select: React.FC = ({ {prompt && } {options.map(option => ( 'options' in option ? - + {option.options.map(child => ( :