pukaad-ui-lib 1.39.0 → 1.41.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/assets/json/address/Amphur.json +7346 -0
- package/dist/runtime/assets/json/address/Province.json +762 -0
- package/dist/runtime/assets/json/address/Tambon.json +64775 -0
- package/dist/runtime/assets/json/address/Zipcode.json +17208 -0
- package/dist/runtime/components/button.vue +1 -1
- package/dist/runtime/components/collapse/collapse.vue +1 -1
- package/dist/runtime/components/drawer/drawer.d.vue.ts +1 -1
- package/dist/runtime/components/drawer/drawer.vue +2 -2
- package/dist/runtime/components/drawer/drawer.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-address.d.vue.ts +14 -32
- package/dist/runtime/components/input/input-address.vue +174 -360
- package/dist/runtime/components/input/input-address.vue.d.ts +14 -32
- package/dist/runtime/components/input/input-autocomplete.vue +2 -2
- package/dist/runtime/components/input/input-combobox.d.vue.ts +12 -5
- package/dist/runtime/components/input/input-combobox.vue +143 -121
- package/dist/runtime/components/input/input-combobox.vue.d.ts +12 -5
- 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-text-field.d.vue.ts +3 -1
- package/dist/runtime/components/input/input-text-field.vue +8 -2
- package/dist/runtime/components/input/input-text-field.vue.d.ts +3 -1
- package/dist/runtime/components/input/input-textarea.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-textarea.vue.d.ts +1 -1
- package/dist/runtime/components/loading.d.vue.ts +2 -4
- package/dist/runtime/components/loading.vue +4 -8
- package/dist/runtime/components/loading.vue.d.ts +2 -4
- package/dist/runtime/components/modal/modal-share.vue +1 -1
- package/dist/runtime/components/modal/modal.d.vue.ts +2 -1
- package/dist/runtime/components/modal/modal.vue +2 -2
- package/dist/runtime/components/modal/modal.vue.d.ts +2 -1
- package/dist/runtime/components/ui/input-group/InputGroupButton.d.vue.ts +1 -1
- package/dist/runtime/components/ui/input-group/InputGroupButton.vue.d.ts +1 -1
- package/dist/runtime/components/ui/input-group/index.d.ts +1 -1
- package/dist/runtime/components/ui/native-select/NativeSelectOptGroup.d.vue.ts +2 -2
- package/dist/runtime/components/ui/native-select/NativeSelectOptGroup.vue.d.ts +2 -2
- package/dist/runtime/components/ui/native-select/NativeSelectOption.d.vue.ts +2 -2
- package/dist/runtime/components/ui/native-select/NativeSelectOption.vue.d.ts +2 -2
- package/dist/runtime/components/ui/tabs/TabsList.vue +6 -4
- package/dist/runtime/components/ui/tabs/TabsTrigger.vue +6 -4
- package/dist/runtime/composables/useThaiAddress.d.ts +45 -0
- package/dist/runtime/composables/useThaiAddress.js +81 -0
- package/package.json +1 -1
|
@@ -1,158 +1,126 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
2
|
+
<div :class="['flex flex-col', props.gap]">
|
|
3
3
|
<!-- Address Selector (Province, District, Sub-district, Zip code) -->
|
|
4
|
-
<
|
|
5
|
-
ref="
|
|
4
|
+
<InputCombobox
|
|
5
|
+
ref="comboboxRef"
|
|
6
6
|
:name="props.name"
|
|
7
|
+
:label="props.label"
|
|
8
|
+
:placeholder="props.placeholder"
|
|
9
|
+
:required="props.required"
|
|
7
10
|
:rules="props.rules || defaultRules"
|
|
8
|
-
v-
|
|
9
|
-
|
|
11
|
+
v-model="internalValue"
|
|
12
|
+
@clear="handleClear"
|
|
10
13
|
>
|
|
11
|
-
<
|
|
12
|
-
<
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
variant="outline"
|
|
23
|
-
role="combobox"
|
|
24
|
-
class="w-full justify-between text-start"
|
|
14
|
+
<template #popover-content="{ close }">
|
|
15
|
+
<ShadCommand class="p-2">
|
|
16
|
+
<ShadTabs v-model="currentTab" class="w-full">
|
|
17
|
+
<ShadTabsList class="w-full grid grid-cols-4">
|
|
18
|
+
<ShadTabsTrigger value="province"> จังหวัด </ShadTabsTrigger>
|
|
19
|
+
<ShadTabsTrigger value="district" :disabled="!selectedProvince">
|
|
20
|
+
อำเภอ/เขต
|
|
21
|
+
</ShadTabsTrigger>
|
|
22
|
+
<ShadTabsTrigger
|
|
23
|
+
value="subDistrict"
|
|
24
|
+
:disabled="!selectedDistrict"
|
|
25
25
|
>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
</
|
|
31
|
-
</
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
placeholder="ค้นหาที่อยู่"
|
|
38
|
-
/>
|
|
39
|
-
<ShadTabs v-model="currentTab" class="w-full">
|
|
40
|
-
<ShadTabsList class="w-full grid grid-cols-4 rounded-none">
|
|
41
|
-
<ShadTabsTrigger value="province" class="rounded-none">
|
|
42
|
-
จังหวัด
|
|
43
|
-
</ShadTabsTrigger>
|
|
44
|
-
<ShadTabsTrigger
|
|
45
|
-
value="district"
|
|
46
|
-
:disabled="!selectedProvince"
|
|
47
|
-
class="rounded-none"
|
|
48
|
-
>
|
|
49
|
-
อำเภอ/เขต
|
|
50
|
-
</ShadTabsTrigger>
|
|
51
|
-
<ShadTabsTrigger
|
|
52
|
-
value="subDistrict"
|
|
53
|
-
:disabled="!selectedDistrict"
|
|
54
|
-
class="rounded-none"
|
|
55
|
-
>
|
|
56
|
-
ตำบล/แขวง
|
|
57
|
-
</ShadTabsTrigger>
|
|
58
|
-
<ShadTabsTrigger
|
|
59
|
-
value="zipCode"
|
|
60
|
-
:disabled="!selectedSubDistrict"
|
|
61
|
-
class="rounded-none"
|
|
62
|
-
>
|
|
63
|
-
รหัสไปรษณีย์
|
|
64
|
-
</ShadTabsTrigger>
|
|
65
|
-
</ShadTabsList>
|
|
26
|
+
ตำบล/แขวง
|
|
27
|
+
</ShadTabsTrigger>
|
|
28
|
+
<ShadTabsTrigger value="zipCode" :disabled="!selectedSubDistrict">
|
|
29
|
+
รหัสไปรษณีย์
|
|
30
|
+
</ShadTabsTrigger>
|
|
31
|
+
</ShadTabsList>
|
|
32
|
+
<InputTextField v-model="searchQuery" placeholder="ค้นหาที่อยู่">
|
|
33
|
+
<template #prepend>
|
|
34
|
+
<Icon name="lucide:search" class="h-4 w-4" />
|
|
35
|
+
</template>
|
|
36
|
+
</InputTextField>
|
|
66
37
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
38
|
+
<!-- Province Tab -->
|
|
39
|
+
<ShadTabsContent value="province" class="m-0">
|
|
40
|
+
<ShadCommandList class="max-h-64">
|
|
41
|
+
<ShadCommandGroup>
|
|
42
|
+
<ShadCommandItem
|
|
43
|
+
v-for="province in provinces"
|
|
44
|
+
:key="province.id"
|
|
45
|
+
:value="province.name_th"
|
|
46
|
+
@select="onSelectProvince(province)"
|
|
47
|
+
>
|
|
48
|
+
{{ province.name_th }}
|
|
49
|
+
<Icon
|
|
50
|
+
v-if="selectedProvince?.id === province.id"
|
|
51
|
+
name="lucide:check"
|
|
52
|
+
class="ml-auto h-4 w-4"
|
|
53
|
+
/>
|
|
54
|
+
</ShadCommandItem>
|
|
55
|
+
</ShadCommandGroup>
|
|
56
|
+
<ShadCommandEmpty :force-show="provinces.length === 0" />
|
|
57
|
+
</ShadCommandList>
|
|
58
|
+
</ShadTabsContent>
|
|
88
59
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
60
|
+
<!-- District Tab -->
|
|
61
|
+
<ShadTabsContent value="district" class="m-0">
|
|
62
|
+
<ShadCommandList class="max-h-64">
|
|
63
|
+
<ShadCommandGroup>
|
|
64
|
+
<ShadCommandItem
|
|
65
|
+
v-for="district in amphurs"
|
|
66
|
+
:key="district.id"
|
|
67
|
+
:value="district.name_th"
|
|
68
|
+
@select="onSelectDistrict(district)"
|
|
69
|
+
>
|
|
70
|
+
{{ district.name_th }}
|
|
71
|
+
<Icon
|
|
72
|
+
v-if="selectedDistrict?.id === district.id"
|
|
73
|
+
name="lucide:check"
|
|
74
|
+
class="ml-auto h-4 w-4"
|
|
75
|
+
/>
|
|
76
|
+
</ShadCommandItem>
|
|
77
|
+
</ShadCommandGroup>
|
|
78
|
+
<ShadCommandEmpty :force-show="amphurs.length === 0" />
|
|
79
|
+
</ShadCommandList>
|
|
80
|
+
</ShadTabsContent>
|
|
110
81
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
82
|
+
<!-- Sub-district Tab -->
|
|
83
|
+
<ShadTabsContent value="subDistrict" class="m-0">
|
|
84
|
+
<ShadCommandList class="max-h-64">
|
|
85
|
+
<ShadCommandGroup>
|
|
86
|
+
<ShadCommandItem
|
|
87
|
+
v-for="subDistrict in tambons"
|
|
88
|
+
:key="subDistrict.id"
|
|
89
|
+
:value="subDistrict.name_th"
|
|
90
|
+
@select="onSelectSubDistrict(subDistrict)"
|
|
91
|
+
>
|
|
92
|
+
{{ subDistrict.name_th }}
|
|
93
|
+
<Icon
|
|
94
|
+
v-if="selectedSubDistrict?.id === subDistrict.id"
|
|
95
|
+
name="lucide:check"
|
|
96
|
+
class="ml-auto h-4 w-4"
|
|
97
|
+
/>
|
|
98
|
+
</ShadCommandItem>
|
|
99
|
+
</ShadCommandGroup>
|
|
100
|
+
<ShadCommandEmpty :force-show="tambons.length === 0" />
|
|
101
|
+
</ShadCommandList>
|
|
102
|
+
</ShadTabsContent>
|
|
132
103
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<ShadFormMessage />
|
|
154
|
-
</ShadFormItem>
|
|
155
|
-
</ShadFormField>
|
|
104
|
+
<!-- Zip Code Tab -->
|
|
105
|
+
<ShadTabsContent value="zipCode" class="m-0">
|
|
106
|
+
<ShadCommandList class="max-h-64">
|
|
107
|
+
<ShadCommandGroup>
|
|
108
|
+
<ShadCommandItem
|
|
109
|
+
v-if="selectedSubDistrict"
|
|
110
|
+
:value="selectedSubDistrict.zipcode_code?.toString() || ''"
|
|
111
|
+
@select="() => onSelectZipCode(close)"
|
|
112
|
+
>
|
|
113
|
+
{{ selectedSubDistrict.zipcode_code }}
|
|
114
|
+
<Icon name="lucide:check" class="ml-auto h-4 w-4" />
|
|
115
|
+
</ShadCommandItem>
|
|
116
|
+
</ShadCommandGroup>
|
|
117
|
+
<ShadCommandEmpty :force-show="!selectedSubDistrict" />
|
|
118
|
+
</ShadCommandList>
|
|
119
|
+
</ShadTabsContent>
|
|
120
|
+
</ShadTabs>
|
|
121
|
+
</ShadCommand>
|
|
122
|
+
</template>
|
|
123
|
+
</InputCombobox>
|
|
156
124
|
|
|
157
125
|
<!-- Address Detail (House number, Soi, Moo, Road) -->
|
|
158
126
|
<InputTextField
|
|
@@ -169,7 +137,10 @@
|
|
|
169
137
|
|
|
170
138
|
<script setup>
|
|
171
139
|
import { ref, computed, watch } from "vue";
|
|
172
|
-
import
|
|
140
|
+
import {
|
|
141
|
+
useThaiAddress
|
|
142
|
+
} from "@/runtime/composables/useThaiAddress";
|
|
143
|
+
const { getProvinces, getAmphursByProvinceId, getTambonsByAmphurId } = useThaiAddress();
|
|
173
144
|
const props = defineProps({
|
|
174
145
|
name: { type: String, required: false, default: "address" },
|
|
175
146
|
label: { type: String, required: false, default: "\u0E08\u0E31\u0E07\u0E2B\u0E27\u0E31\u0E14, \u0E2D\u0E33\u0E40\u0E20\u0E2D/\u0E40\u0E02\u0E15, \u0E15\u0E33\u0E1A\u0E25/\u0E41\u0E02\u0E27\u0E07, \u0E23\u0E2B\u0E31\u0E2A\u0E44\u0E1B\u0E23\u0E29\u0E13\u0E35\u0E22\u0E4C" },
|
|
@@ -179,227 +150,62 @@ const props = defineProps({
|
|
|
179
150
|
required: { type: Boolean, required: false, default: false },
|
|
180
151
|
requiredDetail: { type: Boolean, required: false, default: false },
|
|
181
152
|
rules: { type: [Object, String, Function], required: false },
|
|
182
|
-
|
|
183
|
-
districts: { type: Array, required: false },
|
|
184
|
-
subDistricts: { type: Array, required: false }
|
|
153
|
+
gap: { type: String, required: false, default: "gap-4" }
|
|
185
154
|
});
|
|
186
155
|
const emits = defineEmits(["selectProvince", "selectDistrict", "selectSubDistrict", "selectZipCode", "change"]);
|
|
187
156
|
const modelValue = defineModel({ type: Object, ...{
|
|
188
157
|
default: () => ({})
|
|
189
158
|
} });
|
|
190
|
-
const popoverOpen = ref(false);
|
|
191
159
|
const currentTab = ref("province");
|
|
192
160
|
const searchQuery = ref("");
|
|
193
|
-
const
|
|
161
|
+
const comboboxRef = ref();
|
|
194
162
|
const detailFieldRef = ref();
|
|
195
163
|
const selectedProvince = ref(null);
|
|
196
164
|
const selectedDistrict = ref(null);
|
|
197
165
|
const selectedSubDistrict = ref(null);
|
|
198
|
-
const
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
if (selectedSubDistrict.value) parts.push(selectedSubDistrict.value.name_th);
|
|
203
|
-
if (selectedSubDistrict.value)
|
|
204
|
-
parts.push(selectedSubDistrict.value.zip_code.toString());
|
|
205
|
-
return parts.join(", ");
|
|
206
|
-
});
|
|
207
|
-
const addressDetailValue = ref("");
|
|
208
|
-
const mockProvinces = props.provinces || [
|
|
209
|
-
{ code: 10, name_th: "\u0E01\u0E23\u0E38\u0E07\u0E40\u0E17\u0E1E\u0E21\u0E2B\u0E32\u0E19\u0E04\u0E23", name_en: "Bangkok" },
|
|
210
|
-
{ code: 11, name_th: "\u0E2A\u0E21\u0E38\u0E17\u0E23\u0E1B\u0E23\u0E32\u0E01\u0E32\u0E23", name_en: "Samut Prakan" },
|
|
211
|
-
{ code: 12, name_th: "\u0E19\u0E19\u0E17\u0E1A\u0E38\u0E23\u0E35", name_en: "Nonthaburi" },
|
|
212
|
-
{ code: 13, name_th: "\u0E1B\u0E17\u0E38\u0E21\u0E18\u0E32\u0E19\u0E35", name_en: "Pathum Thani" },
|
|
213
|
-
{ code: 14, name_th: "\u0E1E\u0E23\u0E30\u0E19\u0E04\u0E23\u0E28\u0E23\u0E35\u0E2D\u0E22\u0E38\u0E18\u0E22\u0E32", name_en: "Phra Nakhon Si Ayutthaya" },
|
|
214
|
-
{ code: 20, name_th: "\u0E0A\u0E25\u0E1A\u0E38\u0E23\u0E35", name_en: "Chon Buri" },
|
|
215
|
-
{ code: 50, name_th: "\u0E40\u0E0A\u0E35\u0E22\u0E07\u0E43\u0E2B\u0E21\u0E48", name_en: "Chiang Mai" }
|
|
216
|
-
];
|
|
217
|
-
const mockDistricts = props.districts || [
|
|
218
|
-
// กรุงเทพมหานคร
|
|
219
|
-
{
|
|
220
|
-
code: 1001,
|
|
221
|
-
name_th: "\u0E40\u0E02\u0E15\u0E1E\u0E23\u0E30\u0E19\u0E04\u0E23",
|
|
222
|
-
name_en: "Phra Nakhon",
|
|
223
|
-
province_code: 10
|
|
224
|
-
},
|
|
225
|
-
{ code: 1002, name_th: "\u0E40\u0E02\u0E15\u0E14\u0E38\u0E2A\u0E34\u0E15", name_en: "Dusit", province_code: 10 },
|
|
226
|
-
{
|
|
227
|
-
code: 1003,
|
|
228
|
-
name_th: "\u0E40\u0E02\u0E15\u0E2B\u0E19\u0E2D\u0E07\u0E08\u0E2D\u0E01",
|
|
229
|
-
name_en: "Nong Chok",
|
|
230
|
-
province_code: 10
|
|
231
|
-
},
|
|
232
|
-
{ code: 1004, name_th: "\u0E40\u0E02\u0E15\u0E1A\u0E32\u0E07\u0E23\u0E31\u0E01", name_en: "Bang Rak", province_code: 10 },
|
|
233
|
-
{ code: 1005, name_th: "\u0E40\u0E02\u0E15\u0E1A\u0E32\u0E07\u0E40\u0E02\u0E19", name_en: "Bang Khen", province_code: 10 },
|
|
234
|
-
{
|
|
235
|
-
code: 1006,
|
|
236
|
-
name_th: "\u0E40\u0E02\u0E15\u0E1A\u0E32\u0E07\u0E01\u0E30\u0E1B\u0E34",
|
|
237
|
-
name_en: "Bang Kapi",
|
|
238
|
-
province_code: 10
|
|
239
|
-
},
|
|
240
|
-
{
|
|
241
|
-
code: 1007,
|
|
242
|
-
name_th: "\u0E40\u0E02\u0E15\u0E1B\u0E17\u0E38\u0E21\u0E27\u0E31\u0E19",
|
|
243
|
-
name_en: "Pathum Wan",
|
|
244
|
-
province_code: 10
|
|
245
|
-
},
|
|
246
|
-
// สมุทรปราการ
|
|
247
|
-
{
|
|
248
|
-
code: 1101,
|
|
249
|
-
name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E40\u0E21\u0E37\u0E2D\u0E07\u0E2A\u0E21\u0E38\u0E17\u0E23\u0E1B\u0E23\u0E32\u0E01\u0E32\u0E23",
|
|
250
|
-
name_en: "Mueang Samut Prakan",
|
|
251
|
-
province_code: 11
|
|
252
|
-
},
|
|
253
|
-
{ code: 1102, name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E1A\u0E32\u0E07\u0E1A\u0E48\u0E2D", name_en: "Bang Bo", province_code: 11 },
|
|
254
|
-
// นนทบุรี
|
|
255
|
-
{
|
|
256
|
-
code: 1201,
|
|
257
|
-
name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E40\u0E21\u0E37\u0E2D\u0E07\u0E19\u0E19\u0E17\u0E1A\u0E38\u0E23\u0E35",
|
|
258
|
-
name_en: "Mueang Nonthaburi",
|
|
259
|
-
province_code: 12
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
code: 1202,
|
|
263
|
-
name_th: "\u0E2D\u0E33\u0E40\u0E20\u0E2D\u0E1A\u0E32\u0E07\u0E01\u0E23\u0E27\u0E22",
|
|
264
|
-
name_en: "Bang Kruai",
|
|
265
|
-
province_code: 12
|
|
266
|
-
}
|
|
267
|
-
];
|
|
268
|
-
const mockSubDistricts = props.subDistricts || [
|
|
269
|
-
// เขตพระนคร
|
|
270
|
-
{
|
|
271
|
-
code: 100101,
|
|
272
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E1E\u0E23\u0E30\u0E1A\u0E23\u0E21\u0E21\u0E2B\u0E32\u0E23\u0E32\u0E0A\u0E27\u0E31\u0E07",
|
|
273
|
-
name_en: "Phra Borom Maha Ratchawang",
|
|
274
|
-
district_code: 1001,
|
|
275
|
-
zip_code: 10200
|
|
276
|
-
},
|
|
277
|
-
{
|
|
278
|
-
code: 100102,
|
|
279
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E31\u0E07\u0E1A\u0E39\u0E23\u0E1E\u0E32\u0E20\u0E34\u0E23\u0E21\u0E22\u0E4C",
|
|
280
|
-
name_en: "Wang Burapha Phirom",
|
|
281
|
-
district_code: 1001,
|
|
282
|
-
zip_code: 10200
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
code: 100103,
|
|
286
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E31\u0E14\u0E23\u0E32\u0E0A\u0E1A\u0E1E\u0E34\u0E18",
|
|
287
|
-
name_en: "Wat Ratchabophit",
|
|
288
|
-
district_code: 1001,
|
|
289
|
-
zip_code: 10200
|
|
290
|
-
},
|
|
291
|
-
// เขตดุสิต
|
|
292
|
-
{
|
|
293
|
-
code: 100201,
|
|
294
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E14\u0E38\u0E2A\u0E34\u0E15",
|
|
295
|
-
name_en: "Dusit",
|
|
296
|
-
district_code: 1002,
|
|
297
|
-
zip_code: 10300
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
code: 100202,
|
|
301
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E0A\u0E34\u0E23\u0E1E\u0E22\u0E32\u0E1A\u0E32\u0E25",
|
|
302
|
-
name_en: "Wachiraphayaban",
|
|
303
|
-
district_code: 1002,
|
|
304
|
-
zip_code: 10300
|
|
305
|
-
},
|
|
306
|
-
// เขตบางรัก
|
|
307
|
-
{
|
|
308
|
-
code: 100401,
|
|
309
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E21\u0E2B\u0E32\u0E1E\u0E24\u0E12\u0E32\u0E23\u0E32\u0E21",
|
|
310
|
-
name_en: "Maha Phruettharam",
|
|
311
|
-
district_code: 1004,
|
|
312
|
-
zip_code: 10500
|
|
313
|
-
},
|
|
314
|
-
{
|
|
315
|
-
code: 100402,
|
|
316
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E2A\u0E35\u0E25\u0E21",
|
|
317
|
-
name_en: "Si Lom",
|
|
318
|
-
district_code: 1004,
|
|
319
|
-
zip_code: 10500
|
|
320
|
-
},
|
|
321
|
-
// เขตปทุมวัน
|
|
322
|
-
{
|
|
323
|
-
code: 100701,
|
|
324
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E23\u0E2D\u0E07\u0E40\u0E21\u0E37\u0E2D\u0E07",
|
|
325
|
-
name_en: "Rong Mueang",
|
|
326
|
-
district_code: 1007,
|
|
327
|
-
zip_code: 10330
|
|
328
|
-
},
|
|
329
|
-
{
|
|
330
|
-
code: 100702,
|
|
331
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E27\u0E31\u0E07\u0E43\u0E2B\u0E21\u0E48",
|
|
332
|
-
name_en: "Wang Mai",
|
|
333
|
-
district_code: 1007,
|
|
334
|
-
zip_code: 10330
|
|
335
|
-
},
|
|
336
|
-
{
|
|
337
|
-
code: 100703,
|
|
338
|
-
name_th: "\u0E41\u0E02\u0E27\u0E07\u0E1B\u0E17\u0E38\u0E21\u0E27\u0E31\u0E19",
|
|
339
|
-
name_en: "Pathum Wan",
|
|
340
|
-
district_code: 1007,
|
|
341
|
-
zip_code: 10330
|
|
342
|
-
},
|
|
343
|
-
// อำเภอเมืองสมุทรปราการ
|
|
344
|
-
{
|
|
345
|
-
code: 110101,
|
|
346
|
-
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E1B\u0E32\u0E01\u0E19\u0E49\u0E33",
|
|
347
|
-
name_en: "Pak Nam",
|
|
348
|
-
district_code: 1101,
|
|
349
|
-
zip_code: 10270
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
code: 110102,
|
|
353
|
-
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E2A\u0E33\u0E42\u0E23\u0E07\u0E40\u0E2B\u0E19\u0E37\u0E2D",
|
|
354
|
-
name_en: "Samrong Nuea",
|
|
355
|
-
district_code: 1101,
|
|
356
|
-
zip_code: 10270
|
|
357
|
-
},
|
|
358
|
-
// อำเภอเมืองนนทบุรี
|
|
359
|
-
{
|
|
360
|
-
code: 120101,
|
|
361
|
-
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E2A\u0E27\u0E19\u0E43\u0E2B\u0E0D\u0E48",
|
|
362
|
-
name_en: "Suan Yai",
|
|
363
|
-
district_code: 1201,
|
|
364
|
-
zip_code: 11e3
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
code: 120102,
|
|
368
|
-
name_th: "\u0E15\u0E33\u0E1A\u0E25\u0E15\u0E25\u0E32\u0E14\u0E02\u0E27\u0E31\u0E0D",
|
|
369
|
-
name_en: "Talat Khwan",
|
|
370
|
-
district_code: 1201,
|
|
371
|
-
zip_code: 11e3
|
|
372
|
-
}
|
|
373
|
-
];
|
|
374
|
-
const filteredProvinces = computed(() => {
|
|
375
|
-
if (!searchQuery.value) return mockProvinces;
|
|
166
|
+
const provinces = computed(() => {
|
|
167
|
+
const allProvinces = getProvinces();
|
|
168
|
+
if (!searchQuery.value || currentTab.value !== "province")
|
|
169
|
+
return allProvinces;
|
|
376
170
|
const query = searchQuery.value.toLowerCase();
|
|
377
|
-
return
|
|
171
|
+
return allProvinces.filter(
|
|
378
172
|
(p) => p.name_th.toLowerCase().includes(query) || p.name_en.toLowerCase().includes(query)
|
|
379
173
|
);
|
|
380
174
|
});
|
|
381
|
-
const
|
|
175
|
+
const amphurs = computed(() => {
|
|
382
176
|
if (!selectedProvince.value) return [];
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
);
|
|
386
|
-
if (!searchQuery.value) return districts;
|
|
177
|
+
const allAmphurs = getAmphursByProvinceId(selectedProvince.value.id);
|
|
178
|
+
if (!searchQuery.value || currentTab.value !== "district") return allAmphurs;
|
|
387
179
|
const query = searchQuery.value.toLowerCase();
|
|
388
|
-
return
|
|
389
|
-
(
|
|
180
|
+
return allAmphurs.filter(
|
|
181
|
+
(a) => a.name_th.toLowerCase().includes(query) || a.name_en.toLowerCase().includes(query)
|
|
390
182
|
);
|
|
391
183
|
});
|
|
392
|
-
const
|
|
184
|
+
const tambons = computed(() => {
|
|
393
185
|
if (!selectedDistrict.value) return [];
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
if (!searchQuery.value) return subDistricts;
|
|
186
|
+
const allTambons = getTambonsByAmphurId(selectedDistrict.value.id);
|
|
187
|
+
if (!searchQuery.value || currentTab.value !== "subDistrict")
|
|
188
|
+
return allTambons;
|
|
398
189
|
const query = searchQuery.value.toLowerCase();
|
|
399
|
-
return
|
|
400
|
-
(
|
|
190
|
+
return allTambons.filter(
|
|
191
|
+
(t) => t.name_th.toLowerCase().includes(query) || t.name_en.toLowerCase().includes(query)
|
|
401
192
|
);
|
|
402
193
|
});
|
|
194
|
+
const addressValue = computed(() => {
|
|
195
|
+
const parts = [];
|
|
196
|
+
if (selectedProvince.value) parts.push(selectedProvince.value.name_th);
|
|
197
|
+
if (selectedDistrict.value) parts.push(selectedDistrict.value.name_th);
|
|
198
|
+
if (selectedSubDistrict.value) parts.push(selectedSubDistrict.value.name_th);
|
|
199
|
+
if (selectedSubDistrict.value?.zipcode_code)
|
|
200
|
+
parts.push(selectedSubDistrict.value.zipcode_code.toString());
|
|
201
|
+
return parts.join(", ");
|
|
202
|
+
});
|
|
203
|
+
const internalValue = computed({
|
|
204
|
+
get: () => addressValue.value,
|
|
205
|
+
set: () => {
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
const addressDetailValue = ref("");
|
|
403
209
|
const onSelectProvince = (province) => {
|
|
404
210
|
selectedProvince.value = province;
|
|
405
211
|
selectedDistrict.value = null;
|
|
@@ -424,22 +230,29 @@ const onSelectSubDistrict = (subDistrict) => {
|
|
|
424
230
|
emits("selectSubDistrict", subDistrict);
|
|
425
231
|
updateModelValue();
|
|
426
232
|
};
|
|
427
|
-
const onSelectZipCode = () => {
|
|
428
|
-
if (selectedSubDistrict.value) {
|
|
429
|
-
emits("selectZipCode", selectedSubDistrict.value.
|
|
430
|
-
|
|
233
|
+
const onSelectZipCode = (close) => {
|
|
234
|
+
if (selectedSubDistrict.value?.zipcode_code) {
|
|
235
|
+
emits("selectZipCode", selectedSubDistrict.value.zipcode_code);
|
|
236
|
+
close?.();
|
|
431
237
|
currentTab.value = "province";
|
|
432
238
|
updateModelValue();
|
|
433
239
|
}
|
|
434
240
|
};
|
|
241
|
+
const handleClear = () => {
|
|
242
|
+
selectedProvince.value = null;
|
|
243
|
+
selectedDistrict.value = null;
|
|
244
|
+
selectedSubDistrict.value = null;
|
|
245
|
+
searchQuery.value = "";
|
|
246
|
+
currentTab.value = "province";
|
|
247
|
+
};
|
|
435
248
|
const updateModelValue = () => {
|
|
436
249
|
const value = {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
250
|
+
province_id: selectedProvince.value?.id,
|
|
251
|
+
amphur_id: selectedDistrict.value?.id,
|
|
252
|
+
tambon_id: selectedSubDistrict.value?.id,
|
|
253
|
+
zipcode: selectedSubDistrict.value?.zipcode_code,
|
|
254
|
+
detail_address: addressDetailValue.value || void 0,
|
|
255
|
+
full_address: buildFullAddress()
|
|
443
256
|
};
|
|
444
257
|
modelValue.value = value;
|
|
445
258
|
emits("change", value);
|
|
@@ -450,8 +263,8 @@ const buildFullAddress = () => {
|
|
|
450
263
|
if (selectedSubDistrict.value) parts.push(selectedSubDistrict.value.name_th);
|
|
451
264
|
if (selectedDistrict.value) parts.push(selectedDistrict.value.name_th);
|
|
452
265
|
if (selectedProvince.value) parts.push(selectedProvince.value.name_th);
|
|
453
|
-
if (selectedSubDistrict.value)
|
|
454
|
-
parts.push(selectedSubDistrict.value.
|
|
266
|
+
if (selectedSubDistrict.value?.zipcode_code)
|
|
267
|
+
parts.push(selectedSubDistrict.value.zipcode_code.toString());
|
|
455
268
|
return parts.join(" ");
|
|
456
269
|
};
|
|
457
270
|
watch(addressDetailValue, () => {
|
|
@@ -467,12 +280,12 @@ const defaultRules = (v) => {
|
|
|
467
280
|
return true;
|
|
468
281
|
};
|
|
469
282
|
const validate = async () => {
|
|
470
|
-
const addressValid = await
|
|
283
|
+
const addressValid = await comboboxRef.value?.validate?.();
|
|
471
284
|
const detailValid = await detailFieldRef.value?.validate?.();
|
|
472
|
-
return addressValid?.valid !== false && detailValid !== false;
|
|
285
|
+
return addressValid?.valid !== false && detailValid?.valid !== false;
|
|
473
286
|
};
|
|
474
287
|
const setErrors = (errMsg) => {
|
|
475
|
-
|
|
288
|
+
comboboxRef.value?.setErrors(errMsg);
|
|
476
289
|
};
|
|
477
290
|
const reset = () => {
|
|
478
291
|
selectedProvince.value = null;
|
|
@@ -480,13 +293,14 @@ const reset = () => {
|
|
|
480
293
|
selectedSubDistrict.value = null;
|
|
481
294
|
addressDetailValue.value = "";
|
|
482
295
|
currentTab.value = "province";
|
|
296
|
+
searchQuery.value = "";
|
|
483
297
|
updateModelValue();
|
|
484
298
|
};
|
|
485
299
|
defineExpose({
|
|
486
300
|
validate,
|
|
487
301
|
setErrors,
|
|
488
302
|
reset,
|
|
489
|
-
|
|
303
|
+
comboboxRef,
|
|
490
304
|
detailFieldRef
|
|
491
305
|
});
|
|
492
306
|
</script>
|