feat: add withdraw functionality and related enums
- Introduced WithdrawMethodEnum and ChainEnum in enum.ts for withdrawal methods and blockchain types. - Updated types.ts to include WithdrawBody type for withdrawal requests. - Created a new useResetRef composable for managing form state resets. - Added a withdraw page with form handling in index.vue, including validation and submission logic. - Integrated the new withdraw functionality into the wallet card component. - Updated the main.ts file to include Pinia for state management. - Created a wallet store to manage user balances. - Modified the deposit page to improve user experience and validation. - Added number pattern validation for input fields. - Updated the router to include a new route for the withdraw page. - Refactored input-label component styles for better layout. - Added a new rules.ts file for future validation rules.
This commit is contained in:
2
.env
2
.env
@@ -1 +1 @@
|
||||
VITE_API_URL=http://192.168.1.36:9528
|
||||
VITE_API_URL=http://192.168.1.36:9527
|
||||
6
auto-imports.d.ts
vendored
6
auto-imports.d.ts
vendored
@@ -52,6 +52,7 @@ declare global {
|
||||
const makeDestructurable: typeof import('@vueuse/core').makeDestructurable
|
||||
const markRaw: typeof import('vue').markRaw
|
||||
const nextTick: typeof import('vue').nextTick
|
||||
const numberPattern: typeof import('./src/utils/pattern').numberPattern
|
||||
const onActivated: typeof import('vue').onActivated
|
||||
const onBeforeMount: typeof import('vue').onBeforeMount
|
||||
const onBeforeRouteLeave: typeof import('vue-router').onBeforeRouteLeave
|
||||
@@ -230,6 +231,7 @@ declare global {
|
||||
const usePrevious: typeof import('@vueuse/core').usePrevious
|
||||
const useRafFn: typeof import('@vueuse/core').useRafFn
|
||||
const useRefHistory: typeof import('@vueuse/core').useRefHistory
|
||||
const useResetRef: typeof import('./src/composables/useResetRef').useResetRef
|
||||
const useResizeObserver: typeof import('@vueuse/core').useResizeObserver
|
||||
const useRoute: typeof import('vue-router').useRoute
|
||||
const useRouter: typeof import('vue-router').useRouter
|
||||
@@ -277,6 +279,7 @@ declare global {
|
||||
const useVibrate: typeof import('@vueuse/core').useVibrate
|
||||
const useVirtualList: typeof import('@vueuse/core').useVirtualList
|
||||
const useWakeLock: typeof import('@vueuse/core').useWakeLock
|
||||
const useWalletStore: typeof import('./src/store/wallet').useWalletStore
|
||||
const useWebNotification: typeof import('@vueuse/core').useWebNotification
|
||||
const useWebSocket: typeof import('@vueuse/core').useWebSocket
|
||||
const useWebWorker: typeof import('@vueuse/core').useWebWorker
|
||||
@@ -362,6 +365,7 @@ declare module 'vue' {
|
||||
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']>
|
||||
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']>
|
||||
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']>
|
||||
readonly numberPattern: UnwrapRef<typeof import('./src/utils/pattern')['numberPattern']>
|
||||
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']>
|
||||
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']>
|
||||
readonly onBeforeRouteLeave: UnwrapRef<typeof import('vue-router')['onBeforeRouteLeave']>
|
||||
@@ -540,6 +544,7 @@ declare module 'vue' {
|
||||
readonly usePrevious: UnwrapRef<typeof import('@vueuse/core')['usePrevious']>
|
||||
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']>
|
||||
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']>
|
||||
readonly useResetRef: UnwrapRef<typeof import('./src/composables/useResetRef')['useResetRef']>
|
||||
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']>
|
||||
readonly useRoute: UnwrapRef<typeof import('vue-router')['useRoute']>
|
||||
readonly useRouter: UnwrapRef<typeof import('vue-router')['useRouter']>
|
||||
@@ -587,6 +592,7 @@ declare module 'vue' {
|
||||
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']>
|
||||
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']>
|
||||
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']>
|
||||
readonly useWalletStore: UnwrapRef<typeof import('./src/store/wallet')['useWalletStore']>
|
||||
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']>
|
||||
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']>
|
||||
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']>
|
||||
|
||||
8
components.d.ts
vendored
8
components.d.ts
vendored
@@ -35,7 +35,11 @@ declare module 'vue' {
|
||||
IonLabel: typeof import('@ionic/vue')['IonLabel']
|
||||
IonList: typeof import('@ionic/vue')['IonList']
|
||||
IonModal: typeof import('@ionic/vue')['IonModal']
|
||||
IonNavLink: typeof import('@ionic/vue')['IonNavLink']
|
||||
IonNote: typeof import('@ionic/vue')['IonNote']
|
||||
IonPage: typeof import('@ionic/vue')['IonPage']
|
||||
IonRadio: typeof import('@ionic/vue')['IonRadio']
|
||||
IonRadioGroup: typeof import('@ionic/vue')['IonRadioGroup']
|
||||
IonRouterOutlet: typeof import('@ionic/vue')['IonRouterOutlet']
|
||||
IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
|
||||
IonSelect: typeof import('@ionic/vue')['IonSelect']
|
||||
@@ -81,7 +85,11 @@ declare global {
|
||||
const IonLabel: typeof import('@ionic/vue')['IonLabel']
|
||||
const IonList: typeof import('@ionic/vue')['IonList']
|
||||
const IonModal: typeof import('@ionic/vue')['IonModal']
|
||||
const IonNavLink: typeof import('@ionic/vue')['IonNavLink']
|
||||
const IonNote: typeof import('@ionic/vue')['IonNote']
|
||||
const IonPage: typeof import('@ionic/vue')['IonPage']
|
||||
const IonRadio: typeof import('@ionic/vue')['IonRadio']
|
||||
const IonRadioGroup: typeof import('@ionic/vue')['IonRadioGroup']
|
||||
const IonRouterOutlet: typeof import('@ionic/vue')['IonRouterOutlet']
|
||||
const IonSearchbar: typeof import('@ionic/vue')['IonSearchbar']
|
||||
const IonSelect: typeof import('@ionic/vue')['IonSelect']
|
||||
|
||||
@@ -31,5 +31,6 @@ export default antfu({
|
||||
"unused-imports/no-unused-imports": "off",
|
||||
"vue/no-deprecated-slot-attribute": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"prefer-promise-reject-errors": "off",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,11 +23,13 @@
|
||||
"@elysiajs/eden": "^1.4.5",
|
||||
"@ionic/vue": "^8.7.11",
|
||||
"@ionic/vue-router": "^8.7.11",
|
||||
"@riwa/api-types": "http://192.168.1.36:9527/api/riwa-api-types-0.0.1.tgz",
|
||||
"@nuxt/ui": "^4.2.1",
|
||||
"@riwa/api-types": "http://192.168.1.36:9527/api/riwa-api-types-0.0.6.tgz",
|
||||
"@vueuse/core": "^14.1.0",
|
||||
"better-auth": "^1.4.6",
|
||||
"ionicons": "^8.0.13",
|
||||
"lodash-es": "^4.17.21",
|
||||
"pinia": "^3.0.4",
|
||||
"vue": "^3.5.25",
|
||||
"vue-i18n": "^11.2.2",
|
||||
"vue-router": "^4.6.3"
|
||||
|
||||
1603
pnpm-lock.yaml
generated
1603
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -7,3 +7,15 @@ export enum AssetCodeEnum {
|
||||
USDT = "USDT",
|
||||
OPTS = "OPTS",
|
||||
}
|
||||
|
||||
export enum WithdrawMethodEnum {
|
||||
BANK = "bank",
|
||||
CRYPTO = "crypto",
|
||||
CASH = "cash",
|
||||
}
|
||||
|
||||
export enum ChainEnum {
|
||||
BEP20 = "BEP20",
|
||||
ERC20 = "ERC20",
|
||||
TRC20 = "TRC20",
|
||||
}
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import type { Treaty } from "@elysiajs/eden";
|
||||
import type { client } from ".";
|
||||
import type { AssetCodeEnum, PaymentChannelEnum } from "./enum";
|
||||
import type { AssetCodeEnum, PaymentChannelEnum, WithdrawMethodEnum } from "./enum";
|
||||
|
||||
export type DepositFiatBody = Parameters<typeof client.api.asset.deposit.fiat.post>[0] & {
|
||||
export type DepositFiatBody = Parameters<typeof client.api.deposit.fiat.post>[0] & {
|
||||
paymentChannel: PaymentChannelEnum;
|
||||
assetCode: AssetCodeEnum;
|
||||
};
|
||||
|
||||
export type DepositFiatData = Treaty.Data<typeof client.api.asset.deposit.fiat.post>;
|
||||
export type DepositFiatData = Treaty.Data<typeof client.api.deposit.fiat.post>;
|
||||
|
||||
export type BalancesData = Treaty.Data<typeof client.api.asset.balances.get>;
|
||||
|
||||
export type WithdrawBody = Omit<Parameters<typeof client.api.asset.withdraw.post>[0], "assetCode" | "withdrawMethod"> & {
|
||||
assetCode: AssetCodeEnum;
|
||||
withdrawMethod: WithdrawMethodEnum;
|
||||
};
|
||||
|
||||
@@ -29,7 +29,6 @@ defineExpose({} as ComponentInstance<typeof UiInput>);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 14px;
|
||||
margin-left: 8px;
|
||||
color: var(--ion-text-color-secondary);
|
||||
}
|
||||
</style>
|
||||
|
||||
14
src/composables/useResetRef.ts
Normal file
14
src/composables/useResetRef.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { MaybeRef } from "vue";
|
||||
import cloneDeepWith from "lodash-es/cloneDeepWith";
|
||||
import { isRef, ref } from "vue";
|
||||
|
||||
export function useResetRef<T>(value: MaybeRef<T>) {
|
||||
const _valueDefine = cloneDeepWith(value as any);
|
||||
const _value = isRef(value) ? value : ref(value);
|
||||
|
||||
function reset(value?: T) {
|
||||
_value.value = value ? cloneDeepWith(value) : cloneDeepWith(_valueDefine);
|
||||
}
|
||||
|
||||
return [_value, reset] as const;
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import { IonicVue } from "@ionic/vue";
|
||||
import ui from "@nuxt/ui/vue-plugin";
|
||||
import { createPinia } from "pinia";
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
|
||||
@@ -39,10 +41,14 @@ import "@ionic/vue/css/palettes/dark.system.css";
|
||||
import "./theme/variables.css";
|
||||
import "./theme/ionic.css";
|
||||
|
||||
const pinia = createPinia();
|
||||
|
||||
const app = createApp(App)
|
||||
.use(IonicVue)
|
||||
.use(router)
|
||||
.use(i18n);
|
||||
.use(pinia)
|
||||
.use(i18n)
|
||||
.use(ui);
|
||||
|
||||
router.isReady().then(() => {
|
||||
app.mount("#app");
|
||||
|
||||
@@ -44,6 +44,10 @@ const routes: Array<RouteRecordRaw> = [
|
||||
path: "/deposit/fiat",
|
||||
component: () => import("@/views/deposit/fiat.vue"),
|
||||
},
|
||||
{
|
||||
path: "/withdraw/index",
|
||||
component: () => import("@/views/withdraw/index.vue"),
|
||||
},
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
|
||||
1
src/store/index.ts
Normal file
1
src/store/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./wallet";
|
||||
16
src/store/wallet.ts
Normal file
16
src/store/wallet.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { BalancesData } from "@/api/types";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
interface State {
|
||||
balances: BalancesData | null;
|
||||
}
|
||||
|
||||
export const useWalletStore = defineStore("wallet", () => {
|
||||
const state = reactive<State>({
|
||||
balances: null,
|
||||
});
|
||||
|
||||
return {
|
||||
state,
|
||||
};
|
||||
});
|
||||
@@ -3,7 +3,7 @@ export function formatBalance(amount: MaybeRefOrGetter<number | string>, locale:
|
||||
if (!value) {
|
||||
value = 0;
|
||||
}
|
||||
if (typeof value === "string" && !Number.isNaN(Number(value))) {
|
||||
if (typeof value === "string" && Number.isNaN(Number(value))) {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export const emailPattern = /^(?=.{1,254}$)(?=.{1,64}@)[\w!#$%&'*+/=?^`{|}~-]+(?:\.[\w!#$%&'*+/=?^`{|}~-]+)*@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i;
|
||||
export const numberPattern = /^\d+(?:\.\d+)?$/;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script lang='ts' setup>
|
||||
import type { DepositFiatBody } from "@/api/types";
|
||||
import { toastController } from "@ionic/vue";
|
||||
import { client } from "@/api";
|
||||
import { AssetCodeEnum, PaymentChannelEnum } from "@/api/enum";
|
||||
|
||||
const form = ref<DepositFiatBody>({
|
||||
@@ -19,11 +21,24 @@ function validate(value: string) {
|
||||
if (value === "") {
|
||||
return false;
|
||||
}
|
||||
const isEmailValid = emailPattern.test(form.value.amount);
|
||||
const isNumber = numberPattern.test(value);
|
||||
|
||||
isEmailValid ? inputInstance.value?.$el.classList.add("ion-valid") : inputInstance.value?.$el.classList.add("ion-invalid");
|
||||
isNumber ? inputInstance.value?.$el.classList.add("ion-valid") : inputInstance.value?.$el.classList.add("ion-invalid");
|
||||
|
||||
return isEmailValid;
|
||||
return isNumber;
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
const { data, status } = await client.api.deposit.fiat.post(form.value);
|
||||
if (status === 200) {
|
||||
const toast = await toastController.create({
|
||||
message: "Submission successful!",
|
||||
duration: 1500,
|
||||
position: "bottom",
|
||||
});
|
||||
|
||||
await toast.present();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -38,7 +53,7 @@ function validate(value: string) {
|
||||
</ion-toolbar>
|
||||
</IonHeader>
|
||||
<IonContent :fullscreen="true" class="ion-padding">
|
||||
<div class="flex flex-col gap-10px">
|
||||
<div class="flex flex-col gap-20px">
|
||||
<ui-input-label
|
||||
label="Recharge bank card account"
|
||||
model-value="74321329321312"
|
||||
@@ -47,11 +62,22 @@ function validate(value: string) {
|
||||
disabled
|
||||
/>
|
||||
|
||||
<ion-select v-model="form.assetCode" label="Select Currency" placeholder="Select One" label-placement="floating">
|
||||
<ion-radio-group v-model="form.assetCode">
|
||||
<ion-label class="text-sm">
|
||||
Choose Currency
|
||||
</ion-label>
|
||||
<ion-item v-for="item in AssetCodeEnum" :key="item">
|
||||
<ion-radio :value="item" justify="space-between">
|
||||
{{ item }}
|
||||
</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
|
||||
<!-- <ion-select v-model="form.assetCode" label="Select Currency" placeholder="Select One" label-placement="floating">
|
||||
<ion-select-option v-for="item in AssetCodeEnum" :key="item" :value="item">
|
||||
{{ item }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-select> -->
|
||||
|
||||
<ui-input-label
|
||||
ref="inputInstance"
|
||||
@@ -59,10 +85,17 @@ function validate(value: string) {
|
||||
label="Amount"
|
||||
placeholder="Enter the amount"
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
error-text="Please enter a valid amount."
|
||||
@ion-input="validate($event.target.value as string)"
|
||||
@ion-blur="markTouched"
|
||||
/>
|
||||
|
||||
<ion-note>Please make sure to enter the correct amount. After submission, the funds will be credited to your account after review in the background.</ion-note>
|
||||
|
||||
<ion-button expand="block" @click="onSubmit">
|
||||
Submit
|
||||
</ion-button>
|
||||
</div>
|
||||
</IonContent>
|
||||
</ion-page>
|
||||
|
||||
@@ -1,20 +1,41 @@
|
||||
<script lang='ts' setup>
|
||||
import { onIonViewDidEnter, onIonViewWillEnter } from "@ionic/vue";
|
||||
import { client } from "@/api";
|
||||
import RechargeChannel from "./recharge-channel.vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
const { data } = await client.api.asset.balances.get();
|
||||
const router = useRouter();
|
||||
const { state } = useWalletStore();
|
||||
const rechargeInstance = ref<ModalInstance>();
|
||||
|
||||
async function init() {
|
||||
const { data } = await client.api.asset.balances.get();
|
||||
state.balances = data;
|
||||
}
|
||||
function onCloseModal() {
|
||||
rechargeInstance.value?.$el.dismiss(null, "confirm");
|
||||
}
|
||||
function handleWithdraw() {
|
||||
router.push("/withdraw/index");
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
onIonViewWillEnter(() => {
|
||||
init();
|
||||
});
|
||||
|
||||
onIonViewDidEnter(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mt-20px">
|
||||
<div class="grid grid-cols-2 gap-20px p-20px bg-[var(--ion-card-background)] rounded-t-6px">
|
||||
<div v-for="item in data" :key="item.assetCode" class="flex flex-col gap-4px">
|
||||
<div class="mt-20px shadow-md rounded-6px">
|
||||
<div class="grid grid-cols-2 gap-20px p-20px bg-[var(--ion-card-background)]">
|
||||
<div v-for="item in state.balances" :key="item.assetCode" class="flex flex-col gap-4px">
|
||||
<div class="ion-text-uppercase text-xs color-text-400 font-500 tracking-0.4px">
|
||||
{{ item.assetCode }}
|
||||
</div>
|
||||
@@ -24,26 +45,27 @@ function onCloseModal() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-10px pb-20px bg-[var(--ion-card-background)] rounded-b-6px">
|
||||
<div class="px-10px pb-20px bg-[var(--ion-card-background)]">
|
||||
<ion-buttons class="gap-10px" expand="block">
|
||||
<ion-button id="open-modal" expand="block" fill="clear">
|
||||
<ion-button id="open-recharge-modal" expand="block" fill="clear">
|
||||
{{ t("wallet.recharge") }}
|
||||
</ion-button>
|
||||
|
||||
<ion-button expand="block" fill="clear">
|
||||
<ion-button expand="block" fill="clear" @click="handleWithdraw">
|
||||
{{ t("wallet.withdraw") }}
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ion-modal ref="rechargeInstance" class="recharge-channel-modal" trigger="open-modal" :initial-breakpoint="1" :breakpoints="[0, 1]">
|
||||
<ion-modal ref="rechargeInstance" class="recharge-channel-modal" trigger="open-recharge-modal" :initial-breakpoint="1" :breakpoints="[0, 1]">
|
||||
<RechargeChannel @close="onCloseModal" />
|
||||
</ion-modal>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.recharge-channel-modal {
|
||||
.recharge-channel-modal,
|
||||
.withdraw-channel-modal {
|
||||
--height: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
143
src/views/withdraw/index.vue
Normal file
143
src/views/withdraw/index.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<script lang='ts' setup>
|
||||
import type { WithdrawBody } from "@/api/types";
|
||||
import { toastController } from "@ionic/vue";
|
||||
import { client } from "@/api";
|
||||
import { AssetCodeEnum, ChainEnum, WithdrawMethodEnum } from "@/api/enum";
|
||||
|
||||
const amountInputInst = useTemplateRef<InputInstance>("amountInputInst");
|
||||
const [form, resetForm] = useResetRef<WithdrawBody>({
|
||||
assetCode: AssetCodeEnum.USDT,
|
||||
amount: "",
|
||||
withdrawMethod: WithdrawMethodEnum.BANK,
|
||||
toAddress: "",
|
||||
bankAccountId: "",
|
||||
chain: "BEP20",
|
||||
});
|
||||
const { state } = useWalletStore();
|
||||
const maxAmount = computed(() => {
|
||||
const balance = state.balances?.find(item => item.assetCode === form.value.assetCode);
|
||||
return balance ? balance.available : "0";
|
||||
});
|
||||
|
||||
function markTouched() {
|
||||
amountInputInst.value?.$el.classList.add("ion-touched");
|
||||
}
|
||||
function validate(value: string) {
|
||||
amountInputInst.value?.$el.classList.remove("ion-valid");
|
||||
amountInputInst.value?.$el.classList.remove("ion-invalid");
|
||||
|
||||
if (value === "") {
|
||||
return false;
|
||||
}
|
||||
const isNumber = numberPattern.test(value);
|
||||
|
||||
isNumber ? amountInputInst.value?.$el.classList.add("ion-valid") : amountInputInst.value?.$el.classList.add("ion-invalid");
|
||||
|
||||
return isNumber;
|
||||
}
|
||||
function handleCurrentChange() {
|
||||
form.value.amount = "";
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
const { data, status } = await client.api.asset.withdraw.post(form.value);
|
||||
if (status === 200) {
|
||||
const toast = await toastController.create({
|
||||
message: "Submission successful!",
|
||||
duration: 1500,
|
||||
position: "bottom",
|
||||
});
|
||||
|
||||
await toast.present();
|
||||
|
||||
resetForm();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ion-page>
|
||||
<IonHeader>
|
||||
<ion-toolbar class="ui-toolbar">
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button />
|
||||
</ion-buttons>
|
||||
<ion-title>Withdraw</ion-title>
|
||||
</ion-toolbar>
|
||||
</IonHeader>
|
||||
<IonContent :fullscreen="true" class="ion-padding">
|
||||
<div class="flex flex-col gap-20px">
|
||||
<ion-radio-group v-model="form.assetCode" @ion-change="handleCurrentChange">
|
||||
<ion-label class="text-sm">
|
||||
Choose Currency
|
||||
</ion-label>
|
||||
<ion-item v-for="item in AssetCodeEnum" :key="item">
|
||||
<ion-radio :value="item" justify="space-between">
|
||||
{{ item }}
|
||||
</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
|
||||
<ion-radio-group v-model="form.withdrawMethod">
|
||||
<ion-label class="text-sm">
|
||||
Choose Withdraw Method
|
||||
</ion-label>
|
||||
<ion-item v-for="item in WithdrawMethodEnum" :key="item">
|
||||
<ion-radio :value="item" justify="space-between">
|
||||
{{ item }}
|
||||
</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
|
||||
<ui-input-label
|
||||
ref="amountInputInst"
|
||||
v-model="form.amount"
|
||||
label="Amount"
|
||||
:placeholder="`Enter the amount (Max: ${maxAmount})`"
|
||||
type="number"
|
||||
inputmode="numeric"
|
||||
error-text="Please enter a valid amount."
|
||||
:max="maxAmount"
|
||||
@ion-input="validate($event.target.value as string)"
|
||||
@ion-blur="markTouched"
|
||||
/>
|
||||
|
||||
<ui-input-label
|
||||
v-if="form.withdrawMethod === WithdrawMethodEnum.BANK"
|
||||
v-model="form.bankAccountId"
|
||||
label="Bank Account ID"
|
||||
placeholder="Enter the bank account ID"
|
||||
type="text"
|
||||
inputmode="text"
|
||||
error-text="Please enter a valid bank account ID."
|
||||
/>
|
||||
<template v-else-if="form.withdrawMethod === WithdrawMethodEnum.CRYPTO">
|
||||
<ion-radio-group v-model="form.chain">
|
||||
<ion-label class="text-sm">
|
||||
Choose Chain
|
||||
</ion-label>
|
||||
<ion-item v-for="item in ChainEnum" :key="item">
|
||||
<ion-radio :value="item" justify="space-between">
|
||||
{{ item }}
|
||||
</ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
<ui-input-label
|
||||
v-model="form.toAddress"
|
||||
label="Crypto Address"
|
||||
placeholder="Enter the crypto address"
|
||||
type="text"
|
||||
inputmode="text"
|
||||
error-text="Please enter a valid crypto address."
|
||||
/>
|
||||
</template>
|
||||
|
||||
<ion-button expand="block" @click="onSubmit">
|
||||
Submit
|
||||
</ion-button>
|
||||
</div>
|
||||
</IonContent>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<style lang='css' scoped></style>
|
||||
0
src/views/withdraw/rules.ts
Normal file
0
src/views/withdraw/rules.ts
Normal file
@@ -3,6 +3,11 @@
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"paths": {
|
||||
"#build/ui": [
|
||||
"./node_modules/.nuxt-ui/ui"
|
||||
]
|
||||
},
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"include": ["vite.config.ts"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import path from "node:path";
|
||||
import ui from "@nuxt/ui/vite";
|
||||
import legacy from "@vitejs/plugin-legacy";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import jsx from "@vitejs/plugin-vue-jsx";
|
||||
@@ -22,7 +23,7 @@ export default defineConfig({
|
||||
jsx(),
|
||||
legacy(),
|
||||
autoImport({
|
||||
dirs: ["src/composables", "src/utils"],
|
||||
dirs: ["src/composables", "src/utils", "src/store"],
|
||||
imports: ["vue", "vue-router", "@vueuse/core", "vue-i18n"],
|
||||
resolvers: [IonicResolver()],
|
||||
vueTemplate: true,
|
||||
@@ -35,6 +36,7 @@ export default defineConfig({
|
||||
autoInstall: true,
|
||||
}),
|
||||
UnoCSS(),
|
||||
ui(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
||||
Reference in New Issue
Block a user