profile refactor

This commit is contained in:
2026-06-29 19:57:36 +03:00
parent a5737e12e6
commit 9f45efc9eb
5 changed files with 98 additions and 8 deletions

View File

@@ -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 {

View File

@@ -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}>

View File

@@ -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 : 'Не удалось выполнить свап')

View File

@@ -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 {

View File

@@ -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}>