make all actionable buttons to show loading state with appropriate text

Signed-off-by: Uncle Fatso <uncle.fatso@ghostchain.io>
This commit is contained in:
Uncle Fatso 2026-04-28 15:06:12 +03:00
parent d9aff4dc6a
commit b022a3c64c
Signed by: f4ts0
GPG Key ID: 565F4F2860226EBB
8 changed files with 58 additions and 21 deletions

View File

@ -1,7 +1,7 @@
{
"name": "ghost-dao-interface",
"private": true,
"version": "0.7.29",
"version": "0.7.30",
"type": "module",
"scripts": {
"dev": "vite",

View File

@ -27,6 +27,7 @@ import { useBreakoutModal } from "../../../hooks/breakoutModal";
export const ClaimBonds = ({ chainId, address, secondsTo }) => {
const isSmallScreen = useScreenSize("md");
const [isPending, setIsPending] = useState(false);
const [pendingIndexes, setPendingIndexes] = useState([]);
const [isWarmup, setIsWapmup] = useState(false);
const [isPreClaimConfirmed, setPreClaimConfirmed] = useState(false);
const [isPayoutGhst, _] = useState(true);
@ -55,6 +56,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
const onSubmit = async (indexes) => {
setIsPending(true);
setPendingIndexes(indexes);
const defaultFunction = async () => {
await redeem({ chainId, user: address, isGhst: isPayoutGhst, indexes });
@ -82,6 +84,7 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
breakoutFromBonding({ defaultFunction, toExecute, amount, warmupLeft })
}
setPendingIndexes([]);
setIsPending(false);
}
@ -177,9 +180,10 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
<TertiaryButton
fullWidth
disabled={isPending || secondsTo < note.matured}
loading={isPending && pendingIndexes.includes(note.id)}
onClick={() => onSubmit([note.id])}
>
Claim
{isPending && pendingIndexes.includes(note.id) ? "Claiming" : "Claim"}
</TertiaryButton>
</Box>
</Box>
@ -236,9 +240,10 @@ export const ClaimBonds = ({ chainId, address, secondsTo }) => {
<TertiaryButton
fullWidth
disabled={isPending || secondsTo < note.matured}
loading={isPending && pendingIndexes.includes(note.id)}
onClick={() => onSubmit([note.id])}
>
Claim
{isPending && pendingIndexes.includes(note.id) ? "Claiming" : "Claim"}
</TertiaryButton>
</TableCell>
</TableRow>

View File

@ -278,9 +278,10 @@ const WelcomeView = ({
{warmupPeriod <= 0 && <SecondaryButton
onClick={() => callDefaultFunction()}
disabled={isPending || warmupPeriod > 0}
loading={isPending}
fullWidth
>
Claim {isStakingOpened ? "(3, 3) Stake" : "(1, 1) Bond"}
{isPending ? "Claiming..." : `Claim ${isStakingOpened ? "(3, 3) Stake" : "(1, 1) Bond"}`}
</SecondaryButton>}
<Box display="flex" justifyContent="center" flexDirection="column" alignItems="center">
@ -463,10 +464,11 @@ const ConfirmStep = ({
<PrimaryButton
onClick={() => execute()}
loading={isPending}
disabled={isPending || !acknowledgeWalletCustody || !acknowledgeBridgingRisk}
fullWidth
>
I Confirm
{isPending ? "Confirming..." : "I Confirm"}
</PrimaryButton>
</>
)

View File

@ -246,7 +246,7 @@ export const BridgeCardAction = ({
loading={isPending}
onClick={() => ghostOrConnect()}
>
{address === "" ? "Connect" : "Bridge" }
{address === "" ? "Connect" : isPending ? "Bridging..." : "Bridge" }
</PrimaryButton>
</Box>
)

View File

@ -317,9 +317,9 @@ const PoolContainer = ({
"Connect"
:
pairAddress === "0x0000000000000000000000000000000000000000" ?
"Create Pool"
isPending ? "Creating Pool..." : "Create Pool"
:
"Add Liquidity"
isPending ? "Adding Liquidity..." : "Add Liquidity"
}
</SecondaryButton>
</TokenAllowanceGuard>

View File

@ -147,8 +147,12 @@ const SwapContainer = ({
if (isWrapping) text = "Wrap";
else if (isUnwrapping) text = "Unwrap";
else if (pairAddress === EMPTY_ADDRESS) text = "Create Pool";
if (isPending) text = `${text}ping...`
if (pairAddress === EMPTY_ADDRESS && isPending) text = "Creating Pool..."
return text;
}, [isWrapping, isUnwrapping, pairAddress]);
}, [isPending, isWrapping, isUnwrapping, pairAddress]);
const swapTokens = async () => {
setIsPending(true);

View File

@ -178,6 +178,7 @@ const NewProposal = ({ config, address, connect, chainId }) => {
isPending
}
fullWidth
loading={isPending}
onClick={() => submitProposal()}
>
{isPending ? "Submitting..." : "Submit Proposal"}

View File

@ -80,7 +80,9 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
const { id } = useParams();
const proposalId = BigInt(id);
const [isPending, setIsPending] = useState(false);
const [isPendingVote, setIsPendingVote] = useState(-1);
const [isPendingExecute, setIsPendingExecute] = useState(false);
const [isPendingRelease, setIsPendingRelease] = useState(false);
const [selectedDiscussionUrl, setSelectedDiscussionUrl] = useState(undefined);
const isSemiSmallScreen = useMediaQuery("(max-width: 745px)");
@ -150,8 +152,12 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
return url;
}, [proposalProposer, config]);
const isPending = useMemo(() => {
return isPendingExecute || isPendingRelease || isPendingVote > -1;
}, [isPendingExecute, isPendingRelease, isPendingVote]);
const handleVote = useCallback(async (support) => {
setIsPending(true);
setIsPendingVote(support);
const result = await castVote(chainId, address, proposalId, support);
if (result) {
@ -161,21 +167,21 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
setStorageValue(chainId, address, VOTED_PROPOSALS_PREFIX, proposals.map(id => id.toString()));
await queryClient.invalidateQueries();
}
setIsPending(false);
setIsPendingVote(-1);
}, [chainId, address, proposalId]);
const handleExecute = async () => {
setIsPending(true);
setIsPendingExecute(true);
await executeProposal(chainId, address, proposalId);
await queryClient.invalidateQueries();
setIsPending(false);
setIsPendingExecute(false);
}
const handleRelease = async () => {
setIsPending(true);
setIsPendingRelease(true);
await releaseLocked(chainId, address, proposalId);
await queryClient.invalidateQueries();
setIsPending(false);
setIsPendingRelease(false);
}
return (
@ -292,16 +298,18 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
<SecondaryButton
fullWidth
disabled={proposalState !== 1 || pastVotes?._value === 0n || isPending}
loading={isPendingVote === 1}
onClick={() => handleVote(1)}
>
{isPending ? "Voting..." : "For"}
{isPendingVote === 1 ? "Voting For..." : "For"}
</SecondaryButton>
<SecondaryButton
fullWidth
disabled={proposalState !== 1 || pastVotes?._value === 0n || isPending}
loading={isPendingVote === 0}
onClick={() => handleVote(0)}
>
{isPending ? "Voting..." : "Against"}
{isPendingVote === 0 ? "Voting Against..." : "Against"}
</SecondaryButton>
</>
: <SecondaryButton
@ -337,6 +345,8 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
chainId={chainId}
proposalId={id}
isPending={isPending}
isPendingExecute={isPendingExecute}
isPendingRelease={isPendingRelease}
/>
</Paper>
</Box>
@ -392,7 +402,20 @@ const ProposalDetails = ({ chainId, address, connect, config }) => {
)
}
const VotingTimeline = ({ connect, handleExecute, handleRelease, proposalLocked, proposalId, chainId, state, address, isProposer, isPending }) => {
const VotingTimeline = ({
connect,
handleExecute,
handleRelease,
proposalLocked,
proposalId,
chainId,
state,
address,
isProposer,
isPending,
isPendingExecute,
isPendingRelease,
}) => {
const { delay: propsalVotingDelay } = useProposalVotingDelay(chainId, proposalId);
const { snapshot: proposalSnapshot } = useProposalSnapshot(chainId, proposalId);
const { deadline: proposalDeadline } = useProposalDeadline(chainId, proposalId);
@ -414,13 +437,15 @@ const VotingTimeline = ({ connect, handleExecute, handleRelease, proposalLocked,
<Box width="100%" display="flex" gap="10px">
{(isProposer && (proposalLocked?._value ?? 0n) > 0n) && <SecondaryButton
fullWidth
loading={isPendingRelease}
disabled={isPending || state < 2}
onClick={() => address === "" ? connect() : handleRelease()}
>
{address === "" ? "Connect" : "Release"}
{address === "" ? "Connect" : isPendingRelease ? "Releasing..." : "Release"}
</SecondaryButton>}
<SecondaryButton
fullWidth
loading={isPending}
disabled={isPending || state !== 4}
onClick={() => address === "" ? connect() : handleExecute()}
>
@ -428,7 +453,7 @@ const VotingTimeline = ({ connect, handleExecute, handleRelease, proposalLocked,
? "Connect"
: state !== 4
? convertStatusToLabel(state)
: isPending ? "Executing..." : "Execute"
: isPendingExecute ? "Executing..." : "Execute"
}
</SecondaryButton>
</Box>