Skip to content

Commit

Permalink
added confirmation dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
igorgoldobin committed Feb 9, 2024
1 parent 7556991 commit 914c816
Show file tree
Hide file tree
Showing 10 changed files with 365 additions and 40 deletions.
79 changes: 79 additions & 0 deletions src/components/ConfirmModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React from 'react'

export interface ConfirmModalProps {
title: string;
body: string;
confirmText: string;
cancelText: string;
onConfirm: () => void;
onCancel: () => void;
onClose: () => void;
}

const ConfirmModal:React.FC<ConfirmModalProps> = ({ title, body, confirmText, cancelText, onConfirm, onCancel, onClose }) => {
return (
<div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
<div className="relative top-20 mx-auto w-96 shadow-lg aos-init aos-animate" data-aos="fade-down">
<div className="relative h-full bg-slate-800 rounded-3xl p-px before:absolute before:w-96 before:h-96 before:-left-48 before:-top-48 before:bg-purple-500 before:rounded-full before:opacity-0 before:pointer-events-none before:transition-opacity before:duration-500 before:translate-x-[var(--mouse-x)] before:translate-y-[var(--mouse-y)] before:hover:opacity-20 before:z-30 before:blur-[100px] after:absolute after:inset-0 after:rounded-[inherit] after:opacity-0 after:transition-opacity after:duration-500 after:[background:_radial-gradient(250px_circle_at_var(--mouse-x)_var(--mouse-y),theme(colors.slate.400),transparent)] after:group-hover:opacity-100 after:z-10 overflow-hidden">
<div className="relative h-full bg-slate-900 rounded-[inherit] z-20 overflow-hidden">
<div className="flex flex-col">
<div className="absolute bottom-0 translate-y-1/2 left-1/2 -translate-x-1/2 pointer-events-none -z-10 w-1/2 aspect-square" aria-hidden="true">
<div className="absolute inset-0 translate-z-0 bg-slate-800 rounded-full blur-[80px]"></div>
</div>
<div className="md:max-w-[480px] shrink-0 order-1 md:order-none p-6 pt-0 md:p-6">
<div className="mt-3 text-center">
<div className="flex justify-between items-center">
<h3 className="text-lg leading-6 font-medium text-white">{title}</h3>
<button onClick={onClose} className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="mt-2 py-3">
<p className="text-left text-sm text-gray-200">{body}</p>
</div>
<div className="items-end px-4 py-1 pt-3">
<button onClick={onCancel} className="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-auto shadow-sm hover:bg-gray-400">
{cancelText}
</button>
<button onClick={onConfirm} className="px-4 py-2 bg-purple-500 text-white text-base font-medium rounded-md w-auto shadow-sm hover:bg-blue-400 ml-3">
{confirmText}
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
// <div className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50">
// <div className="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
// <div className="mt-3 text-center">
// <div className="flex justify-between items-center">
// <h3 className="text-lg leading-6 font-medium text-gray-900">{title}</h3>
// <button onClick={onClose} className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center">
// <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
// <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
// </svg>
// </button>
// </div>
// <div className="mt-2 py-3">
// <p className="text-left text-sm text-gray-500">{body}</p>
// </div>
// <div className="items-center px-4 py-3">
// <button onClick={onCancel} className="px-4 py-2 bg-gray-500 text-white text-base font-medium rounded-md w-auto shadow-sm hover:bg-gray-400">
// {cancelText}
// </button>
// <button onClick={onConfirm} className="px-4 py-2 bg-purple-500 text-white text-base font-medium rounded-md w-auto shadow-sm hover:bg-blue-400 ml-3">
// {confirmText}
// </button>
// </div>
// </div>
// </div>
// </div>
)
}

export default ConfirmModal
102 changes: 86 additions & 16 deletions src/components/Content/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ import GLOW_IMAGE from 'assets/images/glow-bottom.svg'

const glowImage = GLOW_IMAGE

import {
useShow,
useShowWithdrawModal,
useShowClaimModal,
useHideModal,
useContent,
useIsClaim,
//useContent,
} from 'state/confirm/hooks'

import {
useRegisterUser,
useClaimRewards,
Expand All @@ -24,6 +34,7 @@ import {
useUserRegistrationStatus,
useUserType,
useUserCollateralAmount,
useTotalSeconds,
} from 'state/user/hooks'

import {
Expand All @@ -37,6 +48,8 @@ import { WITHDRAWAL_DELAY } from '../../constants'

import StatsTile, { StatsTileProps } from './StatsTile'
import { ParticleAnimation } from 'utils/particles'
import ConfirmModal from 'components/ConfirmModal'
import CountdownTimer from 'components/CountdownTimer'

const Content = () => {
const { pending: pendingRegisterUser, registerUser } = useRegisterUser()
Expand All @@ -48,6 +61,7 @@ const Content = () => {
const totalCollateralAmount = useTotalCollateralAmount()
const totalBlockShares = useTotalBlockShares()
const totalRegistrations = useTotalRegistrations()
const totalSeconds = useTotalSeconds()

const userType = useUserType()
const userBalance = useUserBalance()
Expand All @@ -58,22 +72,41 @@ const Content = () => {
const userRegistrationStatus = useUserRegistrationStatus()
const userCollateralAmount = useUserCollateralAmount()

//const userConfirmed = useConfirmed()
const showModal = useShow()
const confirmMessage = useContent()
const isClaim = useIsClaim()

const hideModal = useHideModal()

const showClaimConfirmation = useShowClaimModal()

const showWithdrawConfirmation = useShowWithdrawModal()

const renderAction = useCallback(() => {
if (userRegistrationStatus === RegistrationStatus.UNREGISTERED) {
const isDisabled = pendingRegisterUser || userBalance.lt(userCollateralAmount)

return (
<button
className={`rounded-md px-3 py-2 text-[0.8125rem] font-semibold leading-5 hover:bg-indigo-500 ${
isDisabled
? 'cursor-not-allowed bg-gray-300 text-purple opacity-50'
: 'cursor-pointer bg-purple-800 text-white'
}`}
disabled={isDisabled}
onClick={isDisabled ? undefined : registerUser}
>
Register
</button>
<>
<button
className={`rounded-md px-3 py-2 text-[0.8125rem] font-semibold leading-5 hover:bg-indigo-500 ${
isDisabled
? 'cursor-not-allowed bg-gray-300 text-purple opacity-50'
: 'cursor-pointer bg-purple-800 text-white'
}`}
disabled={isDisabled}
onClick={isDisabled ? undefined : registerUser}
>
Register
</button>
<button
className="rounded-md px-3 py-2 text-[0.8125rem] font-semibold leading-5 hover:bg-indigo-500"
onClick={showClaimConfirmation}
>
Show
</button>
</>
)
} else if (userRegistrationStatus === RegistrationStatus.REGISTERED) {
const isClaimDisabled = userRewards.eq(0) || pendingClaimRewards || pendingStartWithdrawal
Expand All @@ -88,7 +121,7 @@ const Content = () => {
: 'cursor-pointer bg-purple-800 text-white'
}`}
disabled={isClaimDisabled}
onClick={isClaimDisabled ? undefined : claimRewards}
onClick={isClaimDisabled ? undefined : showClaimConfirmation}
>
Claim rewards
</button>
Expand All @@ -99,7 +132,7 @@ const Content = () => {
: 'cursor-pointer bg-purple-800 text-white'
}`}
disabled={isStartDisabled}
onClick={isStartDisabled ? undefined : startWithdrawal}
onClick={isStartDisabled ? undefined : showWithdrawConfirmation}
>
Start withdrawal
</button>
Expand All @@ -108,9 +141,22 @@ const Content = () => {
} else if (userRegistrationStatus === RegistrationStatus.WITHDRAWING) {
const disabled = pendingCompleteWithdrawal || userSinceLastClaim < WITHDRAWAL_DELAY
return (
<button disabled={disabled} onClick={completeWithdrawal}>
Complete withdrawal
</button>
<>
<button
className={`rounded-md px-3 py-2 text-[0.8125rem] font-semibold leading-5 hover:bg-indigo-500 ${
disabled
? 'cursor-not-allowed bg-gray-300 text-purple opacity-50'
: 'cursor-pointer bg-purple-800 text-white'
}`}
disabled={disabled}
onClick={disabled ? undefined : completeWithdrawal}
>
Complete withdrawal
</button>
<div>
{totalSeconds === 0 ? <span>Calculating time...</span> : <CountdownTimer totalSeconds={totalSeconds} />}
</div>
</>
)
}

Expand Down Expand Up @@ -253,8 +299,32 @@ const Content = () => {
</div>
</div>
</section>
{showModal && (
<ConfirmModal
title="Confirm Action"
body={confirmMessage}
confirmText="Confirm"
cancelText="Cancel"
onConfirm={() => {
hideModal().then(() => {
if (isClaim) {
claimRewards()
} else {
startWithdrawal()
}
})
}}
onCancel={() => {
hideModal()
}}
onClose={() => {
hideModal()
}}
/>
)}
</main>
)
}

export default Content

36 changes: 36 additions & 0 deletions src/components/CountdownTimer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useState, useEffect } from 'react'

const CountdownTimer = ({ totalSeconds }: { totalSeconds: number }) => {
const [timeLeft, setTimeLeft] = useState(calculateTimeLeft(totalSeconds))

useEffect(() => {
let timer: NodeJS.Timeout

if (totalSeconds >= 0) {
timer =
setInterval(() => {
setTimeLeft(calculateTimeLeft(totalSeconds - 1))
totalSeconds--
}, 1000)
}

return () => clearInterval(timer)
}, [totalSeconds])

function calculateTimeLeft(seconds: number) {
return {
days: Math.floor(seconds / (60 * 60 * 24)),
hours: Math.floor((seconds / (60 * 60)) % 24),
minutes: Math.floor((seconds / 60) % 60),
seconds: seconds % 60,
}
}

return (
<div>
Time to completion: {timeLeft.days}d {timeLeft.hours}h {timeLeft.minutes}m {timeLeft.seconds}s
</div>
)
}

export default CountdownTimer
39 changes: 15 additions & 24 deletions src/components/Footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,25 @@ const Footer = () => (
</div>
<ul className="flex">
<li>
<a className="flex justify-center items-center text-purple-500 hover:text-purple-400 transition duration-150 ease-in-out"
href="https://twitter.com/stratisplatform" aria-label="Twitter">
<SocialIcon url="https://twitter.com/stratisplatform" fgColor="#a855f7" bgColor="#262626" className="w-8 h-8 fill-current" style={{width: '32px', height: '32px'}} />
{/* <svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path
d="m13.063 9 3.495 4.475L20.601 9h2.454l-5.359 5.931L24 23h-4.938l-3.866-4.893L10.771 23H8.316l5.735-6.342L8 9h5.063Zm-.74 1.347h-1.457l8.875 11.232h1.36l-8.778-11.232Z" />
</svg> */}
</a>
<SocialIcon url="https://twitter.com/stratisplatform" fgColor="#a855f7" bgColor="#262626" className="flex justify-center items-center text-purple-500 hover:text-purple-400 transition duration-150 ease-in-out w-8 h-8 fill-current" style={{width: '32px', height: '32px'}} />
{/* <svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path
d="m13.063 9 3.495 4.475L20.601 9h2.454l-5.359 5.931L24 23h-4.938l-3.866-4.893L10.771 23H8.316l5.735-6.342L8 9h5.063Zm-.74 1.347h-1.457l8.875 11.232h1.36l-8.778-11.232Z" />
</svg> */}
</li>
<li className="ml-2">
<a className="flex justify-center items-center text-purple-500 hover:text-purple-400 transition duration-150 ease-in-out"
href="https://discordapp.com/invite/9tDyfZs" aria-label="Dev.to">
<SocialIcon url="https://discordapp.com/invite/9tDyfZs" fgColor="#a855f7" bgColor="#262626" className="w-8 h-8 fill-current" style={{width: '32px', height: '32px'}} />
{/* <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
<path className="w-8 h-8 fill-current"
d="M12.29 14.3a.69.69 0 0 0-.416-.155h-.623v3.727h.623a.689.689 0 0 0 .416-.156.543.543 0 0 0 .21-.466v-2.488a.547.547 0 0 0-.21-.462ZM22.432 8H9.568C8.704 8 8.002 8.7 8 9.564v12.872A1.568 1.568 0 0 0 9.568 24h12.864c.864 0 1.566-.7 1.568-1.564V9.564A1.568 1.568 0 0 0 22.432 8Zm-8.925 9.257a1.631 1.631 0 0 1-1.727 1.687h-1.657v-5.909h1.692a1.631 1.631 0 0 1 1.692 1.689v2.533ZM17.1 14.09h-1.9v1.372h1.163v1.057H15.2v1.371h1.9v1.056h-2.217a.72.72 0 0 1-.74-.7v-4.471a.721.721 0 0 1 .7-.739H17.1v1.054Zm3.7 4.118c-.471 1.1-1.316.88-1.694 0l-1.372-5.172H18.9l1.058 4.064 1.056-4.062h1.164l-1.378 5.17Z" />
</svg> */}
</a>
<SocialIcon url="https://discordapp.com/invite/9tDyfZs" fgColor="#a855f7" bgColor="#262626" className="flex justify-center items-center text-purple-500 hover:text-purple-400 transition duration-150 ease-in-out w-8 h-8 fill-current" style={{width: '32px', height: '32px'}} />
{/* <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
<path className="w-8 h-8 fill-current"
d="M12.29 14.3a.69.69 0 0 0-.416-.155h-.623v3.727h.623a.689.689 0 0 0 .416-.156.543.543 0 0 0 .21-.466v-2.488a.547.547 0 0 0-.21-.462ZM22.432 8H9.568C8.704 8 8.002 8.7 8 9.564v12.872A1.568 1.568 0 0 0 9.568 24h12.864c.864 0 1.566-.7 1.568-1.564V9.564A1.568 1.568 0 0 0 22.432 8Zm-8.925 9.257a1.631 1.631 0 0 1-1.727 1.687h-1.657v-5.909h1.692a1.631 1.631 0 0 1 1.692 1.689v2.533ZM17.1 14.09h-1.9v1.372h1.163v1.057H15.2v1.371h1.9v1.056h-2.217a.72.72 0 0 1-.74-.7v-4.471a.721.721 0 0 1 .7-.739H17.1v1.054Zm3.7 4.118c-.471 1.1-1.316.88-1.694 0l-1.372-5.172H18.9l1.058 4.064 1.056-4.062h1.164l-1.378 5.17Z" />
</svg> */}
</li>
<li className="ml-2">
<a className="flex justify-center items-center text-purple-500 hover:text-purple-400 transition duration-150 ease-in-out"
href="https://github.com/stratisproject" aria-label="Github">
<SocialIcon url="https://github.com/stratisproject" fgColor="#a855f7" bgColor="#262626" className="w-8 h-8 fill-current" style={{width: '32px', height: '32px'}} />
{/* <svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path
d="M16 8.2c-4.4 0-8 3.6-8 8 0 3.5 2.3 6.5 5.5 7.6.4.1.5-.2.5-.4V22c-2.2.5-2.7-1-2.7-1-.4-.9-.9-1.2-.9-1.2-.7-.5.1-.5.1-.5.8.1 1.2.8 1.2.8.7 1.3 1.9.9 2.3.7.1-.5.3-.9.5-1.1-1.8-.2-3.6-.9-3.6-4 0-.9.3-1.6.8-2.1-.1-.2-.4-1 .1-2.1 0 0 .7-.2 2.2.8.6-.2 1.3-.3 2-.3s1.4.1 2 .3c1.5-1 2.2-.8 2.2-.8.4 1.1.2 1.9.1 2.1.5.6.8 1.3.8 2.1 0 3.1-1.9 3.7-3.7 3.9.3.4.6.9.6 1.6v2.2c0 .2.1.5.6.4 3.2-1.1 5.5-4.1 5.5-7.6-.1-4.4-3.7-8-8.1-8z" />
</svg> */}
</a>
<SocialIcon url="https://github.com/stratisproject" fgColor="#a855f7" bgColor="#262626" className="flex justify-center items-center text-purple-500 hover:text-purple-400 transition duration-150 ease-in-out w-8 h-8 fill-current" style={{width: '32px', height: '32px'}} />
{/* <svg className="w-8 h-8 fill-current" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path
d="M16 8.2c-4.4 0-8 3.6-8 8 0 3.5 2.3 6.5 5.5 7.6.4.1.5-.2.5-.4V22c-2.2.5-2.7-1-2.7-1-.4-.9-.9-1.2-.9-1.2-.7-.5.1-.5.1-.5.8.1 1.2.8 1.2.8.7 1.3 1.9.9 2.3.7.1-.5.3-.9.5-1.1-1.8-.2-3.6-.9-3.6-4 0-.9.3-1.6.8-2.1-.1-.2-.4-1 .1-2.1 0 0 .7-.2 2.2.8.6-.2 1.3-.3 2-.3s1.4.1 2 .3c1.5-1 2.2-.8 2.2-.8.4 1.1.2 1.9.1 2.1.5.6.8 1.3.8 2.1 0 3.1-1.9 3.7-3.7 3.9.3.4.6.9.6 1.6v2.2c0 .2.1.5.6.4 3.2-1.1 5.5-4.1 5.5-7.6-.1-4.4-3.7-8-8.1-8z" />
</svg> */}
</li>
</ul>
</div>
Expand Down
51 changes: 51 additions & 0 deletions src/state/confirm/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { formatEther } from 'ethers/lib/utils'
import { useAppSelector, useAppDispatch } from 'state'
import { useCallback } from 'react'
import { setHide, setShow } from './reducer'
import { useUserRewards } from 'state/user/hooks'

export function useShow() {
return useAppSelector(state => state.confirm.showModal)
}

export function useConfirmed() {
return useAppSelector(state => state.confirm.confirmed)
}

export function useContent() {
return useAppSelector(state => state.confirm.text)
}

export function useIsClaim() {
return useAppSelector(state => state.confirm.isClaim)
}

export function useShowWithdrawModal() {
const dispatch = useAppDispatch()

return useCallback(async () => {
dispatch(setShow({ isClaim: false, text: 'You are attempting to withdraw your collateral. This will have a mandatory colling off period of approximately 2 weeks. Are you sure you want to continue?' }))
}, [])
}

export function useShowClaimModal() {
const dispatch = useAppDispatch()
const rewards = useUserRewards()
const strax = financial(formatEther(rewards))
return useCallback(async () => {
dispatch(setShow({ isClaim: true, text: `You are attempting to claim ${strax} STRAX. Once confirmed, you will receive a prompt in your MetaMask wallet. Would you plike to proceed?` }))
}, [])
}

export function useHideModal() {
const dispatch = useAppDispatch()

return useCallback(async () => {
dispatch(setHide())
}, [])
}

const financial = (x: string) => {
return Number.parseFloat(x).toFixed(5)
}

Loading

0 comments on commit 914c816

Please sign in to comment.