@ramathibodi/nuxt-commons 0.1.73 → 0.1.75
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 +115 -96
- package/dist/module.json +1 -1
- package/dist/module.mjs +1 -0
- package/dist/runtime/components/Alert.vue +58 -54
- package/dist/runtime/components/BarcodeReader.vue +130 -122
- package/dist/runtime/components/ExportCSV.vue +110 -102
- package/dist/runtime/components/FileBtn.vue +79 -67
- package/dist/runtime/components/ImportCSV.vue +151 -139
- package/dist/runtime/components/MrzReader.vue +168 -0
- package/dist/runtime/components/SplitterPanel.vue +67 -59
- package/dist/runtime/components/TabsGroup.vue +39 -31
- package/dist/runtime/components/TextBarcode.vue +66 -54
- package/dist/runtime/components/device/IdCardButton.vue +95 -83
- package/dist/runtime/components/device/IdCardWebSocket.vue +207 -195
- package/dist/runtime/components/device/Scanner.vue +350 -338
- package/dist/runtime/components/dialog/Confirm.vue +112 -100
- package/dist/runtime/components/dialog/Host.vue +88 -84
- package/dist/runtime/components/dialog/Index.vue +84 -72
- package/dist/runtime/components/dialog/Loading.vue +51 -39
- package/dist/runtime/components/dialog/default/Confirm.vue +112 -100
- package/dist/runtime/components/dialog/default/Loading.vue +60 -48
- package/dist/runtime/components/dialog/default/Notify.vue +82 -70
- package/dist/runtime/components/dialog/default/Printing.vue +46 -34
- package/dist/runtime/components/dialog/default/VerifyUser.vue +144 -132
- package/dist/runtime/components/document/Form.vue +50 -42
- package/dist/runtime/components/document/TemplateBuilder.vue +536 -524
- package/dist/runtime/components/form/ActionPad.vue +156 -144
- package/dist/runtime/components/form/Birthdate.vue +116 -104
- package/dist/runtime/components/form/CheckboxGroup.vue +99 -87
- package/dist/runtime/components/form/CodeEditor.vue +45 -37
- package/dist/runtime/components/form/Date.vue +270 -258
- package/dist/runtime/components/form/DateTime.vue +220 -208
- package/dist/runtime/components/form/Dialog.vue +178 -166
- package/dist/runtime/components/form/EditPad.vue +157 -145
- package/dist/runtime/components/form/File.vue +295 -283
- package/dist/runtime/components/form/Hidden.vue +44 -32
- package/dist/runtime/components/form/Iterator.vue +538 -526
- package/dist/runtime/components/form/Login.vue +143 -131
- package/dist/runtime/components/form/Pad.vue +399 -387
- package/dist/runtime/components/form/SignPad.vue +226 -218
- package/dist/runtime/components/form/System.vue +34 -26
- package/dist/runtime/components/form/Table.vue +391 -379
- package/dist/runtime/components/form/TableData.vue +236 -224
- package/dist/runtime/components/form/Time.vue +177 -165
- package/dist/runtime/components/form/images/Capture.vue +245 -237
- package/dist/runtime/components/form/images/Edit.vue +133 -121
- package/dist/runtime/components/form/images/Field.vue +331 -320
- package/dist/runtime/components/form/images/Pad.vue +54 -42
- package/dist/runtime/components/label/Date.vue +37 -29
- package/dist/runtime/components/label/DateAgo.vue +102 -94
- package/dist/runtime/components/label/DateCount.vue +152 -144
- package/dist/runtime/components/label/Field.vue +111 -103
- package/dist/runtime/components/label/FormatMoney.vue +37 -29
- package/dist/runtime/components/label/Mask.vue +46 -38
- package/dist/runtime/components/label/Object.vue +21 -13
- package/dist/runtime/components/master/Autocomplete.vue +89 -81
- package/dist/runtime/components/master/Combobox.vue +88 -80
- package/dist/runtime/components/master/RadioGroup.vue +90 -78
- package/dist/runtime/components/master/Select.vue +70 -62
- package/dist/runtime/components/master/label.vue +55 -47
- package/dist/runtime/components/model/Autocomplete.vue +91 -79
- package/dist/runtime/components/model/Combobox.vue +90 -78
- package/dist/runtime/components/model/Pad.vue +114 -102
- package/dist/runtime/components/model/Select.vue +78 -72
- package/dist/runtime/components/model/Table.vue +370 -358
- package/dist/runtime/components/model/iterator.vue +497 -489
- package/dist/runtime/components/model/label.vue +58 -50
- package/dist/runtime/components/pdf/Print.vue +75 -63
- package/dist/runtime/components/pdf/View.vue +146 -134
- package/dist/runtime/composables/alert.d.ts +4 -0
- package/dist/runtime/composables/api.d.ts +4 -0
- package/dist/runtime/composables/dialog.d.ts +1 -1
- package/dist/runtime/composables/document/templateFormHidden.d.ts +4 -0
- package/dist/runtime/composables/graphql.d.ts +1 -1
- package/dist/runtime/composables/graphqlModel.d.ts +9 -9
- package/dist/runtime/composables/graphqlModelItem.d.ts +7 -7
- package/dist/runtime/composables/graphqlModelOperation.d.ts +6 -6
- package/dist/runtime/composables/localStorageModel.d.ts +4 -0
- package/dist/runtime/composables/lookupList.d.ts +4 -0
- package/dist/runtime/composables/menu.d.ts +4 -0
- package/dist/runtime/composables/useMrzReader.d.ts +48 -0
- package/dist/runtime/composables/useMrzReader.js +423 -0
- package/dist/runtime/composables/useTesseract.d.ts +16 -0
- package/dist/runtime/composables/useTesseract.js +45 -0
- package/dist/runtime/composables/userPermission.d.ts +1 -1
- package/dist/runtime/labs/Calendar.vue +99 -99
- package/dist/runtime/labs/form/EditMobile.vue +152 -152
- package/dist/runtime/labs/form/TextFieldMask.vue +43 -43
- package/dist/runtime/plugins/clientConfig.d.ts +1 -1
- package/dist/runtime/plugins/default.d.ts +1 -1
- package/dist/runtime/plugins/dialogManager.d.ts +1 -1
- package/dist/runtime/plugins/permission.d.ts +1 -1
- package/dist/runtime/types/alert.d.ts +11 -11
- package/dist/runtime/types/clientConfig.d.ts +13 -13
- package/dist/runtime/types/dialogManager.d.ts +35 -35
- package/dist/runtime/types/formDialog.d.ts +5 -5
- package/dist/runtime/types/graphqlOperation.d.ts +23 -23
- package/dist/runtime/types/menu.d.ts +31 -31
- package/dist/runtime/types/modules.d.ts +7 -7
- package/dist/runtime/types/permission.d.ts +13 -13
- package/dist/runtime/utils/asset.d.ts +2 -0
- package/dist/runtime/utils/asset.js +49 -0
- package/package.json +131 -122
- package/scripts/enrich-vue-docs-from-ai.mjs +197 -0
- package/scripts/generate-ai-summary.mjs +321 -0
- package/scripts/generate-composables-md.mjs +129 -0
- package/scripts/postInstall.cjs +70 -70
- package/templates/.codegen/codegen.ts +32 -32
- package/templates/.codegen/plugin-schema-object.js +161 -161
- package/templates/public/tesseract/mrz.traineddata.gz +0 -0
- package/templates/public/tesseract/ocrb.traineddata.gz +0 -0
|
@@ -1,99 +1,99 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import FullCalendar from '@fullcalendar/vue3'
|
|
3
|
-
import dayGridPlugin from '@fullcalendar/daygrid'
|
|
4
|
-
import timeGridPlugin from '@fullcalendar/timegrid'
|
|
5
|
-
import listPlugin from '@fullcalendar/list'
|
|
6
|
-
import interactionPlugin from '@fullcalendar/interaction'
|
|
7
|
-
import { ref, computed, withDefaults } from 'vue'
|
|
8
|
-
import { type CalendarOptions } from '@fullcalendar/core'
|
|
9
|
-
|
|
10
|
-
type Event = {
|
|
11
|
-
id: string | undefined
|
|
12
|
-
title: string
|
|
13
|
-
start: string // YYYY-MM-DD | YYYY-MM-DD HH:mm:ss
|
|
14
|
-
end: string // YYYY-MM-DD
|
|
15
|
-
color: string
|
|
16
|
-
detail?: string
|
|
17
|
-
props: Record<string, any> | any[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface CalendarProps {
|
|
21
|
-
modelValue: Event[]
|
|
22
|
-
locale?: 'th' | 'en'
|
|
23
|
-
toolBarLeft?: string
|
|
24
|
-
toolBarCenter?: string
|
|
25
|
-
toolBarRight?: string
|
|
26
|
-
height?: string | number
|
|
27
|
-
selectViewDay?: string
|
|
28
|
-
mode: 'dayGridMonth' | 'timeGridDay'
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const props = withDefaults(defineProps<CalendarProps>(), {
|
|
32
|
-
locale: 'th',
|
|
33
|
-
height: 1200,
|
|
34
|
-
toolBarLeft: 'today prev,next',
|
|
35
|
-
toolBarCenter: 'title',
|
|
36
|
-
toolBarRight: 'timeGridDay,timeGridWeek,dayGridMonth',
|
|
37
|
-
mode: 'dayGridMonth',
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const emit = defineEmits(['select', 'dialog'])
|
|
41
|
-
|
|
42
|
-
const buttonText = computed(() => {
|
|
43
|
-
return {
|
|
44
|
-
today: props.locale === 'th' ? 'วันนี้' : 'today',
|
|
45
|
-
month: props.locale === 'th' ? 'เดือน' : 'month',
|
|
46
|
-
week: props.locale === 'th' ? 'สัปดาห์' : 'week',
|
|
47
|
-
day: props.locale === 'th' ? 'วัน' : 'day',
|
|
48
|
-
list: props.locale === 'th' ? 'รายการ' : 'list',
|
|
49
|
-
year: props.locale === 'th' ? 'ปี' : 'year',
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
const calendarRef = ref<InstanceType<typeof FullCalendar>>()
|
|
54
|
-
const dateViewDay = ref({ date: '', props: {} })
|
|
55
|
-
|
|
56
|
-
const handleDateClick = (info: any) => {
|
|
57
|
-
emit('select', info.event)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const handleEventClick = (info: any) => {
|
|
61
|
-
emit('dialog', true)
|
|
62
|
-
emit('select', info.event)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const eventContentDay = (arg: any) => {
|
|
66
|
-
const list = document.createElement('div')
|
|
67
|
-
list.innerHTML = document.getElementById(arg.event.id.toString())?.innerHTML || ''
|
|
68
|
-
return { domNodes: [list] }
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// @ts-expect-error
|
|
72
|
-
const calendarOptions = ref<CalendarOptions>({
|
|
73
|
-
plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin],
|
|
74
|
-
initialView: props.mode,
|
|
75
|
-
locale: props.locale,
|
|
76
|
-
dayMaxEvents: true,
|
|
77
|
-
timeZone: 'UTC',
|
|
78
|
-
headerToolbar: {
|
|
79
|
-
left: props.toolBarLeft,
|
|
80
|
-
center: props.toolBarCenter,
|
|
81
|
-
right: props.toolBarRight,
|
|
82
|
-
},
|
|
83
|
-
buttonText: buttonText.value,
|
|
84
|
-
events: props.modelValue,
|
|
85
|
-
initialDate: props.selectViewDay,
|
|
86
|
-
dateClick: handleDateClick,
|
|
87
|
-
eventClick: handleEventClick,
|
|
88
|
-
nowIndicator: true,
|
|
89
|
-
height: props.height,
|
|
90
|
-
eventColor: '#378006',
|
|
91
|
-
})
|
|
92
|
-
</script>
|
|
93
|
-
|
|
94
|
-
<template>
|
|
95
|
-
<FullCalendar
|
|
96
|
-
ref="calendarRef"
|
|
97
|
-
:options="calendarOptions as CalendarOptions"
|
|
98
|
-
/>
|
|
99
|
-
</template>
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import FullCalendar from '@fullcalendar/vue3'
|
|
3
|
+
import dayGridPlugin from '@fullcalendar/daygrid'
|
|
4
|
+
import timeGridPlugin from '@fullcalendar/timegrid'
|
|
5
|
+
import listPlugin from '@fullcalendar/list'
|
|
6
|
+
import interactionPlugin from '@fullcalendar/interaction'
|
|
7
|
+
import { ref, computed, withDefaults } from 'vue'
|
|
8
|
+
import { type CalendarOptions } from '@fullcalendar/core'
|
|
9
|
+
|
|
10
|
+
type Event = {
|
|
11
|
+
id: string | undefined
|
|
12
|
+
title: string
|
|
13
|
+
start: string // YYYY-MM-DD | YYYY-MM-DD HH:mm:ss
|
|
14
|
+
end: string // YYYY-MM-DD
|
|
15
|
+
color: string
|
|
16
|
+
detail?: string
|
|
17
|
+
props: Record<string, any> | any[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface CalendarProps {
|
|
21
|
+
modelValue: Event[]
|
|
22
|
+
locale?: 'th' | 'en'
|
|
23
|
+
toolBarLeft?: string
|
|
24
|
+
toolBarCenter?: string
|
|
25
|
+
toolBarRight?: string
|
|
26
|
+
height?: string | number
|
|
27
|
+
selectViewDay?: string
|
|
28
|
+
mode: 'dayGridMonth' | 'timeGridDay'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const props = withDefaults(defineProps<CalendarProps>(), {
|
|
32
|
+
locale: 'th',
|
|
33
|
+
height: 1200,
|
|
34
|
+
toolBarLeft: 'today prev,next',
|
|
35
|
+
toolBarCenter: 'title',
|
|
36
|
+
toolBarRight: 'timeGridDay,timeGridWeek,dayGridMonth',
|
|
37
|
+
mode: 'dayGridMonth',
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const emit = defineEmits(['select', 'dialog'])
|
|
41
|
+
|
|
42
|
+
const buttonText = computed(() => {
|
|
43
|
+
return {
|
|
44
|
+
today: props.locale === 'th' ? 'วันนี้' : 'today',
|
|
45
|
+
month: props.locale === 'th' ? 'เดือน' : 'month',
|
|
46
|
+
week: props.locale === 'th' ? 'สัปดาห์' : 'week',
|
|
47
|
+
day: props.locale === 'th' ? 'วัน' : 'day',
|
|
48
|
+
list: props.locale === 'th' ? 'รายการ' : 'list',
|
|
49
|
+
year: props.locale === 'th' ? 'ปี' : 'year',
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const calendarRef = ref<InstanceType<typeof FullCalendar>>()
|
|
54
|
+
const dateViewDay = ref({ date: '', props: {} })
|
|
55
|
+
|
|
56
|
+
const handleDateClick = (info: any) => {
|
|
57
|
+
emit('select', info.event)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const handleEventClick = (info: any) => {
|
|
61
|
+
emit('dialog', true)
|
|
62
|
+
emit('select', info.event)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const eventContentDay = (arg: any) => {
|
|
66
|
+
const list = document.createElement('div')
|
|
67
|
+
list.innerHTML = document.getElementById(arg.event.id.toString())?.innerHTML || ''
|
|
68
|
+
return { domNodes: [list] }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// @ts-expect-error
|
|
72
|
+
const calendarOptions = ref<CalendarOptions>({
|
|
73
|
+
plugins: [dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin],
|
|
74
|
+
initialView: props.mode,
|
|
75
|
+
locale: props.locale,
|
|
76
|
+
dayMaxEvents: true,
|
|
77
|
+
timeZone: 'UTC',
|
|
78
|
+
headerToolbar: {
|
|
79
|
+
left: props.toolBarLeft,
|
|
80
|
+
center: props.toolBarCenter,
|
|
81
|
+
right: props.toolBarRight,
|
|
82
|
+
},
|
|
83
|
+
buttonText: buttonText.value,
|
|
84
|
+
events: props.modelValue,
|
|
85
|
+
initialDate: props.selectViewDay,
|
|
86
|
+
dateClick: handleDateClick,
|
|
87
|
+
eventClick: handleEventClick,
|
|
88
|
+
nowIndicator: true,
|
|
89
|
+
height: props.height,
|
|
90
|
+
eventColor: '#378006',
|
|
91
|
+
})
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<template>
|
|
95
|
+
<FullCalendar
|
|
96
|
+
ref="calendarRef"
|
|
97
|
+
:options="calendarOptions as CalendarOptions"
|
|
98
|
+
/>
|
|
99
|
+
</template>
|
|
@@ -1,153 +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>
|
|
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
153
|
</template>
|
|
@@ -1,43 +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: /\d/, 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="(_, name, index) in ($slots as {})"
|
|
34
|
-
:key="index"
|
|
35
|
-
#[name]="slotData"
|
|
36
|
-
>
|
|
37
|
-
<slot
|
|
38
|
-
:name="name"
|
|
39
|
-
v-bind="((slotData || {}) as object)"
|
|
40
|
-
/>
|
|
41
|
-
</template>
|
|
42
|
-
</v-text-field>
|
|
43
|
-
</template>
|
|
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: /\d/, 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="(_, name, index) in ($slots as {})"
|
|
34
|
+
:key="index"
|
|
35
|
+
#[name]="slotData"
|
|
36
|
+
>
|
|
37
|
+
<slot
|
|
38
|
+
:name="name"
|
|
39
|
+
v-bind="((slotData || {}) as object)"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
</v-text-field>
|
|
43
|
+
</template>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("
|
|
1
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("
|
|
1
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("
|
|
1
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("
|
|
1
|
+
declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,11 +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
|
-
}
|
|
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
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { ClientConfig,ClientConfigService } from "../composables/clientConfig";
|
|
2
|
-
|
|
3
|
-
declare module "#app" {
|
|
4
|
-
interface NuxtApp {
|
|
5
|
-
$clientConfig: ClientConfig;
|
|
6
|
-
$clientConfigService: ClientConfigService;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface RuntimeNuxtApp {
|
|
10
|
-
$clientConfig: ClientConfig;
|
|
11
|
-
$clientConfigService: ClientConfigService;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
1
|
+
import type { ClientConfig,ClientConfigService } from "../composables/clientConfig";
|
|
2
|
+
|
|
3
|
+
declare module "#app" {
|
|
4
|
+
interface NuxtApp {
|
|
5
|
+
$clientConfig: ClientConfig;
|
|
6
|
+
$clientConfigService: ClientConfigService;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface RuntimeNuxtApp {
|
|
10
|
+
$clientConfig: ClientConfig;
|
|
11
|
+
$clientConfigService: ClientConfigService;
|
|
12
|
+
}
|
|
13
|
+
}
|