pukaad-ui-lib 1.147.0 → 1.149.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/drawer/drawer-post-blog.vue +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-content.d.vue.ts +2 -0
- package/dist/runtime/components/input/input-content.vue +114 -18
- package/dist/runtime/components/input/input-content.vue.d.ts +2 -0
- 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.d.ts +1 -1
- package/dist/runtime/components/input/input-slider.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-slider.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-password-confirmed.d.vue.ts +1 -1
- package/dist/runtime/components/modal/modal-password-confirmed.vue.d.ts +1 -1
- package/dist/runtime/composables/useConvert.d.ts +3 -3
- package/dist/runtime/composables/useConvert.js +6 -6
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -36,9 +36,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
36
36
|
id: string;
|
|
37
37
|
name: string;
|
|
38
38
|
description: string;
|
|
39
|
+
limit: number;
|
|
39
40
|
options: AutocompleteOption[] | string[] | number[];
|
|
40
41
|
placeholder: string;
|
|
41
|
-
limit: number;
|
|
42
42
|
disabledErrorMessage: boolean;
|
|
43
43
|
disabledBorder: boolean;
|
|
44
44
|
showCounter: boolean;
|
|
@@ -36,9 +36,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
36
36
|
id: string;
|
|
37
37
|
name: string;
|
|
38
38
|
description: string;
|
|
39
|
+
limit: number;
|
|
39
40
|
options: AutocompleteOption[] | string[] | number[];
|
|
40
41
|
placeholder: string;
|
|
41
|
-
limit: number;
|
|
42
42
|
disabledErrorMessage: boolean;
|
|
43
43
|
disabledBorder: boolean;
|
|
44
44
|
showCounter: boolean;
|
|
@@ -8,6 +8,7 @@ export interface InputContentProps {
|
|
|
8
8
|
placeholder?: string;
|
|
9
9
|
disabledBorder?: boolean;
|
|
10
10
|
disableMedia?: boolean;
|
|
11
|
+
state?: "personal" | "business";
|
|
11
12
|
}
|
|
12
13
|
type __VLS_Props = InputContentProps;
|
|
13
14
|
type __VLS_ModelProps = {
|
|
@@ -31,6 +32,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
31
32
|
required: boolean;
|
|
32
33
|
id: string;
|
|
33
34
|
name: string;
|
|
35
|
+
state: "personal" | "business";
|
|
34
36
|
disableMedia: boolean;
|
|
35
37
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
36
38
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
<script setup>
|
|
39
39
|
import { ref, onMounted, onUnmounted } from "vue";
|
|
40
40
|
import { useNuxtApp } from "nuxt/app";
|
|
41
|
+
import { useApi } from "../../composables/useApi";
|
|
41
42
|
const { $quill } = useNuxtApp();
|
|
43
|
+
const api = useApi();
|
|
42
44
|
const contentRef = ref(null);
|
|
43
45
|
let quillEditor = null;
|
|
44
46
|
const props = defineProps({
|
|
@@ -50,7 +52,8 @@ const props = defineProps({
|
|
|
50
52
|
height: { type: [String, Number], required: false, default: 288 },
|
|
51
53
|
placeholder: { type: String, required: false },
|
|
52
54
|
disabledBorder: { type: Boolean, required: false },
|
|
53
|
-
disableMedia: { type: Boolean, required: false, default: false }
|
|
55
|
+
disableMedia: { type: Boolean, required: false, default: false },
|
|
56
|
+
state: { type: String, required: false, default: "personal" }
|
|
54
57
|
});
|
|
55
58
|
const modelValue = defineModel();
|
|
56
59
|
const isDraggingMedia = ref(false);
|
|
@@ -69,6 +72,66 @@ defineExpose({
|
|
|
69
72
|
validate,
|
|
70
73
|
fieldRef
|
|
71
74
|
});
|
|
75
|
+
const getUploadState = () => {
|
|
76
|
+
return props.state === "business" ? "business-blog-media" : "blog-media";
|
|
77
|
+
};
|
|
78
|
+
const uploadImageToPresigned = async (file) => {
|
|
79
|
+
const res = await api("/storage/presigned-urls", {
|
|
80
|
+
method: "POST",
|
|
81
|
+
body: {
|
|
82
|
+
file_name: [file.name],
|
|
83
|
+
state: getUploadState()
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (res.code !== 200 || !res.data?.items?.[0]) {
|
|
87
|
+
throw new Error(res.message || "Failed to generate upload URL");
|
|
88
|
+
}
|
|
89
|
+
const item = res.data.items[0];
|
|
90
|
+
await fetch(item.upload_url, {
|
|
91
|
+
method: "PUT",
|
|
92
|
+
body: file,
|
|
93
|
+
headers: {
|
|
94
|
+
"Content-Type": file.type
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
return item.public_url;
|
|
98
|
+
};
|
|
99
|
+
const insertUploadedImage = async (file) => {
|
|
100
|
+
if (!quillEditor) return;
|
|
101
|
+
try {
|
|
102
|
+
const url = await uploadImageToPresigned(file);
|
|
103
|
+
const range = quillEditor.getSelection(true);
|
|
104
|
+
quillEditor.insertEmbed(range.index, "image", url, "user");
|
|
105
|
+
quillEditor.setSelection(range.index + 1, 0);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error("Image upload failed:", error);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const handlePasteImage = (e) => {
|
|
111
|
+
if (props.disableMedia) return;
|
|
112
|
+
const clipboardData = e.clipboardData;
|
|
113
|
+
if (!clipboardData) return;
|
|
114
|
+
const imageFiles = Array.from(clipboardData.files).filter(
|
|
115
|
+
(file) => file.type.startsWith("image/")
|
|
116
|
+
);
|
|
117
|
+
if (imageFiles.length > 0) {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
imageFiles.forEach((file) => insertUploadedImage(file));
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const handleDropUpload = (e) => {
|
|
123
|
+
if (props.disableMedia) return;
|
|
124
|
+
const dataTransfer = e.dataTransfer;
|
|
125
|
+
if (!dataTransfer) return;
|
|
126
|
+
const imageFiles = Array.from(dataTransfer.files).filter(
|
|
127
|
+
(file) => file.type.startsWith("image/")
|
|
128
|
+
);
|
|
129
|
+
if (imageFiles.length > 0) {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
e.stopPropagation();
|
|
132
|
+
imageFiles.forEach((file) => insertUploadedImage(file));
|
|
133
|
+
}
|
|
134
|
+
};
|
|
72
135
|
onMounted(() => {
|
|
73
136
|
if (contentRef.value) {
|
|
74
137
|
const toolbarOptions = [
|
|
@@ -79,40 +142,59 @@ onMounted(() => {
|
|
|
79
142
|
[{ indent: "-1" }, { indent: "+1" }],
|
|
80
143
|
[{ color: [] }, { background: [] }],
|
|
81
144
|
[{ align: [] }],
|
|
82
|
-
props.disableMedia ? ["link"] : ["link", "image"
|
|
145
|
+
props.disableMedia ? ["link"] : ["link", "image"]
|
|
83
146
|
];
|
|
84
147
|
const modules = {
|
|
85
|
-
toolbar: toolbarOptions
|
|
86
|
-
|
|
87
|
-
if (props.disableMedia) {
|
|
88
|
-
modules.clipboard = {
|
|
148
|
+
toolbar: toolbarOptions,
|
|
149
|
+
clipboard: {
|
|
89
150
|
matchers: [
|
|
90
151
|
[
|
|
91
|
-
"
|
|
152
|
+
"VIDEO",
|
|
92
153
|
() => {
|
|
93
154
|
return { ops: [] };
|
|
94
155
|
}
|
|
95
156
|
],
|
|
96
157
|
[
|
|
97
|
-
"
|
|
98
|
-
() => {
|
|
99
|
-
|
|
158
|
+
"IMG",
|
|
159
|
+
(node, delta) => {
|
|
160
|
+
if (props.disableMedia) {
|
|
161
|
+
return { ops: [] };
|
|
162
|
+
}
|
|
163
|
+
const src = node.getAttribute("src");
|
|
164
|
+
if (src && src.startsWith("data:")) {
|
|
165
|
+
return { ops: [] };
|
|
166
|
+
}
|
|
167
|
+
return delta;
|
|
100
168
|
}
|
|
101
169
|
]
|
|
102
170
|
]
|
|
103
|
-
}
|
|
104
|
-
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
105
173
|
quillEditor = new $quill(contentRef.value, {
|
|
106
174
|
theme: "snow",
|
|
107
175
|
placeholder: props.placeholder,
|
|
108
176
|
modules
|
|
109
177
|
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (
|
|
178
|
+
const toolbar = quillEditor.getModule("toolbar");
|
|
179
|
+
if (toolbar && toolbar.addHandler) {
|
|
180
|
+
if (props.disableMedia) {
|
|
113
181
|
toolbar.addHandler("image", () => {
|
|
114
182
|
});
|
|
115
|
-
|
|
183
|
+
} else {
|
|
184
|
+
toolbar.addHandler("image", () => {
|
|
185
|
+
const fileInput = document.createElement("input");
|
|
186
|
+
fileInput.setAttribute("type", "file");
|
|
187
|
+
fileInput.setAttribute(
|
|
188
|
+
"accept",
|
|
189
|
+
"image/jpeg,image/png,image/webp,image/bmp,image/gif"
|
|
190
|
+
);
|
|
191
|
+
fileInput.addEventListener("change", () => {
|
|
192
|
+
const file = fileInput.files?.[0];
|
|
193
|
+
if (file) {
|
|
194
|
+
insertUploadedImage(file);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
fileInput.click();
|
|
116
198
|
});
|
|
117
199
|
}
|
|
118
200
|
}
|
|
@@ -123,10 +205,18 @@ onMounted(() => {
|
|
|
123
205
|
if (source === "user") {
|
|
124
206
|
if (!quillEditor) return;
|
|
125
207
|
const currentDeltaJson = quillEditor.getContents();
|
|
126
|
-
if (
|
|
208
|
+
if (currentDeltaJson.ops) {
|
|
127
209
|
const filteredOps = currentDeltaJson.ops.filter((op) => {
|
|
128
210
|
if (op.insert && typeof op.insert === "object") {
|
|
129
|
-
|
|
211
|
+
const isVideo = !!op.insert.video;
|
|
212
|
+
const isImage = !!op.insert.image;
|
|
213
|
+
if (props.disableMedia) {
|
|
214
|
+
return !isVideo && !isImage;
|
|
215
|
+
}
|
|
216
|
+
if (isImage && typeof op.insert.image === "string" && op.insert.image.startsWith("data:")) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
return !isVideo;
|
|
130
220
|
}
|
|
131
221
|
return true;
|
|
132
222
|
});
|
|
@@ -141,12 +231,15 @@ onMounted(() => {
|
|
|
141
231
|
}
|
|
142
232
|
}
|
|
143
233
|
});
|
|
234
|
+
quillEditor.root.addEventListener("paste", handlePasteImage);
|
|
144
235
|
if (props.disableMedia) {
|
|
145
236
|
const editorRoot = quillEditor.root;
|
|
146
237
|
editorRoot.addEventListener("dragenter", handleDragEnter);
|
|
147
238
|
editorRoot.addEventListener("dragover", handleDragOver);
|
|
148
239
|
editorRoot.addEventListener("dragleave", handleDragLeave);
|
|
149
240
|
editorRoot.addEventListener("drop", handleDrop);
|
|
241
|
+
} else {
|
|
242
|
+
quillEditor.root.addEventListener("drop", handleDropUpload);
|
|
150
243
|
}
|
|
151
244
|
}
|
|
152
245
|
});
|
|
@@ -184,12 +277,15 @@ const handleDrop = (e) => {
|
|
|
184
277
|
onUnmounted(() => {
|
|
185
278
|
if (quillEditor && contentRef.value) {
|
|
186
279
|
quillEditor.off("text-change");
|
|
280
|
+
quillEditor.root.removeEventListener("paste", handlePasteImage);
|
|
187
281
|
if (props.disableMedia) {
|
|
188
282
|
const editorRoot = quillEditor.root;
|
|
189
283
|
editorRoot.removeEventListener("dragenter", handleDragEnter);
|
|
190
284
|
editorRoot.removeEventListener("dragover", handleDragOver);
|
|
191
285
|
editorRoot.removeEventListener("dragleave", handleDragLeave);
|
|
192
286
|
editorRoot.removeEventListener("drop", handleDrop);
|
|
287
|
+
} else {
|
|
288
|
+
quillEditor.root.removeEventListener("drop", handleDropUpload);
|
|
193
289
|
}
|
|
194
290
|
const toolbar = contentRef.value.previousElementSibling;
|
|
195
291
|
if (toolbar && toolbar.classList.contains("ql-toolbar")) {
|
|
@@ -8,6 +8,7 @@ export interface InputContentProps {
|
|
|
8
8
|
placeholder?: string;
|
|
9
9
|
disabledBorder?: boolean;
|
|
10
10
|
disableMedia?: boolean;
|
|
11
|
+
state?: "personal" | "business";
|
|
11
12
|
}
|
|
12
13
|
type __VLS_Props = InputContentProps;
|
|
13
14
|
type __VLS_ModelProps = {
|
|
@@ -31,6 +32,7 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
31
32
|
required: boolean;
|
|
32
33
|
id: string;
|
|
33
34
|
name: string;
|
|
35
|
+
state: "personal" | "business";
|
|
34
36
|
disableMedia: boolean;
|
|
35
37
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
36
38
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -31,8 +31,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
31
31
|
fullHeight: boolean;
|
|
32
32
|
name: string;
|
|
33
33
|
limit: number;
|
|
34
|
-
disabledErrorMessage: boolean;
|
|
35
34
|
accept: string;
|
|
35
|
+
disabledErrorMessage: boolean;
|
|
36
36
|
labelIcon: string;
|
|
37
37
|
disabledDrop: boolean;
|
|
38
38
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -31,8 +31,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
31
31
|
fullHeight: boolean;
|
|
32
32
|
name: string;
|
|
33
33
|
limit: number;
|
|
34
|
-
disabledErrorMessage: boolean;
|
|
35
34
|
accept: string;
|
|
35
|
+
disabledErrorMessage: boolean;
|
|
36
36
|
labelIcon: string;
|
|
37
37
|
disabledDrop: boolean;
|
|
38
38
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -18,8 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
18
18
|
}>, {
|
|
19
19
|
id: string;
|
|
20
20
|
name: string;
|
|
21
|
-
new: boolean;
|
|
22
21
|
disabledForgotPassword: boolean;
|
|
22
|
+
new: boolean;
|
|
23
23
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
24
|
declare const _default: typeof __VLS_export;
|
|
25
25
|
export default _default;
|
|
@@ -18,8 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
18
18
|
}>, {
|
|
19
19
|
id: string;
|
|
20
20
|
name: string;
|
|
21
|
-
new: boolean;
|
|
22
21
|
disabledForgotPassword: boolean;
|
|
22
|
+
new: boolean;
|
|
23
23
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
24
24
|
declare const _default: typeof __VLS_export;
|
|
25
25
|
export default _default;
|
|
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
12
12
|
label: string;
|
|
13
13
|
color: InputSliderColor;
|
|
14
14
|
fullWidth: boolean;
|
|
15
|
+
step: number;
|
|
15
16
|
max: number;
|
|
16
17
|
min: number;
|
|
17
|
-
step: number;
|
|
18
18
|
lineHeight: number | string;
|
|
19
19
|
appearance: boolean;
|
|
20
20
|
thumbSize: number | string;
|
|
@@ -12,9 +12,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
12
12
|
label: string;
|
|
13
13
|
color: InputSliderColor;
|
|
14
14
|
fullWidth: boolean;
|
|
15
|
+
step: number;
|
|
15
16
|
max: number;
|
|
16
17
|
min: number;
|
|
17
|
-
step: number;
|
|
18
18
|
lineHeight: number | string;
|
|
19
19
|
appearance: boolean;
|
|
20
20
|
thumbSize: number | string;
|
|
@@ -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;
|
|
@@ -24,8 +24,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
|
|
|
24
24
|
onClose?: (() => 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
|
onClose?: (() => 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;
|
|
@@ -6,17 +6,17 @@ export declare class Convert {
|
|
|
6
6
|
convertNumber: (num: number) => string;
|
|
7
7
|
/**
|
|
8
8
|
* Convert date to Thai format
|
|
9
|
-
* @example convertDate("2024-01-01") => "1
|
|
9
|
+
* @example convertDate("2024-01-01") => "1 มกราคม 2567"
|
|
10
10
|
*/
|
|
11
11
|
convertDate: (date: string | Date | null | undefined, format?: string) => string;
|
|
12
12
|
/**
|
|
13
13
|
* Convert date time to Thai format
|
|
14
|
-
* @example convertDateTime("2024-01-01 12:00") => "1
|
|
14
|
+
* @example convertDateTime("2024-01-01 12:00") => "1 มกราคม 2567 12:00"
|
|
15
15
|
*/
|
|
16
16
|
convertDateTime: (date: string | Date | null | undefined, format?: string) => string;
|
|
17
17
|
/**
|
|
18
18
|
* Convert date to relative text
|
|
19
|
-
* @example "เมื่อสักครู่", "10 นาทีที่ผ่านมา", "2 ชั่วโมงที่ผ่านมา", "17
|
|
19
|
+
* @example "เมื่อสักครู่", "10 นาทีที่ผ่านมา", "2 ชั่วโมงที่ผ่านมา", "17 กุมภาพันธ์ 2569, 13:19"
|
|
20
20
|
*/
|
|
21
21
|
convertDateTorelativeText: (date: string | Date | null | undefined) => string;
|
|
22
22
|
}
|
|
@@ -25,23 +25,23 @@ export class Convert {
|
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
27
|
* Convert date to Thai format
|
|
28
|
-
* @example convertDate("2024-01-01") => "1
|
|
28
|
+
* @example convertDate("2024-01-01") => "1 มกราคม 2567"
|
|
29
29
|
*/
|
|
30
|
-
convertDate = (date, format = "D
|
|
30
|
+
convertDate = (date, format = "D MMMM BBBB") => {
|
|
31
31
|
if (!date) return "-";
|
|
32
32
|
return dayjs(date).format(format);
|
|
33
33
|
};
|
|
34
34
|
/**
|
|
35
35
|
* Convert date time to Thai format
|
|
36
|
-
* @example convertDateTime("2024-01-01 12:00") => "1
|
|
36
|
+
* @example convertDateTime("2024-01-01 12:00") => "1 มกราคม 2567 12:00"
|
|
37
37
|
*/
|
|
38
|
-
convertDateTime = (date, format = "D
|
|
38
|
+
convertDateTime = (date, format = "D MMMM BBBB, HH:mm") => {
|
|
39
39
|
if (!date) return "-";
|
|
40
40
|
return dayjs(date).format(format);
|
|
41
41
|
};
|
|
42
42
|
/**
|
|
43
43
|
* Convert date to relative text
|
|
44
|
-
* @example "เมื่อสักครู่", "10 นาทีที่ผ่านมา", "2 ชั่วโมงที่ผ่านมา", "17
|
|
44
|
+
* @example "เมื่อสักครู่", "10 นาทีที่ผ่านมา", "2 ชั่วโมงที่ผ่านมา", "17 กุมภาพันธ์ 2569, 13:19"
|
|
45
45
|
*/
|
|
46
46
|
convertDateTorelativeText = (date) => {
|
|
47
47
|
if (!date) return "-";
|
|
@@ -58,7 +58,7 @@ export class Convert {
|
|
|
58
58
|
if (diffHour < 24) {
|
|
59
59
|
return `${diffHour} \u0E0A\u0E31\u0E48\u0E27\u0E42\u0E21\u0E07\u0E17\u0E35\u0E48\u0E1C\u0E48\u0E32\u0E19\u0E21\u0E32`;
|
|
60
60
|
}
|
|
61
|
-
return this.convertDateTime(date, "D
|
|
61
|
+
return this.convertDateTime(date, "D MMMM BBBB, HH:mm");
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
const convertInstance = new Convert();
|