-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #350 from pendulum-chain/improve-feedback-on-login
Improve UI on log-in modal.
- Loading branch information
Showing
10 changed files
with
140 additions
and
148 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,105 +1,125 @@ | ||
import { Progress } from 'react-daisyui'; | ||
import { FC } from 'preact/compat'; | ||
import accountBalanceWalletIcon from '../../assets/account-balance-wallet.svg'; | ||
import { FC, useState, useEffect } from 'preact/compat'; | ||
import { motion, AnimatePresence } from 'framer-motion'; | ||
|
||
import { SigningPhase } from '../../hooks/offramp/useMainProcess'; | ||
import { isNetworkEVM, Networks } from '../../helpers/networks'; | ||
import accountBalanceWalletIcon from '../../assets/account-balance-wallet-blue.svg'; | ||
import { OfframpSigningPhase } from '../../types/offramp'; | ||
import { isNetworkEVM } from '../../helpers/networks'; | ||
import { useNetwork } from '../../contexts/network'; | ||
import { Spinner } from '../Spinner'; | ||
|
||
type ProgressStep = { | ||
started: string; | ||
signed: string; | ||
finished: string; | ||
approved: string; | ||
type ProgressConfig = { | ||
[key in OfframpSigningPhase]: number; | ||
}; | ||
|
||
type SignatureConfig = { | ||
maxSignatures: number; | ||
getSignatureNumber: (step: SigningPhase) => string; | ||
const PROGRESS_CONFIGS: Record<'EVM' | 'NON_EVM', ProgressConfig> = { | ||
EVM: { | ||
started: 25, | ||
approved: 50, | ||
signed: 75, | ||
finished: 100, | ||
login: 15, | ||
}, | ||
NON_EVM: { | ||
started: 33, | ||
finished: 100, | ||
signed: 0, | ||
approved: 0, | ||
login: 15, | ||
}, | ||
}; | ||
|
||
const EVM_PROGRESS_CONFIG: ProgressStep = { | ||
started: '25', | ||
approved: '50', | ||
signed: '75', | ||
finished: '100', | ||
}; | ||
|
||
const NON_EVM_PROGRESS_CONFIG: ProgressStep = { | ||
started: '33', | ||
finished: '100', | ||
signed: '0', | ||
approved: '0', | ||
}; | ||
|
||
const EVM_SIGNATURE_CONFIG: SignatureConfig = { | ||
maxSignatures: 2, | ||
getSignatureNumber: (step: SigningPhase) => (step === 'started' ? '1' : '2'), | ||
}; | ||
|
||
const NON_EVM_SIGNATURE_CONFIG: SignatureConfig = { | ||
maxSignatures: 1, | ||
getSignatureNumber: () => '1', | ||
}; | ||
|
||
const getProgressConfig = (network: Networks): ProgressStep => { | ||
return isNetworkEVM(network) ? EVM_PROGRESS_CONFIG : NON_EVM_PROGRESS_CONFIG; | ||
}; | ||
|
||
const getSignatureConfig = (network: Networks): SignatureConfig => { | ||
return isNetworkEVM(network) ? EVM_SIGNATURE_CONFIG : NON_EVM_SIGNATURE_CONFIG; | ||
const getSignatureDetails = (step: OfframpSigningPhase, isEVM: boolean) => { | ||
if (!isEVM) return { max: 1, current: 1 }; | ||
if (step === 'login') return { max: 1, current: 1 }; | ||
if (step === 'started') return { max: 2, current: 1 }; | ||
return { max: 2, current: 2 }; | ||
}; | ||
|
||
interface SigningBoxProps { | ||
step?: SigningPhase; | ||
step?: OfframpSigningPhase; | ||
} | ||
|
||
const isValidStep = (step: SigningPhase | undefined, network: Networks): step is SigningPhase => { | ||
const isValidStep = (step: OfframpSigningPhase | undefined, isEVM: boolean): step is OfframpSigningPhase => { | ||
if (!step) return false; | ||
if (!['started', 'approved', 'signed'].includes(step)) return false; | ||
if (!isNetworkEVM(network) && (step === 'approved' || step === 'signed')) return false; | ||
if (step === 'finished' || step === 'login') return true; | ||
if (!isEVM && (step === 'approved' || step === 'signed')) return false; | ||
return true; | ||
}; | ||
|
||
export const SigningBox: FC<SigningBoxProps> = ({ step }) => { | ||
const { selectedNetwork } = useNetwork(); | ||
const isEVM = isNetworkEVM(selectedNetwork); | ||
const progressConfig = isEVM ? PROGRESS_CONFIGS.EVM : PROGRESS_CONFIGS.NON_EVM; | ||
|
||
if (!isValidStep(step, selectedNetwork)) return null; | ||
const [progress, setProgress] = useState(0); | ||
const [signatureState, setSignatureState] = useState({ max: 0, current: 0 }); | ||
const [shouldExit, setShouldExit] = useState(false); | ||
|
||
const progressValue = getProgressConfig(selectedNetwork)[step]; | ||
const { maxSignatures, getSignatureNumber } = getSignatureConfig(selectedNetwork); | ||
useEffect(() => { | ||
if (!isValidStep(step, isEVM)) return; | ||
|
||
return ( | ||
<section className="z-50 toast toast-end"> | ||
<div className="shadow-2xl"> | ||
<header className="bg-pink-500 rounded-t"> | ||
<h1 className="w-full py-2 text-center text-white">Action Required</h1> | ||
</header> | ||
|
||
<main className="px-8 bg-white"> | ||
<div className="flex items-center justify-center"> | ||
<div className="flex items-center justify-center w-10 h-10 border rounded-full border-primary"> | ||
<img src={accountBalanceWalletIcon} alt="wallet account button" /> | ||
</div> | ||
<div className="mx-4 my-5 text-xs"> | ||
<p>Please sign the transaction in</p> | ||
<p>your connected wallet to proceed</p> | ||
</div> | ||
</div> | ||
if (step !== 'finished' && shouldExit) { | ||
setShouldExit(false); | ||
} | ||
|
||
<div className="w-full pb-2.5"> | ||
<Progress value={progressValue} max="100" className="h-4 bg-white border progress-primary border-primary" /> | ||
if (step === 'finished') { | ||
setProgress(100); | ||
setTimeout(() => setShouldExit(true), 2500); | ||
return; | ||
} | ||
|
||
setProgress(progressConfig[step]); | ||
setSignatureState(getSignatureDetails(step, isEVM)); | ||
}, [step, isEVM, progressConfig, shouldExit]); | ||
|
||
return ( | ||
<AnimatePresence mode="wait"> | ||
{!isValidStep(step, isEVM) || shouldExit ? null : ( | ||
<motion.section | ||
className="z-50 toast toast-end" | ||
initial={{ y: 150 }} | ||
animate={{ y: 0, transition: { type: 'spring', bounce: 0.4 } }} | ||
exit={{ y: 150 }} | ||
transition={{ duration: 0.5 }} | ||
key="signing-box" | ||
> | ||
<div className="shadow-2xl"> | ||
<motion.header className="bg-pink-500 rounded-t"> | ||
<h1 className="w-full py-2 text-center text-white">Action Required</h1> | ||
</motion.header> | ||
|
||
<main className="px-8 bg-white"> | ||
<motion.div className="flex items-center justify-center"> | ||
<div className="flex items-center justify-center w-10 h-10 border rounded-full border-primary"> | ||
<img src={accountBalanceWalletIcon} alt="wallet account button" /> | ||
</div> | ||
<div className="mx-4 my-5 text-xs"> | ||
<p>Please sign the transaction in</p> | ||
<p>your connected wallet to proceed</p> | ||
</div> | ||
</motion.div> | ||
|
||
<motion.div className="w-full pb-2.5"> | ||
<div className="w-full h-4 overflow-hidden bg-white border rounded-full border-primary"> | ||
<motion.div | ||
className="h-full rounded-full bg-primary" | ||
initial={{ width: 0 }} | ||
animate={{ width: `${progress}%` }} | ||
transition={{ duration: 0.5, ease: 'linear' }} | ||
/> | ||
</div> | ||
</motion.div> | ||
</main> | ||
|
||
<motion.footer className="flex items-center justify-center bg-[#5E88D5] text-white rounded-b"> | ||
<Spinner /> | ||
<p className="ml-2.5 my-2 text-xs"> | ||
Waiting for signature {signatureState.current}/{signatureState.max} | ||
</p> | ||
</motion.footer> | ||
</div> | ||
</main> | ||
|
||
<footer className="flex items-center justify-center bg-[#5E88D5] text-white rounded-b"> | ||
<Spinner /> | ||
<p className="ml-2.5 my-2 text-xs"> | ||
Waiting for signature {getSignatureNumber(step)}/{maxSignatures} | ||
</p> | ||
</footer> | ||
</div> | ||
</section> | ||
</motion.section> | ||
)} | ||
</AnimatePresence> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.