fix: refactor, emails list, breath circle
This commit is contained in:
parent
806a5d3050
commit
041112bdaa
@ -11,6 +11,7 @@ function BreathCircle(): JSX.Element {
|
|||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const [text, setText] = useState(t(''))
|
const [text, setText] = useState(t(''))
|
||||||
const [render, setRender] = useState(false)
|
const [render, setRender] = useState(false)
|
||||||
|
const [counter, setCounter] = useState(0)
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -29,10 +30,13 @@ function BreathCircle(): JSX.Element {
|
|||||||
return sleep(4000)
|
return sleep(4000)
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
handleNext()
|
setCounter((prevState) => prevState + 1)
|
||||||
|
if (counter === 3) {
|
||||||
|
handleNext()
|
||||||
|
}
|
||||||
setRender((prevState) => !prevState)
|
setRender((prevState) => !prevState)
|
||||||
})
|
})
|
||||||
}, [t, render, navigate])
|
}, [t, render, navigate, counter])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles['outer-circle']}>
|
<div className={styles['outer-circle']}>
|
||||||
|
|||||||
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
.inner-circle {
|
.inner-circle {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 200px;
|
width: 240px;
|
||||||
height: 200px;
|
height: 240px;
|
||||||
background-color: #69a8e7;
|
background-color: #69a8e7;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -10,7 +10,9 @@ import { AICompatCategories, useApi, useApiCall } from "@/api";
|
|||||||
|
|
||||||
function CompatibilityPage(): JSX.Element {
|
function CompatibilityPage(): JSX.Element {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const [isDisabled, setIsDisabled] = useState(false);
|
const [isDisabled, setIsDisabled] = useState(true);
|
||||||
|
const [isDisabledName, setIsDisabledName] = useState(true);
|
||||||
|
const [isDisabledDate, setIsDisabledDate] = useState(true);
|
||||||
const [name, setName] = useState<string>('');
|
const [name, setName] = useState<string>('');
|
||||||
const [date, setDate] = useState<string | IDate>('');
|
const [date, setDate] = useState<string | IDate>('');
|
||||||
const [compatCategory, setCompatCategory] = useState(2);
|
const [compatCategory, setCompatCategory] = useState(2);
|
||||||
@ -25,13 +27,19 @@ function CompatibilityPage(): JSX.Element {
|
|||||||
const { data } = useApiCall<AICompatCategories.CompatCategory[]>(loadData)
|
const { data } = useApiCall<AICompatCategories.CompatCategory[]>(loadData)
|
||||||
|
|
||||||
const handleValidName = (name: string) => {
|
const handleValidName = (name: string) => {
|
||||||
setIsDisabled(name === '');
|
setIsDisabledName(!name.length);
|
||||||
setName(name)
|
setName(name)
|
||||||
|
checkAllDisabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleValidDate = (date: IDate | string) => {
|
const handleValidDate = (date: IDate | string) => {
|
||||||
setIsDisabled(date === '');
|
setIsDisabledDate(date === '');
|
||||||
setDate(date)
|
setDate(date)
|
||||||
|
checkAllDisabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAllDisabled = () => {
|
||||||
|
setIsDisabled(isDisabledName || isDisabledDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeCompatCategory = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const changeCompatCategory = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
@ -58,7 +66,7 @@ function CompatibilityPage(): JSX.Element {
|
|||||||
value={name}
|
value={name}
|
||||||
placeholder={t('name')}
|
placeholder={t('name')}
|
||||||
onValid={handleValidName}
|
onValid={handleValidName}
|
||||||
onInvalid={() => setIsDisabled(true)}
|
onInvalid={() => setIsDisabledName(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles['input-container__date-container']}>
|
<div className={styles['input-container__date-container']}>
|
||||||
@ -67,7 +75,7 @@ function CompatibilityPage(): JSX.Element {
|
|||||||
value={getDateAsString(date)}
|
value={getDateAsString(date)}
|
||||||
inputClassName={styles['date-input']}
|
inputClassName={styles['date-input']}
|
||||||
onValid={handleValidDate}
|
onValid={handleValidDate}
|
||||||
onInvalid={() => setIsDisabled(true)}
|
onInvalid={() => setIsDisabledDate(true)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -4,25 +4,45 @@ import styles from './styles.module.css'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
|
||||||
const emails: IEmailItem[] = []
|
// const getEmails = (): IEmailItem[] => {
|
||||||
|
// const emails: IEmailItem[] = []
|
||||||
|
|
||||||
|
// for (let i = 0; i < 2; i++) {
|
||||||
|
// const subList = []
|
||||||
|
// for (let j = 0; j < 4; j++) {
|
||||||
|
// subList.push({
|
||||||
|
// email: getRandomName(),
|
||||||
|
// price: 9
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// subList[getRandomArbitrary(0, 4)].price = [5, 13.67][getRandomArbitrary(0, 2)]
|
||||||
|
// emails.push(...subList)
|
||||||
|
// }
|
||||||
|
|
||||||
for (let i = 0; i < 25; i++) {
|
// return emails
|
||||||
const sublist = []
|
// }
|
||||||
for (let j = 0; j < 4; j++) {
|
|
||||||
sublist.push({
|
const getEmails = (): IEmailItem[] => {
|
||||||
|
const emails: IEmailItem[] = []
|
||||||
|
|
||||||
|
for (let index = 0; index < 5; index++) {
|
||||||
|
emails.push({
|
||||||
email: getRandomName(),
|
email: getRandomName(),
|
||||||
price: 9
|
price: [9, 9, 9, 9, 9, 5, 13.67][getRandomArbitrary(0, 7)]
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
sublist[getRandomArbitrary(0, 4)].price = [5, 13.67][getRandomArbitrary(0, 2)]
|
|
||||||
emails.push(...sublist)
|
return emails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function EmailsList(): JSX.Element {
|
function EmailsList(): JSX.Element {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [countUsers, setCountUsers] = useState(752)
|
const [countUsers, setCountUsers] = useState(752)
|
||||||
|
const [emails, setEmails] = useState(getEmails())
|
||||||
|
const [elementIdx, setElementIdx] = useState(0)
|
||||||
const itemsRef = useRef<HTMLDivElement[]>([]);
|
const itemsRef = useRef<HTMLDivElement[]>([]);
|
||||||
let elementIdx = 0
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const randomDelay = getRandomArbitrary(3000, 5000)
|
const randomDelay = getRandomArbitrary(3000, 5000)
|
||||||
@ -30,28 +50,39 @@ function EmailsList(): JSX.Element {
|
|||||||
setCountUsers((prevState) => prevState + 1)
|
setCountUsers((prevState) => prevState + 1)
|
||||||
}, randomDelay)
|
}, randomDelay)
|
||||||
return () => clearTimeout(countUsersTimeOut)
|
return () => clearTimeout(countUsersTimeOut)
|
||||||
}, [countUsers, elementIdx])
|
}, [countUsers])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const randomDelay = getRandomArbitrary(500, 5000)
|
||||||
|
|
||||||
const itemsRefInterval = setInterval(() => {
|
const itemsRefInterval = setInterval(() => {
|
||||||
|
if (itemsRef.current[elementIdx - 1]) {
|
||||||
|
itemsRef.current[elementIdx - 1].remove()
|
||||||
|
}
|
||||||
if (itemsRef.current[elementIdx]?.style) {
|
if (itemsRef.current[elementIdx]?.style) {
|
||||||
itemsRef.current[elementIdx].className = styles.hidden
|
itemsRef.current[elementIdx].classList.add(styles.hidden)
|
||||||
}
|
}
|
||||||
elementIdx++
|
setEmails((prevState) => {
|
||||||
}, 3000)
|
const array = prevState.slice(0)
|
||||||
return () => clearTimeout(itemsRefInterval)
|
array.push({
|
||||||
}, [elementIdx])
|
email: getRandomName(),
|
||||||
|
price: [9, 9, 9, 9, 9, 5, 13.67][getRandomArbitrary(0, 7)]
|
||||||
|
})
|
||||||
|
return array
|
||||||
|
})
|
||||||
|
setElementIdx((prevState) => prevState + 1)
|
||||||
|
}, randomDelay)
|
||||||
|
return () => clearInterval(itemsRefInterval)
|
||||||
|
}, [emails, elementIdx])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
<span className={styles['title']}>{t('people_joined_today', { countPeoples: <strong>{countUsers}</strong> })}</span>
|
<span className={styles['title']}>{t('people_joined_today', { countPeoples: <strong>{countUsers}</strong> })}</span>
|
||||||
<div className={styles['emails-container']}>
|
<div className={styles['emails-container']}>
|
||||||
{emails.map(({email, price}, idx) => (
|
{emails.map(({email, price}, idx) => (
|
||||||
<div ref={(el: HTMLDivElement) => itemsRef.current[idx] = el} key={idx}>
|
<div className={styles['email-item']} ref={(el: HTMLDivElement) => itemsRef.current[idx] = el} key={idx}>
|
||||||
<EmailItem email={email} price={price} />
|
<EmailItem email={email} price={price} />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -13,22 +13,28 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #494747;
|
color: #494747;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.emails-container {
|
.emails-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex-grow: 3;
|
height: 108px;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column-reverse;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.email-item {
|
||||||
transition: all 1s ease;
|
margin-top: 0;
|
||||||
margin-top: -26px;
|
opacity: 1;
|
||||||
opacity: 0;
|
will-change: margin-top, opacity;
|
||||||
will-change: margin-top, opacity;
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
transition: all .5s ease;
|
||||||
|
margin-bottom: -26px;
|
||||||
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import Title from '../Title'
|
import Title from '../Title'
|
||||||
import routes from '@/routes'
|
import routes from '@/routes'
|
||||||
import styles from './styles.module.css'
|
import styles from './styles.module.css'
|
||||||
import { useCallback } from 'react'
|
import { MouseEventHandler, TouchEventHandler, useCallback } from 'react'
|
||||||
import { useDispatch } from 'react-redux'
|
import { useDispatch } from 'react-redux'
|
||||||
import { actions } from '@/store'
|
import { actions } from '@/store'
|
||||||
|
|
||||||
@ -19,15 +19,27 @@ function FreePeriodInfoPage(): JSX.Element {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}, [dispatch])
|
}, [dispatch])
|
||||||
const handleNext = (e: any) => {
|
|
||||||
const X = e.clientX || Math.round(e.touches[0].clientX)
|
const handleNext = () => {
|
||||||
const Y = e.clientY || Math.round(e.touches[0].clientY)
|
|
||||||
updateCoordinates(X, Y)
|
|
||||||
navigate(routes.client.createProfile())
|
navigate(routes.client.createProfile())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mouseDown: MouseEventHandler<HTMLElement> = (e) => {
|
||||||
|
const X = e.clientX
|
||||||
|
const Y = e.clientY
|
||||||
|
updateCoordinates(X, Y)
|
||||||
|
handleNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
const touchStart: TouchEventHandler<HTMLElement> = (e) => {
|
||||||
|
const X = e.touches[0].clientX
|
||||||
|
const Y = e.touches[0].clientY
|
||||||
|
updateCoordinates(X, Y)
|
||||||
|
handleNext()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={`${styles.page} page`} onMouseDown={handleNext} onTouchStart={handleNext}>
|
<section className={`${styles.page} page`} onMouseDown={mouseDown} onTouchStart={touchStart}>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<Title variant='h4' className={styles.title}>{t('touch_screen')}</Title>
|
<Title variant='h4' className={styles.title}>{t('touch_screen')}</Title>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -22,15 +22,21 @@ const removeAfterDot = (value: string): string => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface PriceItemProps {
|
interface PriceItemProps {
|
||||||
click: () => void
|
active: boolean
|
||||||
|
click: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function PriceItem({ id, value, click }: IPrice & PriceItemProps): JSX.Element {
|
function PriceItem({ id, value, active, click }: IPrice & PriceItemProps): JSX.Element {
|
||||||
console.log(id);
|
|
||||||
const _price = new Price(roundToWhole(value), currency, locale)
|
const _price = new Price(roundToWhole(value), currency, locale)
|
||||||
|
|
||||||
|
const compatClassName = () => {
|
||||||
|
const isPopular = id === 3
|
||||||
|
const isActive = active
|
||||||
|
return `${styles.container} ${isPopular ? styles.popular : ''} ${isActive ? styles.active : ''}`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div onClick={click} className={`${styles.container} ${value === 9 ? styles.popular : ''}`}>
|
<div onClick={click} className={compatClassName()}>
|
||||||
{removeAfterDot(_price.format())}
|
{removeAfterDot(_price.format())}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -11,6 +11,12 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background-color: #30bf52;
|
||||||
|
border-color: #30bf52;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.popular {
|
.popular {
|
||||||
border-color: #30bf52;
|
border-color: #30bf52;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,16 +26,16 @@ const prices: IPrice[] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
interface PriceListProps {
|
interface PriceListProps {
|
||||||
click: () => void
|
activeItem: number | null
|
||||||
|
click: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function PriceList({click}: PriceListProps): JSX.Element {
|
function PriceList({click, activeItem}: PriceListProps): JSX.Element {
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.container}`}>
|
<div className={`${styles.container}`}>
|
||||||
{prices.map((price, idx) => (
|
{prices.map((price, idx) => (
|
||||||
<PriceItem key={idx} value={price.value} id={price.id} click={click} />
|
<PriceItem active={price.id === activeItem} key={idx} value={price.value} id={price.id} click={click} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -12,11 +12,12 @@ import PriceList from '../PriceList'
|
|||||||
function PriceListPage(): JSX.Element {
|
function PriceListPage(): JSX.Element {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const selectedPrice = useSelector(selectors.selectSelectedPrice)
|
||||||
|
|
||||||
const email = useSelector(selectors.selectEmail)
|
const email = useSelector(selectors.selectEmail)
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
navigate(routes.client.breath())
|
navigate(routes.client.breath())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -28,7 +29,7 @@ function PriceListPage(): JSX.Element {
|
|||||||
<EmailsList />
|
<EmailsList />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles['price-list-container']}>
|
<div className={styles['price-list-container']}>
|
||||||
<PriceList click={handleNext} />
|
<PriceList activeItem={selectedPrice} click={handleNext} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
.emails-list-container {
|
.emails-list-container {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
height: 130px;
|
/* height: 136px; */
|
||||||
margin-top: 48px;
|
margin-top: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,9 @@ import routes from '@/routes'
|
|||||||
import styles from './styles.module.css'
|
import styles from './styles.module.css'
|
||||||
import ModalTop from '../ModalTop'
|
import ModalTop from '../ModalTop'
|
||||||
import Header from '../Header'
|
import Header from '../Header'
|
||||||
|
import { useCallback } from 'react'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
import { actions } from '@/store'
|
||||||
|
|
||||||
interface ModalTopProps {
|
interface ModalTopProps {
|
||||||
open: boolean
|
open: boolean
|
||||||
@ -14,7 +17,14 @@ interface ModalTopProps {
|
|||||||
function SpecialWelcomeOffer({ open, onClose }: ModalTopProps): JSX.Element {
|
function SpecialWelcomeOffer({ open, onClose }: ModalTopProps): JSX.Element {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const updateSelectedPrice = useCallback((selectedPrice: number | null) => {
|
||||||
|
dispatch(actions.payment.update({
|
||||||
|
selectedPrice
|
||||||
|
}))
|
||||||
|
}, [dispatch])
|
||||||
const handleNext = () => {
|
const handleNext = () => {
|
||||||
|
updateSelectedPrice(1)
|
||||||
navigate(routes.client.emailEnter())
|
navigate(routes.client.emailEnter())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,15 @@ import token, { actions as tokenActions, selectToken } from './token'
|
|||||||
import user, { actions as userActions, selectUser } from './user'
|
import user, { actions as userActions, selectUser } from './user'
|
||||||
import form, { actions as formActions, selectors as formSelectors } from './form'
|
import form, { actions as formActions, selectors as formSelectors } from './form'
|
||||||
import aura, { actions as auraActions } from './aura'
|
import aura, { actions as auraActions } from './aura'
|
||||||
|
import payment, { actions as paymentActions } from './payment'
|
||||||
import subscriptionPlans, { actions as subscriptionPlasActions, selectPlanById } from './subscriptionPlan'
|
import subscriptionPlans, { actions as subscriptionPlasActions, selectPlanById } from './subscriptionPlan'
|
||||||
import status, { actions as userStatusActions, selectStatus } from './status'
|
import status, { actions as userStatusActions, selectStatus } from './status'
|
||||||
import { loadStore, backupStore } from './storageHelper'
|
import { loadStore, backupStore } from './storageHelper'
|
||||||
import { selectAuraCoordinates } from './aura'
|
import { selectAuraCoordinates } from './aura'
|
||||||
|
import { selectSelectedPrice } from './payment'
|
||||||
|
|
||||||
const preloadedState = loadStore()
|
const preloadedState = loadStore()
|
||||||
export const reducer = combineReducers({ token, user, form, status, subscriptionPlans, aura })
|
export const reducer = combineReducers({ token, user, form, status, subscriptionPlans, aura, payment })
|
||||||
export const actions = {
|
export const actions = {
|
||||||
token: tokenActions,
|
token: tokenActions,
|
||||||
user: userActions,
|
user: userActions,
|
||||||
@ -17,6 +19,7 @@ export const actions = {
|
|||||||
status: userStatusActions,
|
status: userStatusActions,
|
||||||
subscriptionPlan: subscriptionPlasActions,
|
subscriptionPlan: subscriptionPlasActions,
|
||||||
aura: auraActions,
|
aura: auraActions,
|
||||||
|
payment: paymentActions,
|
||||||
reset: createAction('reset'),
|
reset: createAction('reset'),
|
||||||
}
|
}
|
||||||
export const selectors = {
|
export const selectors = {
|
||||||
@ -25,6 +28,7 @@ export const selectors = {
|
|||||||
selectStatus,
|
selectStatus,
|
||||||
selectPlanById,
|
selectPlanById,
|
||||||
selectAuraCoordinates,
|
selectAuraCoordinates,
|
||||||
|
selectSelectedPrice,
|
||||||
...formSelectors,
|
...formSelectors,
|
||||||
}
|
}
|
||||||
export type RootState = ReturnType<typeof reducer>
|
export type RootState = ReturnType<typeof reducer>
|
||||||
|
|||||||
28
src/store/payment.ts
Normal file
28
src/store/payment.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { createSlice, createSelector } from '@reduxjs/toolkit'
|
||||||
|
import type { PayloadAction } from '@reduxjs/toolkit'
|
||||||
|
|
||||||
|
interface IPayment {
|
||||||
|
selectedPrice: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: IPayment = {
|
||||||
|
selectedPrice: null
|
||||||
|
}
|
||||||
|
|
||||||
|
const paymentSlice = createSlice({
|
||||||
|
name: 'payment',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
update(state, action: PayloadAction<Partial<IPayment>>) {
|
||||||
|
return { ...state, ...action.payload }
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extraReducers: (builder) => builder.addCase('reset', () => initialState),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const { actions } = paymentSlice
|
||||||
|
export const selectSelectedPrice = createSelector(
|
||||||
|
(state: { payment: IPayment }) => state.payment.selectedPrice,
|
||||||
|
(payment) => payment
|
||||||
|
)
|
||||||
|
export default paymentSlice.reducer
|
||||||
Loading…
Reference in New Issue
Block a user