@ramathibodi/nuxt-commons 0.0.1
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/README.md +81 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.mts +7 -0
- package/dist/module.d.ts +7 -0
- package/dist/module.json +8 -0
- package/dist/module.mjs +34 -0
- package/dist/runtime/components/Alert.vue +52 -0
- package/dist/runtime/components/BarcodeReader.vue +98 -0
- package/dist/runtime/components/Calendar.vue +99 -0
- package/dist/runtime/components/Camera.vue +116 -0
- package/dist/runtime/components/ExportCSV.vue +55 -0
- package/dist/runtime/components/FileBtn.vue +56 -0
- package/dist/runtime/components/ImportCSV.vue +64 -0
- package/dist/runtime/components/Pdf/Print.vue +63 -0
- package/dist/runtime/components/Pdf/View.vue +70 -0
- package/dist/runtime/components/TabsGroup.vue +28 -0
- package/dist/runtime/components/TextBarcode.vue +52 -0
- package/dist/runtime/components/dialog/Confirm.vue +100 -0
- package/dist/runtime/components/dialog/Index.vue +72 -0
- package/dist/runtime/components/dialog/Loading.vue +34 -0
- package/dist/runtime/components/form/Date.vue +163 -0
- package/dist/runtime/components/form/DateTime.vue +107 -0
- package/dist/runtime/components/form/File.vue +187 -0
- package/dist/runtime/components/form/Login.vue +131 -0
- package/dist/runtime/components/form/Pad.vue +179 -0
- package/dist/runtime/components/form/SignPad.vue +186 -0
- package/dist/runtime/components/form/Time.vue +158 -0
- package/dist/runtime/components/form/images/CameraCrop.vue +58 -0
- package/dist/runtime/components/form/images/Edit.vue +143 -0
- package/dist/runtime/components/form/images/Preview.vue +48 -0
- package/dist/runtime/components/label/Date.vue +29 -0
- package/dist/runtime/components/label/FormatMoney.vue +29 -0
- package/dist/runtime/composables/alert.d.ts +13 -0
- package/dist/runtime/composables/alert.mjs +44 -0
- package/dist/runtime/composables/utils/validation.d.ts +32 -0
- package/dist/runtime/composables/utils/validation.mjs +36 -0
- package/dist/runtime/labs/form/EditMobile.vue +153 -0
- package/dist/runtime/labs/form/TextFieldMask.vue +43 -0
- package/dist/runtime/plugins/vueSignaturePad.d.ts +2 -0
- package/dist/runtime/plugins/vueSignaturePad.mjs +5 -0
- package/dist/runtime/types/alert.d.ts +11 -0
- package/dist/runtime/types/modules.d.ts +5 -0
- package/dist/runtime/utils/datetime.d.ts +25 -0
- package/dist/runtime/utils/datetime.mjs +166 -0
- package/dist/runtime/utils/object.d.ts +8 -0
- package/dist/runtime/utils/object.mjs +28 -0
- package/dist/types.d.mts +16 -0
- package/dist/types.d.ts +16 -0
- package/package.json +90 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref, withDefaults } from 'vue';
|
|
3
|
+
import FormPad from "../../components/form/Pad.vue";
|
|
4
|
+
import { useAlert } from "../../composables/alert";
|
|
5
|
+
import { Mask } from "maska";
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
modelValue: number;
|
|
9
|
+
decimal?: number;
|
|
10
|
+
currency?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const masksInput = new Mask({
|
|
14
|
+
mask: "###-###-N",
|
|
15
|
+
tokens: {
|
|
16
|
+
N: { pattern: /[0-9]/, multiple: true }
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const alert = useAlert();
|
|
21
|
+
const dialog = ref(false);
|
|
22
|
+
const phone = ref();
|
|
23
|
+
const typePhone = ref([]);
|
|
24
|
+
const formPadTemplate = ref();
|
|
25
|
+
const phoneNoField: any = ref(null);
|
|
26
|
+
const objAddNew = ref({ phone: "", type: <any>[] });
|
|
27
|
+
|
|
28
|
+
const listPhonesAll = ref([
|
|
29
|
+
{ "phone": "082745855410101", "type": ["default"] },
|
|
30
|
+
{ "phone": "0827196038", "type": null },
|
|
31
|
+
{ "phone": "0956458547", "type": ["post", "receipt"] }
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
const listPhonesType = ref([
|
|
35
|
+
{ "id": "default", "name": "ค่าเริ่มต้น" },
|
|
36
|
+
{ "id": "post", "name": "จัดส่งไปรษณีย์" },
|
|
37
|
+
{ "id": "receipt", "name": "จัดส่งใบเสร็จ (e-receipt)" }
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
const property = withDefaults(defineProps<Props>(), {
|
|
41
|
+
modelValue: 0,
|
|
42
|
+
decimal: 2,
|
|
43
|
+
currency: "",
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const focusOnTextField = () => {
|
|
47
|
+
if (phoneNoField.value) {
|
|
48
|
+
phoneNoField.value.focus();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const mapTypeName = (id: string) => {
|
|
53
|
+
const item = listPhonesType.value.find(entry => entry.id === id);
|
|
54
|
+
return item ? item.name : undefined;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const mapPhoneCurrent = (phone: string) => {
|
|
58
|
+
const item = listPhonesAll.value.find(entry => entry.phone === phone);
|
|
59
|
+
return item ? item.phone : "";
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const add = () => {
|
|
63
|
+
if (formPadTemplate.value.isValid) {
|
|
64
|
+
objAddNew.value.phone = phone.value.phone;
|
|
65
|
+
objAddNew.value.type = typePhone.value.length === 0 ? ["default"] : typePhone.value;
|
|
66
|
+
|
|
67
|
+
if (mapPhoneCurrent(objAddNew.value.phone) != "") {
|
|
68
|
+
focusOnTextField();
|
|
69
|
+
alert?.addAlert({ message: "เบอร์โทรศัพท์ซ้ำ กรุณาตรวจสอบ", alertType: 'error' });
|
|
70
|
+
} else {
|
|
71
|
+
dialog.value = false;
|
|
72
|
+
listPhonesAll.value.push(objAddNew.value);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const registerPhone = () => {
|
|
78
|
+
dialog.value = true;
|
|
79
|
+
phone.value = "";
|
|
80
|
+
typePhone.value = [];
|
|
81
|
+
};
|
|
82
|
+
</script>
|
|
83
|
+
|
|
84
|
+
<template>
|
|
85
|
+
<v-row class="ma-5">
|
|
86
|
+
<v-col cols="4">
|
|
87
|
+
<div>
|
|
88
|
+
<v-card v-for="item in listPhonesAll" :key="item.phone"
|
|
89
|
+
class="mt-1"
|
|
90
|
+
variant="tonal"
|
|
91
|
+
width="auto"
|
|
92
|
+
:title="masksInput.masked(item.phone)"
|
|
93
|
+
>
|
|
94
|
+
<v-card-text class="pl-10">
|
|
95
|
+
<v-chip color="primary" v-for="itemType in item.type">{{ mapTypeName(itemType) }}</v-chip>
|
|
96
|
+
</v-card-text>
|
|
97
|
+
<template v-slot:prepend>
|
|
98
|
+
<v-icon icon="mdi mdi-phone"></v-icon>
|
|
99
|
+
</template>
|
|
100
|
+
<template v-slot:append>
|
|
101
|
+
<v-icon icon="mdi mdi-pencil"></v-icon>
|
|
102
|
+
</template>
|
|
103
|
+
</v-card>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="mt-1">
|
|
106
|
+
<v-btn size="large" prepend-icon="mdi mdi-plus" color="primary" :block="true" @click="registerPhone">เพิ่มเบอร์โทรศัพท์ใหม่</v-btn>
|
|
107
|
+
</div>
|
|
108
|
+
</v-col>
|
|
109
|
+
<v-col cols="4">
|
|
110
|
+
</v-col>
|
|
111
|
+
</v-row>
|
|
112
|
+
<v-dialog v-model="dialog" width="550">
|
|
113
|
+
<v-card title="เบอร์โทรศัพท์ใหม่">
|
|
114
|
+
<template v-slot:prepend>
|
|
115
|
+
<v-icon icon="mdi mdi-phone-plus"></v-icon>
|
|
116
|
+
</template>
|
|
117
|
+
<template v-slot:append>
|
|
118
|
+
<v-icon icon="mdi mdi-close" @click="dialog = false"></v-icon>
|
|
119
|
+
</template>
|
|
120
|
+
<v-card-text>
|
|
121
|
+
<form-pad ref="formPadTemplate" v-model="phone">
|
|
122
|
+
<template v-slot:default="{ data, rules }">
|
|
123
|
+
<v-text-field
|
|
124
|
+
ref="phoneNoField"
|
|
125
|
+
color="primary"
|
|
126
|
+
label="เบอร์โทรศัพท์ (Phone Number)"
|
|
127
|
+
variant="underlined"
|
|
128
|
+
:rules="[rules.telephone('เบอร์โทรศัพท์ไม่ถูกต้อง'), rules.require()]"
|
|
129
|
+
v-model="data.phone"
|
|
130
|
+
:autofocus="true"
|
|
131
|
+
></v-text-field>
|
|
132
|
+
</template>
|
|
133
|
+
</form-pad>
|
|
134
|
+
<v-chip-group
|
|
135
|
+
v-model="typePhone"
|
|
136
|
+
column
|
|
137
|
+
multiple
|
|
138
|
+
selected-class="text-primary"
|
|
139
|
+
>
|
|
140
|
+
<v-chip v-for="item in listPhonesType" :key="item.id" :value="item.id"
|
|
141
|
+
filter
|
|
142
|
+
variant="outlined"
|
|
143
|
+
>
|
|
144
|
+
{{ item.name }}
|
|
145
|
+
</v-chip>
|
|
146
|
+
</v-chip-group>
|
|
147
|
+
</v-card-text>
|
|
148
|
+
<v-card-actions>
|
|
149
|
+
<v-btn color="primary" variant="flat" @click="add" :block="true">ยืนยัน</v-btn>
|
|
150
|
+
</v-card-actions>
|
|
151
|
+
</v-card>
|
|
152
|
+
</v-dialog>
|
|
153
|
+
</template>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import { VTextField } from 'vuetify/components/VTextField'
|
|
4
|
+
import { type MaskaDetail, type MaskOptions, vMaska } from 'maska'
|
|
5
|
+
|
|
6
|
+
export interface Props extends /* @vue-ignore */ InstanceType<typeof VTextField['$props']> {
|
|
7
|
+
type: 'eReceipt' | 'telephone'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = defineProps<Props>()
|
|
11
|
+
const emit = defineEmits<{
|
|
12
|
+
(event: 'update:modelValue', value: string): void
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const computedMaskOption = computed<MaskOptions>(() => {
|
|
16
|
+
if (props.type == 'eReceipt') return { mask: '##-##-N', tokens: { N: { pattern: /[0-9]/, multiple: true } } }
|
|
17
|
+
if (props.type == 'telephone') return { mask: '###-###-####' }
|
|
18
|
+
return {}
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
function onMaska(event: CustomEvent<MaskaDetail>) {
|
|
22
|
+
emit('update:modelValue', event.detail.unmasked)
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<template>
|
|
27
|
+
<v-text-field
|
|
28
|
+
v-maska:[computedMaskOption]
|
|
29
|
+
v-bind="$attrs"
|
|
30
|
+
@maska="onMaska"
|
|
31
|
+
>
|
|
32
|
+
<template
|
|
33
|
+
v-for="(_, slot, index) in ($slots as {})"
|
|
34
|
+
:key="index"
|
|
35
|
+
#[slot]="scope"
|
|
36
|
+
>
|
|
37
|
+
<slot
|
|
38
|
+
:name="slot"
|
|
39
|
+
v-bind="{ scope }"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
</v-text-field>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface AlertItem {
|
|
2
|
+
message: string
|
|
3
|
+
statusCode?: number
|
|
4
|
+
statusMessage?: string
|
|
5
|
+
alertLocation?: string
|
|
6
|
+
alertType?: 'error' | 'success' | 'warning' | 'info' | undefined
|
|
7
|
+
alertIcon?: string
|
|
8
|
+
alertDateTime?: number
|
|
9
|
+
alertExpireIn?: number
|
|
10
|
+
data?: object
|
|
11
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type DateObjectUnits, type DateTimeFormatOptions, DateTime } from 'luxon';
|
|
2
|
+
export type supportedLocale = 'EN' | 'TH';
|
|
3
|
+
export type dateFormat = 'tinyDate' | 'monthShortDate' | 'shortDate' | 'longDate';
|
|
4
|
+
export type dateTimeFormat = 'tinyDateTime' | 'shortDateTime' | 'longDateTime';
|
|
5
|
+
export declare const Datetime: () => {
|
|
6
|
+
luxonDateTime: DateTime<false>;
|
|
7
|
+
fromString: (dateTime: string | null, formatDate?: string, locale?: supportedLocale) => any;
|
|
8
|
+
fromStringTime: (time: string | null, formatTime?: string, locale?: supportedLocale) => any;
|
|
9
|
+
fromISO: (dateTime: string, locale?: supportedLocale) => any;
|
|
10
|
+
fromObject: (dateTime: DateObjectUnits, locale?: supportedLocale) => any;
|
|
11
|
+
setDateTime: (inputDate: DateTime, locale?: supportedLocale) => any;
|
|
12
|
+
toFormat: (format: string, locale?: supportedLocale) => any;
|
|
13
|
+
toISO: () => any;
|
|
14
|
+
toLocaleFormat: (locale: supportedLocale, format: DateTimeFormatOptions) => any;
|
|
15
|
+
toTinyDate: (locale?: supportedLocale) => any;
|
|
16
|
+
toMonthShortDate: (locale?: supportedLocale) => any;
|
|
17
|
+
toShortDate: (locale?: supportedLocale) => any;
|
|
18
|
+
toLongDate: (locale?: supportedLocale) => any;
|
|
19
|
+
toTinyDateTime: (locale?: supportedLocale) => any;
|
|
20
|
+
toShortDateTime: (locale?: supportedLocale) => any;
|
|
21
|
+
toLongDateTime: (locale?: supportedLocale) => any;
|
|
22
|
+
now: () => any;
|
|
23
|
+
};
|
|
24
|
+
export declare function verifyDateFormat(date: string): string | null;
|
|
25
|
+
export declare function returnVerifyDate(date: string): string | null;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
export const Datetime = () => ({
|
|
3
|
+
luxonDateTime: DateTime.invalid("Uninitialized"),
|
|
4
|
+
fromString: function(dateTime, formatDate, locale = "EN") {
|
|
5
|
+
if (!dateTime)
|
|
6
|
+
return this.setDateTime(DateTime.invalid("No datetime string provided"), locale);
|
|
7
|
+
let inputDate = void 0;
|
|
8
|
+
if (formatDate)
|
|
9
|
+
inputDate = DateTime.fromFormat(dateTime, formatDate, { locale });
|
|
10
|
+
if (!inputDate?.isValid)
|
|
11
|
+
inputDate = DateTime.fromISO(dateTime, { locale });
|
|
12
|
+
if (!inputDate?.isValid) {
|
|
13
|
+
const formats = [
|
|
14
|
+
"ddMMyyyy",
|
|
15
|
+
"ddMMyy",
|
|
16
|
+
"dd/MM/yyyy",
|
|
17
|
+
"yyyyMMdd",
|
|
18
|
+
"dd/MM/yyyy",
|
|
19
|
+
"dd/M/yyyy",
|
|
20
|
+
"d/MM/yyyy",
|
|
21
|
+
"d/M/yyyy",
|
|
22
|
+
"dd MMM yyyy",
|
|
23
|
+
"d MMM yyyy",
|
|
24
|
+
"yyyy-MM-dd HH:mm",
|
|
25
|
+
"yyyy-MM-dd HH:mm:ss"
|
|
26
|
+
];
|
|
27
|
+
for (let i = 0; i < formats.length; ++i) {
|
|
28
|
+
inputDate = DateTime.fromFormat(dateTime, formats[i], { locale });
|
|
29
|
+
if (inputDate.isValid)
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return this.setDateTime(inputDate, locale);
|
|
34
|
+
},
|
|
35
|
+
fromStringTime: function(time, formatTime, locale = "EN") {
|
|
36
|
+
if (!time)
|
|
37
|
+
return this.setDateTime(DateTime.invalid("No datetime string provided"), locale);
|
|
38
|
+
let inputTime = void 0;
|
|
39
|
+
if (formatTime)
|
|
40
|
+
inputTime = DateTime.fromFormat(time, formatTime, { locale });
|
|
41
|
+
if (!inputTime?.isValid) {
|
|
42
|
+
const formats = [
|
|
43
|
+
"HHmm",
|
|
44
|
+
"Hmm",
|
|
45
|
+
"HHmmss",
|
|
46
|
+
"HH:mm",
|
|
47
|
+
"H:mm",
|
|
48
|
+
"HH:mm:ss"
|
|
49
|
+
];
|
|
50
|
+
for (let i = 0; i < formats.length; ++i) {
|
|
51
|
+
inputTime = DateTime.fromFormat(time, formats[i], { locale });
|
|
52
|
+
if (inputTime.isValid)
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!inputTime?.isValid)
|
|
57
|
+
inputTime = DateTime.fromISO(time, { locale });
|
|
58
|
+
return this.setDateTime(inputTime, locale);
|
|
59
|
+
},
|
|
60
|
+
fromISO: function(dateTime, locale = "EN") {
|
|
61
|
+
const inputDate = DateTime.fromISO(dateTime, { locale });
|
|
62
|
+
return this.setDateTime(inputDate, locale);
|
|
63
|
+
},
|
|
64
|
+
fromObject: function(dateTime, locale = "EN") {
|
|
65
|
+
const inputDate = DateTime.fromObject(dateTime, { locale });
|
|
66
|
+
return this.setDateTime(inputDate, locale);
|
|
67
|
+
},
|
|
68
|
+
setDateTime: function(inputDate, locale = "EN") {
|
|
69
|
+
if (inputDate.isValid) {
|
|
70
|
+
if (inputDate.year - DateTime.now().year > 300)
|
|
71
|
+
inputDate.set({ year: inputDate.year - 543 });
|
|
72
|
+
}
|
|
73
|
+
this.luxonDateTime = inputDate;
|
|
74
|
+
if (locale == "TH")
|
|
75
|
+
this.luxonDateTime = this.luxonDateTime.setLocale(locale).reconfigure({ outputCalendar: "buddhist" });
|
|
76
|
+
else
|
|
77
|
+
this.luxonDateTime = this.luxonDateTime.setLocale(locale).reconfigure({ outputCalendar: "gregory" });
|
|
78
|
+
return this;
|
|
79
|
+
},
|
|
80
|
+
toFormat: function(format, locale = "EN") {
|
|
81
|
+
if (format == "tinyDate")
|
|
82
|
+
return this.toTinyDate(locale);
|
|
83
|
+
if (format == "monthShortDate")
|
|
84
|
+
return this.toMonthShortDate(locale);
|
|
85
|
+
if (format == "shortDate")
|
|
86
|
+
return this.toShortDate(locale);
|
|
87
|
+
if (format == "longDate")
|
|
88
|
+
return this.toLongDate(locale);
|
|
89
|
+
if (format == "tinyDateTime")
|
|
90
|
+
return this.toTinyDateTime(locale);
|
|
91
|
+
if (format == "shortDateTime")
|
|
92
|
+
return this.toShortDateTime(locale);
|
|
93
|
+
if (format == "longDateTime")
|
|
94
|
+
return this.toLongDateTime(locale);
|
|
95
|
+
if (locale == "TH")
|
|
96
|
+
this.luxonDateTime = this.luxonDateTime.setLocale(locale).reconfigure({ outputCalendar: "buddhist" });
|
|
97
|
+
else
|
|
98
|
+
this.luxonDateTime = this.luxonDateTime.setLocale(locale).reconfigure({ outputCalendar: "gregory" });
|
|
99
|
+
return this.luxonDateTime.toFormat(format);
|
|
100
|
+
},
|
|
101
|
+
toISO: function() {
|
|
102
|
+
return this.luxonDateTime.toISO();
|
|
103
|
+
},
|
|
104
|
+
toLocaleFormat: function(locale, format) {
|
|
105
|
+
if (locale == "TH")
|
|
106
|
+
this.luxonDateTime = this.luxonDateTime.setLocale(locale).reconfigure({ outputCalendar: "buddhist" });
|
|
107
|
+
else
|
|
108
|
+
this.luxonDateTime = this.luxonDateTime.setLocale(locale).reconfigure({ outputCalendar: "gregory" });
|
|
109
|
+
return this.luxonDateTime.setLocale(locale).toLocaleString(format);
|
|
110
|
+
},
|
|
111
|
+
toTinyDate: function(locale = "EN") {
|
|
112
|
+
return this.toLocaleFormat(locale, DateTime.DATE_SHORT);
|
|
113
|
+
},
|
|
114
|
+
toMonthShortDate: function(locale = "EN") {
|
|
115
|
+
return this.toLocaleFormat(locale, DateTime.DATE_MED);
|
|
116
|
+
},
|
|
117
|
+
toShortDate: function(locale = "EN") {
|
|
118
|
+
return this.toLocaleFormat(locale, DateTime.DATE_FULL);
|
|
119
|
+
},
|
|
120
|
+
toLongDate: function(locale = "EN") {
|
|
121
|
+
return this.toLocaleFormat(locale, DateTime.DATE_HUGE);
|
|
122
|
+
},
|
|
123
|
+
toTinyDateTime: function(locale = "EN") {
|
|
124
|
+
return this.toLocaleFormat(locale, DateTime.DATETIME_SHORT);
|
|
125
|
+
},
|
|
126
|
+
toShortDateTime: function(locale = "EN") {
|
|
127
|
+
return this.toLocaleFormat(locale, DateTime.DATETIME_MED);
|
|
128
|
+
},
|
|
129
|
+
toLongDateTime: function(locale = "EN") {
|
|
130
|
+
return this.toLocaleFormat(locale, DateTime.DATETIME_HUGE);
|
|
131
|
+
},
|
|
132
|
+
now: function() {
|
|
133
|
+
const DateNow = DateTime.now();
|
|
134
|
+
this.luxonDateTime = DateNow;
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
export function verifyDateFormat(date) {
|
|
139
|
+
const dateFormatRegex = /^(\d{4}|0{4})-(\d{2}|0{2})-(\d{2}|0{2})$/;
|
|
140
|
+
const match = date.match(dateFormatRegex);
|
|
141
|
+
if (match) {
|
|
142
|
+
const year = match[1];
|
|
143
|
+
const month = match[2];
|
|
144
|
+
const day = match[3];
|
|
145
|
+
const formatYear = Number.parseInt(year) > 0 ? "yyyy" : "";
|
|
146
|
+
const fotmatMonth = Number.parseInt(month) > 0 && Number.parseInt(month) <= 12 ? "MM" : "";
|
|
147
|
+
const formatDay = Number.parseInt(day) > 0 && Number.parseInt(day) <= 31 ? "dd" : "";
|
|
148
|
+
return `${formatYear}${fotmatMonth}${formatDay}`;
|
|
149
|
+
} else {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
export function returnVerifyDate(date) {
|
|
154
|
+
const dateFormatRegex = /^(\d{4}|0{4})-(\d{2}|0{2})-(\d{2}|0{2})$/;
|
|
155
|
+
const match = date.match(dateFormatRegex);
|
|
156
|
+
if (match) {
|
|
157
|
+
const year = match[1];
|
|
158
|
+
const month = match[2];
|
|
159
|
+
const day = match[3];
|
|
160
|
+
const fullMonth = Number.parseInt(month) == 0 || Number.parseInt(month) >= 13 ? "01" : month;
|
|
161
|
+
const fullDay = Number.parseInt(day) == 0 || Number.parseInt(month) >= 32 ? "01" : day;
|
|
162
|
+
return `${year}-${fullMonth}-${fullDay}`;
|
|
163
|
+
} else {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ClassConstructor<T> = {
|
|
2
|
+
new (...args: any[]): T;
|
|
3
|
+
};
|
|
4
|
+
export declare function isClassConstructor<T>(arg: any): arg is ClassConstructor<T>;
|
|
5
|
+
export declare function onlyClassAttributes<T extends Record<string, any>>(cls: ClassConstructor<T>, object: Record<string, any>): Record<string, any>;
|
|
6
|
+
export declare function classAttributes<T extends Record<string, any>>(cls: ClassConstructor<T>): string[];
|
|
7
|
+
export declare function onlyAttributes(keys: string[], object: Record<string, any>): Record<string, any>;
|
|
8
|
+
export declare function renameAttributes(object: Record<string, any>, mapper: Record<string, string>): Record<string, any>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cloneDeep } from "lodash-es";
|
|
2
|
+
export function isClassConstructor(arg) {
|
|
3
|
+
return typeof arg === "function" && /^class\s/.test(arg.toString());
|
|
4
|
+
}
|
|
5
|
+
export function onlyClassAttributes(cls, object) {
|
|
6
|
+
return onlyAttributes(classAttributes(cls), object);
|
|
7
|
+
}
|
|
8
|
+
export function classAttributes(cls) {
|
|
9
|
+
return Object.keys(new cls());
|
|
10
|
+
}
|
|
11
|
+
export function onlyAttributes(keys, object) {
|
|
12
|
+
let returnObject = cloneDeep(object);
|
|
13
|
+
Object.keys(object).forEach((localKey) => {
|
|
14
|
+
if (!keys.includes(localKey))
|
|
15
|
+
delete returnObject[localKey];
|
|
16
|
+
});
|
|
17
|
+
return returnObject;
|
|
18
|
+
}
|
|
19
|
+
export function renameAttributes(object, mapper) {
|
|
20
|
+
let returnObject = cloneDeep(object);
|
|
21
|
+
Object.keys(mapper).forEach((key) => {
|
|
22
|
+
if (returnObject.hasOwnProperty(key)) {
|
|
23
|
+
returnObject[mapper[key]] = cloneDeep(returnObject[key]);
|
|
24
|
+
delete returnObject[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return returnObject;
|
|
28
|
+
}
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import type { ModuleOptions } from './module.js'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
declare module '@nuxt/schema' {
|
|
6
|
+
interface NuxtConfig { ['nuxt-commons']?: Partial<ModuleOptions> }
|
|
7
|
+
interface NuxtOptions { ['nuxt-commons']?: ModuleOptions }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare module 'nuxt/schema' {
|
|
11
|
+
interface NuxtConfig { ['nuxt-commons']?: Partial<ModuleOptions> }
|
|
12
|
+
interface NuxtOptions { ['nuxt-commons']?: ModuleOptions }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export type { ModuleOptions, default } from './module.js'
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import type { ModuleOptions } from './module'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
declare module '@nuxt/schema' {
|
|
6
|
+
interface NuxtConfig { ['nuxt-commons']?: Partial<ModuleOptions> }
|
|
7
|
+
interface NuxtOptions { ['nuxt-commons']?: ModuleOptions }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare module 'nuxt/schema' {
|
|
11
|
+
interface NuxtConfig { ['nuxt-commons']?: Partial<ModuleOptions> }
|
|
12
|
+
interface NuxtOptions { ['nuxt-commons']?: ModuleOptions }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export type { ModuleOptions, default } from './module'
|
package/package.json
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ramathibodi/nuxt-commons",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Ramathibodi Nuxt modules for common components",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://gitlab.rama.mahidol.ac.th/ramacare/frontend/rama-modules.git"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/types.d.ts",
|
|
14
|
+
"import": "./dist/module.mjs",
|
|
15
|
+
"require": "./dist/module.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./utils/*": {
|
|
18
|
+
"types": "./dist/runtime/utils/*.d.ts",
|
|
19
|
+
"import": "./dist/runtime/utils/*.mjs",
|
|
20
|
+
"require": "./dist/runtime/utils/*.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./lab/*" : "./dist/runtime/labs/*.vue",
|
|
23
|
+
"./lab/*/*" : "./dist/runtime/labs/*/*.vue"
|
|
24
|
+
},
|
|
25
|
+
"main": "./dist/module.cjs",
|
|
26
|
+
"types": "./dist/types.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"prepack": "nuxt-module-build build",
|
|
32
|
+
"dev": "nuxi dev playground",
|
|
33
|
+
"dev:build": "nuxi build playground",
|
|
34
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
|
|
35
|
+
"release": "npm run lint && npm run test && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
36
|
+
"lint": "eslint .",
|
|
37
|
+
"lint:fix": "eslint . --fix",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest watch"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@fortawesome/fontawesome-free": "^6.5.2",
|
|
43
|
+
"@fullcalendar/core": "^6.1.11",
|
|
44
|
+
"@fullcalendar/daygrid": "^6.1.11",
|
|
45
|
+
"@fullcalendar/interaction": "^6.1.11",
|
|
46
|
+
"@fullcalendar/list": "^6.1.11",
|
|
47
|
+
"@fullcalendar/multimonth": "^6.1.11",
|
|
48
|
+
"@fullcalendar/timegrid": "^6.1.11",
|
|
49
|
+
"@fullcalendar/vue3": "^6.1.11",
|
|
50
|
+
"@mdi/font": "^7.4.47",
|
|
51
|
+
"@nuxt/kit": "^3.11.2",
|
|
52
|
+
"@nuxtjs/apollo": "5.0.0-alpha.14",
|
|
53
|
+
"@vue/apollo-composable": "^4.0.2",
|
|
54
|
+
"@vuepic/vue-datepicker": "^7.4.1",
|
|
55
|
+
"@zxing/browser": "^0.1.4",
|
|
56
|
+
"cropperjs": "^1.6.2",
|
|
57
|
+
"currency.js": "^2.0.4",
|
|
58
|
+
"gql-query-builder": "^3.8.0",
|
|
59
|
+
"lodash": "^4.17.21",
|
|
60
|
+
"luxon": "^3.4.4",
|
|
61
|
+
"maska": "^2.1.11",
|
|
62
|
+
"pdf-vue3": "^1.0.12",
|
|
63
|
+
"print-js": "^1.6.0",
|
|
64
|
+
"uid": "^2.0.2",
|
|
65
|
+
"vue": "^3.4.25",
|
|
66
|
+
"vue-signature-pad": "^3.0.2",
|
|
67
|
+
"vuetify": "^3.5.17",
|
|
68
|
+
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@nuxt/devtools": "^1.2.0",
|
|
72
|
+
"@nuxt/eslint-config": "^0.3.9",
|
|
73
|
+
"@nuxt/module-builder": "^0.5.5",
|
|
74
|
+
"@nuxt/schema": "^3.11.2",
|
|
75
|
+
"@nuxt/test-utils": "^3.12.1",
|
|
76
|
+
"@types/lodash": "^4.17.0",
|
|
77
|
+
"@types/luxon": "^3.4.2",
|
|
78
|
+
"@types/node": "^18.17.5",
|
|
79
|
+
"@vueuse/core": "^10.9.0",
|
|
80
|
+
"@vueuse/nuxt": "^10.9.0",
|
|
81
|
+
"changelogen": "^0.5.5",
|
|
82
|
+
"eslint": "^9.1.1",
|
|
83
|
+
"nuxt": "^3.11.2",
|
|
84
|
+
"nuxt-lodash": "^2.5.3",
|
|
85
|
+
"sass": "^1.75.0",
|
|
86
|
+
"typescript": "^5.4.5",
|
|
87
|
+
"vitest": "^1.5.1",
|
|
88
|
+
"vue-tsc": "^1.8.27"
|
|
89
|
+
}
|
|
90
|
+
}
|