feat(#1330): added arrow loader (#437)

* feat(#1330): added arrow loader

* refactor(#1330): refactoring

* refactor(#1330): rename
keep-around/af30b88d367751c9e05a735e4a0467a96238ef47
Иван Пиминов 4 years ago committed by GitHub
parent 1769ff51a2
commit 183f0ff399
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      public/images/arrowGroup.svg
  2. 11
      src/features/AddCardForm/components/Form/hooks/index.tsx
  3. 10
      src/features/AddCardForm/components/Form/index.tsx
  4. 11
      src/features/AddCardForm/index.tsx
  5. 19
      src/features/ArrowLoader/index.tsx
  6. 39
      src/features/ArrowLoader/styled.tsx
  7. 6
      src/features/ArrowLoader/types.tsx
  8. 18
      src/features/BuyMatchPopup/components/SubscriptionSelectionStep/index.tsx
  9. 6
      src/features/BuyMatchPopup/store/hooks/index.tsx
  10. 11
      src/features/CardsStore/hooks/index.tsx
  11. 12
      src/features/UserAccount/components/BankCard/index.tsx
  12. 2
      src/features/UserAccount/components/PageBankCards/index.tsx
  13. 6
      src/features/UserAccount/styled.tsx

@ -0,0 +1,4 @@
<svg width="37" height="34" viewBox="0 0 37 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.7273 23.7334L28.0666 27.1107C22.5472 32.6929 13.509 32.6929 7.98953 27.1107C6.30609 25.4081 5.216 23.3706 4.56746 21.2214L2.22168 21.8913C2.99441 24.4033 4.31908 26.7897 6.30609 28.7993C12.8329 35.4003 23.1957 35.4003 29.7225 28.7993L33.0618 32.1765L36.0423 20.8027H35.6007L24.7273 23.7334Z" fill="white"/>
<path d="M11.3977 10.2801L8.03084 6.90283C13.5779 1.3206 22.6575 1.3206 28.1907 6.90283C29.8604 8.5775 30.9505 10.6011 31.599 12.7223L33.9448 12.0385C33.1721 9.55439 31.8474 7.1959 29.8604 5.20025C23.306 -1.40073 12.888 -1.40073 6.3336 5.20025L2.99432 1.823L0 13.1968H0.441558L11.3977 10.2801Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 733 B

@ -32,6 +32,7 @@ export type Props = {
children?: ReactNode,
initialformOpen?: boolean,
inputsBackground?: string,
loader?: boolean,
onAddSuccess?: () => void,
}
@ -54,6 +55,7 @@ export const useFormSubmit = ({ onAddSuccess }: Props) => {
const [name, setName] = useState('')
const [inputStates, setInputStates] = useObjectState(initialState)
const [error, setError] = useState('')
const [loader, setLoader] = useState(false)
const onNameChange = (e: ChangeEvent<HTMLInputElement>) => {
const { value } = e.target
@ -104,7 +106,7 @@ export const useFormSubmit = ({ onAddSuccess }: Props) => {
const cardNumberElement = elements.getElement(CardNumberElement)
if (!cardNumberElement) return
setLoader(true)
const { error: tokenError, token } = await stripe.createToken(
cardNumberElement,
{ name },
@ -112,8 +114,12 @@ export const useFormSubmit = ({ onAddSuccess }: Props) => {
if (tokenError) {
setError(tokenError.message || '')
setLoader(false)
} else if (token) {
onAddCard(token.id).then(onAddSuccess)
setLoader(true)
onAddCard(token.id)
.then(onAddSuccess)
.then(() => setLoader(false))
}
}
@ -125,6 +131,7 @@ export const useFormSubmit = ({ onAddSuccess }: Props) => {
error,
handleSubmit,
isLabelVisible,
loader,
name,
onInputsBlur,
onInputsChange,

@ -8,7 +8,7 @@ import { isMobileDevice } from 'config/userAgent'
import { T9n } from 'features/T9n'
import { useCardsStore } from 'features/CardsStore'
import { SolidButton } from 'features/UserAccount/styled'
import { ArrowLoader } from 'features/ArrowLoader'
import { ElementContainer } from '../ElementContainer'
@ -51,6 +51,7 @@ export const AddCardFormInner = (props: Props) => {
error: formError,
handleSubmit,
isLabelVisible,
loader,
name,
onInputsBlur,
onInputsChange,
@ -121,12 +122,7 @@ export const AddCardFormInner = (props: Props) => {
<T9n t={cardError} />
</Errors>
) }
{children || (
<SolidButton type='submit'>
Сохранить
</SolidButton>
)}
{loader ? <ArrowLoader disabled width='204px' /> : children}
</ButtonsBlock>
</Form>
)

@ -3,13 +3,16 @@ import type { MouseEvent } from 'react'
import { useToggle } from 'hooks'
import { T9n } from 'features/T9n'
import { OutlineButton, Icon } from 'features/UserAccount/styled'
import {
OutlineButton,
Icon,
SolidButton,
} from 'features/UserAccount/styled'
import type { Props } from './components/Form/hooks'
import { AddCardFormInner } from './components/Form'
export const AddCardForm = ({
children,
initialformOpen,
inputsBackground,
onAddSuccess,
@ -33,7 +36,9 @@ export const AddCardForm = ({
inputsBackground={inputsBackground}
onAddSuccess={onSuccess}
>
{children}
<SolidButton type='submit'>
Сохранить
</SolidButton>
</AddCardFormInner>
)
: (

@ -0,0 +1,19 @@
import { ArrowLoaderProps } from './types'
import { Wrapper, Arrows } from './styled'
export const ArrowLoader = ({
backgroundColor,
backgroundSize,
disabled,
width,
}: ArrowLoaderProps) => (
<Wrapper
width={width}
backgroundColor={backgroundColor}
disabled={disabled}
>
<Arrows backgroundSize={backgroundSize} />
</Wrapper>
)
export const ArrowLoaderUI = { ArrowLoader, Arrows }

@ -0,0 +1,39 @@
import styled from 'styled-components/macro'
import { keyframes } from 'styled-components'
import { ArrowLoaderProps } from './types'
const rotate = keyframes`
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
`
export const Wrapper = styled.button<ArrowLoaderProps>`
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
border-color: transparent;
width: ${({ width = 'auto' }) => width};
height: 50px;
background-color: ${({ backgroundColor = '#294fc4' }) => backgroundColor};
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
:disabled {
opacity: 0.5;
}
`
export const Arrows = styled.div<ArrowLoaderProps>`
width: 36px;
height: 34px;
background-size: ${({ backgroundSize = 'contain' }) => backgroundSize};
background-image: url(/images/arrowGroup.svg);
background-repeat: no-repeat;
background-position: center;
animation: ${rotate} 1s linear infinite;
`

@ -0,0 +1,6 @@
export type ArrowLoaderProps = {
backgroundColor?: string,
backgroundSize?: string,
disabled?: boolean,
width?:string,
}

@ -11,6 +11,7 @@ import {
import { T9n } from 'features/T9n'
import { Name } from 'features/Name'
import { useCardsStore } from 'features/CardsStore'
import { ArrowLoader } from 'features/ArrowLoader'
import { useBuyMatchPopupStore } from '../../store'
import { SelectedCard } from '../SelectedCard'
@ -32,6 +33,7 @@ export const SubscriptionSelectionStep = () => {
const {
close,
loader,
match,
onBuyClick,
selectedSubscription,
@ -62,12 +64,16 @@ export const SubscriptionSelectionStep = () => {
<SelectedCard />
</Body>
<Footer>
<Button
disabled={!selectedSubscription}
onClick={onBuyClick}
>
<T9n t='buy_subscription' />
</Button>
{loader
? <ArrowLoader width='204px' disabled />
: (
<Button
disabled={!selectedSubscription}
onClick={onBuyClick}
>
<T9n t='buy_subscription' />
</Button>
)}
</Footer>
</Wrapper>
)

@ -42,10 +42,12 @@ export const useBuyMatchPopup = () => {
const [steps, setSteps] = useState<Array<Steps>>([])
const [match, setMatch] = useState<Match | null>(null)
const [error, setError] = useState('')
const [loader, setLoader] = useState(false)
const goTo = useCallback(
(step: Steps, e?: MouseEvent<HTMLButtonElement>) => setSteps((state) => {
e?.stopPropagation()
setLoader(false)
return [...state, step]
}),
[],
@ -134,7 +136,7 @@ export const useBuyMatchPopup = () => {
const item = selectedSubscription.originalObject
const buy = requests[selectedSubscription.type]
setLoader(true)
buy({ cardId: defaultCard.id, item }).then(
onSuccessfulSubscription,
onUnsuccessfulSubscription,
@ -142,6 +144,7 @@ export const useBuyMatchPopup = () => {
}
const onBuyClick = (e?: MouseEvent<HTMLButtonElement>) => {
e?.stopPropagation()
if (defaultCard) {
subscribeToMatch()
} else {
@ -161,6 +164,7 @@ export const useBuyMatchPopup = () => {
error,
goBack,
goTo,
loader,
match,
matchSubscriptions,
onBuyClick,

@ -12,13 +12,14 @@ import { addCard } from 'requests/addCard'
import { deleteCard } from 'requests/deleteCard'
import { setDefaultCard as setDefaultCardRequest } from 'requests/setDefaultCard'
import { useToggle } from 'hooks'
import { useRequest, useToggle } from 'hooks'
export const useBankCards = () => {
const {
isOpen: infoModalOpen,
toggle: toggleInfoModal,
} = useToggle()
const [error, setError] = useState('')
const [cards, setCards] = useState<Cards | null>(null)
const defaultCard = useMemo(
@ -37,12 +38,13 @@ export const useBankCards = () => {
.then(fetchCards)
)
const onDeleteCard = (cardId: string) => {
deleteCard(cardId).then(() => {
const onDeleteCard = async (cardId: string) => {
await deleteCard(cardId).then(() => {
fetchCards()
toggleInfoModal()
})
}
const { isFetching, request: handleCardDelete } = useRequest(onDeleteCard)
const onSetDefaultCard = (cardId: string) => {
setDefaultCardRequest(cardId).then(fetchCards)
@ -54,8 +56,9 @@ export const useBankCards = () => {
error,
fetchCards,
infoModalOpen,
isFetching,
onAddCard,
onDeleteCard,
onDeleteCard: handleCardDelete,
onSetDefaultCard,
setError,
toggleInfoModal,

@ -1,6 +1,7 @@
import type { Card } from 'requests/getCardsList'
import { T9n } from 'features/T9n'
import { Arrows } from 'features/ArrowLoader/styled'
import { InlineButton } from '../../styled'
import { CardNumberWrapper, CustomRadio } from './styled'
@ -8,6 +9,7 @@ import { CardNumberWrapper, CustomRadio } from './styled'
type Props = {
card: Card,
checked?: boolean,
loader?: boolean,
onChange: (cardId: string) => void,
onDelete: (cardId: string) => void,
}
@ -15,6 +17,7 @@ type Props = {
export const BankCard = ({
card,
checked,
loader,
onChange,
onDelete,
}: Props) => (
@ -24,8 +27,13 @@ export const BankCard = ({
checked={checked}
onChange={() => onChange(card.id)}
/>
<InlineButton onClick={() => onDelete(card.id)}>
<T9n t='remove' />
<InlineButton
disabled={loader}
onClick={() => onDelete(card.id)}
>
{loader
? <Arrows backgroundSize='20px 20px' />
: <T9n t='remove' />}
</InlineButton>
</CardNumberWrapper>
)

@ -29,6 +29,7 @@ export const PageBankCards = () => {
defaultCard,
fetchCards,
infoModalOpen,
isFetching,
onDeleteCard,
onSetDefaultCard,
toggleInfoModal,
@ -49,6 +50,7 @@ export const PageBankCards = () => {
checked={card.id === defaultCard?.id}
onChange={onSetDefaultCard}
onDelete={onDeleteCard}
loader={isFetching}
/>
))}
<PaymentInfoText>

@ -159,6 +159,9 @@ type InlineButtonProps = {
}
export const InlineButton = styled.button<InlineButtonProps>`
display: flex;
justify-content: center;
align-items: center;
position: absolute;
right: 0;
border: none;
@ -173,4 +176,7 @@ export const InlineButton = styled.button<InlineButtonProps>`
cursor: pointer;
transition: transform 0.3s ease-in-out;
transform: translateX(calc(100% + 1px));
:disabled {
opacity: 0.5;
}
`

Loading…
Cancel
Save