diff --git a/.env.production b/.env.production index 652f4c5..ca1bedc 100644 --- a/.env.production +++ b/.env.production @@ -1 +1 @@ -VITE_API_URL=http://192.168.1.22:9527 \ No newline at end of file +VITE_API_URL=http://192.168.1.27:9527 \ No newline at end of file diff --git a/components.d.ts b/components.d.ts index 031172c..4755a1e 100644 --- a/components.d.ts +++ b/components.d.ts @@ -20,11 +20,6 @@ declare module 'vue' { IonBackButton: typeof import('@ionic/vue')['IonBackButton'] IonButton: typeof import('@ionic/vue')['IonButton'] IonButtons: typeof import('@ionic/vue')['IonButtons'] - IonCard: typeof import('@ionic/vue')['IonCard'] - IonCardContent: typeof import('@ionic/vue')['IonCardContent'] - IonCardHeader: typeof import('@ionic/vue')['IonCardHeader'] - IonCardSubtitle: typeof import('@ionic/vue')['IonCardSubtitle'] - IonCardTitle: typeof import('@ionic/vue')['IonCardTitle'] IonCol: typeof import('@ionic/vue')['IonCol'] IonContent: typeof import('@ionic/vue')['IonContent'] IonDatetime: typeof import('@ionic/vue')['IonDatetime'] @@ -37,6 +32,7 @@ declare module 'vue' { IonInfiniteScrollContent: typeof import('@ionic/vue')['IonInfiniteScrollContent'] IonInput: typeof import('@ionic/vue')['IonInput'] IonInputOtp: typeof import('@ionic/vue')['IonInputOtp'] + IonInputPasswordToggle: typeof import('@ionic/vue')['IonInputPasswordToggle'] IonItem: typeof import('@ionic/vue')['IonItem'] IonLabel: typeof import('@ionic/vue')['IonLabel'] IonList: typeof import('@ionic/vue')['IonList'] @@ -87,11 +83,6 @@ declare global { const IonBackButton: typeof import('@ionic/vue')['IonBackButton'] const IonButton: typeof import('@ionic/vue')['IonButton'] const IonButtons: typeof import('@ionic/vue')['IonButtons'] - const IonCard: typeof import('@ionic/vue')['IonCard'] - const IonCardContent: typeof import('@ionic/vue')['IonCardContent'] - const IonCardHeader: typeof import('@ionic/vue')['IonCardHeader'] - const IonCardSubtitle: typeof import('@ionic/vue')['IonCardSubtitle'] - const IonCardTitle: typeof import('@ionic/vue')['IonCardTitle'] const IonCol: typeof import('@ionic/vue')['IonCol'] const IonContent: typeof import('@ionic/vue')['IonContent'] const IonDatetime: typeof import('@ionic/vue')['IonDatetime'] @@ -104,6 +95,7 @@ declare global { const IonInfiniteScrollContent: typeof import('@ionic/vue')['IonInfiniteScrollContent'] const IonInput: typeof import('@ionic/vue')['IonInput'] const IonInputOtp: typeof import('@ionic/vue')['IonInputOtp'] + const IonInputPasswordToggle: typeof import('@ionic/vue')['IonInputPasswordToggle'] const IonItem: typeof import('@ionic/vue')['IonItem'] const IonLabel: typeof import('@ionic/vue')['IonLabel'] const IonList: typeof import('@ionic/vue')['IonList'] diff --git a/package.json b/package.json index 164ee1f..83bb361 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@elysiajs/eden": "^1.4.5", "@ionic/vue": "^8.7.11", "@ionic/vue-router": "^8.7.11", - "@riwa/api-types": "http://192.168.1.27:9527/api/riwa-api-types-0.0.37.tgz", + "@riwa/api-types": "http://192.168.1.27:9527/api/riwa-api-types-0.0.39.tgz", "@tailwindcss/vite": "^4.1.18", "@vee-validate/yup": "^4.15.1", "@vueuse/core": "^14.1.0", @@ -50,6 +50,7 @@ "devDependencies": { "@antfu/eslint-config": "^6.6.1", "@capacitor/cli": "8.0.0", + "@iconify-json/circle-flags": "^1.2.10", "@iconify-json/cryptocurrency-color": "^1.2.4", "@iconify-json/ic": "^1.2.4", "@iconify-json/material-icon-theme": "^1.2.44", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bcf67be..8b10af1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ importers: specifier: ^8.7.11 version: 8.7.11(@stencil/core@4.39.0)(vue-router@4.6.3(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3)) '@riwa/api-types': - specifier: http://192.168.1.27:9527/api/riwa-api-types-0.0.37.tgz - version: http://192.168.1.27:9527/api/riwa-api-types-0.0.37.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3))) + specifier: http://192.168.1.27:9527/api/riwa-api-types-0.0.39.tgz + version: http://192.168.1.27:9527/api/riwa-api-types-0.0.39.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3))) '@tailwindcss/vite': specifier: ^4.1.18 version: 4.1.18(vite@7.2.7(@types/node@24.10.2)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) @@ -102,6 +102,9 @@ importers: '@capacitor/cli': specifier: 8.0.0 version: 8.0.0 + '@iconify-json/circle-flags': + specifier: ^1.2.10 + version: 1.2.10 '@iconify-json/cryptocurrency-color': specifier: ^1.2.4 version: 1.2.4 @@ -1145,6 +1148,9 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@iconify-json/circle-flags@1.2.10': + resolution: {integrity: sha512-sZRxs689a281RtZvuAiKtV7pQHv8Tk0HkinSM7QvLgdLEK8xgGRCcbDvL09Rq+/KtemmsMzGhS9/qt+r3ca+Ug==} + '@iconify-json/cryptocurrency-color@1.2.4': resolution: {integrity: sha512-8vjIfTAAMg0zo3/CdVWV7YjViY1L/q4TFfjROmqRPCRPhM6iVecW4TzMFS8hxm48S2Ge69SNM1yC8FmHT+jfHw==} @@ -1315,9 +1321,9 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.37.tgz': - resolution: {tarball: http://192.168.1.27:9527/api/riwa-api-types-0.0.37.tgz} - version: 0.0.37 + '@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.39.tgz': + resolution: {tarball: http://192.168.1.27:9527/api/riwa-api-types-0.0.39.tgz} + version: 0.0.39 peerDependencies: '@elysiajs/eden': ^1.4.5 @@ -6086,6 +6092,10 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@iconify-json/circle-flags@1.2.10': + dependencies: + '@iconify/types': 2.0.0 + '@iconify-json/cryptocurrency-color@1.2.4': dependencies: '@iconify/types': 2.0.0 @@ -6390,7 +6400,7 @@ snapshots: '@pkgr/core@0.2.9': {} - '@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.37.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))': + '@riwa/api-types@http://192.168.1.27:9527/api/riwa-api-types-0.0.39.tgz(@elysiajs/eden@1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)))': dependencies: '@elysiajs/eden': 1.4.5(elysia@1.4.18(@sinclair/typebox@0.34.41)(exact-mirror@0.2.5(@sinclair/typebox@0.34.41))(file-type@21.1.1)(openapi-types@12.1.3)(typescript@5.9.3)) diff --git a/src/api/types.ts b/src/api/types.ts index 3f0ad6f..63dd7d3 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1,6 +1,7 @@ import type { Treaty } from "@elysiajs/eden"; import type { client } from "."; import type { AssetCodeEnum, PaymentChannelEnum, WithdrawMethodEnum } from "./enum"; +import type { authClient } from "@/auth"; export type DepositFiatBody = Parameters[0] & { paymentChannel: PaymentChannelEnum; @@ -51,3 +52,9 @@ export type RwaData = Treaty.Data; export type MySubscribeRwaBody = TreatyQuery; + +export type PhoneNumberVerifyClient = TreatyBody; + +export type UsernameClient = TreatyBody; + +export type EmailVerifyClient = TreatyBody; diff --git a/src/auth/components/login/email/step1.vue b/src/auth/components/login/email/step1.vue deleted file mode 100644 index 7c3dd65..0000000 --- a/src/auth/components/login/email/step1.vue +++ /dev/null @@ -1,89 +0,0 @@ - - - - - diff --git a/src/auth/components/login/email/step2.vue b/src/auth/components/login/email/step2.vue deleted file mode 100644 index 67ffe8a..0000000 --- a/src/auth/components/login/email/step2.vue +++ /dev/null @@ -1,45 +0,0 @@ - - - - - diff --git a/src/auth/components/login/index.vue b/src/auth/components/login/index.vue deleted file mode 100644 index b26f0f0..0000000 --- a/src/auth/components/login/index.vue +++ /dev/null @@ -1,55 +0,0 @@ - - - - - diff --git a/src/auth/components/signup/email/step1.vue b/src/auth/components/signup/email/step1.vue deleted file mode 100644 index 805f4bc..0000000 --- a/src/auth/components/signup/email/step1.vue +++ /dev/null @@ -1,93 +0,0 @@ - - - - - diff --git a/src/auth/components/signup/email/step2.vue b/src/auth/components/signup/email/step2.vue deleted file mode 100644 index d1782f4..0000000 --- a/src/auth/components/signup/email/step2.vue +++ /dev/null @@ -1,49 +0,0 @@ - - - - - diff --git a/src/auth/components/signup/index.vue b/src/auth/components/signup/index.vue deleted file mode 100644 index 5abeb0d..0000000 --- a/src/auth/components/signup/index.vue +++ /dev/null @@ -1,27 +0,0 @@ - - - diff --git a/src/auth/components/signup/verification-code.vue b/src/auth/components/signup/verification-code.vue deleted file mode 100644 index 49c8ba9..0000000 --- a/src/auth/components/signup/verification-code.vue +++ /dev/null @@ -1,63 +0,0 @@ - - - - - diff --git a/src/auth/index.ts b/src/auth/index.ts index aad235a..d2aadf9 100644 --- a/src/auth/index.ts +++ b/src/auth/index.ts @@ -1,34 +1,53 @@ -import { modalController } from "@ionic/vue"; -import { emailOTPClient } from "better-auth/client/plugins"; +import type { PhoneCountry } from "./type"; +import { emailOTPClient, phoneNumberClient, usernameClient } from "better-auth/client/plugins"; import { createAuthClient } from "better-auth/vue"; +import CircleFlagsCnHk from "~icons/circle-flags/cn-hk"; +import CircleFlagsEnUs from "~icons/circle-flags/en-us"; +import CircleFlagsTw from "~icons/circle-flags/tw"; +import CircleFlagsZh from "~icons/circle-flags/zh"; export const authClient = createAuthClient({ fetchOptions: { credentials: "include", }, - plugins: [emailOTPClient()], + plugins: [emailOTPClient(), phoneNumberClient(), usernameClient()], }); -export async function modelControllerSignup(presentingElement?: HTMLElement) { - const SignupContent = await import("./components/signup/index.vue"); - - const modal = await modalController.create({ - component: SignupContent.default, - presentingElement, - canDismiss: async (data, role) => role !== "gesture", - }); - - return modal; -} - -export async function modelControllerLogin(presentingElement?: HTMLElement) { - const LoginContent = await import("./components/login/index.vue"); - - const modal = await modalController.create({ - component: LoginContent.default, - presentingElement, - canDismiss: async (data, role) => role !== "gesture", - }); - - return modal; -} +export const countries: PhoneCountry[] = [ + { + code: "CN", + dialCode: "+86", + name: "中国大陆", + pattern: /^1[3-9]\d{9}$/, + maxLength: 11, + placeholder: "13800138000", + icon: CircleFlagsZh, + }, + { + code: "HK", + dialCode: "+852", + name: "中国香港", + pattern: /^[5-9]\d{7}$/, + maxLength: 8, + placeholder: "51234567", + icon: CircleFlagsCnHk, + }, + { + code: "TW", + dialCode: "+886", + name: "中国台湾", + pattern: /^9\d{8}$/, + maxLength: 9, + placeholder: "912345678", + icon: CircleFlagsTw, + }, + { + code: "US", + dialCode: "+1", + name: "美国", + pattern: /^\d{10}$/, + maxLength: 10, + placeholder: "2025550123", + icon: CircleFlagsEnUs, + }, +]; diff --git a/src/auth/type.ts b/src/auth/type.ts index 8bd3131..903bb8b 100644 --- a/src/auth/type.ts +++ b/src/auth/type.ts @@ -1,3 +1,5 @@ +import type { FunctionalComponent, SVGAttributes } from "vue"; + export interface AuthUserSignup { name: string; email: string; @@ -5,3 +7,13 @@ export interface AuthUserSignup { confirmPassword: string; verificationCode: string; } + +export interface PhoneCountry { + code: string; + dialCode: string; + name: string; + pattern: RegExp; + maxLength: number; + placeholder: string; + icon: FunctionalComponent; +} diff --git a/src/components/ui/input/index.vue b/src/components/ui/input/index.vue index ceff0c7..6083086 100644 --- a/src/components/ui/input/index.vue +++ b/src/components/ui/input/index.vue @@ -13,7 +13,7 @@ defineExpose({} as ComponentInstance); diff --git a/src/views/auth/login/components/email.vue b/src/views/auth/login/components/email.vue new file mode 100644 index 0000000..65d1255 --- /dev/null +++ b/src/views/auth/login/components/email.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/src/views/auth/login/components/phone-number.vue b/src/views/auth/login/components/phone-number.vue new file mode 100644 index 0000000..1330e60 --- /dev/null +++ b/src/views/auth/login/components/phone-number.vue @@ -0,0 +1,210 @@ + + + + + diff --git a/src/views/auth/login/index.vue b/src/views/auth/login/index.vue new file mode 100644 index 0000000..196d36e --- /dev/null +++ b/src/views/auth/login/index.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/views/market/components/category.vue b/src/views/market/components/category.vue index ca1a512..d6cc15e 100644 --- a/src/views/market/components/category.vue +++ b/src/views/market/components/category.vue @@ -4,7 +4,7 @@ import { client, safeClient } from "@/api"; const { t } = useI18n(); const model = defineModel({ type: String, default: "" }); -const { data: categories } = await safeClient(() => client.api.rwa.issuance.categories.get()); +const { data: categories } = await safeClient(() => client.api.rwa.category.categories.get());