From b1fff6be8999b594dbb069d022a905b575ad0902 Mon Sep 17 00:00:00 2001 From: muddlebee Date: Wed, 20 Nov 2024 20:34:26 +0530 Subject: [PATCH] fix : Confirming Swap Dialog --- src/app/page.tsx | 150 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 121 insertions(+), 29 deletions(-) diff --git a/src/app/page.tsx b/src/app/page.tsx index 3b9c8ef..ebecc1e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -11,7 +11,7 @@ import { DialogTrigger, DialogFooter, } from "@/components/ui/dialog" -import { Settings, RotateCcw, ArrowRight, Wallet, Check, Loader2, ChevronsDown, History } from 'lucide-react' +import { Settings, RotateCcw, ArrowRight, Wallet, Check, Loader2, ChevronsDown, History, X } from 'lucide-react' import { motion } from 'framer-motion' import { Toaster, toast } from 'react-hot-toast' @@ -45,6 +45,15 @@ interface SwapHistoryItem { timestamp: Date; } +// First, define a proper type for step status +type StepStatus = 'waiting' | 'pending' | 'loading' | 'completed' | 'failed'; + +interface SwapStep { + id: number; + title: string; + status: StepStatus; +} + export default function Component() { const [inputToken, setInputToken] = useState({ name: 'DOT', icon: '●', price: '$2.00' }) const [outputToken, setOutputToken] = useState({ name: 'ETH', icon: 'Ξ', price: '$2000' }) @@ -55,17 +64,20 @@ export default function Component() { const [isConnected, setIsConnected] = useState(false) const [walletAddress, setWalletAddress] = useState('') const [isSwapping, setIsSwapping] = useState(false) - const [swapSteps, setSwapSteps] = useState([ + const [swapSteps, setSwapSteps] = useState([ { id: 1, title: 'Approve DOT', status: 'pending' }, { id: 2, title: 'Swap DOT → USDC', status: 'waiting' }, { id: 3, title: 'Swap USDC → ETH', status: 'waiting' }, ]) const [swapHistory, setSwapHistory] = useState([]) const [showHistory, setShowHistory] = useState(false) + const [balance] = useState(1234.56) + const [insufficientBalance, setInsufficientBalance] = useState(false) const handleInputChange = (value: string) => { setInputAmount(value) setOutputAmount((parseFloat(value) * 2).toString()) + setInsufficientBalance(parseFloat(value) > balance) } const handleWalletConnect = () => { @@ -111,46 +123,71 @@ export default function Component() { const handleSwap = async () => { if (!isConnected) { - toast.error('Please connect your wallet first', { - icon: '🔒', - }) + toast.error('Please connect your wallet first', { icon: '🔒' }) return } setIsSwapping(true) try { + // Reset all steps to their initial state when starting a new swap + setSwapSteps(steps => steps.map((step, index) => ({ + ...step, + status: index === 0 ? 'pending' : 'waiting' + }))) + for (let i = 0; i < swapSteps.length; i++) { - setSwapSteps(steps => steps.map(step => - step.id === i + 1 ? { ...step, status: 'loading' } : step - )) + // Set current step to loading + setSwapSteps(steps => steps.map(step => ({ + ...step, + status: + step.id < i + 1 ? 'completed' : + step.id === i + 1 ? 'loading' : + 'waiting' + }))) await new Promise(r => setTimeout(r, 2000 + Math.random() * 1000)) - const success = await mockBlockchainTransaction() if (!success) { + // If transaction fails, mark current step as failed and keep subsequent steps as waiting + setSwapSteps(steps => steps.map(step => ({ + ...step, + status: + step.id < i + 1 ? 'completed' : + step.id === i + 1 ? 'failed' : + 'waiting' + }))) throw new Error(`Step ${i + 1} failed`) } - setSwapSteps(steps => steps.map(step => - step.id === i + 1 ? { ...step, status: 'completed' } : step - )) + // Mark current step as completed + setSwapSteps(steps => steps.map(step => ({ + ...step, + status: + step.id <= i + 1 ? 'completed' : + 'waiting' + }))) } const successMessage = `Swapped ${inputAmount} ${inputToken.name} for ${outputAmount} ${outputToken.name}` toast.success(successMessage, { icon: '🎉' }) - setSwapHistory(prev => [{ id: Date.now(), type: 'success', message: successMessage, timestamp: new Date() }, ...prev]) + setSwapHistory(prev => [{ + id: Date.now(), + type: 'success', + message: successMessage, + timestamp: new Date() + }, ...prev]) } catch (error) { console.error('Swap failed:', error) - setSwapSteps(steps => steps.map(step => - step.status === 'loading' ? { ...step, status: 'pending' } : step - )) const errorMessage = 'Swap failed. Please try again.' toast.error(errorMessage, { icon: '❌' }) - setSwapHistory(prev => [{ id: Date.now(), type: 'error', message: errorMessage, timestamp: new Date() }, ...prev]) - } finally { - setIsSwapping(false) + setSwapHistory(prev => [{ + id: Date.now(), + type: 'error', + message: errorMessage, + timestamp: new Date() + }, ...prev]) } } @@ -172,6 +209,23 @@ export default function Component() { { label: 'MAX', value: 1 }, ] + const getStepStatusMessage = (status: StepStatus) => { + switch (status) { + case 'completed': + return 'Transaction confirmed' + case 'loading': + return 'Processing transaction...' + case 'failed': + return 'Transaction failed' + case 'pending': + return 'Ready to process' + case 'waiting': + return 'Waiting to start' + default: + return 'Unknown status' + } + } + // Render the main action button based on connection state const renderActionButton = () => { if (!isConnected) { @@ -187,14 +241,24 @@ export default function Component() { } return ( - + { + if (!open && !swapSteps.every(step => step.status === 'completed')) { + return + } + setIsSwapping(open) + }} + > + + {/* Confirming Swap Dialog */} - Confirming Swap + + {swapSteps.every(step => step.status === 'completed') + ? 'Swap Complete' + : swapSteps.some(step => step.status === 'failed') + ? 'Swap Failed' + : 'Confirming Swap' + } +
{swapSteps.map((step, index) => ( @@ -216,6 +289,8 @@ export default function Component() { className={`w-10 h-10 rounded-full flex items-center justify-center ${step.status === 'completed' ? 'bg-green-500/20 text-green-500' : step.status === 'loading' ? 'bg-blue-500/20 text-blue-500' : + step.status === 'failed' ? 'bg-red-500/20 text-red-500' : + step.status === 'pending' ? 'bg-yellow-500/20 text-yellow-500' : 'bg-slate-800 text-slate-400'}`} initial={{ scale: 0.8, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} @@ -225,21 +300,24 @@ export default function Component() { ) : step.status === 'loading' ? ( + ) : step.status === 'failed' ? ( + ) : ( {step.id} )} {index < swapSteps.length - 1 && (
+ ${step.status === 'completed' ? 'border-green-500/50' : + step.status === 'failed' ? 'border-red-500/50' : + 'border-slate-700'}`} + /> )}

{step.title}

- {step.status === 'completed' ? 'Transaction confirmed' : - step.status === 'loading' ? 'Waiting for confirmation...' : - 'Waiting to start'} + {getStepStatusMessage(step.status)}

@@ -251,7 +329,21 @@ export default function Component() { className="w-full bg-green-500 hover:bg-green-600 text-white text-lg font-semibold py-6 rounded-xl transition-all duration-200" onClick={() => setIsSwapping(false)} > - Swap Complete + Close + + ) : swapSteps.some(step => step.status === 'failed') ? ( + ) : ( )}