pukaad-ui-lib 1.239.0 → 1.241.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/dist/runtime/components/input/input-autocomplete.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-autocomplete.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-file.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-file.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-password.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-password.vue +6 -3
- package/dist/runtime/components/input/input-password.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-tag.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-tag.vue.d.ts +1 -1
- package/dist/runtime/components/modal/modal-2FA-generate.vue +11 -25
- package/dist/runtime/components/modal/modal-email-OTP.d.vue.ts +12 -2
- package/dist/runtime/components/modal/modal-email-OTP.vue +23 -18
- package/dist/runtime/components/modal/modal-email-OTP.vue.d.ts +12 -2
- package/dist/runtime/components/modal/modal-forgot-password.d.vue.ts +13 -0
- package/dist/runtime/components/modal/modal-forgot-password.vue +146 -0
- package/dist/runtime/components/modal/modal-forgot-password.vue.d.ts +13 -0
- package/dist/runtime/components/modal/modal-password-confirmed.d.vue.ts +1 -1
- package/dist/runtime/components/modal/modal-password-confirmed.vue.d.ts +1 -1
- package/dist/runtime/components/modal/modal-password-new.d.vue.ts +4 -2
- package/dist/runtime/components/modal/modal-password-new.vue +40 -14
- package/dist/runtime/components/modal/modal-password-new.vue.d.ts +4 -2
- package/dist/runtime/components/modal/modal-password-verify.d.vue.ts +1 -1
- package/dist/runtime/components/modal/modal-password-verify.vue +3 -3
- package/dist/runtime/components/modal/modal-password-verify.vue.d.ts +1 -1
- package/dist/runtime/components/modal/modal-phone-OTP.d.vue.ts +1 -1
- package/dist/runtime/components/modal/modal-phone-OTP.vue.d.ts +1 -1
- package/dist/runtime/components/modal/modal-secure.vue +11 -18
- package/dist/runtime/components/modal/modal-user-account-search.d.vue.ts +13 -3
- package/dist/runtime/components/modal/modal-user-account-search.vue +130 -18
- package/dist/runtime/components/modal/modal-user-account-search.vue.d.ts +13 -3
- package/package.json +1 -1
- package/dist/runtime/components/dialog/dialog-2FA-generate.d.vue.ts +0 -18
- package/dist/runtime/components/dialog/dialog-2FA-generate.vue +0 -113
- package/dist/runtime/components/dialog/dialog-2FA-generate.vue.d.ts +0 -18
- package/dist/runtime/components/dialog/dialog-2FA.d.vue.ts +0 -18
- package/dist/runtime/components/dialog/dialog-2FA.vue +0 -65
- package/dist/runtime/components/dialog/dialog-2FA.vue.d.ts +0 -18
- package/dist/runtime/components/dialog/dialog-email-OTP.d.vue.ts +0 -20
- package/dist/runtime/components/dialog/dialog-email-OTP.vue +0 -120
- package/dist/runtime/components/dialog/dialog-email-OTP.vue.d.ts +0 -20
- package/dist/runtime/components/dialog/dialog-phone-OTP.d.vue.ts +0 -22
- package/dist/runtime/components/dialog/dialog-phone-OTP.vue +0 -62
- package/dist/runtime/components/dialog/dialog-phone-OTP.vue.d.ts +0 -22
- package/dist/runtime/components/modal/modal-user-account-list.d.vue.ts +0 -18
- package/dist/runtime/components/modal/modal-user-account-list.vue +0 -51
- package/dist/runtime/components/modal/modal-user-account-list.vue.d.ts +0 -18
|
@@ -28,8 +28,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
28
28
|
}>, {
|
|
29
29
|
title: string;
|
|
30
30
|
mode: "login" | "secure";
|
|
31
|
-
disabledForgotPassword: boolean;
|
|
32
31
|
confirmText: string;
|
|
32
|
+
disabledForgotPassword: boolean;
|
|
33
33
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
34
34
|
declare const _default: typeof __VLS_export;
|
|
35
35
|
export default _default;
|
|
@@ -50,7 +50,7 @@ const handleSubmit = async () => {
|
|
|
50
50
|
method: "POST",
|
|
51
51
|
body: { password: password.value }
|
|
52
52
|
});
|
|
53
|
-
if (res.title !== "\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08") throw "\u0E23\u0E2B\u0E31\u0E2A\u0E1C\u0E48\u0E32\u0E19\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07";
|
|
53
|
+
if (res.message?.title !== "\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08") throw "\u0E23\u0E2B\u0E31\u0E2A\u0E1C\u0E48\u0E32\u0E19\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07";
|
|
54
54
|
emit("complete", { secId: "" });
|
|
55
55
|
isOpen.value = false;
|
|
56
56
|
} else {
|
|
@@ -70,11 +70,11 @@ const handleSubmit = async () => {
|
|
|
70
70
|
emit("complete", { secId: res.data?.sec_id || "" });
|
|
71
71
|
isOpen.value = false;
|
|
72
72
|
} else {
|
|
73
|
-
inputRef.value?.setErrors?.(res.message
|
|
73
|
+
inputRef.value?.setErrors?.(res.message.description);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
} catch (e) {
|
|
77
|
-
inputRef.value?.setErrors?.(e?.data?.message
|
|
77
|
+
inputRef.value?.setErrors?.(e?.data?.message.description);
|
|
78
78
|
} finally {
|
|
79
79
|
loading.value = false;
|
|
80
80
|
}
|
|
@@ -28,8 +28,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
28
28
|
}>, {
|
|
29
29
|
title: string;
|
|
30
30
|
mode: "login" | "secure";
|
|
31
|
-
disabledForgotPassword: boolean;
|
|
32
31
|
confirmText: string;
|
|
32
|
+
disabledForgotPassword: boolean;
|
|
33
33
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
34
34
|
declare const _default: typeof __VLS_export;
|
|
35
35
|
export default _default;
|
|
@@ -14,8 +14,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
14
14
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
15
15
|
onComplete?: ((value: string) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
-
confirmedText: string;
|
|
18
17
|
phone: string;
|
|
18
|
+
confirmedText: string;
|
|
19
19
|
phoneLabel: string;
|
|
20
20
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
21
|
declare const _default: typeof __VLS_export;
|
|
@@ -14,8 +14,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
14
14
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
15
15
|
onComplete?: ((value: string) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
-
confirmedText: string;
|
|
18
17
|
phone: string;
|
|
18
|
+
confirmedText: string;
|
|
19
19
|
phoneLabel: string;
|
|
20
20
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
21
21
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<component
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
:is="modal.component"
|
|
6
|
-
:email="props.email"
|
|
7
|
-
mode="secure"
|
|
8
|
-
@complete="(data) => handleComplete(modal.key, data)"
|
|
9
|
-
:confirmed-text="isLastStep ? '\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19' : '\u0E16\u0E31\u0E14\u0E44\u0E1B'"
|
|
10
|
-
@close="isOpen = false"
|
|
11
|
-
v-model="modalStates[modal.key]"
|
|
12
|
-
/>
|
|
2
|
+
<component v-for="modal in modals" :key="modal.key" :is="modal.component" :email="props.email" mode="secure"
|
|
3
|
+
@complete="(data) => handleComplete(modal.key, data)" :confirmed-text="isLastStep ? '\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19' : '\u0E16\u0E31\u0E14\u0E44\u0E1B'"
|
|
4
|
+
@close="isOpen = false" v-model="modalStates[modal.key]" />
|
|
13
5
|
</template>
|
|
14
6
|
|
|
15
7
|
<script setup>
|
|
@@ -126,30 +118,31 @@ const handleComplete = (key, data) => {
|
|
|
126
118
|
};
|
|
127
119
|
const onEnabled2FA = async (token) => {
|
|
128
120
|
try {
|
|
129
|
-
const {
|
|
121
|
+
const { message } = await api("/me/two-fa-enabled", {
|
|
130
122
|
method: "POST",
|
|
131
123
|
body: { token }
|
|
132
124
|
});
|
|
133
|
-
if (
|
|
125
|
+
if (message?.title !== "\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08") throw "2FA \u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07";
|
|
134
126
|
$toast.success("\u0E40\u0E1B\u0E34\u0E14\u0E01\u0E32\u0E23\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19\u0E15\u0E31\u0E27\u0E15\u0E19\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08 !");
|
|
135
127
|
isOpen.value = false;
|
|
136
128
|
emit("complete", "enabled-2fa");
|
|
137
129
|
} catch (error) {
|
|
138
|
-
|
|
139
|
-
|
|
130
|
+
const errorMsg = error?.data?.message?.description || "\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14\u0E40\u0E1B\u0E34\u0E14\u0E01\u0E32\u0E23\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19\u0E15\u0E31\u0E27\u0E15\u0E19\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08 !";
|
|
131
|
+
$toast.error(errorMsg);
|
|
140
132
|
}
|
|
141
133
|
};
|
|
142
134
|
const onDisabled2FA = async () => {
|
|
143
135
|
try {
|
|
144
|
-
const {
|
|
136
|
+
const { message } = await api("/me/two-fa-disabled", {
|
|
145
137
|
method: "POST"
|
|
146
138
|
});
|
|
147
|
-
if (
|
|
139
|
+
if (message?.title !== "\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08") throw "2FA \u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07";
|
|
148
140
|
$toast.success("\u0E1B\u0E34\u0E14\u0E01\u0E32\u0E23\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19\u0E15\u0E31\u0E27\u0E15\u0E19\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08 !");
|
|
149
141
|
isOpen.value = false;
|
|
150
142
|
emit("complete", "disabled-2fa");
|
|
151
143
|
} catch (error) {
|
|
152
|
-
|
|
144
|
+
const errorMsg = error?.data?.message?.description || "\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14\u0E1B\u0E34\u0E14\u0E01\u0E32\u0E23\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19\u0E15\u0E31\u0E27\u0E15\u0E19\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08 !";
|
|
145
|
+
$toast.error(errorMsg);
|
|
153
146
|
console.error("Error:", error);
|
|
154
147
|
}
|
|
155
148
|
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export interface ModalUserAccountSearchResult {
|
|
2
|
+
phone: string;
|
|
3
|
+
method: "sms" | "email";
|
|
4
|
+
maskedPhone: string;
|
|
5
|
+
maskedEmail: string | null;
|
|
6
|
+
hasEmail: boolean;
|
|
7
|
+
}
|
|
1
8
|
type __VLS_Props = {
|
|
2
9
|
confirmedText?: string;
|
|
3
10
|
};
|
|
@@ -6,11 +13,14 @@ type __VLS_ModelProps = {
|
|
|
6
13
|
};
|
|
7
14
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
8
15
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
"update:modelValue": (value: boolean) => any;
|
|
17
|
+
} & {
|
|
18
|
+
close: () => any;
|
|
19
|
+
complete: (data: ModalUserAccountSearchResult) => any;
|
|
11
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
21
|
+
onClose?: (() => any) | undefined;
|
|
12
22
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
13
|
-
onComplete?: ((
|
|
23
|
+
onComplete?: ((data: ModalUserAccountSearchResult) => any) | undefined;
|
|
14
24
|
}>, {
|
|
15
25
|
confirmedText: string;
|
|
16
26
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -1,44 +1,156 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Modal
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
<Modal
|
|
3
|
+
:title="step === 'search' ? '\u0E04\u0E49\u0E19\u0E2B\u0E32\u0E1A\u0E31\u0E0D\u0E0A\u0E35\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13' : '\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E27\u0E34\u0E18\u0E35\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A'"
|
|
4
|
+
v-model="modelValue"
|
|
5
|
+
width="425px"
|
|
6
|
+
:loading="isLoading"
|
|
7
|
+
>
|
|
8
|
+
<!-- Step 1: phone + recaptcha -->
|
|
9
|
+
<div v-if="step === 'search'" class="flex flex-col gap-[24px]">
|
|
10
|
+
<p class="font-body-large">
|
|
5
11
|
ป้อนเบอร์โทรศัพท์ที่เชื่อมโยงกับบัญชีของคุณ เพื่อเปลี่ยนรหัสผ่าน
|
|
6
|
-
</
|
|
12
|
+
</p>
|
|
7
13
|
<InputPhone
|
|
8
14
|
label="เบอร์โทรศัพท์"
|
|
9
15
|
placeholder="กรอกเบอร์โทรศัพท์"
|
|
10
16
|
v-model="phone"
|
|
11
|
-
full-width
|
|
12
17
|
/>
|
|
13
18
|
<InputRecaptcha ref="recaptchaRef" name="recaptcha" v-model="recaptcha" />
|
|
14
19
|
</div>
|
|
20
|
+
|
|
21
|
+
<!-- Step 2: select OTP method -->
|
|
22
|
+
<div v-else-if="step === 'list'" class="flex flex-col">
|
|
23
|
+
<template v-for="(item, index) in accountItems" :key="index">
|
|
24
|
+
<div class="py-[12px] px-[16px]">
|
|
25
|
+
<InputRadio
|
|
26
|
+
:item="item.value"
|
|
27
|
+
label-position="left"
|
|
28
|
+
v-model="selectedMethod"
|
|
29
|
+
>
|
|
30
|
+
<template v-slot:[`label-${item.value}-text`]>
|
|
31
|
+
<div
|
|
32
|
+
class="flex flex-col w-full text-gray font-body-medium-prominent"
|
|
33
|
+
>
|
|
34
|
+
<div v-if="item.type === 'email'">ส่งรหัสไปทางอีเมล</div>
|
|
35
|
+
<div v-else-if="item.type === 'phone'">ส่งรหัสไปทาง SMS</div>
|
|
36
|
+
<div>{{ item.label }}</div>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
39
|
+
</InputRadio>
|
|
40
|
+
</div>
|
|
41
|
+
<Divider v-if="index !== accountItems.length - 1" />
|
|
42
|
+
</template>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<!-- Footer slot (must be direct child of Modal) -->
|
|
15
46
|
<template #footer>
|
|
16
47
|
<Button
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
48
|
+
v-if="step === 'search'"
|
|
49
|
+
class="w-full"
|
|
50
|
+
color="primary"
|
|
51
|
+
:disabled="!phone || !recaptcha || isLoading"
|
|
52
|
+
@click="onSearchNext"
|
|
21
53
|
>
|
|
22
|
-
|
|
54
|
+
ถัดไป
|
|
23
55
|
</Button>
|
|
56
|
+
<div v-else-if="step === 'list'" class="flex flex-col gap-[8px] w-full">
|
|
57
|
+
<Button
|
|
58
|
+
class="w-full"
|
|
59
|
+
color="primary"
|
|
60
|
+
:disabled="!selectedMethod"
|
|
61
|
+
@click="onListConfirm"
|
|
62
|
+
>
|
|
63
|
+
{{ props.confirmedText }}
|
|
64
|
+
</Button>
|
|
65
|
+
<Button variant="text" color="primary" class="w-full" @click="goBack"
|
|
66
|
+
>ไม่ใช่คุณใช่ไหม?</Button
|
|
67
|
+
>
|
|
68
|
+
</div>
|
|
24
69
|
</template>
|
|
25
70
|
</Modal>
|
|
26
71
|
</template>
|
|
27
72
|
|
|
28
73
|
<script setup>
|
|
29
|
-
import { ref } from "vue";
|
|
30
|
-
|
|
74
|
+
import { ref, computed, watch } from "vue";
|
|
75
|
+
import { useNuxtApp } from "nuxt/app";
|
|
76
|
+
import { useApi } from "../../composables/useApi";
|
|
77
|
+
import Button from "../button.vue";
|
|
78
|
+
const { $toast } = useNuxtApp();
|
|
79
|
+
const api = useApi();
|
|
80
|
+
const emit = defineEmits(["complete", "close"]);
|
|
31
81
|
const props = defineProps({
|
|
32
82
|
confirmedText: { type: String, required: false, default: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19" }
|
|
33
83
|
});
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
} });
|
|
84
|
+
const modelValue = defineModel({ type: Boolean, ...{ default: false } });
|
|
85
|
+
const step = ref("search");
|
|
86
|
+
const isLoading = ref(false);
|
|
38
87
|
const phone = ref("");
|
|
39
88
|
const recaptcha = ref("");
|
|
40
|
-
const
|
|
41
|
-
|
|
89
|
+
const recaptchaRef = ref(null);
|
|
90
|
+
const maskedPhone = ref("");
|
|
91
|
+
const maskedEmail = ref(null);
|
|
92
|
+
const hasEmail = ref(false);
|
|
93
|
+
const selectedMethod = ref(null);
|
|
94
|
+
const accountItems = computed(() => {
|
|
95
|
+
const items = [
|
|
96
|
+
{ type: "phone", value: "sms", label: maskedPhone.value }
|
|
97
|
+
];
|
|
98
|
+
if (hasEmail.value && maskedEmail.value) {
|
|
99
|
+
items.push({ type: "email", value: "email", label: maskedEmail.value });
|
|
100
|
+
}
|
|
101
|
+
return items;
|
|
102
|
+
});
|
|
103
|
+
const onSearchNext = async () => {
|
|
104
|
+
isLoading.value = true;
|
|
105
|
+
try {
|
|
106
|
+
const res = await api("/auth/forgot-password/find-account", {
|
|
107
|
+
method: "POST",
|
|
108
|
+
body: { phone: phone.value, token: recaptcha.value }
|
|
109
|
+
});
|
|
110
|
+
maskedPhone.value = res.data.masked_phone;
|
|
111
|
+
maskedEmail.value = res.data.masked_email;
|
|
112
|
+
hasEmail.value = res.data.has_email;
|
|
113
|
+
selectedMethod.value = null;
|
|
114
|
+
step.value = "list";
|
|
115
|
+
} catch (e) {
|
|
116
|
+
const msg = e?.data?.message?.description || e?.data?.message || "\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E1A\u0E31\u0E0D\u0E0A\u0E35\u0E17\u0E35\u0E48\u0E43\u0E0A\u0E49\u0E40\u0E1A\u0E2D\u0E23\u0E4C\u0E42\u0E17\u0E23\u0E19\u0E35\u0E49";
|
|
117
|
+
$toast?.error?.(msg);
|
|
118
|
+
} finally {
|
|
119
|
+
isLoading.value = false;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const onListConfirm = () => {
|
|
123
|
+
if (!selectedMethod.value) return;
|
|
124
|
+
emitComplete();
|
|
125
|
+
};
|
|
126
|
+
const emitComplete = () => {
|
|
127
|
+
emit("complete", {
|
|
128
|
+
phone: phone.value,
|
|
129
|
+
method: selectedMethod.value ?? "sms",
|
|
130
|
+
maskedPhone: maskedPhone.value,
|
|
131
|
+
maskedEmail: maskedEmail.value,
|
|
132
|
+
hasEmail: hasEmail.value
|
|
133
|
+
});
|
|
42
134
|
modelValue.value = false;
|
|
43
135
|
};
|
|
136
|
+
const goBack = () => {
|
|
137
|
+
step.value = "search";
|
|
138
|
+
phone.value = "";
|
|
139
|
+
recaptcha.value = "";
|
|
140
|
+
selectedMethod.value = null;
|
|
141
|
+
maskedPhone.value = "";
|
|
142
|
+
maskedEmail.value = null;
|
|
143
|
+
hasEmail.value = false;
|
|
144
|
+
};
|
|
145
|
+
watch(modelValue, (v) => {
|
|
146
|
+
if (!v) {
|
|
147
|
+
step.value = "search";
|
|
148
|
+
phone.value = "";
|
|
149
|
+
recaptcha.value = "";
|
|
150
|
+
selectedMethod.value = null;
|
|
151
|
+
maskedPhone.value = "";
|
|
152
|
+
maskedEmail.value = null;
|
|
153
|
+
hasEmail.value = false;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
44
156
|
</script>
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export interface ModalUserAccountSearchResult {
|
|
2
|
+
phone: string;
|
|
3
|
+
method: "sms" | "email";
|
|
4
|
+
maskedPhone: string;
|
|
5
|
+
maskedEmail: string | null;
|
|
6
|
+
hasEmail: boolean;
|
|
7
|
+
}
|
|
1
8
|
type __VLS_Props = {
|
|
2
9
|
confirmedText?: string;
|
|
3
10
|
};
|
|
@@ -6,11 +13,14 @@ type __VLS_ModelProps = {
|
|
|
6
13
|
};
|
|
7
14
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
8
15
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
"update:modelValue": (value: boolean) => any;
|
|
17
|
+
} & {
|
|
18
|
+
close: () => any;
|
|
19
|
+
complete: (data: ModalUserAccountSearchResult) => any;
|
|
11
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
21
|
+
onClose?: (() => any) | undefined;
|
|
12
22
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
13
|
-
onComplete?: ((
|
|
23
|
+
onComplete?: ((data: ModalUserAccountSearchResult) => any) | undefined;
|
|
14
24
|
}>, {
|
|
15
25
|
confirmedText: string;
|
|
16
26
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
package/package.json
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Modal2FAGenerateProps } from "@/types/components/modal/modal-2FA-generate";
|
|
2
|
-
type __VLS_Props = Modal2FAGenerateProps;
|
|
3
|
-
type __VLS_ModelProps = {
|
|
4
|
-
modelValue?: boolean;
|
|
5
|
-
};
|
|
6
|
-
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
7
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
-
"update:modelValue": (value: boolean) => any;
|
|
9
|
-
} & {
|
|
10
|
-
complete: () => any;
|
|
11
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
|
-
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
13
|
-
onComplete?: (() => any) | undefined;
|
|
14
|
-
}>, {
|
|
15
|
-
confirmedText: string;
|
|
16
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
-
declare const _default: typeof __VLS_export;
|
|
18
|
-
export default _default;
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<ShadDialog v-model:open="isOpen">
|
|
3
|
-
<ShadDialogContent class="w-[540px]">
|
|
4
|
-
<ShadDialogHeader class="flex justify-center">
|
|
5
|
-
<ShadDialogTitle class="text-center">คำแนะนำการตั้งค่า</ShadDialogTitle>
|
|
6
|
-
</ShadDialogHeader>
|
|
7
|
-
<div class="flex flex-col gap-[16px]">
|
|
8
|
-
<div class="flex flex-col gap-[8px] text-gray font-body-large">
|
|
9
|
-
<div class="font-body-large-prominent text-black">
|
|
10
|
-
1.ดาวน์โหลดแอพยืนยันตัวตน
|
|
11
|
-
</div>
|
|
12
|
-
<div>
|
|
13
|
-
เราแนะนำให้ดาวน์โหลด Google Authenticator หากคุณยังไม่ได้ติดตั้ง
|
|
14
|
-
</div>
|
|
15
|
-
</div>
|
|
16
|
-
<div class="flex flex-col gap-[8px] text-gray font-body-large">
|
|
17
|
-
<div class="font-body-large-prominent text-black">
|
|
18
|
-
2.สแกนบาร์โค้ด/คิวอาร์โค้ดนี้หรือคัดลอกคีย์
|
|
19
|
-
</div>
|
|
20
|
-
<div>
|
|
21
|
-
สแกนบาร์โค้ด/คิวอาร์โค้ดนี้ในแอพยืนยันตัวตนหรือคัดลอกคีย์แล้ววางลงในแอพ
|
|
22
|
-
ยืนยันตัวตน
|
|
23
|
-
</div>
|
|
24
|
-
</div>
|
|
25
|
-
<div class="flex justify-center items-center">
|
|
26
|
-
<div class="flex items-center gap-[32px]">
|
|
27
|
-
<Image width="146" height="145" :src="barcode2FA" />
|
|
28
|
-
<div class="w-[168px] gap-[8px] flex flex-col justify-between">
|
|
29
|
-
<div class="font-body-large-prominent">
|
|
30
|
-
{{ key }}
|
|
31
|
-
</div>
|
|
32
|
-
<div
|
|
33
|
-
class="cursor-pointer text-primary font-body-large"
|
|
34
|
-
@click="copyToClipboard(key)"
|
|
35
|
-
>
|
|
36
|
-
คัดลอกคีย์
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
<div class="flex flex-col gap-[8px] text-gray font-body-large">
|
|
42
|
-
<div class="font-body-large-prominent text-black">
|
|
43
|
-
3.คัดลอกแล้วป้อนรหัสตัวเลข 6 หลัก
|
|
44
|
-
</div>
|
|
45
|
-
<div>
|
|
46
|
-
หลังจากสแกนบาร์โค้ด/คิวอาร์โค้ด หรือคัดลอกคีย์แล้ว
|
|
47
|
-
แอพยืนยันตัวตนจะสร้าง รหัสตัวเลข 6 หลัก
|
|
48
|
-
ให้คัดลอกรหัสนั้นแล้วกลับมาป้อนบน Pukaad
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<ShadDialogFooter>
|
|
54
|
-
<Button class="w-full" @click="onComplete">
|
|
55
|
-
{{ props.confirmedText }}
|
|
56
|
-
</Button>
|
|
57
|
-
</ShadDialogFooter>
|
|
58
|
-
</ShadDialogContent>
|
|
59
|
-
</ShadDialog>
|
|
60
|
-
</template>
|
|
61
|
-
|
|
62
|
-
<script setup>
|
|
63
|
-
import { ref, watch } from "vue";
|
|
64
|
-
import { useClipboard } from "@/runtime/composables/useCopy";
|
|
65
|
-
import { useRuntimeConfig } from "nuxt/app";
|
|
66
|
-
const { BASE_URL_API } = useRuntimeConfig().public;
|
|
67
|
-
const { copyToClipboard } = useClipboard();
|
|
68
|
-
const emit = defineEmits(["complete"]);
|
|
69
|
-
const props = defineProps({
|
|
70
|
-
confirmedText: { type: String, required: false, default: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19" },
|
|
71
|
-
title: { type: String, required: false },
|
|
72
|
-
description: { type: String, required: false },
|
|
73
|
-
footer: { type: String, required: false }
|
|
74
|
-
});
|
|
75
|
-
const isOpen = defineModel({ type: Boolean, ...{
|
|
76
|
-
default: false
|
|
77
|
-
} });
|
|
78
|
-
const key = ref("");
|
|
79
|
-
const barcode2FA = ref("");
|
|
80
|
-
const isLoading = ref(false);
|
|
81
|
-
const isDisabled = ref(true);
|
|
82
|
-
const twoFaGenerate = async () => {
|
|
83
|
-
try {
|
|
84
|
-
isLoading.value = true;
|
|
85
|
-
const { status, data } = await $fetch(`${BASE_URL_API}/me/two-fa-generate`, {
|
|
86
|
-
credentials: "include"
|
|
87
|
-
});
|
|
88
|
-
if (status !== "success") throw "Generate \u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08";
|
|
89
|
-
key.value = data.key;
|
|
90
|
-
barcode2FA.value = data.qr_code;
|
|
91
|
-
isDisabled.value = false;
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error("error:", error);
|
|
94
|
-
} finally {
|
|
95
|
-
isLoading.value = false;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const onComplete = () => {
|
|
99
|
-
emit("complete");
|
|
100
|
-
isOpen.value = false;
|
|
101
|
-
};
|
|
102
|
-
watch(
|
|
103
|
-
isOpen,
|
|
104
|
-
(v) => {
|
|
105
|
-
if (v) {
|
|
106
|
-
twoFaGenerate();
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
immediate: true
|
|
111
|
-
}
|
|
112
|
-
);
|
|
113
|
-
</script>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Modal2FAGenerateProps } from "@/types/components/modal/modal-2FA-generate";
|
|
2
|
-
type __VLS_Props = Modal2FAGenerateProps;
|
|
3
|
-
type __VLS_ModelProps = {
|
|
4
|
-
modelValue?: boolean;
|
|
5
|
-
};
|
|
6
|
-
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
7
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
-
"update:modelValue": (value: boolean) => any;
|
|
9
|
-
} & {
|
|
10
|
-
complete: () => any;
|
|
11
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
|
-
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
13
|
-
onComplete?: (() => any) | undefined;
|
|
14
|
-
}>, {
|
|
15
|
-
confirmedText: string;
|
|
16
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
-
declare const _default: typeof __VLS_export;
|
|
18
|
-
export default _default;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Modal2FAProps } from "@/types/components/modal/modal-2FA";
|
|
2
|
-
type __VLS_Props = Modal2FAProps;
|
|
3
|
-
type __VLS_ModelProps = {
|
|
4
|
-
modelValue?: boolean;
|
|
5
|
-
};
|
|
6
|
-
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
7
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
-
"update:modelValue": (value: boolean) => any;
|
|
9
|
-
} & {
|
|
10
|
-
complete: (verify: boolean) => any;
|
|
11
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
|
-
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
13
|
-
onComplete?: ((verify: boolean) => any) | undefined;
|
|
14
|
-
}>, {
|
|
15
|
-
confirmedText: string;
|
|
16
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
-
declare const _default: typeof __VLS_export;
|
|
18
|
-
export default _default;
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Dialog v-model:open="isOpen">
|
|
3
|
-
<DialogContent class="w-[425px]">
|
|
4
|
-
<Form v-slot="{ meta }" @submit="onVerify2FA">
|
|
5
|
-
<div class="flex flex-col gap-[24px]">
|
|
6
|
-
<DialogHeader class="flex justify-center">
|
|
7
|
-
<ShadDialogTitle>การยืนยันตัวตนแบบสองชั้น</ShadDialogTitle>
|
|
8
|
-
<DialogDescription>
|
|
9
|
-
ป้อนรหัสยืนยันที่คุณเห็นในแอปยืนยันตัวตน
|
|
10
|
-
</DialogDescription>
|
|
11
|
-
</DialogHeader>
|
|
12
|
-
<InputOTP ref="twoFaRef" v-model="valueOTP" />
|
|
13
|
-
<DialogFooter>
|
|
14
|
-
<Button class="w-full" type="submit" :disabled="!meta.valid">
|
|
15
|
-
{{ props.confirmedText }}
|
|
16
|
-
</Button>
|
|
17
|
-
</DialogFooter>
|
|
18
|
-
</div>
|
|
19
|
-
</Form>
|
|
20
|
-
</DialogContent>
|
|
21
|
-
</Dialog>
|
|
22
|
-
</template>
|
|
23
|
-
|
|
24
|
-
<script setup>
|
|
25
|
-
import { ref, watch } from "vue";
|
|
26
|
-
import { useRuntimeConfig } from "nuxt/app";
|
|
27
|
-
const { BASE_URL_API } = useRuntimeConfig().public;
|
|
28
|
-
const emit = defineEmits(["complete"]);
|
|
29
|
-
const props = defineProps({
|
|
30
|
-
phone: { type: String, required: false },
|
|
31
|
-
confirmedText: { type: String, required: false, default: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19" },
|
|
32
|
-
title: { type: String, required: false },
|
|
33
|
-
description: { type: String, required: false },
|
|
34
|
-
footer: { type: String, required: false }
|
|
35
|
-
});
|
|
36
|
-
const isOpen = defineModel({ type: Boolean, ...{
|
|
37
|
-
default: false
|
|
38
|
-
} });
|
|
39
|
-
const twoFaRef = ref();
|
|
40
|
-
const valueOTP = ref("");
|
|
41
|
-
const isLoading = ref(false);
|
|
42
|
-
const onVerify2FA = async () => {
|
|
43
|
-
try {
|
|
44
|
-
const { data } = await $fetch(
|
|
45
|
-
!props.phone ? `${BASE_URL_API}/me/two-fa-verify` : `${BASE_URL_API}/auth/two-fa-verify`,
|
|
46
|
-
{
|
|
47
|
-
method: "POST",
|
|
48
|
-
body: {
|
|
49
|
-
phone: props.phone,
|
|
50
|
-
code: valueOTP.value
|
|
51
|
-
},
|
|
52
|
-
credentials: "include"
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
|
-
if (!data) throw "error";
|
|
56
|
-
emit("complete", data);
|
|
57
|
-
isOpen.value = false;
|
|
58
|
-
} catch (e) {
|
|
59
|
-
twoFaRef.value.setErrors(["\u0E23\u0E2B\u0E31\u0E2A\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07"]);
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
watch(isOpen, (value) => {
|
|
63
|
-
valueOTP.value = "";
|
|
64
|
-
});
|
|
65
|
-
</script>
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Modal2FAProps } from "@/types/components/modal/modal-2FA";
|
|
2
|
-
type __VLS_Props = Modal2FAProps;
|
|
3
|
-
type __VLS_ModelProps = {
|
|
4
|
-
modelValue?: boolean;
|
|
5
|
-
};
|
|
6
|
-
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
7
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
-
"update:modelValue": (value: boolean) => any;
|
|
9
|
-
} & {
|
|
10
|
-
complete: (verify: boolean) => any;
|
|
11
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
12
|
-
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
13
|
-
onComplete?: ((verify: boolean) => any) | undefined;
|
|
14
|
-
}>, {
|
|
15
|
-
confirmedText: string;
|
|
16
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
-
declare const _default: typeof __VLS_export;
|
|
18
|
-
export default _default;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ModalEmailOTPProps } from "~/types/components/modal/modal-email-otp";
|
|
2
|
-
type __VLS_Props = ModalEmailOTPProps;
|
|
3
|
-
type __VLS_ModelProps = {
|
|
4
|
-
modelValue?: boolean;
|
|
5
|
-
};
|
|
6
|
-
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
7
|
-
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
8
|
-
"update:modelValue": (value: boolean) => any;
|
|
9
|
-
} & {
|
|
10
|
-
close: () => any;
|
|
11
|
-
complete: () => any;
|
|
12
|
-
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
13
|
-
onClose?: (() => any) | undefined;
|
|
14
|
-
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
15
|
-
onComplete?: (() => any) | undefined;
|
|
16
|
-
}>, {
|
|
17
|
-
confirmedText: string;
|
|
18
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
-
declare const _default: typeof __VLS_export;
|
|
20
|
-
export default _default;
|