profile refactor
This commit is contained in:
@@ -7,6 +7,11 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
animation: overlayIn 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.closing {
|
||||||
|
animation: overlayOut 0.2s ease forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
@@ -19,6 +24,31 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
animation: cardIn 0.24s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.closing {
|
||||||
|
animation: cardOut 0.2s cubic-bezier(0.55, 0, 1, 0.45) forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes overlayIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes overlayOut {
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cardIn {
|
||||||
|
from { opacity: 0; transform: translateY(16px) scale(0.96); }
|
||||||
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cardOut {
|
||||||
|
from { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
to { opacity: 0; transform: translateY(16px) scale(0.96); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
import styles from './SwapConfirmModal.module.css'
|
import styles from './SwapConfirmModal.module.css'
|
||||||
|
|
||||||
interface SwapData {
|
interface SwapData {
|
||||||
@@ -22,16 +23,30 @@ interface Props {
|
|||||||
export function SwapConfirmModal({ data, insufficientBalance, onConfirm, onClose }: Props) {
|
export function SwapConfirmModal({ data, insufficientBalance, onConfirm, onClose }: Props) {
|
||||||
const { details, fees } = data
|
const { details, fees } = data
|
||||||
const { currencyIn, currencyOut, totalImpact, rate } = details
|
const { currencyIn, currencyOut, totalImpact, rate } = details
|
||||||
|
const [closing, setClosing] = useState(false)
|
||||||
|
|
||||||
const impactPercent = parseFloat(totalImpact.percent)
|
const impactPercent = parseFloat(totalImpact.percent)
|
||||||
const rateFormatted = parseFloat(rate).toFixed(4)
|
const rateFormatted = parseFloat(rate).toFixed(4)
|
||||||
|
|
||||||
|
// Play the exit animation first, then actually unmount once it ends.
|
||||||
|
function requestClose() {
|
||||||
|
setClosing(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAnimationEnd() {
|
||||||
|
if (closing) onClose()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.overlay} onClick={onClose}>
|
<div className={`${styles.overlay} ${closing ? styles.closing : ''}`} onClick={requestClose}>
|
||||||
<div className={styles.card} onClick={e => e.stopPropagation()}>
|
<div
|
||||||
|
className={`${styles.card} ${closing ? styles.closing : ''}`}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
onAnimationEnd={handleAnimationEnd}
|
||||||
|
>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<span className={styles.title}>Подтвердить своп</span>
|
<span className={styles.title}>Подтвердить своп</span>
|
||||||
<button className={styles.closeBtn} onClick={onClose}>×</button>
|
<button className={styles.closeBtn} onClick={requestClose}>×</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.flow}>
|
<div className={styles.flow}>
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ export function SwapForm() {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', fromNetwork] })
|
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', fromNetwork] })
|
||||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
||||||
navigate(ROUTES.WALLET)
|
navigate(`${ROUTES.WALLET}/${fromNetwork.toLowerCase()}`)
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
setErrorMessage(err instanceof Error ? err.message : 'Не удалось подписать транзакцию')
|
setErrorMessage(err instanceof Error ? err.message : 'Не удалось подписать транзакцию')
|
||||||
@@ -206,7 +206,7 @@ export function SwapForm() {
|
|||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', 'TRX'] })
|
queryClient.invalidateQueries({ queryKey: ['wallet', 'balance', 'TRX'] })
|
||||||
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
queryClient.invalidateQueries({ queryKey: ['wallet', 'portfolio'] })
|
||||||
navigate(ROUTES.WALLET)
|
navigate(`${ROUTES.WALLET}/${fromNetwork.toLowerCase()}`)
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
setErrorMessage(err instanceof Error ? err.message : 'Не удалось выполнить свап')
|
setErrorMessage(err instanceof Error ? err.message : 'Не удалось выполнить свап')
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
animation: overlayIn 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay.closing {
|
||||||
|
animation: overlayOut 0.2s ease forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
@@ -19,6 +24,31 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
|
animation: cardIn 0.24s cubic-bezier(0.22, 1, 0.36, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.closing {
|
||||||
|
animation: cardOut 0.2s cubic-bezier(0.55, 0, 1, 0.45) forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes overlayIn {
|
||||||
|
from { opacity: 0; }
|
||||||
|
to { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes overlayOut {
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cardIn {
|
||||||
|
from { opacity: 0; transform: translateY(16px) scale(0.96); }
|
||||||
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cardOut {
|
||||||
|
from { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
to { opacity: 0; transform: translateY(16px) scale(0.96); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
import type { TrxSwapQuoteData } from '@features/wallet'
|
import type { TrxSwapQuoteData } from '@features/wallet'
|
||||||
import styles from './TrxConfirmModal.module.css'
|
import styles from './TrxConfirmModal.module.css'
|
||||||
|
|
||||||
@@ -13,13 +14,27 @@ interface Props {
|
|||||||
|
|
||||||
export function TrxConfirmModal({ quote, fromSymbol, toSymbol, amountHuman, insufficientBalance, onConfirm, onClose }: Props) {
|
export function TrxConfirmModal({ quote, fromSymbol, toSymbol, amountHuman, insufficientBalance, onConfirm, onClose }: Props) {
|
||||||
const { expectedOutFormatted, minOutFormatted, fees } = quote
|
const { expectedOutFormatted, minOutFormatted, fees } = quote
|
||||||
|
const [closing, setClosing] = useState(false)
|
||||||
|
|
||||||
|
// Play the exit animation first, then actually unmount once it ends.
|
||||||
|
function requestClose() {
|
||||||
|
setClosing(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAnimationEnd() {
|
||||||
|
if (closing) onClose()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.overlay} onClick={onClose}>
|
<div className={`${styles.overlay} ${closing ? styles.closing : ''}`} onClick={requestClose}>
|
||||||
<div className={styles.card} onClick={e => e.stopPropagation()}>
|
<div
|
||||||
|
className={`${styles.card} ${closing ? styles.closing : ''}`}
|
||||||
|
onClick={e => e.stopPropagation()}
|
||||||
|
onAnimationEnd={handleAnimationEnd}
|
||||||
|
>
|
||||||
<div className={styles.header}>
|
<div className={styles.header}>
|
||||||
<span className={styles.title}>Подтвердить своп</span>
|
<span className={styles.title}>Подтвердить своп</span>
|
||||||
<button className={styles.closeBtn} onClick={onClose}>×</button>
|
<button className={styles.closeBtn} onClick={requestClose}>×</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.flow}>
|
<div className={styles.flow}>
|
||||||
|
|||||||
Reference in New Issue
Block a user