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
package/dist/module.json
CHANGED
|
@@ -50,8 +50,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
50
50
|
name: string;
|
|
51
51
|
description: string;
|
|
52
52
|
options: AutocompleteOption[] | string[] | number[];
|
|
53
|
-
placeholder: string;
|
|
54
53
|
limit: number;
|
|
54
|
+
placeholder: string;
|
|
55
55
|
disabledErrorMessage: boolean;
|
|
56
56
|
disabledBorder: boolean;
|
|
57
57
|
showCounter: boolean;
|
|
@@ -50,8 +50,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
50
50
|
name: string;
|
|
51
51
|
description: string;
|
|
52
52
|
options: AutocompleteOption[] | string[] | number[];
|
|
53
|
-
placeholder: string;
|
|
54
53
|
limit: number;
|
|
54
|
+
placeholder: string;
|
|
55
55
|
disabledErrorMessage: boolean;
|
|
56
56
|
disabledBorder: boolean;
|
|
57
57
|
showCounter: boolean;
|
|
@@ -35,8 +35,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
35
35
|
fullHeight: boolean;
|
|
36
36
|
name: string;
|
|
37
37
|
limit: number;
|
|
38
|
-
disabledErrorMessage: boolean;
|
|
39
38
|
accept: string;
|
|
39
|
+
disabledErrorMessage: boolean;
|
|
40
40
|
labelIcon: string;
|
|
41
41
|
disabledDrop: boolean;
|
|
42
42
|
column: boolean;
|
|
@@ -35,8 +35,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
35
35
|
fullHeight: boolean;
|
|
36
36
|
name: string;
|
|
37
37
|
limit: number;
|
|
38
|
-
disabledErrorMessage: boolean;
|
|
39
38
|
accept: string;
|
|
39
|
+
disabledErrorMessage: boolean;
|
|
40
40
|
labelIcon: string;
|
|
41
41
|
disabledDrop: boolean;
|
|
42
42
|
column: boolean;
|
|
@@ -22,8 +22,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
22
22
|
}>, {
|
|
23
23
|
id: string;
|
|
24
24
|
name: string;
|
|
25
|
-
new: boolean;
|
|
26
25
|
disabledForgotPassword: boolean;
|
|
26
|
+
new: boolean;
|
|
27
27
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
28
|
declare const _default: typeof __VLS_export;
|
|
29
29
|
export default _default;
|
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
{{ props.label }}
|
|
16
16
|
<span v-if="props.required" class="text-destructive">*</span>
|
|
17
17
|
</div>
|
|
18
|
-
<
|
|
18
|
+
<Button
|
|
19
19
|
v-if="!props.disabledForgotPassword"
|
|
20
|
-
|
|
20
|
+
variant="text"
|
|
21
|
+
color="primary"
|
|
22
|
+
class="font-body-medium"
|
|
21
23
|
@click="handleForgotPassword"
|
|
22
24
|
>
|
|
23
25
|
ลืมรหัสผ่าน
|
|
24
|
-
</
|
|
26
|
+
</Button>
|
|
25
27
|
</ShadFormLabel>
|
|
26
28
|
</template>
|
|
27
29
|
</InputTextField>
|
|
@@ -46,6 +48,7 @@
|
|
|
46
48
|
|
|
47
49
|
<script setup>
|
|
48
50
|
import { ref, computed } from "vue";
|
|
51
|
+
import Button from "../button.vue";
|
|
49
52
|
const props = defineProps({
|
|
50
53
|
new: { type: Boolean, required: false, default: false },
|
|
51
54
|
disabledForgotPassword: { type: Boolean, required: false, default: false },
|
|
@@ -22,8 +22,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
22
22
|
}>, {
|
|
23
23
|
id: string;
|
|
24
24
|
name: string;
|
|
25
|
-
new: boolean;
|
|
26
25
|
disabledForgotPassword: boolean;
|
|
26
|
+
new: boolean;
|
|
27
27
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
28
28
|
declare const _default: typeof __VLS_export;
|
|
29
29
|
export default _default;
|
|
@@ -26,8 +26,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
26
26
|
}>, {
|
|
27
27
|
name: string;
|
|
28
28
|
state: "user" | "admin";
|
|
29
|
-
placeholder: string;
|
|
30
29
|
limit: number;
|
|
30
|
+
placeholder: string;
|
|
31
31
|
ignore: string[];
|
|
32
32
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
33
|
declare const _default: typeof __VLS_export;
|
|
@@ -26,8 +26,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
26
26
|
}>, {
|
|
27
27
|
name: string;
|
|
28
28
|
state: "user" | "admin";
|
|
29
|
-
placeholder: string;
|
|
30
29
|
limit: number;
|
|
30
|
+
placeholder: string;
|
|
31
31
|
ignore: string[];
|
|
32
32
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
33
33
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<Modal
|
|
3
|
-
width="550"
|
|
4
|
-
title="คำแนะนำการตั้งค่า"
|
|
5
|
-
title-position="center"
|
|
6
|
-
:loading="isLoading"
|
|
7
|
-
v-model="isOpen"
|
|
8
|
-
>
|
|
2
|
+
<Modal class="w-[512px]" title="คำแนะนำการตั้งค่า" :loading="isLoading" v-model="isOpen">
|
|
9
3
|
<div class="flex flex-col gap-[16px]">
|
|
10
|
-
<div class="flex flex-col gap[8px] text-gray font-body-large">
|
|
11
|
-
<div class="font-body-large-prominent">1.ดาวน์โหลดแอพยืนยันตัวตน</div>
|
|
4
|
+
<div class="flex flex-col gap-[8px] text-gray font-body-large">
|
|
5
|
+
<div class="font-body-large-prominent text-black">1.ดาวน์โหลดแอพยืนยันตัวตน</div>
|
|
12
6
|
<div>
|
|
13
7
|
เราแนะนำให้ดาวน์โหลด Google Authenticator หากคุณยังไม่ได้ติดตั้ง
|
|
14
8
|
</div>
|
|
15
9
|
</div>
|
|
16
|
-
<div class="flex flex-col gap[8px] text-gray font-body-large">
|
|
17
|
-
<div class="font-body-large-prominent">
|
|
10
|
+
<div class="flex flex-col gap-[8px] text-gray font-body-large">
|
|
11
|
+
<div class="font-body-large-prominent text-black">
|
|
18
12
|
2.สแกนบาร์โค้ด/คิวอาร์โค้ดนี้หรือคัดลอกคีย์
|
|
19
13
|
</div>
|
|
20
14
|
<div>
|
|
@@ -29,17 +23,14 @@
|
|
|
29
23
|
<div class="font-body-large-prominent">
|
|
30
24
|
{{ key }}
|
|
31
25
|
</div>
|
|
32
|
-
<div
|
|
33
|
-
class="cursor-pointer text-primary font-body-large"
|
|
34
|
-
@click="copyToClipboard(key)"
|
|
35
|
-
>
|
|
26
|
+
<div class="cursor-pointer text-primary font-body-large" @click="copyToClipboard(key)">
|
|
36
27
|
คัดลอกคีย์
|
|
37
28
|
</div>
|
|
38
29
|
</div>
|
|
39
30
|
</div>
|
|
40
31
|
</div>
|
|
41
|
-
<div class="flex flex-col gap[8px] text-gray font-body-large">
|
|
42
|
-
<div class="font-body-large-prominent">
|
|
32
|
+
<div class="flex flex-col gap-[8px] text-gray font-body-large">
|
|
33
|
+
<div class="font-body-large-prominent text-black">
|
|
43
34
|
3.คัดลอกแล้วป้อนรหัสตัวเลข 6 หลัก
|
|
44
35
|
</div>
|
|
45
36
|
<div>
|
|
@@ -51,12 +42,7 @@
|
|
|
51
42
|
</div>
|
|
52
43
|
|
|
53
44
|
<template #footer>
|
|
54
|
-
<Button
|
|
55
|
-
color="primary"
|
|
56
|
-
full-width
|
|
57
|
-
:disabled="isDisabled"
|
|
58
|
-
@click="onComplete"
|
|
59
|
-
>
|
|
45
|
+
<Button color="primary" class="w-full" :disabled="isDisabled" @click="onComplete">
|
|
60
46
|
{{ props.confirmedText }}
|
|
61
47
|
</Button>
|
|
62
48
|
</template>
|
|
@@ -86,8 +72,8 @@ const isDisabled = ref(true);
|
|
|
86
72
|
const twoFaGenerate = async () => {
|
|
87
73
|
try {
|
|
88
74
|
isLoading.value = true;
|
|
89
|
-
const {
|
|
90
|
-
if (
|
|
75
|
+
const { message, data } = await api("/me/two-fa-generate");
|
|
76
|
+
if (message?.title !== "\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08") throw "Generate \u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08";
|
|
91
77
|
key.value = data.key;
|
|
92
78
|
barcode2FA.value = data.qr_code;
|
|
93
79
|
isDisabled.value = false;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export interface ModalEmailOTPProps {
|
|
2
2
|
email?: string;
|
|
3
3
|
confirmedText?: string;
|
|
4
|
+
/** Custom API path for requesting OTP. Defaults to /me/email-otp-request */
|
|
5
|
+
requestPath?: string;
|
|
6
|
+
/** Custom request body. When provided, used instead of { email }. */
|
|
7
|
+
requestBody?: Record<string, any>;
|
|
8
|
+
/** Custom API path for verifying OTP. Defaults to /me/email-otp-verify */
|
|
9
|
+
verifyPath?: string;
|
|
10
|
+
/** Extra body fields merged with { code } when verifying. Defaults to { email }. */
|
|
11
|
+
verifyBody?: Record<string, any>;
|
|
12
|
+
/** If provided, sets the initial countdown and skips auto-request on open. */
|
|
13
|
+
initialExpiredTime?: string;
|
|
4
14
|
}
|
|
5
15
|
type __VLS_Props = ModalEmailOTPProps;
|
|
6
16
|
type __VLS_ModelProps = {
|
|
@@ -10,10 +20,10 @@ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
|
10
20
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
21
|
"update:modelValue": (value: boolean) => any;
|
|
12
22
|
} & {
|
|
13
|
-
complete: () => any;
|
|
23
|
+
complete: (data?: any) => any;
|
|
14
24
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
25
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
16
|
-
onComplete?: (() => any) | undefined;
|
|
26
|
+
onComplete?: ((data?: any) => any) | undefined;
|
|
17
27
|
}>, {
|
|
18
28
|
confirmedText: string;
|
|
19
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -44,7 +44,12 @@ const { CountdownTime } = useCountDown();
|
|
|
44
44
|
const emits = defineEmits(["complete"]);
|
|
45
45
|
const props = defineProps({
|
|
46
46
|
email: { type: String, required: false },
|
|
47
|
-
confirmedText: { type: String, required: false, default: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19" }
|
|
47
|
+
confirmedText: { type: String, required: false, default: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19" },
|
|
48
|
+
requestPath: { type: String, required: false },
|
|
49
|
+
requestBody: { type: Object, required: false },
|
|
50
|
+
verifyPath: { type: String, required: false },
|
|
51
|
+
verifyBody: { type: Object, required: false },
|
|
52
|
+
initialExpiredTime: { type: String, required: false }
|
|
48
53
|
});
|
|
49
54
|
const isOpen = defineModel({ type: Boolean, ...{
|
|
50
55
|
default: false
|
|
@@ -64,16 +69,15 @@ const maskedEmail = computed(() => {
|
|
|
64
69
|
});
|
|
65
70
|
const onVerifyOTP = async () => {
|
|
66
71
|
try {
|
|
67
|
-
|
|
72
|
+
const path = props.verifyPath ?? "/me/email-otp-verify";
|
|
73
|
+
const body = props.verifyBody ? { ...props.verifyBody, code: valueOTP.value } : { code: valueOTP.value, email: props.email };
|
|
74
|
+
const response = await api(path, {
|
|
68
75
|
method: "POST",
|
|
69
|
-
body
|
|
70
|
-
code: valueOTP.value,
|
|
71
|
-
email: props.email
|
|
72
|
-
}
|
|
76
|
+
body
|
|
73
77
|
});
|
|
74
78
|
valueOTP.value = "";
|
|
75
79
|
isOpen.value = false;
|
|
76
|
-
emits("complete");
|
|
80
|
+
emits("complete", response?.data);
|
|
77
81
|
} catch (e) {
|
|
78
82
|
$toast.error("OTP \u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07");
|
|
79
83
|
}
|
|
@@ -81,16 +85,13 @@ const onVerifyOTP = async () => {
|
|
|
81
85
|
const handleSendEmail = async () => {
|
|
82
86
|
try {
|
|
83
87
|
isLoading.value = true;
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
);
|
|
88
|
+
const path = props.requestPath ?? "/me/email-otp-request";
|
|
89
|
+
const body = props.requestBody ?? { email: props.email };
|
|
90
|
+
if (!props.requestBody && !props.email) throw new Error("\u0E01\u0E23\u0E38\u0E13\u0E32\u0E23\u0E30\u0E1A\u0E38 email");
|
|
91
|
+
const response = await api(path, {
|
|
92
|
+
method: "POST",
|
|
93
|
+
body
|
|
94
|
+
});
|
|
94
95
|
timeExp.value = response.data.expired_time;
|
|
95
96
|
} catch (err) {
|
|
96
97
|
$toast.error("\u0E1E\u0E1A\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14 \u0E1A\u0E32\u0E07\u0E2D\u0E22\u0E48\u0E32\u0E07 !");
|
|
@@ -101,7 +102,11 @@ const handleSendEmail = async () => {
|
|
|
101
102
|
watch(isOpen, (v) => {
|
|
102
103
|
if (v) {
|
|
103
104
|
valueOTP.value = "";
|
|
104
|
-
|
|
105
|
+
if (props.initialExpiredTime) {
|
|
106
|
+
timeExp.value = props.initialExpiredTime;
|
|
107
|
+
} else {
|
|
108
|
+
handleSendEmail();
|
|
109
|
+
}
|
|
105
110
|
} else {
|
|
106
111
|
timeExp.value = "";
|
|
107
112
|
}
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
export interface ModalEmailOTPProps {
|
|
2
2
|
email?: string;
|
|
3
3
|
confirmedText?: string;
|
|
4
|
+
/** Custom API path for requesting OTP. Defaults to /me/email-otp-request */
|
|
5
|
+
requestPath?: string;
|
|
6
|
+
/** Custom request body. When provided, used instead of { email }. */
|
|
7
|
+
requestBody?: Record<string, any>;
|
|
8
|
+
/** Custom API path for verifying OTP. Defaults to /me/email-otp-verify */
|
|
9
|
+
verifyPath?: string;
|
|
10
|
+
/** Extra body fields merged with { code } when verifying. Defaults to { email }. */
|
|
11
|
+
verifyBody?: Record<string, any>;
|
|
12
|
+
/** If provided, sets the initial countdown and skips auto-request on open. */
|
|
13
|
+
initialExpiredTime?: string;
|
|
4
14
|
}
|
|
5
15
|
type __VLS_Props = ModalEmailOTPProps;
|
|
6
16
|
type __VLS_ModelProps = {
|
|
@@ -10,10 +20,10 @@ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
|
10
20
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
21
|
"update:modelValue": (value: boolean) => any;
|
|
12
22
|
} & {
|
|
13
|
-
complete: () => any;
|
|
23
|
+
complete: (data?: any) => any;
|
|
14
24
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
25
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
16
|
-
onComplete?: (() => any) | undefined;
|
|
26
|
+
onComplete?: ((data?: any) => any) | undefined;
|
|
17
27
|
}>, {
|
|
18
28
|
confirmedText: string;
|
|
19
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type __VLS_ModelProps = {
|
|
2
|
+
modelValue?: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
|
+
"update:modelValue": (value: boolean) => any;
|
|
6
|
+
} & {
|
|
7
|
+
complete: () => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
9
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
10
|
+
onComplete?: (() => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<component
|
|
3
|
+
v-for="modal in modals"
|
|
4
|
+
:key="modal.key"
|
|
5
|
+
:is="modal.component"
|
|
6
|
+
v-bind="modalProps[modal.key]"
|
|
7
|
+
v-model="modalStates[modal.key]"
|
|
8
|
+
@complete="(data) => handleComplete(modal.key, data)"
|
|
9
|
+
@close="isOpen = false"
|
|
10
|
+
/>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup>
|
|
14
|
+
import { reactive, ref, computed, watch } from "vue";
|
|
15
|
+
import { useNuxtApp } from "nuxt/app";
|
|
16
|
+
import { useApi } from "../../composables/useApi";
|
|
17
|
+
import ModalUserAccountSearch from "@/runtime/components/modal/modal-user-account-search.vue";
|
|
18
|
+
import ModalPhoneOTP from "@/runtime/components/modal/modal-phone-OTP.vue";
|
|
19
|
+
import ModalEmailOTP from "@/runtime/components/modal/modal-email-OTP.vue";
|
|
20
|
+
import ModalPasswordNew from "@/runtime/components/modal/modal-password-new.vue";
|
|
21
|
+
const { $toast } = useNuxtApp();
|
|
22
|
+
const api = useApi();
|
|
23
|
+
const emit = defineEmits(["complete"]);
|
|
24
|
+
const isOpen = defineModel({ type: Boolean, ...{ default: false } });
|
|
25
|
+
const phone = ref("");
|
|
26
|
+
const maskedPhone = ref("");
|
|
27
|
+
const maskedEmail = ref(null);
|
|
28
|
+
const method = ref("sms");
|
|
29
|
+
const expiredTime = ref("");
|
|
30
|
+
const resetToken = ref("");
|
|
31
|
+
const isLoading = ref(false);
|
|
32
|
+
const modals = [
|
|
33
|
+
{ key: "accountSearch", component: ModalUserAccountSearch },
|
|
34
|
+
{ key: "phoneOTP", component: ModalPhoneOTP },
|
|
35
|
+
{ key: "emailOTP", component: ModalEmailOTP },
|
|
36
|
+
{ key: "passwordNew", component: ModalPasswordNew }
|
|
37
|
+
];
|
|
38
|
+
const modalStates = reactive(
|
|
39
|
+
Object.fromEntries(modals.map((m) => [m.key, false]))
|
|
40
|
+
);
|
|
41
|
+
const modalProps = computed(() => ({
|
|
42
|
+
accountSearch: {
|
|
43
|
+
confirmedText: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19"
|
|
44
|
+
},
|
|
45
|
+
phoneOTP: {
|
|
46
|
+
phone: phone.value,
|
|
47
|
+
phoneLabel: maskedPhone.value,
|
|
48
|
+
confirmedText: "\u0E16\u0E31\u0E14\u0E44\u0E1B"
|
|
49
|
+
},
|
|
50
|
+
emailOTP: {
|
|
51
|
+
email: maskedEmail.value ?? "",
|
|
52
|
+
requestPath: "/auth/forgot-password/send-otp",
|
|
53
|
+
requestBody: { phone: phone.value, method: "email" },
|
|
54
|
+
verifyPath: "/auth/forgot-password/verify-otp",
|
|
55
|
+
verifyBody: { phone: phone.value },
|
|
56
|
+
initialExpiredTime: expiredTime.value,
|
|
57
|
+
confirmedText: "\u0E16\u0E31\u0E14\u0E44\u0E1B"
|
|
58
|
+
},
|
|
59
|
+
passwordNew: {
|
|
60
|
+
resetToken: resetToken.value,
|
|
61
|
+
disabledForceLogout: false,
|
|
62
|
+
title: "\u0E15\u0E31\u0E49\u0E07\u0E23\u0E2B\u0E31\u0E2A\u0E1C\u0E48\u0E32\u0E19\u0E43\u0E2B\u0E21\u0E48",
|
|
63
|
+
confirmText: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19"
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
const handleComplete = async (key, data) => {
|
|
67
|
+
if (key === "accountSearch") {
|
|
68
|
+
const result = data;
|
|
69
|
+
phone.value = result.phone;
|
|
70
|
+
method.value = result.method;
|
|
71
|
+
maskedPhone.value = result.maskedPhone;
|
|
72
|
+
maskedEmail.value = result.maskedEmail;
|
|
73
|
+
await callSendOTP();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (key === "phoneOTP") {
|
|
77
|
+
await callVerifyOTP(data);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (key === "emailOTP") {
|
|
81
|
+
const token = data?.reset_token;
|
|
82
|
+
if (!token) {
|
|
83
|
+
$toast?.error?.("\u0E44\u0E21\u0E48\u0E1E\u0E1A reset token");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
resetToken.value = token;
|
|
87
|
+
modalStates.passwordNew = true;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (key === "passwordNew") {
|
|
91
|
+
isOpen.value = false;
|
|
92
|
+
$toast?.success?.("\u0E23\u0E35\u0E40\u0E0B\u0E47\u0E15\u0E23\u0E2B\u0E31\u0E2A\u0E1C\u0E48\u0E32\u0E19\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08 !");
|
|
93
|
+
emit("complete");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const callSendOTP = async () => {
|
|
98
|
+
isLoading.value = true;
|
|
99
|
+
try {
|
|
100
|
+
const res = await api("/auth/forgot-password/send-otp", {
|
|
101
|
+
method: "POST",
|
|
102
|
+
body: { phone: phone.value, method: method.value }
|
|
103
|
+
});
|
|
104
|
+
expiredTime.value = res.data.expired_time;
|
|
105
|
+
if (method.value === "sms") {
|
|
106
|
+
modalStates.phoneOTP = true;
|
|
107
|
+
} else {
|
|
108
|
+
modalStates.emailOTP = true;
|
|
109
|
+
}
|
|
110
|
+
} catch (e) {
|
|
111
|
+
const msg = e?.data?.message?.description || e?.data?.message || "\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14\u0E43\u0E19\u0E01\u0E32\u0E23\u0E2A\u0E48\u0E07 OTP";
|
|
112
|
+
$toast?.error?.(msg);
|
|
113
|
+
} finally {
|
|
114
|
+
isLoading.value = false;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const callVerifyOTP = async (code) => {
|
|
118
|
+
isLoading.value = true;
|
|
119
|
+
try {
|
|
120
|
+
const res = await api("/auth/forgot-password/verify-otp", {
|
|
121
|
+
method: "POST",
|
|
122
|
+
body: { phone: phone.value, code }
|
|
123
|
+
});
|
|
124
|
+
resetToken.value = res.data.reset_token;
|
|
125
|
+
modalStates.passwordNew = true;
|
|
126
|
+
} catch (e) {
|
|
127
|
+
const msg = e?.data?.message?.description || e?.data?.message || "OTP \u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07\u0E2B\u0E23\u0E37\u0E2D\u0E2B\u0E21\u0E14\u0E2D\u0E32\u0E22\u0E38";
|
|
128
|
+
$toast?.error?.(msg);
|
|
129
|
+
} finally {
|
|
130
|
+
isLoading.value = false;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
watch(isOpen, (v) => {
|
|
134
|
+
if (v) {
|
|
135
|
+
phone.value = "";
|
|
136
|
+
maskedPhone.value = "";
|
|
137
|
+
maskedEmail.value = null;
|
|
138
|
+
method.value = "sms";
|
|
139
|
+
expiredTime.value = "";
|
|
140
|
+
resetToken.value = "";
|
|
141
|
+
modalStates.accountSearch = true;
|
|
142
|
+
} else {
|
|
143
|
+
modals.forEach((m) => modalStates[m.key] = false);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
</script>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type __VLS_ModelProps = {
|
|
2
|
+
modelValue?: boolean;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
5
|
+
"update:modelValue": (value: boolean) => any;
|
|
6
|
+
} & {
|
|
7
|
+
complete: () => any;
|
|
8
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
9
|
+
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
10
|
+
onComplete?: (() => any) | undefined;
|
|
11
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -24,8 +24,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
24
24
|
}) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
26
|
title: string;
|
|
27
|
-
disabledForgotPassword: boolean;
|
|
28
27
|
confirmText: string;
|
|
28
|
+
disabledForgotPassword: boolean;
|
|
29
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
30
|
declare const _default: typeof __VLS_export;
|
|
31
31
|
export default _default;
|
|
@@ -24,8 +24,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
24
24
|
}) => any) | undefined;
|
|
25
25
|
}>, {
|
|
26
26
|
title: string;
|
|
27
|
-
disabledForgotPassword: boolean;
|
|
28
27
|
confirmText: string;
|
|
28
|
+
disabledForgotPassword: boolean;
|
|
29
29
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
30
30
|
declare const _default: typeof __VLS_export;
|
|
31
31
|
export default _default;
|
|
@@ -2,6 +2,8 @@ interface Props {
|
|
|
2
2
|
title?: string;
|
|
3
3
|
confirmText?: string;
|
|
4
4
|
loginToken?: string;
|
|
5
|
+
/** When provided, uses forgot-password reset endpoint instead of password/create */
|
|
6
|
+
resetToken?: string;
|
|
5
7
|
disabledForceLogout?: boolean;
|
|
6
8
|
}
|
|
7
9
|
type __VLS_Props = Props;
|
|
@@ -14,13 +16,13 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
14
16
|
"update:modelValue": (value: boolean) => any;
|
|
15
17
|
complete: (data: {
|
|
16
18
|
secId: string;
|
|
17
|
-
}) => any;
|
|
19
|
+
} | null) => any;
|
|
18
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
19
21
|
onClose?: (() => any) | undefined;
|
|
20
22
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
21
23
|
onComplete?: ((data: {
|
|
22
24
|
secId: string;
|
|
23
|
-
}) => any) | undefined;
|
|
25
|
+
} | null) => any) | undefined;
|
|
24
26
|
}>, {
|
|
25
27
|
title: string;
|
|
26
28
|
confirmText: string;
|
|
@@ -5,21 +5,23 @@
|
|
|
5
5
|
v-model="isOpen"
|
|
6
6
|
@close="emit('close')"
|
|
7
7
|
@submit="handleSubmit"
|
|
8
|
+
width="425px"
|
|
8
9
|
>
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
<div class="flex flex-col gap-2">
|
|
11
|
+
<InputPassword
|
|
12
|
+
disabled-forgot-password
|
|
13
|
+
new
|
|
14
|
+
required
|
|
15
|
+
label="รหัสผ่าน"
|
|
16
|
+
placeholder="กรอกรหัสผ่าน"
|
|
17
|
+
v-model="password"
|
|
18
|
+
/>
|
|
19
|
+
<InputCheckbox
|
|
20
|
+
v-if="!props.disabledForceLogout"
|
|
21
|
+
label="ออกจากระบบ Pukaad ในอุปกรณ์อื่นๆทั้งหมด"
|
|
22
|
+
v-model="logoutAll"
|
|
23
|
+
/>
|
|
24
|
+
</div>
|
|
23
25
|
<template #footer="{ meta }">
|
|
24
26
|
<Button
|
|
25
27
|
type="submit"
|
|
@@ -36,15 +38,18 @@
|
|
|
36
38
|
<script setup>
|
|
37
39
|
import { ref, computed, watch } from "vue";
|
|
38
40
|
import { useNuxtApp, useRuntimeConfig } from "nuxt/app";
|
|
41
|
+
import { useApi } from "../../composables/useApi";
|
|
39
42
|
const props = defineProps({
|
|
40
43
|
title: { type: String, required: false, default: "\u0E23\u0E2B\u0E31\u0E2A\u0E1C\u0E48\u0E32\u0E19\u0E43\u0E2B\u0E21\u0E48" },
|
|
41
44
|
confirmText: { type: String, required: false, default: "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19" },
|
|
42
45
|
loginToken: { type: String, required: false },
|
|
46
|
+
resetToken: { type: String, required: false },
|
|
43
47
|
disabledForceLogout: { type: Boolean, required: false, default: false }
|
|
44
48
|
});
|
|
45
49
|
const emit = defineEmits(["complete", "close"]);
|
|
46
50
|
const { $toast } = useNuxtApp();
|
|
47
51
|
const config = useRuntimeConfig();
|
|
52
|
+
const api = useApi();
|
|
48
53
|
const isOpen = defineModel({ type: Boolean, ...{ default: false } });
|
|
49
54
|
const loading = ref(false);
|
|
50
55
|
const password = ref("");
|
|
@@ -59,6 +64,27 @@ watch(isOpen, (open) => {
|
|
|
59
64
|
}
|
|
60
65
|
});
|
|
61
66
|
const handleSubmit = async () => {
|
|
67
|
+
if (props.resetToken) {
|
|
68
|
+
loading.value = true;
|
|
69
|
+
try {
|
|
70
|
+
await api("/auth/forgot-password/reset-password", {
|
|
71
|
+
method: "POST",
|
|
72
|
+
body: {
|
|
73
|
+
reset_token: props.resetToken,
|
|
74
|
+
new_password: password.value,
|
|
75
|
+
logout_all: logoutAll.value
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
emit("complete", null);
|
|
79
|
+
isOpen.value = false;
|
|
80
|
+
} catch (e) {
|
|
81
|
+
const msg = e?.data?.message?.description || e?.data?.message || "\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14\u0E43\u0E19\u0E01\u0E32\u0E23\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D";
|
|
82
|
+
$toast?.error?.(msg);
|
|
83
|
+
} finally {
|
|
84
|
+
loading.value = false;
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
62
88
|
if (!props.loginToken) {
|
|
63
89
|
$toast?.error?.("\u0E44\u0E21\u0E48\u0E1E\u0E1A login token");
|
|
64
90
|
return;
|
|
@@ -2,6 +2,8 @@ interface Props {
|
|
|
2
2
|
title?: string;
|
|
3
3
|
confirmText?: string;
|
|
4
4
|
loginToken?: string;
|
|
5
|
+
/** When provided, uses forgot-password reset endpoint instead of password/create */
|
|
6
|
+
resetToken?: string;
|
|
5
7
|
disabledForceLogout?: boolean;
|
|
6
8
|
}
|
|
7
9
|
type __VLS_Props = Props;
|
|
@@ -14,13 +16,13 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
14
16
|
"update:modelValue": (value: boolean) => any;
|
|
15
17
|
complete: (data: {
|
|
16
18
|
secId: string;
|
|
17
|
-
}) => any;
|
|
19
|
+
} | null) => any;
|
|
18
20
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
19
21
|
onClose?: (() => any) | undefined;
|
|
20
22
|
"onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
|
|
21
23
|
onComplete?: ((data: {
|
|
22
24
|
secId: string;
|
|
23
|
-
}) => any) | undefined;
|
|
25
|
+
} | null) => any) | undefined;
|
|
24
26
|
}>, {
|
|
25
27
|
title: string;
|
|
26
28
|
confirmText: string;
|