refactor: clean up code formatting and improve readability across multiple components
- Standardized the use of quotes and spacing in various files. - Removed unnecessary line breaks and trailing spaces in components. - Improved the structure of computed properties and methods for better clarity. - Enhanced the consistency of prop definitions and emit events in Vue components. - Updated the GraphQL composable to streamline error handling and data processing. - Refactored network configuration files for better organization and readability. - Cleaned up model files by removing redundant lines and ensuring consistent formatting. - Adjusted router configuration for improved readability. - Enhanced utility functions for better maintainability and clarity.
This commit is contained in:
@@ -31,11 +31,11 @@ const getWalletTransactions = async () => {
|
||||
user.setLoadingWalletTransactions(true);
|
||||
if (walletAddress.value) {
|
||||
const walletDeposits = await listValidDepositTransactionsByWalletAddress(
|
||||
walletAddress.value
|
||||
walletAddress.value,
|
||||
);
|
||||
|
||||
const allUserTransactions = await listAllTransactionByWalletAddress(
|
||||
walletAddress.value
|
||||
walletAddress.value,
|
||||
);
|
||||
|
||||
activeLockAmount.value = await getActiveLockAmount(walletAddress.value);
|
||||
@@ -53,7 +53,10 @@ const getWalletTransactions = async () => {
|
||||
const callWithdraw = async (amount: string) => {
|
||||
if (amount) {
|
||||
user.setLoadingWalletTransactions(true);
|
||||
const withdraw = await withdrawDeposit(amount, user.network.value.tokens[user.selectedToken.value].address);
|
||||
const withdraw = await withdrawDeposit(
|
||||
amount,
|
||||
user.network.value.tokens[user.selectedToken.value].address,
|
||||
);
|
||||
if (withdraw) {
|
||||
console.log("Saque realizado!");
|
||||
await getWalletTransactions();
|
||||
|
||||
@@ -55,14 +55,14 @@ const getUserCredit = async (userAddress: Address): Promise<bigint> => {
|
||||
try {
|
||||
const { address, abi, client } = await getContract(true);
|
||||
const userKey = castAddrToKey(userAddress);
|
||||
|
||||
|
||||
const userCredit = await client.readContract({
|
||||
address,
|
||||
abi,
|
||||
functionName: "userRecord",
|
||||
args: [userKey],
|
||||
});
|
||||
|
||||
|
||||
return userCredit as bigint;
|
||||
} catch (error) {
|
||||
console.error("Error fetching user credit:", error);
|
||||
@@ -73,13 +73,13 @@ const getUserCredit = async (userAddress: Address): Promise<bigint> => {
|
||||
const getReputationAddress = async (): Promise<Address | null> => {
|
||||
try {
|
||||
const { address, abi, client } = await getContract(true);
|
||||
|
||||
|
||||
const reputationAddr = await client.readContract({
|
||||
address,
|
||||
abi,
|
||||
functionName: "reputation",
|
||||
});
|
||||
|
||||
|
||||
return reputationAddr as Address;
|
||||
} catch (error) {
|
||||
console.error("Error fetching reputation address:", error);
|
||||
@@ -91,16 +91,16 @@ const getSpendLimit = async (userCredit: bigint): Promise<bigint> => {
|
||||
try {
|
||||
const reputationAddr = await getReputationAddress();
|
||||
if (!reputationAddr) return BigInt(0);
|
||||
|
||||
|
||||
const { client } = await getContract(true);
|
||||
|
||||
|
||||
const spendLimit = await client.readContract({
|
||||
address: reputationAddr,
|
||||
abi: reputationAbi,
|
||||
functionName: "limiter",
|
||||
args: [userCredit],
|
||||
});
|
||||
|
||||
|
||||
return spendLimit as bigint;
|
||||
} catch (error) {
|
||||
console.error("Error fetching spend limit:", error);
|
||||
@@ -110,26 +110,25 @@ const getSpendLimit = async (userCredit: bigint): Promise<bigint> => {
|
||||
|
||||
const checkReputationLimit = async (inputValue: number): Promise<void> => {
|
||||
exceedsReputationLimit.value = false;
|
||||
|
||||
|
||||
if (!walletAddress.value) {
|
||||
reputationLimit.value = null;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (inputValue === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const userCredit = await getUserCredit(walletAddress.value);
|
||||
const spendLimitRaw = await getSpendLimit(userCredit);
|
||||
|
||||
|
||||
const spendLimitNumber = Number(spendLimitRaw);
|
||||
reputationLimit.value = spendLimitNumber;
|
||||
|
||||
|
||||
exceedsReputationLimit.value = spendLimitNumber < inputValue;
|
||||
enableConfirmButton.value = !exceedsReputationLimit.value;
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error checking reputation limit:", error);
|
||||
reputationLimit.value = null;
|
||||
@@ -145,7 +144,7 @@ const connectAccount = async (): Promise<void> => {
|
||||
|
||||
const emitConfirmButton = async (): Promise<void> => {
|
||||
const deposit = selectedDeposits.value?.find(
|
||||
(d) => d.network === network.value
|
||||
(d) => d.network === network.value,
|
||||
);
|
||||
if (!deposit) return;
|
||||
deposit.participantID = await getParticipantID(deposit.seller, deposit.token);
|
||||
@@ -185,17 +184,14 @@ const handleSelectedToken = (token: TokenEnum): void => {
|
||||
// Verify if there is a valid deposit to buy
|
||||
const verifyLiquidity = (): void => {
|
||||
enableConfirmButton.value = false;
|
||||
if (!walletAddress.value)
|
||||
return;
|
||||
if (!walletAddress.value) return;
|
||||
const selDeposits = verifyNetworkLiquidity(
|
||||
tokenValue.value,
|
||||
walletAddress.value,
|
||||
depositsValidList.value
|
||||
depositsValidList.value,
|
||||
);
|
||||
selectedDeposits.value = selDeposits;
|
||||
hasLiquidity.value = !!selDeposits.find(
|
||||
(d) => d.network === network.value
|
||||
);
|
||||
hasLiquidity.value = !!selDeposits.find((d) => d.network === network.value);
|
||||
enableOrDisableConfirmButton();
|
||||
};
|
||||
|
||||
@@ -225,7 +221,7 @@ watch(walletAddress, (): void => {
|
||||
const availableNetworks = computed(() => {
|
||||
if (!selectedDeposits.value) return [];
|
||||
return Object.values(Networks).filter((network) =>
|
||||
selectedDeposits.value?.some((d) => d.network.id === network.id)
|
||||
selectedDeposits.value?.some((d) => d.network.id === network.id),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -364,7 +360,10 @@ const handleSubmit = async (e: Event): Promise<void> => {
|
||||
<div
|
||||
class="flex justify-center"
|
||||
v-else-if="
|
||||
!hasLiquidity && !loadingNetworkLiquidity && tokenValue > 0 && !exceedsReputationLimit
|
||||
!hasLiquidity &&
|
||||
!loadingNetworkLiquidity &&
|
||||
tokenValue > 0 &&
|
||||
!exceedsReputationLimit
|
||||
"
|
||||
>
|
||||
<span class="text-red-500 font-normal text-sm"
|
||||
@@ -375,11 +374,14 @@ const handleSubmit = async (e: Event): Promise<void> => {
|
||||
<div
|
||||
class="flex justify-center"
|
||||
v-if="
|
||||
exceedsReputationLimit && !loadingNetworkLiquidity && reputationLimit !== null
|
||||
exceedsReputationLimit &&
|
||||
!loadingNetworkLiquidity &&
|
||||
reputationLimit !== null
|
||||
"
|
||||
>
|
||||
<span class="text-red-500 font-normal text-sm"
|
||||
>O valor excede o limite permitido pela sua reputação. Limite máximo: {{ reputationLimit }} {{ selectedToken }}</span
|
||||
>O valor excede o limite permitido pela sua reputação. Limite
|
||||
máximo: {{ reputationLimit }} {{ selectedToken }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,7 @@ const checkSolicitationStatus = async () => {
|
||||
|
||||
try {
|
||||
const response = await getSolicitation(
|
||||
solicitationData.value.numeroSolicitacao
|
||||
solicitationData.value.numeroSolicitacao,
|
||||
);
|
||||
|
||||
if (response.signature) {
|
||||
@@ -82,7 +82,6 @@ const startPolling = () => {
|
||||
pollingInterval.value = setInterval(checkSolicitationStatus, 10000);
|
||||
};
|
||||
|
||||
|
||||
const copyToClipboard = async () => {
|
||||
if (!qrCode.value) {
|
||||
return;
|
||||
@@ -108,13 +107,10 @@ const copyToClipboard = async () => {
|
||||
onMounted(async () => {
|
||||
try {
|
||||
const { tokenAddress, sellerAddress, amount } = await getUnreleasedLockById(
|
||||
BigInt(props.lockID)
|
||||
BigInt(props.lockID),
|
||||
);
|
||||
|
||||
const participantId = await getParticipantID(
|
||||
sellerAddress,
|
||||
tokenAddress
|
||||
);
|
||||
const participantId = await getParticipantID(sellerAddress, tokenAddress);
|
||||
|
||||
const offer: Offer = {
|
||||
amount,
|
||||
|
||||
@@ -3,14 +3,14 @@ interface Props {
|
||||
title: string;
|
||||
value: string;
|
||||
change?: string;
|
||||
changeType?: 'positive' | 'negative' | 'neutral';
|
||||
changeType?: "positive" | "negative" | "neutral";
|
||||
icon?: string;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
changeType: 'neutral',
|
||||
loading: false
|
||||
changeType: "neutral",
|
||||
loading: false,
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -22,7 +22,11 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
</div>
|
||||
<div v-else class="analytics-value">{{ value }}</div>
|
||||
<div class="analytics-title">{{ title }}</div>
|
||||
<div v-if="change && !loading" class="analytics-change" :class="`change-${changeType}`">
|
||||
<div
|
||||
v-if="change && !loading"
|
||||
class="analytics-change"
|
||||
:class="`change-${changeType}`"
|
||||
>
|
||||
{{ change }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref } from "vue";
|
||||
|
||||
interface Transaction {
|
||||
id: string;
|
||||
type: 'deposit' | 'lock' | 'release' | 'return';
|
||||
type: "deposit" | "lock" | "release" | "return";
|
||||
timestamp: string;
|
||||
seller?: string;
|
||||
buyer?: string | null;
|
||||
@@ -25,22 +25,27 @@ const copyFeedbackTimeout = ref<{ [key: string]: NodeJS.Timeout | null }>({});
|
||||
|
||||
const getTransactionTypeInfo = (type: string) => {
|
||||
const typeMap = {
|
||||
deposit: { label: 'Depósito', status: 'completed' as const },
|
||||
lock: { label: 'Bloqueio', status: 'open' as const },
|
||||
release: { label: 'Liberação', status: 'completed' as const },
|
||||
return: { label: 'Retorno', status: 'expired' as const }
|
||||
deposit: { label: "Depósito", status: "completed" as const },
|
||||
lock: { label: "Bloqueio", status: "open" as const },
|
||||
release: { label: "Liberação", status: "completed" as const },
|
||||
return: { label: "Retorno", status: "expired" as const },
|
||||
};
|
||||
return typeMap[type as keyof typeof typeMap] || { label: type, status: 'pending' as const };
|
||||
return (
|
||||
typeMap[type as keyof typeof typeMap] || {
|
||||
label: type,
|
||||
status: "pending" as const,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const getTransactionTypeColor = (type: string) => {
|
||||
const colorMap = {
|
||||
deposit: 'text-emerald-600',
|
||||
lock: 'text-amber-600',
|
||||
release: 'text-emerald-600',
|
||||
return: 'text-gray-600'
|
||||
deposit: "text-emerald-600",
|
||||
lock: "text-amber-600",
|
||||
release: "text-emerald-600",
|
||||
return: "text-gray-600",
|
||||
};
|
||||
return colorMap[type as keyof typeof colorMap] || 'text-gray-600';
|
||||
return colorMap[type as keyof typeof colorMap] || "text-gray-600";
|
||||
};
|
||||
|
||||
const formatAddress = (address: string) => {
|
||||
@@ -74,7 +79,7 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
copyFeedback.value[key] = false;
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
console.error('Error copying to clipboard:', error);
|
||||
console.error("Error copying to clipboard:", error);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -85,25 +90,31 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
<tr class="border-b border-gray-200">
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">Horário</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">
|
||||
Horário
|
||||
</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">Tipo</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">Participantes</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">
|
||||
Participantes
|
||||
</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">Valor</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">Bloco</th>
|
||||
<th class="text-left py-3 px-4 text-gray-700 font-medium">Ações</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="transaction in transactions"
|
||||
<tr
|
||||
v-for="transaction in transactions"
|
||||
:key="transaction.id"
|
||||
class="border-b border-gray-100 hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
<td class="py-4 px-4">
|
||||
<div class="text-sm text-gray-600">{{ transaction.timestamp }}</div>
|
||||
<div class="text-sm text-gray-600">
|
||||
{{ transaction.timestamp }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="py-4 px-4">
|
||||
<span
|
||||
<span
|
||||
:class="getTransactionTypeColor(transaction.type)"
|
||||
class="text-sm font-medium"
|
||||
>
|
||||
@@ -115,9 +126,14 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
<div v-if="transaction.seller" class="text-sm">
|
||||
<span class="text-gray-600">Vendedor: </span>
|
||||
<div class="relative inline-block">
|
||||
<span
|
||||
<span
|
||||
class="text-gray-900 font-mono cursor-pointer hover:text-amber-500 transition-colors"
|
||||
@click="copyToClipboard(transaction.seller, `seller-${transaction.id}`)"
|
||||
@click="
|
||||
copyToClipboard(
|
||||
transaction.seller,
|
||||
`seller-${transaction.id}`,
|
||||
)
|
||||
"
|
||||
title="Copiar"
|
||||
>
|
||||
{{ formatAddress(transaction.seller) }}
|
||||
@@ -135,9 +151,14 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
<div v-if="transaction.buyer" class="text-sm">
|
||||
<span class="text-gray-600">Comprador: </span>
|
||||
<div class="relative inline-block">
|
||||
<span
|
||||
<span
|
||||
class="text-gray-900 font-mono cursor-pointer hover:text-amber-500 transition-colors"
|
||||
@click="copyToClipboard(transaction.buyer, `buyer-${transaction.id}`)"
|
||||
@click="
|
||||
copyToClipboard(
|
||||
transaction.buyer,
|
||||
`buyer-${transaction.id}`,
|
||||
)
|
||||
"
|
||||
title="Copiar"
|
||||
>
|
||||
{{ formatAddress(transaction.buyer) }}
|
||||
@@ -181,13 +202,13 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
|
||||
<!-- Mobile Cards -->
|
||||
<div class="lg:hidden space-y-4">
|
||||
<div
|
||||
v-for="transaction in transactions"
|
||||
<div
|
||||
v-for="transaction in transactions"
|
||||
:key="transaction.id"
|
||||
class="bg-gray-50 rounded-lg p-4 border border-gray-200"
|
||||
>
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<span
|
||||
<span
|
||||
:class="getTransactionTypeColor(transaction.type)"
|
||||
class="text-sm font-medium"
|
||||
>
|
||||
@@ -195,14 +216,19 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
</span>
|
||||
<div class="text-sm text-gray-600">{{ transaction.timestamp }}</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="space-y-2 mb-4">
|
||||
<div v-if="transaction.seller" class="text-sm">
|
||||
<span class="text-gray-600">Vendedor: </span>
|
||||
<div class="relative inline-block">
|
||||
<span
|
||||
<span
|
||||
class="text-gray-900 font-mono cursor-pointer hover:text-amber-500 transition-colors"
|
||||
@click="copyToClipboard(transaction.seller, `seller-${transaction.id}`)"
|
||||
@click="
|
||||
copyToClipboard(
|
||||
transaction.seller,
|
||||
`seller-${transaction.id}`,
|
||||
)
|
||||
"
|
||||
title="Copiar"
|
||||
>
|
||||
{{ formatAddress(transaction.seller) }}
|
||||
@@ -220,9 +246,11 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
<div v-if="transaction.buyer" class="text-sm">
|
||||
<span class="text-gray-600">Comprador: </span>
|
||||
<div class="relative inline-block">
|
||||
<span
|
||||
<span
|
||||
class="text-gray-900 font-mono cursor-pointer hover:text-amber-500 transition-colors"
|
||||
@click="copyToClipboard(transaction.buyer, `buyer-${transaction.id}`)"
|
||||
@click="
|
||||
copyToClipboard(transaction.buyer, `buyer-${transaction.id}`)
|
||||
"
|
||||
title="Copiar"
|
||||
>
|
||||
{{ formatAddress(transaction.buyer) }}
|
||||
@@ -239,14 +267,18 @@ const copyToClipboard = async (address: string, key: string) => {
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
<span class="text-gray-600">Valor: </span>
|
||||
<span class="font-semibold text-emerald-600">{{ formatAmount(transaction.amount, 18) }} BRZ</span>
|
||||
</div>
|
||||
<span class="font-semibold text-emerald-600"
|
||||
>{{ formatAmount(transaction.amount, 18) }} BRZ</span
|
||||
>
|
||||
</div>
|
||||
<div class="text-sm">
|
||||
<span class="text-gray-600">Bloco: </span>
|
||||
<span class="text-gray-900 font-mono">#{{ transaction.blockNumber }}</span>
|
||||
<span class="text-gray-900 font-mono"
|
||||
>#{{ transaction.blockNumber }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<a
|
||||
:href="getExplorerUrl(transaction.transactionHash)"
|
||||
target="_blank"
|
||||
|
||||
@@ -162,10 +162,7 @@ onMounted(() => {
|
||||
</span>
|
||||
</div>
|
||||
<hr v-show="isCollapsibleOpen" class="pb-3" />
|
||||
<div
|
||||
v-show="isCollapsibleOpen"
|
||||
class="flex justify-between items-center"
|
||||
>
|
||||
<div v-show="isCollapsibleOpen" class="flex justify-between items-center">
|
||||
<h1
|
||||
@click="cancelWithdraw"
|
||||
class="text-black font-medium cursor-pointer hover:text-gray-600 transition-colors"
|
||||
@@ -212,4 +209,3 @@ input[type="number"]::-webkit-outer-spin-button {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ const openEtherscanUrl = (transactionHash: string): void => {
|
||||
const loadMore = (): void => {
|
||||
const itemsShowing = itemsToShow.value.length;
|
||||
itemsToShow.value?.push(
|
||||
...props.walletTransactions.slice(itemsShowing, itemsShowing + 3)
|
||||
...props.walletTransactions.slice(itemsShowing, itemsShowing + 3),
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ const eventName = computed(() => {
|
||||
});
|
||||
|
||||
const explorerName = computed(() => {
|
||||
return Networks[(props.networkName as string).toLowerCase()].blockExplorers?.default.name;
|
||||
return Networks[(props.networkName as string).toLowerCase()].blockExplorers
|
||||
?.default.name;
|
||||
});
|
||||
|
||||
const statusType = computed((): StatusType => {
|
||||
@@ -58,16 +59,16 @@ const showContinueButton = computed(() => {
|
||||
|
||||
const formattedDate = computed(() => {
|
||||
if (!props.transaction.blockTimestamp) return "";
|
||||
|
||||
|
||||
const timestamp = props.transaction.blockTimestamp;
|
||||
const date = new Date(timestamp * 1000);
|
||||
|
||||
|
||||
const day = String(date.getDate()).padStart(2, "0");
|
||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const year = date.getFullYear();
|
||||
const hours = String(date.getHours()).padStart(2, "0");
|
||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||
|
||||
|
||||
return `${day}/${month}/${year} ${hours}:${minutes}`;
|
||||
});
|
||||
|
||||
@@ -142,4 +143,3 @@ const handleExplorerClick = () => {
|
||||
@apply rounded-lg border-amber-300 border-2 px-3 py-2 text-gray-900 font-semibold sm:text-base text-xs hover:bg-transparent w-full text-center;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ const filteredBanks = computed(() => {
|
||||
if (!bankSearchQuery.value) return [];
|
||||
return bankList
|
||||
.filter((bank) =>
|
||||
bank.longName.toLowerCase().includes(bankSearchQuery.value.toLowerCase())
|
||||
bank.longName.toLowerCase().includes(bankSearchQuery.value.toLowerCase()),
|
||||
)
|
||||
.slice(0, 5);
|
||||
});
|
||||
|
||||
@@ -55,12 +55,10 @@ watch(connectedChain, (newVal: any) => {
|
||||
// Check if connected chain is valid, otherwise default to Sepolia
|
||||
if (
|
||||
!newVal ||
|
||||
!Object.values(Networks).some(
|
||||
(network) => network.id === Number(newVal.id)
|
||||
)
|
||||
!Object.values(Networks).some((network) => network.id === Number(newVal.id))
|
||||
) {
|
||||
console.log(
|
||||
"Invalid or unsupported network detected, defaulting to Sepolia"
|
||||
"Invalid or unsupported network detected, defaulting to Sepolia",
|
||||
);
|
||||
user.setNetwork(DEFAULT_NETWORK);
|
||||
return;
|
||||
@@ -69,13 +67,12 @@ watch(connectedChain, (newVal: any) => {
|
||||
});
|
||||
|
||||
const formatWalletAddress = (): string => {
|
||||
if (!walletAddress.value)
|
||||
throw new Error("Wallet not connected");
|
||||
if (!walletAddress.value) throw new Error("Wallet not connected");
|
||||
const walletAddressLength = walletAddress.value.length;
|
||||
const initialText = walletAddress.value.substring(0, 5);
|
||||
const finalText = walletAddress.value.substring(
|
||||
walletAddressLength - 4,
|
||||
walletAddressLength
|
||||
walletAddressLength,
|
||||
);
|
||||
return `${initialText}...${finalText}`;
|
||||
};
|
||||
@@ -92,10 +89,10 @@ const closeMenu = (): void => {
|
||||
|
||||
const networkChange = async (network: NetworkConfig): Promise<void> => {
|
||||
currencyMenuOpenToggle.value = false;
|
||||
|
||||
|
||||
// If wallet is connected, try to change chain in wallet
|
||||
if (connectedWallet.value) {
|
||||
const chainId = network.id.toString(16)
|
||||
const chainId = network.id.toString(16);
|
||||
try {
|
||||
await setChain({
|
||||
chainId: `0x${chainId}`,
|
||||
@@ -195,7 +192,10 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
|
||||
<template>
|
||||
<header class="z-20">
|
||||
<RouterLink :to="'/'" class="default-button flex items-center md:h-auto md:py-2 h-10 py-0">
|
||||
<RouterLink
|
||||
:to="'/'"
|
||||
class="default-button flex items-center md:h-auto md:py-2 h-10 py-0"
|
||||
>
|
||||
<img
|
||||
alt="P2Pix logo"
|
||||
class="logo hidden md:inline-block"
|
||||
@@ -217,13 +217,11 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
<button
|
||||
ref="infoMenuRef"
|
||||
class="default-button hidden md:inline-block cursor-pointer"
|
||||
@click="
|
||||
[
|
||||
(infoMenuOpenToggle = !infoMenuOpenToggle),
|
||||
(menuOpenToggle = false),
|
||||
(currencyMenuOpenToggle = false),
|
||||
]
|
||||
"
|
||||
@click="[
|
||||
(infoMenuOpenToggle = !infoMenuOpenToggle),
|
||||
(menuOpenToggle = false),
|
||||
(currencyMenuOpenToggle = false),
|
||||
]"
|
||||
>
|
||||
<h1
|
||||
class="topbar-text topbar-link"
|
||||
@@ -245,7 +243,7 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
<div class="bg-white rounded-md z-10 -left-36 w-52">
|
||||
<template
|
||||
v-for="(option, index) in infoMenuOptions.filter(
|
||||
(opt) => opt.showInDesktop
|
||||
(opt) => opt.showInDesktop,
|
||||
)"
|
||||
:key="index"
|
||||
>
|
||||
@@ -273,7 +271,8 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
<div
|
||||
v-if="
|
||||
index <
|
||||
infoMenuOptions.filter((opt) => opt.showInDesktop).length -
|
||||
infoMenuOptions.filter((opt) => opt.showInDesktop)
|
||||
.length -
|
||||
1
|
||||
"
|
||||
class="w-full flex justify-center"
|
||||
@@ -339,13 +338,11 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
ref="currencyRef"
|
||||
class="top-bar-info cursor-pointer h-10 group hover:bg-gray-50 transition-all duration-500 ease-in-out"
|
||||
:class="{ 'bg-gray-50': currencyMenuOpenToggle }"
|
||||
@click="
|
||||
[
|
||||
(currencyMenuOpenToggle = !currencyMenuOpenToggle),
|
||||
(menuOpenToggle = false),
|
||||
(infoMenuOpenToggle = false),
|
||||
]
|
||||
"
|
||||
@click="[
|
||||
(currencyMenuOpenToggle = !currencyMenuOpenToggle),
|
||||
(menuOpenToggle = false),
|
||||
(infoMenuOpenToggle = false),
|
||||
]"
|
||||
>
|
||||
<img
|
||||
alt="Choosed network image"
|
||||
@@ -357,9 +354,7 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
class="default-text hidden sm:inline-block text-gray-50 group-hover:text-gray-900 transition-all duration-500 ease-in-out whitespace-nowrap text-ellipsis overflow-hidden"
|
||||
:class="{ '!text-gray-900': currencyMenuOpenToggle }"
|
||||
>
|
||||
{{
|
||||
user.network.value.name || "Invalid Chain"
|
||||
}}
|
||||
{{ user.network.value.name || "Invalid Chain" }}
|
||||
</span>
|
||||
<div
|
||||
class="transition-all duration-500 ease-in-out mt-1"
|
||||
@@ -426,13 +421,11 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
ref="walletAddressRef"
|
||||
class="top-bar-info cursor-pointer h-10 group hover:bg-gray-50 transition-all duration-500 ease-in-out"
|
||||
:class="{ 'bg-gray-50': menuOpenToggle }"
|
||||
@click="
|
||||
[
|
||||
(menuOpenToggle = !menuOpenToggle),
|
||||
(currencyMenuOpenToggle = false),
|
||||
(infoMenuOpenToggle = false),
|
||||
]
|
||||
"
|
||||
@click="[
|
||||
(menuOpenToggle = !menuOpenToggle),
|
||||
(currencyMenuOpenToggle = false),
|
||||
(infoMenuOpenToggle = false),
|
||||
]"
|
||||
>
|
||||
<img alt="Account image" src="@/assets/account.svg?url" />
|
||||
<span
|
||||
@@ -463,7 +456,7 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
>
|
||||
<template
|
||||
v-for="(option, index) in walletMenuOptions.filter(
|
||||
(opt) => opt.showInDesktop
|
||||
(opt) => opt.showInDesktop,
|
||||
)"
|
||||
:key="index"
|
||||
>
|
||||
@@ -510,7 +503,7 @@ const handleMenuOptionClick = (option: MenuOption): void => {
|
||||
<div class="bg-white rounded-md z-10 h-full">
|
||||
<template
|
||||
v-for="(option, index) in walletMenuOptions.filter(
|
||||
(opt) => opt.showInMobile
|
||||
(opt) => opt.showInMobile,
|
||||
)"
|
||||
:key="index"
|
||||
>
|
||||
@@ -653,6 +646,8 @@ a:hover {
|
||||
max-height: calc(100vh - 60px);
|
||||
overflow-y: auto;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
box-shadow:
|
||||
0 4px 6px -1px rgba(0, 0, 0, 0.1),
|
||||
0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -27,7 +27,7 @@ const props = withDefaults(
|
||||
minValue: 0,
|
||||
disabled: false,
|
||||
required: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -68,9 +68,9 @@ const handleInput = (event: Event) => {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const value = target.value;
|
||||
inputValue.value = value;
|
||||
|
||||
|
||||
const numValue = Number(value);
|
||||
|
||||
|
||||
// Validar decimais
|
||||
if (decimalCount(value) > 2) {
|
||||
validDecimals.value = false;
|
||||
@@ -79,7 +79,7 @@ const handleInput = (event: Event) => {
|
||||
return;
|
||||
}
|
||||
validDecimals.value = true;
|
||||
|
||||
|
||||
// Validar range
|
||||
if (props.minValue !== undefined && numValue < props.minValue) {
|
||||
validRange.value = false;
|
||||
@@ -94,7 +94,7 @@ const handleInput = (event: Event) => {
|
||||
return;
|
||||
}
|
||||
validRange.value = true;
|
||||
|
||||
|
||||
emit("update:modelValue", numValue);
|
||||
emit("error", null);
|
||||
emit("valid", true);
|
||||
@@ -106,11 +106,14 @@ const handleTokenChange = (token: TokenEnum) => {
|
||||
emit("update:selectedToken", token);
|
||||
};
|
||||
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
if (newVal !== Number(inputValue.value)) {
|
||||
inputValue.value = String(newVal || "");
|
||||
}
|
||||
});
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newVal) => {
|
||||
if (newVal !== Number(inputValue.value)) {
|
||||
inputValue.value = String(newVal || "");
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -130,7 +133,7 @@ watch(() => props.modelValue, (newVal) => {
|
||||
step="0.01"
|
||||
@input="debouncedHandleInput"
|
||||
/>
|
||||
|
||||
|
||||
<TokenSelector
|
||||
v-if="showTokenSelector"
|
||||
:model-value="selectedToken"
|
||||
@@ -138,26 +141,22 @@ watch(() => props.modelValue, (newVal) => {
|
||||
size="md"
|
||||
@update:model-value="handleTokenChange"
|
||||
/>
|
||||
|
||||
|
||||
<div v-else class="token-display">
|
||||
{{ selectedToken }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
|
||||
<div class="info-row">
|
||||
<p v-if="showConversion" class="conversion-text">
|
||||
~ R$ {{ convertedValue }}
|
||||
</p>
|
||||
<slot name="extra-info"></slot>
|
||||
</div>
|
||||
|
||||
<ErrorMessage
|
||||
v-if="errorMessage"
|
||||
:message="errorMessage"
|
||||
type="error"
|
||||
/>
|
||||
|
||||
<ErrorMessage v-if="errorMessage" :message="errorMessage" type="error" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -205,4 +204,3 @@ watch(() => props.modelValue, (newVal) => {
|
||||
@apply text-gray-500 font-normal text-sm;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ const props = withDefaults(
|
||||
{
|
||||
disabled: false,
|
||||
placeholder: "Busque e selecione seu banco",
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -46,7 +46,7 @@ const searchQuery = computed({
|
||||
|
||||
const filteredBanks = computed(() => {
|
||||
if (!searchQuery.value) return [];
|
||||
|
||||
|
||||
const query = searchQuery.value.toLowerCase();
|
||||
return bankList
|
||||
.filter((bank) => bank.longName.toLowerCase().includes(query))
|
||||
@@ -73,7 +73,7 @@ const selectBank = (bank: Bank) => {
|
||||
class="bank-input"
|
||||
autocomplete="off"
|
||||
/>
|
||||
|
||||
|
||||
<transition name="dropdown-fade">
|
||||
<div v-if="showBankList" class="bank-list">
|
||||
<div
|
||||
@@ -134,4 +134,3 @@ const selectBank = (bank: Bank) => {
|
||||
@apply opacity-0 -translate-y-2;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ const props = withDefaults(
|
||||
iconPosition: "left",
|
||||
fullWidth: true,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits(["buttonClicked"]);
|
||||
|
||||
@@ -3,6 +3,8 @@ import { ref, computed } from "vue";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import ChevronDown from "@/assets/chevronDown.svg";
|
||||
|
||||
defineOptions({ name: "UiDropdown" });
|
||||
|
||||
export interface DropdownItem<T = any> {
|
||||
value: T;
|
||||
label: string;
|
||||
@@ -26,7 +28,7 @@ const props = withDefaults(
|
||||
disabled: false,
|
||||
size: "md",
|
||||
showIcon: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -46,11 +48,9 @@ const filteredItems = computed(() => {
|
||||
if (!props.searchable || !searchQuery.value) {
|
||||
return props.items;
|
||||
}
|
||||
|
||||
|
||||
const query = searchQuery.value.toLowerCase();
|
||||
return props.items.filter((item) =>
|
||||
item.label.toLowerCase().includes(query)
|
||||
);
|
||||
return props.items.filter((item) => item.label.toLowerCase().includes(query));
|
||||
});
|
||||
|
||||
const toggleDropdown = () => {
|
||||
@@ -97,10 +97,7 @@ onClickOutside(dropdownRef, () => {
|
||||
<span class="selected-text">
|
||||
{{ selectedItem?.label || placeholder }}
|
||||
</span>
|
||||
<ChevronDown
|
||||
class="chevron"
|
||||
:class="{ rotated: isOpen }"
|
||||
/>
|
||||
<ChevronDown class="chevron" :class="{ rotated: isOpen }" />
|
||||
</button>
|
||||
|
||||
<transition name="dropdown-fade">
|
||||
@@ -113,7 +110,7 @@ onClickOutside(dropdownRef, () => {
|
||||
placeholder="Buscar..."
|
||||
@click.stop
|
||||
/>
|
||||
|
||||
|
||||
<div class="items-container">
|
||||
<div
|
||||
v-for="item in filteredItems"
|
||||
@@ -135,7 +132,7 @@ onClickOutside(dropdownRef, () => {
|
||||
/>
|
||||
<span class="item-label">{{ item.label }}</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="filteredItems.length === 0" class="no-results">
|
||||
Nenhum resultado encontrado
|
||||
</div>
|
||||
@@ -245,4 +242,3 @@ onClickOutside(dropdownRef, () => {
|
||||
@apply opacity-0 -translate-y-2;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const props = withDefaults(
|
||||
type: "error",
|
||||
centered: true,
|
||||
icon: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const colorClasses = {
|
||||
@@ -52,4 +52,3 @@ const colorClasses = {
|
||||
@apply leading-tight;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ const props = withDefaults(
|
||||
padding: "md",
|
||||
fullWidth: true,
|
||||
noBorder: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -52,4 +52,3 @@ const props = withDefaults(
|
||||
@apply px-12 py-8;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ const props = withDefaults(
|
||||
iconPosition: "left",
|
||||
disabled: false,
|
||||
fullWidth: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -144,4 +144,3 @@ const handleClick = () => {
|
||||
@apply flex-shrink-0;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const props = withDefaults(
|
||||
placement: "right",
|
||||
iconSrc: "",
|
||||
showOnHover: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const showTooltip = ref<boolean>(false);
|
||||
@@ -24,7 +24,12 @@ const floatingArrow = ref(null);
|
||||
onMounted(() => {
|
||||
useFloating(reference, floating, {
|
||||
placement: props.placement,
|
||||
middleware: [offset(10), flip(), shift(), arrow({ element: floatingArrow })],
|
||||
middleware: [
|
||||
offset(10),
|
||||
flip(),
|
||||
shift(),
|
||||
arrow({ element: floatingArrow }),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -88,4 +93,3 @@ const toggleTooltip = () => {
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ const props = withDefaults(
|
||||
size: "md",
|
||||
centered: true,
|
||||
inline: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const sizeMap = {
|
||||
@@ -24,12 +24,7 @@ const sizeMap = {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="[
|
||||
'loading-state',
|
||||
{ centered: centered, inline: inline },
|
||||
]"
|
||||
>
|
||||
<div :class="['loading-state', { centered: centered, inline: inline }]">
|
||||
<span v-if="message" :class="['loading-message', sizeMap[size].text]">
|
||||
{{ message }}
|
||||
</span>
|
||||
@@ -57,4 +52,3 @@ const sizeMap = {
|
||||
@apply text-gray-900 font-normal;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const props = withDefaults(
|
||||
{
|
||||
size: "md",
|
||||
showLabel: false,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const sizeMap = {
|
||||
@@ -69,4 +69,3 @@ const networkData = computed(() => {
|
||||
@apply text-sm font-medium text-gray-900;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ const props = withDefaults(
|
||||
{
|
||||
disabled: false,
|
||||
size: "md",
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -23,7 +23,7 @@ const emit = defineEmits<{
|
||||
change: [value: NetworkConfig];
|
||||
}>();
|
||||
|
||||
const networkItems = computed((): DropdownItem<NetworkConfig>[] => {
|
||||
const networkItems = computed((): DropdownItem<NetworkConfig>[] => {
|
||||
return Object.values(Networks).map((network) => ({
|
||||
value: network,
|
||||
label: network.name,
|
||||
@@ -47,4 +47,3 @@ const handleChange = (value: NetworkConfig) => {
|
||||
@update:model-value="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -11,14 +11,12 @@ const props = withDefaults(
|
||||
{
|
||||
size: "lg",
|
||||
centered: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
:class="['page-header', `size-${size}`, { centered: centered }]"
|
||||
>
|
||||
<div :class="['page-header', `size-${size}`, { centered: centered }]">
|
||||
<h1 class="title text-white font-extrabold">
|
||||
{{ title }}
|
||||
</h1>
|
||||
@@ -63,4 +61,3 @@ const props = withDefaults(
|
||||
@apply sm:text-base text-sm sm:max-w-[28rem] max-w-[30rem] sm:tracking-normal tracking-wide;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -47,4 +47,3 @@ const displayText = computed(() => {
|
||||
@apply text-xs sm:text-base font-medium text-gray-900 rounded-lg text-center px-2 py-1;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ const checkNetwork = () => {
|
||||
const switchNetwork = async () => {
|
||||
try {
|
||||
if (connectedWallet.value && connectedWallet.value.provider) {
|
||||
let chainId = network.value.id.toString(16);
|
||||
const chainId = network.value.id.toString(16);
|
||||
await connectedWallet.value.provider.request({
|
||||
method: "wallet_switchEthereumChain",
|
||||
params: [
|
||||
@@ -66,7 +66,9 @@ watch(network, checkNetwork, { immediate: true });
|
||||
<style scoped>
|
||||
.slide-up-enter-active,
|
||||
.slide-up-leave-active {
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
transition:
|
||||
transform 0.3s ease,
|
||||
opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.slide-up-enter-from,
|
||||
|
||||
@@ -13,7 +13,7 @@ const props = withDefaults(
|
||||
{
|
||||
disabled: false,
|
||||
size: "md",
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -45,4 +45,3 @@ const handleChange = (value: TokenEnum) => {
|
||||
@update:model-value="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const props = withDefaults(
|
||||
{
|
||||
variant: "primary",
|
||||
showMenu: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -30,12 +30,12 @@ const isConnected = computed(() => {
|
||||
|
||||
const formattedAddress = computed(() => {
|
||||
if (!props.walletAddress) return "";
|
||||
|
||||
|
||||
const address = props.walletAddress;
|
||||
const length = address.length;
|
||||
const start = address.substring(0, 5);
|
||||
const end = address.substring(length - 4, length);
|
||||
|
||||
|
||||
return `${start}...${end}`;
|
||||
});
|
||||
|
||||
@@ -72,17 +72,13 @@ onClickOutside(menuRef, () => {
|
||||
:variant="variant"
|
||||
@button-clicked="handleConnect"
|
||||
/>
|
||||
|
||||
|
||||
<div v-else ref="menuRef" class="wallet-connected">
|
||||
<button
|
||||
type="button"
|
||||
class="wallet-button"
|
||||
@click="toggleMenu"
|
||||
>
|
||||
<button type="button" class="wallet-button" @click="toggleMenu">
|
||||
<span class="wallet-address">{{ formattedAddress }}</span>
|
||||
<div class="wallet-indicator"></div>
|
||||
</button>
|
||||
|
||||
|
||||
<transition name="menu-fade">
|
||||
<div v-if="menuOpen && showMenu" class="wallet-menu">
|
||||
<button
|
||||
@@ -149,4 +145,3 @@ onClickOutside(menuRef, () => {
|
||||
@apply opacity-0 -translate-y-2;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user