Skip to content

Commit

Permalink
clean up duration function
Browse files Browse the repository at this point in the history
  • Loading branch information
storywithoutend committed Sep 3, 2024
1 parent b0f4796 commit 2b4ab85
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 138 deletions.
47 changes: 30 additions & 17 deletions src/components/@molecules/DateSelection/DateSelection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,64 @@ describe('DateSelection', () => {
vi.resetAllMocks()
})
it('should render a plus minus counter if no name was provided', () => {
render(<DateSelection minSeconds={0} seconds={ONE_YEAR} setSeconds={() => {}} />)
render(
<DateSelection
minSeconds={0}
seconds={ONE_YEAR}
setSeconds={() => {}}
durationType="years"
/>,
)

expect(screen.getByTestId('plus-minus-control-input')).toBeInTheDocument()
})
it('should show a calendar if user is picking by date', async () => {
render(<DateSelection minSeconds={0} seconds={ONE_YEAR} setSeconds={() => {}} />)

screen.getByTestId('date-selection').click()

render(
<DateSelection minSeconds={0} seconds={ONE_YEAR} setSeconds={() => {}} durationType="date" />,
)
expect(screen.getByText('unit.years.1 registration.')).toBeVisible()
})
it('should set back to one year when switching to a year toggle if previously was set to less', async () => {
const { result } = renderHook(() => useState(ONE_YEAR))
const { rerender } = render(
<DateSelection minSeconds={0} seconds={result.current[0]} setSeconds={result.current[1]} />,
let { result: durationTypeResult } = renderHook(() => useState<'years' | 'date'>('years'))

const DateSelectionComponent = () => (
<DateSelection
minSeconds={0}
seconds={result.current[0]}
setSeconds={result.current[1]}
durationType={durationTypeResult.current[0]}
onChangeDurationType={durationTypeResult.current[1]}
/>
)

const { rerender } = render(<DateSelectionComponent />)

const dateSelection = screen.getByTestId('date-selection')

await userEvent.click(dateSelection)

rerender(<DateSelectionComponent />)

await waitFor(() => {
expect(screen.getByText('calendar.pick_by_years')).toBeVisible()
})

const currentDate = new Date()
act(() => {
result.current[1](secondsFromDateDiff({ startDate: currentDate, additionalMonths: 1 }))
})
result.current[1](secondsFromDateDiff({ startDate: new Date(), additionalMonths: 1 }))

rerender(
<DateSelection minSeconds={0} seconds={result.current[0]} setSeconds={result.current[1]} />,
)
rerender(<DateSelectionComponent />)

expect(screen.getByText('unit.months.1 registration.')).toBeVisible()

await userEvent.click(dateSelection)

rerender(<DateSelectionComponent />)

await waitFor(() => {
expect(screen.getByText('calendar.pick_by_date')).toBeVisible()
})

rerender(
<DateSelection minSeconds={0} seconds={result.current[0]} setSeconds={result.current[1]} />,
)
rerender(<DateSelectionComponent />)

expect(screen.getByText('unit.years.1 registration.')).toBeVisible()
})
Expand Down
37 changes: 18 additions & 19 deletions src/components/@molecules/DateSelection/DateSelection.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useMemo, useState } from 'react'
import { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'

Expand Down Expand Up @@ -33,21 +33,23 @@ const now = Math.floor(Date.now() / 1000)
export const DateSelection = ({
seconds,
setSeconds,
durationType,
onChangeDurationType,
name,
minSeconds,
mode = 'register',
expiry,
}: {
seconds: number
setSeconds: (seconds: number) => void
durationType: 'years' | 'date'
name?: string
minSeconds: number
mode?: 'register' | 'extend'
expiry?: number
onChangeDurationType?: (type: 'years' | 'date') => void
}) => {
const currentTime = expiry ?? now
const [yearPickView, setYearPickView] = useState<'years' | 'date'>('years')
const toggleYearPickView = () => setYearPickView(yearPickView === 'date' ? 'years' : 'date')

const { t } = useTranslation()

Expand All @@ -57,29 +59,23 @@ export const DateSelection = ({
}, [minSeconds, seconds])

const dateInYears = Math.floor(secondsToYears(seconds))
const extensionPeriod = useMemo(() => {
return formatDurationOfDates(
new Date(currentTime * 1000),
new Date((currentTime + seconds) * 1000),
t,
)
}, [currentTime, seconds, t])

// When the duration type is years, normalise the seconds to a year value
useEffect(() => {
if (yearPickView === 'years' && currentTime) {
if (durationType === 'years' && currentTime) {
setSeconds(
secondsFromDateDiff({
startDate: new Date(currentTime * 1000),
additionalYears: dateInYears < 1 ? 1 : dateInYears,
additionalYears: Math.max(1, dateInYears),
}),
)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dateInYears, yearPickView])
}, [dateInYears, durationType])

return (
<Container>
{yearPickView === 'date' ? (
{durationType === 'date' ? (
<Calendar
value={currentTime + seconds}
onChange={(e) => {
Expand Down Expand Up @@ -111,15 +107,18 @@ export const DateSelection = ({
/>
)}
<Typography color="greyPrimary" fontVariant="smallBold" data-testid="date-selection-info">
{extensionPeriod === t('unit.invalid_date', { ns: 'common' })
? extensionPeriod
: `${extensionPeriod} ${mode === 'register' ? 'registration.' : 'extension.'}`}{' '}
{formatDurationOfDates({
startDate: new Date(currentTime * 1000),
endDate: new Date((currentTime + seconds) * 1000),
postFix: mode === 'register' ? ' registration. ' : ' extension. ',
t,
})}
<YearsViewSwitch
type="button"
data-testid="date-selection"
onClick={() => toggleYearPickView()}
onClick={() => onChangeDurationType?.(durationType === 'years' ? 'date' : 'years')}
>
{t(`calendar.pick_by_${yearPickView === 'date' ? 'years' : 'date'}`, { ns: 'common' })}
{t(`calendar.pick_by_${durationType === 'date' ? 'years' : 'date'}`, { ns: 'common' })}
</YearsViewSwitch>
</Typography>
</Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ const FullInvoice = ({
return [
{
label: t('invoice.timeRegistration', {
time: formatDurationOfDates(new Date(), new Date(now + seconds * 1000), t),
time: formatDurationOfDates({
startDate: new Date(),
endDate: new Date(now + seconds * 1000),
t,
}),
}),
bufferPercentage: CURRENCY_FLUCTUATION_BUFFER_PERCENTAGE,
value: totalDurationBasedFee,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,15 @@ const Registration = ({ nameDetails, isLoading }: Props) => {
seconds,
reverseRecord,
paymentMethodChoice,
durationType,
}: RegistrationStepData['pricing']) => {
if (paymentMethodChoice === PaymentMethod.moonpay) {
initiateMoonpayRegistrationMutation.mutate(secondsToYears(seconds))
return
}
dispatch({
name: 'setPricingData',
payload: { seconds, reverseRecord },
payload: { seconds, reverseRecord, durationType },
selected,
})
if (!item.queue.includes('profile')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ export type ActionButtonProps = {
seconds: number
balance: GetBalanceData | undefined
totalRequiredBalance?: bigint
durationType: 'date' | 'years'
}

export const ActionButton = (props: ActionButtonProps) => {
Expand All @@ -404,12 +405,13 @@ export const ActionButton = (props: ActionButtonProps) => {
reverseRecord,
seconds,
paymentMethodChoice,
durationType,
callback,
}) => (
<Button
loading={initiateMoonpayRegistrationMutation.isPending}
data-testid="next-button"
onClick={() => callback({ reverseRecord, seconds, paymentMethodChoice })}
onClick={() => callback({ reverseRecord, seconds, paymentMethodChoice, durationType })}
disabled={!paymentMethodChoice || initiateMoonpayRegistrationMutation.isPending}
>
{t('action.next', { ns: 'common' })}
Expand Down Expand Up @@ -438,10 +440,10 @@ export const ActionButton = (props: ActionButtonProps) => {
</Button>
),
)
.otherwise(({ reverseRecord, seconds, paymentMethodChoice, callback }) => (
.otherwise(({ reverseRecord, seconds, paymentMethodChoice, durationType, callback }) => (
<Button
data-testid="next-button"
onClick={() => callback({ reverseRecord, seconds, paymentMethodChoice })}
onClick={() => callback({ reverseRecord, seconds, paymentMethodChoice, durationType })}
disabled={!paymentMethodChoice}
>
{t('action.next', { ns: 'common' })}
Expand Down Expand Up @@ -486,6 +488,9 @@ const Pricing = ({
const resolverAddress = useContractAddress({ contract: 'ensPublicResolver' })

const [seconds, setSeconds] = useState(() => registrationData.seconds ?? ONE_YEAR)
const [durationType, setDurationType] = useState<'date' | 'years'>(
registrationData.durationType ?? 'years',
)

const [reverseRecord, setReverseRecord] = useState(() =>
registrationData.started ? registrationData.reverseRecord : !hasPrimaryName,
Expand Down Expand Up @@ -550,7 +555,10 @@ const Pricing = ({
return (
<StyledCard>
<StyledHeading>{t('heading', { name: beautifiedName })}</StyledHeading>
<DateSelection {...{ seconds, setSeconds, minSeconds }} />
<DateSelection
{...{ seconds, setSeconds, minSeconds, durationType }}
onChangeDurationType={setDurationType}
/>
<FullInvoice {...fullEstimate} />
{hasPremium && gracePeriodEndDate ? (
<TemporaryPremium startDate={gracePeriodEndDate} name={name} />
Expand Down Expand Up @@ -594,6 +602,7 @@ const Pricing = ({
seconds,
balance,
totalRequiredBalance,
durationType,
}}
/>
</MobileFullWidth>
Expand Down
1 change: 1 addition & 0 deletions src/components/pages/profile/[name]/registration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type RegistrationStepData = {
seconds: number
reverseRecord: boolean
paymentMethodChoice: PaymentMethod | ''
durationType: 'date' | 'years'
}
profile: {
records: ProfileRecord[]
Expand Down
3 changes: 3 additions & 0 deletions src/hooks/useRegistrationReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const defaultData: RegistrationReducerDataItem = {
isMoonpayFlow: false,
externalTransactionId: '',
chainId: 1,
durationType: 'years',
version: REGISTRATION_REDUCER_DATA_ITEM_VERSION,
}

Expand All @@ -52,6 +53,7 @@ const makeDefaultData = (selected: SelectedItemProperties): RegistrationReducerD
isMoonpayFlow: false,
externalTransactionId: '',
version: REGISTRATION_REDUCER_DATA_ITEM_VERSION,
durationType: 'years',
...selected,
})

Expand Down Expand Up @@ -107,6 +109,7 @@ const reducer = (state: RegistrationReducerData, action: RegistrationReducerActi
case 'setPricingData': {
item.seconds = action.payload.seconds
item.reverseRecord = action.payload.reverseRecord
item.durationType = action.payload.durationType
break
}
case 'setTransactionsData': {
Expand Down
15 changes: 9 additions & 6 deletions src/transaction-flow/input/ExtendNames/ExtendNames-flow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ const ExtendNames = ({ data: { names, isSelf }, dispatch, onDismiss }: Props) =>
const view = flow[viewIdx]

const [seconds, setSeconds] = useState(ONE_YEAR)
const [durationType, setDurationType] = useState<'years' | 'date'>('years')

const years = secondsToYears(seconds)

Expand All @@ -213,15 +214,15 @@ const ExtendNames = ({ data: { names, isSelf }, dispatch, onDismiss }: Props) =>
const previousYearlyFee = usePreviousDistinct(yearlyFee) || 0n
const unsafeDisplayYearlyFee = yearlyFee !== 0n ? yearlyFee : previousYearlyFee
const isShowingPreviousYearlyFee = yearlyFee === 0n && previousYearlyFee > 0n
const { data: expiryData } = useExpiry({ enabled: names.length > 1, name: names[0] })
const expireDate = expiryData?.expiry?.date ? new Date(expiryData?.expiry?.date) : new Date()
const extendedDate = new Date(expireDate.getTime() + seconds * 1000)
const { data: expiryData } = useExpiry({ enabled: names.length === 1, name: names[0] })
const expiryDate = expiryData?.expiry?.date
const extendedDate = expiryDate ? new Date(expiryDate.getTime() + seconds * 1000) : undefined

const transactions = [
createTransactionItem('extendNames', {
names,
duration: seconds,
startDateTimestamp: expireDate.getTime(),
startDateTimestamp: expiryDate?.getTime(),
displayPrice: makeCurrencyDisplay({
eth: totalRentFee,
ethPrice,
Expand All @@ -243,7 +244,7 @@ const ExtendNames = ({ data: { names, isSelf }, dispatch, onDismiss }: Props) =>
data: {
duration: seconds,
names,
startDateTimestamp: expireDate.getTime(),
startDateTimestamp: expiryDate?.getTime(),
},
stateOverride: [
{
Expand All @@ -266,7 +267,7 @@ const ExtendNames = ({ data: { names, isSelf }, dispatch, onDismiss }: Props) =>
const items: InvoiceItem[] = [
{
label: t('input.extendNames.invoice.extension', {
time: formatDurationOfDates(expireDate, extendedDate, t),
time: formatDurationOfDates({ startDate: expiryDate, endDate: extendedDate, t }),
}),
value: totalRentFee,
bufferPercentage: CURRENCY_FLUCTUATION_BUFFER_PERCENTAGE,
Expand Down Expand Up @@ -328,6 +329,8 @@ const ExtendNames = ({ data: { names, isSelf }, dispatch, onDismiss }: Props) =>
minSeconds={minSeconds}
mode="extend"
expiry={Number(expiryData?.expiry.value)}
durationType={durationType}
onChangeDurationType={setDurationType}
/>
) : (
<PlusMinusControl
Expand Down
10 changes: 5 additions & 5 deletions src/transaction-flow/transaction/extendNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { calculateValueWithBuffer, formatDurationOfDates } from '../../utils/uti
type Data = {
names: string[]
duration: number
startDateTimestamp: number
startDateTimestamp?: number
displayPrice?: string
}

Expand All @@ -30,11 +30,11 @@ const displayItems = (
},
{
label: 'duration',
value: formatDurationOfDates(
new Date(startDateTimestamp),
new Date(startDateTimestamp + duration * 1000),
value: formatDurationOfDates({
startDate: startDateTimestamp ? new Date(startDateTimestamp) : undefined,
endDate: startDateTimestamp ? new Date(startDateTimestamp + duration * 1000) : undefined,
t,
),
}),
},
{
label: 'cost',
Expand Down
6 changes: 5 additions & 1 deletion src/transaction-flow/transaction/registerName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ const displayItems = (
},
{
label: 'duration',
value: formatDurationOfDates(new Date(), new Date(now + duration * 1000), t),
value: formatDurationOfDates({
startDate: new Date(),
endDate: new Date(now + duration * 1000),
t,
}),
},
]

Expand Down
Loading

0 comments on commit 2b4ab85

Please sign in to comment.