-
Notifications
You must be signed in to change notification settings - Fork 22
feat: implement Buy G$ page with 3-step progress bar and responsive Onramper widget #605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
supersonicwisd1
wants to merge
28
commits into
GoodDollar:master
Choose a base branch
from
supersonicwisd1:feat/buy-gd
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
6004194
fix: Prevent Uniswap widget crashes on 100% price impact trades
supersonicwisd1 ad8846f
updated patch_reference.md
supersonicwisd1 3e16bb0
separate concerns
supersonicwisd1 f39e512
Revert "updated patch_reference.md"
supersonicwisd1 9b2be7e
Add clean uniswap patch for 100% price impact fix
supersonicwisd1 2c71b08
Add clean uniswap patch for price impact fix
supersonicwisd1 27225ef
fix: handle uniswap widget error
supersonicwisd1 c2d859b
Update gitignore
supersonicwisd1 4eb0910
updated gitignore file
supersonicwisd1 54c30ed
updates suggest by yhy the reviewer
supersonicwisd1 655c4c5
Update .gitignore
supersonicwisd1 d75cfa5
Merge branch 'GoodDollar:master' into master
supersonicwisd1 90e423a
feat: implement Buy G$ page with progress bar and Onramper widget
supersonicwisd1 0edd742
remove: removed fallback on posthog
supersonicwisd1 aa1dfac
chore: update localization catalogs
supersonicwisd1 42994ce
rm: Updated gitignore file
supersonicwisd1 16768e3
fix: fixing critical bugs and standards
supersonicwisd1 4b4fd71
rm: remove falback for posthog
supersonicwisd1 2d9cfb6
fix: feedback fix on security, performance, functionality and design
supersonicwisd1 2410d7d
fix: security and functionality fix
supersonicwisd1 c33295d
fix: address all Korbit AI review feedback for Buy G$ feature
supersonicwisd1 e96a55f
fix: connect widget events to progress bar and fix swap lock bug
supersonicwisd1 41e4994
Merge branch 'master' of https://github.com/GoodDollar/GoodProtocolUI…
L03TJ3 6c842be
Update src/components/CustomGdOnramperWidget/CustomOnramper.tsx
L03TJ3 2074013
fix: show wallet connection placeholder on Buy G$ page
supersonicwisd1 9431ac8
Merge branch 'feat/buy-gd' of github.com:supersonicwisd1/GoodProtocol…
supersonicwisd1 87d5232
fix: update BuyGD to use new wallet connection system
supersonicwisd1 7363f3e
refactor: use GdOnramperWidget from good-design package
supersonicwisd1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or 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 |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| import React, { useEffect, useState, useMemo } from 'react' | ||
| import { Box, HStack, Circle, Text } from 'native-base' | ||
|
|
||
| export type BuyStep = 1 | 2 | 3 | ||
|
|
||
| export interface StepConfig { | ||
| number: number | ||
| label: string | ||
| } | ||
|
|
||
| interface BuyProgressBarProps { | ||
| currentStep: BuyStep | ||
| isLoading?: boolean | ||
| steps?: StepConfig[] | ||
| } | ||
|
|
||
| const BuyProgressBar: React.FC<BuyProgressBarProps> = ({ | ||
| currentStep, | ||
| isLoading = false, | ||
| steps = [ | ||
| { number: 1, label: 'Buy cUSD' }, | ||
| { number: 2, label: 'We swap cUSD to G$' }, | ||
| { number: 3, label: 'Done' }, | ||
| ], | ||
| }) => { | ||
| const [animatedWidth, setAnimatedWidth] = useState(0) | ||
|
|
||
| // Handle animated progress line | ||
| useEffect(() => { | ||
| if (isLoading && currentStep >= 1) { | ||
| // Explicitly reset animatedWidth to 0 at the start of a new loading phase | ||
| setAnimatedWidth(0) | ||
| // Animate progress line when loading | ||
| let progress = 0 | ||
| const interval = setInterval(() => { | ||
| progress += 2 | ||
| if (progress <= 100) { | ||
| setAnimatedWidth(progress) | ||
| } else { | ||
| clearInterval(interval) | ||
| } | ||
| }, 50) // 50ms intervals for smooth animation | ||
|
|
||
| return () => clearInterval(interval) | ||
| } else { | ||
| // Set to 100% if not loading (completed state) | ||
| setAnimatedWidth(100) | ||
| } | ||
| }, [isLoading, currentStep]) | ||
|
|
||
| const getStepStatus = (stepNumber: number) => { | ||
| // Step 1 should ALWAYS be blue (active when current, completed when past) | ||
| if (stepNumber === 1) { | ||
| if (currentStep === 1) { | ||
| return isLoading ? 'loading' : 'active' | ||
| } else { | ||
| return 'completed' // Step 1 is completed when we're on step 2 or 3 | ||
| } | ||
| } | ||
| // Steps 2 and 3 follow normal logic | ||
| if (stepNumber < currentStep) return 'completed' | ||
| if (stepNumber === currentStep) return isLoading ? 'loading' : 'active' | ||
| return 'pending' | ||
| } | ||
|
|
||
| // Memoize circle props objects to avoid recreation on every render | ||
| const circlePropsMap = useMemo( | ||
| () => ({ | ||
| completed: { | ||
| size: '12', | ||
| mb: 2, | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| bg: 'blue.500', | ||
| }, | ||
| active: { | ||
| size: '12', | ||
| mb: 2, | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| bg: 'blue.500', | ||
| }, | ||
| loading: { | ||
| size: '12', | ||
| mb: 2, | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| bg: 'blue.500', | ||
| borderWidth: 3, | ||
| borderColor: 'blue.200', | ||
| animation: 'pulse 2s infinite', | ||
| }, | ||
| pending: { | ||
| size: '12', | ||
| mb: 2, | ||
| justifyContent: 'center', | ||
| alignItems: 'center', | ||
| bg: 'gray.300', | ||
| }, | ||
| }), | ||
| [] | ||
| ) | ||
|
|
||
| const getCircleProps = (status: string) => { | ||
| return circlePropsMap[status as keyof typeof circlePropsMap] || circlePropsMap.pending | ||
| } | ||
|
|
||
| const getLineProps = (stepNumber: number, lineIndex: number) => { | ||
| // Line between step 1 and 2 (lineIndex = 0) | ||
| if (lineIndex === 0) { | ||
| if (currentStep === 1 && isLoading) { | ||
| // Animation state: "1 Blue with progress bar animation" | ||
| return { | ||
| bg: 'blue.500', | ||
| width: `${animatedWidth}%`, | ||
| transition: 'width 0.1s ease-out', | ||
| } | ||
| } else if (currentStep >= 2) { | ||
| // Static line when step 2 or higher | ||
| return { | ||
| bg: 'blue.500', | ||
| width: '100%', | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Line between step 2 and 3 (lineIndex = 1) | ||
| if (lineIndex === 1) { | ||
| if (currentStep === 2 && isLoading) { | ||
| // Animation state: "2 Blue with progress bar animation" | ||
| return { | ||
| bg: 'blue.500', | ||
| width: `${animatedWidth}%`, | ||
| transition: 'width 0.1s ease-out', | ||
| } | ||
| } else if (currentStep >= 3) { | ||
| // Static line when step 3 | ||
| return { | ||
| bg: 'blue.500', | ||
| width: '100%', | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Default: gray line (not active) | ||
| return { | ||
| bg: 'gray.300', | ||
| width: '100%', | ||
| } | ||
| } | ||
|
|
||
| const getTextColor = (status: string) => { | ||
| return status === 'pending' ? 'gray.500' : 'black' | ||
| } | ||
|
|
||
| return ( | ||
| <Box width="100%" mb={6} mt={4} data-testid="custom-progress-bar"> | ||
| <HStack justifyContent="space-between" alignItems="flex-start" position="relative"> | ||
| {steps.map((step, index) => { | ||
| const status = getStepStatus(step.number) | ||
|
|
||
| return ( | ||
| <React.Fragment key={step.number}> | ||
| <Box alignItems="center" flex={1} position="relative"> | ||
| <Circle {...getCircleProps(status)}> | ||
| <Text color="white" fontWeight="bold" fontSize="md"> | ||
| {step.number} | ||
| </Text> | ||
| </Circle> | ||
| <Text | ||
| textAlign="center" | ||
| fontSize="sm" | ||
| color={getTextColor(status)} | ||
| fontFamily="subheading" | ||
| maxWidth="120px" | ||
| lineHeight="tight" | ||
| > | ||
| {step.label} | ||
| </Text> | ||
| </Box> | ||
|
|
||
| {index < steps.length - 1 && ( | ||
| <Box | ||
| position="absolute" | ||
| top="6" | ||
| left={`${33.33 * (index + 1) - 16.67}%`} | ||
| right={`${66.67 - 33.33 * (index + 1) + 16.67}%`} | ||
| height="2px" | ||
| bg="gray.300" | ||
| zIndex={-1} | ||
| > | ||
| <Box height="100%" {...getLineProps(step.number + 1, index)} borderRadius="1px" /> | ||
| </Box> | ||
| )} | ||
| </React.Fragment> | ||
| ) | ||
| })} | ||
| </HStack> | ||
| </Box> | ||
| ) | ||
| } | ||
|
|
||
| export { BuyProgressBar } | ||
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.