pukaad-ui-lib 1.369.9 → 1.371.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/svg/flags/uk.svg +14 -0
- package/dist/runtime/components/card/card-opening-hours.d.vue.ts +16 -0
- package/dist/runtime/components/card/card-opening-hours.vue +90 -0
- package/dist/runtime/components/card/card-opening-hours.vue.d.ts +16 -0
- package/dist/runtime/components/card/card-place-detail.d.vue.ts +2 -32
- package/dist/runtime/components/card/card-place-detail.vue +32 -69
- package/dist/runtime/components/card/card-place-detail.vue.d.ts +2 -32
- package/dist/runtime/components/drawer/drawer-suggest-place/suggest-place-map.d.vue.ts +2 -0
- package/dist/runtime/components/drawer/drawer-suggest-place/suggest-place-map.vue +11 -5
- package/dist/runtime/components/drawer/drawer-suggest-place/suggest-place-map.vue.d.ts +2 -0
- package/dist/runtime/components/input/input-autocomplete.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-autocomplete.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-file.d.vue.ts +1 -1
- package/dist/runtime/components/input/input-file.vue.d.ts +1 -1
- package/dist/runtime/components/input/input-link.d.vue.ts +5 -0
- package/dist/runtime/components/input/input-link.vue +14 -8
- package/dist/runtime/components/input/input-link.vue.d.ts +5 -0
- package/dist/runtime/components/input/input-typed-field.vue +3 -1
- package/dist/runtime/components/modal/suggest-edit-place/modal-suggest-edit-place.d.vue.ts +118 -0
- package/dist/runtime/components/modal/suggest-edit-place/modal-suggest-edit-place.vue +568 -0
- package/dist/runtime/components/modal/suggest-edit-place/modal-suggest-edit-place.vue.d.ts +118 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-Addlink.d.vue.ts +11 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-Addlink.vue +20 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-Addlink.vue.d.ts +11 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-Addphone.d.vue.ts +10 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-Addphone.vue +18 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-Addphone.vue.d.ts +10 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-address.d.vue.ts +31 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-address.vue +66 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-address.vue.d.ts +31 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-category.d.vue.ts +21 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-category.vue +47 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-category.vue.d.ts +21 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-dateopening.d.vue.ts +25 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-dateopening.vue +58 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-dateopening.vue.d.ts +25 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-description.d.vue.ts +17 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-description.vue +48 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-description.vue.d.ts +17 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-link.d.vue.ts +18 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-link.vue +64 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-link.vue.d.ts +18 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-name.d.vue.ts +37 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-name.vue +110 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-name.vue.d.ts +37 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-phone.d.vue.ts +17 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-phone.vue +40 -0
- package/dist/runtime/components/modal/suggest-edit-place/place-phone.vue.d.ts +17 -0
- package/dist/runtime/components/timeline.d.vue.ts +14 -0
- package/dist/runtime/components/timeline.vue +29 -10
- package/dist/runtime/components/timeline.vue.d.ts +14 -0
- package/dist/runtime/components/ui/chart/ChartTooltipContent.d.vue.ts +1 -1
- package/dist/runtime/components/ui/chart/ChartTooltipContent.vue.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/utils/opening-hours.d.ts +21 -0
- package/dist/runtime/utils/opening-hours.js +20 -0
- package/package.json +1 -1
- /package/dist/runtime/assets/svg/socials/{facebook.svg → Facebook.svg} +0 -0
- /package/dist/runtime/assets/svg/socials/{instagram.svg → Instagram.svg} +0 -0
- /package/dist/runtime/assets/svg/socials/{Tiktok.svg → TikTok.svg} +0 -0
- /package/dist/runtime/assets/svg/socials/{Whatsapp.svg → WhatsApp.svg} +0 -0
- /package/dist/runtime/assets/svg/socials/{Youtube.svg → YouTube.svg} +0 -0
package/dist/module.json
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_8829_2067)">
|
|
3
|
+
<path d="M0 0H20V20H0V0Z" fill="#012169"/>
|
|
4
|
+
<path d="M20 0V2.5L12.5781 10L20 17.3047V20H17.3828L9.92188 12.6562L2.65625 20H0V17.3438L7.26562 10.0391L0 2.89062V0H2.42188L9.92188 7.34375L17.1875 0H20Z" fill="white"/>
|
|
5
|
+
<path d="M7.1875 12.6562L7.61719 13.9844L1.64062 20H0V19.8828L7.1875 12.6562ZM12.0312 12.1875L14.1406 12.5L20 18.2422V20L12.0312 12.1875ZM20 0L12.5 7.65625L12.3438 5.9375L18.2031 0H20ZM0 0.0390625L7.53906 7.42188L5.23438 7.10938L0 1.91406V0.0390625Z" fill="#C8102E"/>
|
|
6
|
+
<path d="M6.875 0V20H13.125V0H6.875ZM0 6.875V13.125H20V6.875H0Z" fill="white"/>
|
|
7
|
+
<path d="M0 8.125V11.875H20V8.125H0ZM8.125 0V20H11.875V0H8.125Z" fill="#C8102E"/>
|
|
8
|
+
</g>
|
|
9
|
+
<defs>
|
|
10
|
+
<clipPath id="clip0_8829_2067">
|
|
11
|
+
<rect width="20" height="20" rx="10" fill="white"/>
|
|
12
|
+
</clipPath>
|
|
13
|
+
</defs>
|
|
14
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OpeningHour, SpecialDay } from "#pukaad-ui/runtime/utils/opening-hours";
|
|
2
|
+
export type { OpeningHour, SpecialDay, TimeSlot, } from "#pukaad-ui/runtime/utils/opening-hours";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
items?: OpeningHour[];
|
|
5
|
+
specialDays?: SpecialDay[];
|
|
6
|
+
openStatus?: string;
|
|
7
|
+
filterUpcomingSpecialDays?: boolean;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
10
|
+
items: OpeningHour[];
|
|
11
|
+
specialDays: SpecialDay[];
|
|
12
|
+
openStatus: string;
|
|
13
|
+
filterUpcomingSpecialDays: boolean;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="font-body-large flex flex-col gap-[4px] w-full">
|
|
3
|
+
<!-- สถานะปิดชั่วคราว -->
|
|
4
|
+
<div
|
|
5
|
+
v-if="props.openStatus === 'temporarily_closed'"
|
|
6
|
+
class="font-body-large-prominent text-error"
|
|
7
|
+
>
|
|
8
|
+
ปิดชั่วคราว
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<!-- เวลาทำการปกติ -->
|
|
12
|
+
<div
|
|
13
|
+
v-for="(line, index) in lines"
|
|
14
|
+
:key="index"
|
|
15
|
+
class="flex items-start justify-between"
|
|
16
|
+
>
|
|
17
|
+
<span>{{ line.day }}</span>
|
|
18
|
+
<div class="flex flex-col items-end">
|
|
19
|
+
<span v-for="(time, timeIndex) in line.time_lines" :key="timeIndex">
|
|
20
|
+
{{ time }}
|
|
21
|
+
</span>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- วันทำการพิเศษ -->
|
|
26
|
+
<template v-if="formattedSpecialDays.length">
|
|
27
|
+
<div class="font-body-large-prominent text-warning">วันทำการพิเศษ</div>
|
|
28
|
+
<div
|
|
29
|
+
v-for="(special, index) in formattedSpecialDays"
|
|
30
|
+
:key="index"
|
|
31
|
+
class="flex items-start justify-between text-warning"
|
|
32
|
+
>
|
|
33
|
+
<span>{{ special.date_label }}</span>
|
|
34
|
+
<div class="flex flex-col items-end">
|
|
35
|
+
<span
|
|
36
|
+
v-for="(time, timeIndex) in special.time_lines"
|
|
37
|
+
:key="timeIndex"
|
|
38
|
+
>
|
|
39
|
+
{{ time }}
|
|
40
|
+
</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<div
|
|
46
|
+
v-if="
|
|
47
|
+
!lines.length && !formattedSpecialDays.length && props.openStatus !== 'temporarily_closed'
|
|
48
|
+
"
|
|
49
|
+
class="text-cloud"
|
|
50
|
+
>
|
|
51
|
+
ไม่มีข้อมูลเวลาทำการ
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
|
|
56
|
+
<script setup>
|
|
57
|
+
import { computed } from "vue";
|
|
58
|
+
import dayjs from "#pukaad-ui/runtime/utils/dayjs";
|
|
59
|
+
import { useConvert } from "#pukaad-ui/runtime/composables/useConvert";
|
|
60
|
+
import {
|
|
61
|
+
toDayLines,
|
|
62
|
+
getTimeLines
|
|
63
|
+
} from "#pukaad-ui/runtime/utils/opening-hours";
|
|
64
|
+
const props = defineProps({
|
|
65
|
+
items: { type: Array, required: false, default: () => [] },
|
|
66
|
+
specialDays: { type: Array, required: false, default: () => [] },
|
|
67
|
+
openStatus: { type: String, required: false, default: void 0 },
|
|
68
|
+
filterUpcomingSpecialDays: { type: Boolean, required: false, default: true }
|
|
69
|
+
});
|
|
70
|
+
const { convertDate } = useConvert();
|
|
71
|
+
const toArray = (value) => Array.isArray(value) ? value : [];
|
|
72
|
+
const lines = computed(() => toDayLines(props.items));
|
|
73
|
+
const sortedSpecialDays = computed(() => {
|
|
74
|
+
const allSpecial = toArray(props.specialDays).filter(
|
|
75
|
+
(s) => !!s?.date
|
|
76
|
+
);
|
|
77
|
+
if (!props.filterUpcomingSpecialDays) return allSpecial;
|
|
78
|
+
const today = dayjs().startOf("day");
|
|
79
|
+
const maxDate = today.add(30, "day").endOf("day");
|
|
80
|
+
return allSpecial.map((s) => ({ ...s, parsedDate: dayjs(s.date) })).filter((s) => s.parsedDate.isValid()).filter(
|
|
81
|
+
(s) => !s.parsedDate.isBefore(today) && !s.parsedDate.isAfter(maxDate)
|
|
82
|
+
).sort((a, b) => a.parsedDate.valueOf() - b.parsedDate.valueOf());
|
|
83
|
+
});
|
|
84
|
+
const formattedSpecialDays = computed(
|
|
85
|
+
() => sortedSpecialDays.value.map((s) => ({
|
|
86
|
+
date_label: convertDate(s.date),
|
|
87
|
+
time_lines: getTimeLines(s.isOpen, s.timeSlots)
|
|
88
|
+
}))
|
|
89
|
+
);
|
|
90
|
+
</script>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OpeningHour, SpecialDay } from "#pukaad-ui/runtime/utils/opening-hours";
|
|
2
|
+
export type { OpeningHour, SpecialDay, TimeSlot, } from "#pukaad-ui/runtime/utils/opening-hours";
|
|
3
|
+
type __VLS_Props = {
|
|
4
|
+
items?: OpeningHour[];
|
|
5
|
+
specialDays?: SpecialDay[];
|
|
6
|
+
openStatus?: string;
|
|
7
|
+
filterUpcomingSpecialDays?: boolean;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
10
|
+
items: OpeningHour[];
|
|
11
|
+
specialDays: SpecialDay[];
|
|
12
|
+
openStatus: string;
|
|
13
|
+
filterUpcomingSpecialDays: boolean;
|
|
14
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -1,35 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
category_name: string;
|
|
4
|
-
}
|
|
5
|
-
export interface TimeSlot {
|
|
6
|
-
start: string;
|
|
7
|
-
end: string;
|
|
8
|
-
}
|
|
9
|
-
export interface OpeningHour {
|
|
10
|
-
day: number;
|
|
11
|
-
isOpen: boolean;
|
|
12
|
-
isAllDay?: boolean;
|
|
13
|
-
timeSlots?: TimeSlot[];
|
|
14
|
-
}
|
|
15
|
-
export interface ContactChannel {
|
|
16
|
-
channel_type: string;
|
|
17
|
-
value: string;
|
|
18
|
-
}
|
|
19
|
-
export interface SpecialDay {
|
|
20
|
-
date: string | Date;
|
|
21
|
-
isOpen: boolean;
|
|
22
|
-
timeSlots?: TimeSlot[];
|
|
23
|
-
}
|
|
24
|
-
export interface PlaceDetailItem {
|
|
25
|
-
description?: string;
|
|
26
|
-
categories?: Category[];
|
|
27
|
-
open_status?: string;
|
|
28
|
-
opening_hours?: OpeningHour[];
|
|
29
|
-
special_days?: SpecialDay[];
|
|
30
|
-
phone?: string;
|
|
31
|
-
contact_channels?: ContactChannel[];
|
|
32
|
-
}
|
|
1
|
+
import type { PlaceDetailItem } from "#pukaad-ui/types/models/place";
|
|
2
|
+
export type { PlaceDetailItem } from "#pukaad-ui/types/models/place";
|
|
33
3
|
type __VLS_Props = {
|
|
34
4
|
item?: PlaceDetailItem;
|
|
35
5
|
};
|
|
@@ -30,50 +30,13 @@
|
|
|
30
30
|
props.item.open_status === 'temporarily_closed' ? 'text-destructive' : 'text-primary '
|
|
31
31
|
]"
|
|
32
32
|
/>
|
|
33
|
-
<div
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</div>
|
|
40
|
-
<div
|
|
41
|
-
v-for="(hour, index) in businessHours"
|
|
42
|
-
:key="index"
|
|
43
|
-
class="flex items-start justify-between"
|
|
44
|
-
>
|
|
45
|
-
<span>{{ hour.day }}</span>
|
|
46
|
-
<div class="flex flex-col items-end">
|
|
47
|
-
<span v-for="(line, li) in hour.time_lines" :key="li">{{
|
|
48
|
-
line
|
|
49
|
-
}}</span>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<template v-if="upcomingSpecialDays.length">
|
|
54
|
-
<div class="font-body-large-prominent text-warning">
|
|
55
|
-
วันทำการพิเศษ
|
|
56
|
-
</div>
|
|
57
|
-
<div
|
|
58
|
-
v-for="(special, index) in upcomingSpecialDays"
|
|
59
|
-
:key="index"
|
|
60
|
-
class="flex items-start justify-between text-warning"
|
|
61
|
-
>
|
|
62
|
-
<span>{{ special.date_label }}</span>
|
|
63
|
-
<div class="flex flex-col items-end">
|
|
64
|
-
<span v-for="(line, li) in special.time_lines" :key="li">{{
|
|
65
|
-
line
|
|
66
|
-
}}</span>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
</template>
|
|
70
|
-
</div>
|
|
71
|
-
<div v-else-if="props.item.open_status === 'temporarily_closed'">
|
|
72
|
-
<div class="font-body-large-prominent text-destructive">
|
|
73
|
-
ปิดชั่วคราว
|
|
74
|
-
</div>
|
|
33
|
+
<div class="flex-1 min-w-0">
|
|
34
|
+
<CardOpeningHours
|
|
35
|
+
:items="props.item.opening_hours"
|
|
36
|
+
:special-days="props.item.special_days"
|
|
37
|
+
:open-status="props.item.open_status"
|
|
38
|
+
/>
|
|
75
39
|
</div>
|
|
76
|
-
<div v-else class="text-cloud">ไม่มีข้อมูลเวลาทำการ</div>
|
|
77
40
|
</div>
|
|
78
41
|
|
|
79
42
|
<div class="flex gap-[12px]">
|
|
@@ -85,7 +48,25 @@
|
|
|
85
48
|
<div v-if="props.item.phone">{{ props.item.phone }}</div>
|
|
86
49
|
<div v-else class="text-cloud">ไม่มีข้อมูลเบอร์โทรศัพท์</div>
|
|
87
50
|
</div>
|
|
88
|
-
|
|
51
|
+
<div class="flex gap-[12px]">
|
|
52
|
+
<Icon
|
|
53
|
+
name="lucide:shield-check"
|
|
54
|
+
:size="20"
|
|
55
|
+
class="text-primary shrink-0 mt-[2px]"
|
|
56
|
+
/>
|
|
57
|
+
<div class="font-body-large">หากคุณเป็นเจ้าของธุรกิจนี้</div>
|
|
58
|
+
</div>
|
|
59
|
+
<div
|
|
60
|
+
class="flex gap-[12px] hover:cursor-pointer"
|
|
61
|
+
@click="isOpenModalSuggestEdit = true"
|
|
62
|
+
>
|
|
63
|
+
<Icon
|
|
64
|
+
name="lucide:square-pen"
|
|
65
|
+
:size="20"
|
|
66
|
+
class="text-primary shrink-0 mt-[2px]"
|
|
67
|
+
/>
|
|
68
|
+
<div class="font-body-large">แนะนำให้แก้ไข</div>
|
|
69
|
+
</div>
|
|
89
70
|
<Divider />
|
|
90
71
|
|
|
91
72
|
<div v-if="socialLinks.length" class="flex flex-col gap-[8px]">
|
|
@@ -108,11 +89,15 @@
|
|
|
108
89
|
<span class="text-cloud">ไม่มีข้อมูลช่องทางติดต่อ</span>
|
|
109
90
|
</div>
|
|
110
91
|
</div>
|
|
92
|
+
<ModalSuggestEditPlace
|
|
93
|
+
v-model="isOpenModalSuggestEdit"
|
|
94
|
+
:item="props.item"
|
|
95
|
+
/>
|
|
111
96
|
</Card>
|
|
112
97
|
</template>
|
|
113
98
|
|
|
114
99
|
<script setup>
|
|
115
|
-
import { computed } from "vue";
|
|
100
|
+
import { computed, ref } from "vue";
|
|
116
101
|
import dayjs from "#pukaad-ui/runtime/utils/dayjs";
|
|
117
102
|
const DAY_NAMES = [
|
|
118
103
|
"\u0E27\u0E31\u0E19\u0E2D\u0E32\u0E17\u0E34\u0E15\u0E22\u0E4C",
|
|
@@ -126,21 +111,10 @@ const DAY_NAMES = [
|
|
|
126
111
|
const props = defineProps({
|
|
127
112
|
item: { type: Object, required: false, default: () => ({}) }
|
|
128
113
|
});
|
|
114
|
+
const isOpenModalSuggestEdit = ref(false);
|
|
129
115
|
const toArray = (value) => Array.isArray(value) ? value : [];
|
|
130
116
|
const categoryText = computed(
|
|
131
|
-
() =>
|
|
132
|
-
);
|
|
133
|
-
const getTimeLines = (isOpen, timeSlots, isAllDay) => {
|
|
134
|
-
if (!isOpen) return ["\u0E2B\u0E22\u0E38\u0E14\u0E17\u0E33\u0E01\u0E32\u0E23"];
|
|
135
|
-
const slots = toArray(timeSlots);
|
|
136
|
-
if (isAllDay || slots.length === 0) return ["\u0E40\u0E1B\u0E34\u0E14\u0E15\u0E25\u0E2D\u0E14 24 \u0E0A\u0E21."];
|
|
137
|
-
return slots.map((t) => `${t.start} - ${t.end} \u0E19.`);
|
|
138
|
-
};
|
|
139
|
-
const businessHours = computed(
|
|
140
|
-
() => toArray(props.item.opening_hours).filter((h) => !!h).map((h) => ({
|
|
141
|
-
day: DAY_NAMES[h.day] ?? "",
|
|
142
|
-
time_lines: getTimeLines(h.isOpen, h.timeSlots, h.isAllDay)
|
|
143
|
-
}))
|
|
117
|
+
() => props.item.categories?.map((c) => c.category_name).join(", ") ?? ""
|
|
144
118
|
);
|
|
145
119
|
const socialLinks = computed(
|
|
146
120
|
() => toArray(props.item.contact_channels).filter((ch) => ch?.value).map((ch) => ({
|
|
@@ -148,17 +122,6 @@ const socialLinks = computed(
|
|
|
148
122
|
link: ch.value
|
|
149
123
|
}))
|
|
150
124
|
);
|
|
151
|
-
const sortedSpecialDays = computed(() => {
|
|
152
|
-
const today = dayjs().startOf("day");
|
|
153
|
-
const maxDate = today.add(30, "day").endOf("day");
|
|
154
|
-
return toArray(props.item.special_days).filter((s) => !!s?.date).map((s) => ({ ...s, date: dayjs(s.date) })).filter((s) => s.date.isValid()).filter((s) => !s.date.isBefore(today) && !s.date.isAfter(maxDate)).sort((a, b) => a.date.valueOf() - b.date.valueOf());
|
|
155
|
-
});
|
|
156
|
-
const upcomingSpecialDays = computed(
|
|
157
|
-
() => sortedSpecialDays.value.map((s) => ({
|
|
158
|
-
date_label: s.date.locale("th").format("D MMMM BBBB"),
|
|
159
|
-
time_lines: getTimeLines(s.isOpen, s.timeSlots)
|
|
160
|
-
}))
|
|
161
|
-
);
|
|
162
125
|
const onClickLink = (link) => {
|
|
163
126
|
window.open(link, "_blank");
|
|
164
127
|
};
|
|
@@ -1,35 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
category_name: string;
|
|
4
|
-
}
|
|
5
|
-
export interface TimeSlot {
|
|
6
|
-
start: string;
|
|
7
|
-
end: string;
|
|
8
|
-
}
|
|
9
|
-
export interface OpeningHour {
|
|
10
|
-
day: number;
|
|
11
|
-
isOpen: boolean;
|
|
12
|
-
isAllDay?: boolean;
|
|
13
|
-
timeSlots?: TimeSlot[];
|
|
14
|
-
}
|
|
15
|
-
export interface ContactChannel {
|
|
16
|
-
channel_type: string;
|
|
17
|
-
value: string;
|
|
18
|
-
}
|
|
19
|
-
export interface SpecialDay {
|
|
20
|
-
date: string | Date;
|
|
21
|
-
isOpen: boolean;
|
|
22
|
-
timeSlots?: TimeSlot[];
|
|
23
|
-
}
|
|
24
|
-
export interface PlaceDetailItem {
|
|
25
|
-
description?: string;
|
|
26
|
-
categories?: Category[];
|
|
27
|
-
open_status?: string;
|
|
28
|
-
opening_hours?: OpeningHour[];
|
|
29
|
-
special_days?: SpecialDay[];
|
|
30
|
-
phone?: string;
|
|
31
|
-
contact_channels?: ContactChannel[];
|
|
32
|
-
}
|
|
1
|
+
import type { PlaceDetailItem } from "#pukaad-ui/types/models/place";
|
|
2
|
+
export type { PlaceDetailItem } from "#pukaad-ui/types/models/place";
|
|
33
3
|
type __VLS_Props = {
|
|
34
4
|
item?: PlaceDetailItem;
|
|
35
5
|
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "vue";
|
|
1
2
|
type __VLS_Props = {
|
|
2
3
|
provinceId?: number;
|
|
3
4
|
amphurId?: number;
|
|
4
5
|
tambonId?: number;
|
|
6
|
+
class?: HTMLAttributes["class"];
|
|
5
7
|
};
|
|
6
8
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
7
9
|
"update:latLng": (val: {
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
class="relative w-[334px] h-[434px] rounded-[12px] overflow-hidden bg-gray-300 z-0"
|
|
4
|
-
>
|
|
2
|
+
<div :class="rootClass">
|
|
5
3
|
<div ref="mapContainer" class="w-full h-full z-0"></div>
|
|
6
4
|
</div>
|
|
7
5
|
</template>
|
|
8
6
|
|
|
9
7
|
<script setup>
|
|
10
|
-
import { ref, onMounted, watch } from "vue";
|
|
8
|
+
import { computed, ref, onMounted, watch } from "vue";
|
|
11
9
|
import mapPinSvg from "#pukaad-ui/runtime/assets/svg/map-pin.svg?raw";
|
|
10
|
+
import { cn } from "#pukaad-ui/runtime/plugins/shadcn";
|
|
12
11
|
const props = defineProps({
|
|
13
12
|
provinceId: { type: Number, required: false },
|
|
14
13
|
amphurId: { type: Number, required: false },
|
|
15
|
-
tambonId: { type: Number, required: false }
|
|
14
|
+
tambonId: { type: Number, required: false },
|
|
15
|
+
class: { type: null, required: false }
|
|
16
16
|
});
|
|
17
|
+
const rootClass = computed(
|
|
18
|
+
() => cn(
|
|
19
|
+
"relative w-[334px] h-[434px] rounded-[12px] overflow-hidden bg-gray-300 z-0",
|
|
20
|
+
props.class
|
|
21
|
+
)
|
|
22
|
+
);
|
|
17
23
|
const emits = defineEmits(["update:latLng"]);
|
|
18
24
|
const mapContainer = ref(null);
|
|
19
25
|
let map = null;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { HTMLAttributes } from "vue";
|
|
1
2
|
type __VLS_Props = {
|
|
2
3
|
provinceId?: number;
|
|
3
4
|
amphurId?: number;
|
|
4
5
|
tambonId?: number;
|
|
6
|
+
class?: HTMLAttributes["class"];
|
|
5
7
|
};
|
|
6
8
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
7
9
|
"update:latLng": (val: {
|
|
@@ -48,8 +48,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
48
48
|
id: string;
|
|
49
49
|
name: string;
|
|
50
50
|
required: boolean;
|
|
51
|
-
options: AutocompleteOption[] | string[] | number[];
|
|
52
51
|
description: string;
|
|
52
|
+
options: AutocompleteOption[] | string[] | number[];
|
|
53
53
|
labelKey: string;
|
|
54
54
|
placeholder: string;
|
|
55
55
|
limit: number;
|
|
@@ -48,8 +48,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
48
48
|
id: string;
|
|
49
49
|
name: string;
|
|
50
50
|
required: boolean;
|
|
51
|
-
options: AutocompleteOption[] | string[] | number[];
|
|
52
51
|
description: string;
|
|
52
|
+
options: AutocompleteOption[] | string[] | number[];
|
|
53
53
|
labelKey: string;
|
|
54
54
|
placeholder: string;
|
|
55
55
|
limit: number;
|
|
@@ -35,8 +35,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
35
35
|
fullHeight: boolean;
|
|
36
36
|
fullWidth: boolean;
|
|
37
37
|
limit: number;
|
|
38
|
-
accept: string;
|
|
39
38
|
disabledErrorMessage: boolean;
|
|
39
|
+
accept: string;
|
|
40
40
|
labelIcon: string;
|
|
41
41
|
disabledDrop: boolean;
|
|
42
42
|
column: boolean;
|
|
@@ -35,8 +35,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
|
|
|
35
35
|
fullHeight: boolean;
|
|
36
36
|
fullWidth: boolean;
|
|
37
37
|
limit: number;
|
|
38
|
-
accept: string;
|
|
39
38
|
disabledErrorMessage: boolean;
|
|
39
|
+
accept: string;
|
|
40
40
|
labelIcon: string;
|
|
41
41
|
disabledDrop: boolean;
|
|
42
42
|
column: boolean;
|
|
@@ -2,8 +2,10 @@ import type { InputLinkItem, ContactChannel, InputLinkProps } from "#pukaad-ui/t
|
|
|
2
2
|
type __VLS_Props = InputLinkProps & {
|
|
3
3
|
modelValue?: InputLinkItem[] | ContactChannel[];
|
|
4
4
|
defaultFirst?: boolean;
|
|
5
|
+
defaultType?: string;
|
|
5
6
|
showCounter?: boolean;
|
|
6
7
|
limit?: number;
|
|
8
|
+
label?: string;
|
|
7
9
|
};
|
|
8
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
9
11
|
hasError: () => boolean;
|
|
@@ -12,11 +14,14 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
|
12
14
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
15
|
"onUpdate:modelValue"?: ((value: InputLinkItem[] | ContactChannel[]) => any) | undefined;
|
|
14
16
|
}>, {
|
|
17
|
+
label: string;
|
|
15
18
|
name: string;
|
|
16
19
|
modelValue: InputLinkItem[] | ContactChannel[];
|
|
17
20
|
limit: number;
|
|
18
21
|
showCounter: boolean;
|
|
19
22
|
format: "legacy" | "contact_channel";
|
|
23
|
+
hideType: boolean;
|
|
24
|
+
hideAddButton: boolean;
|
|
20
25
|
defaultFirst: boolean;
|
|
21
26
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
27
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="relative">
|
|
3
|
-
<div class="font-body-large-prominent text-gray"
|
|
3
|
+
<div class="font-body-large-prominent text-gray">{{ props.label }}</div>
|
|
4
4
|
<ul class="flex flex-col gap-[16px]">
|
|
5
5
|
<li v-for="(link, i) in linkValue" :key="i">
|
|
6
6
|
<InputTypedField
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
:rules="(v) => rules(v, link.name)"
|
|
11
11
|
:show-counter="props.showCounter"
|
|
12
12
|
:limit="props.limit"
|
|
13
|
+
:hide-type="props.hideType"
|
|
13
14
|
v-model:type="link.name"
|
|
14
15
|
v-model:value="link.link"
|
|
15
16
|
@change="onChangeLink(link, i)"
|
|
16
17
|
/>
|
|
17
18
|
</li>
|
|
18
|
-
<li>
|
|
19
|
+
<li v-if="!props.hideAddButton">
|
|
19
20
|
<Button variant="text" color="primary" @click="addLink">
|
|
20
21
|
<Icon name="lucide:plus" />
|
|
21
22
|
เพิ่มช่องทาง
|
|
@@ -30,10 +31,14 @@ import { computed, ref, watch, onMounted } from "vue";
|
|
|
30
31
|
const props = defineProps({
|
|
31
32
|
name: { type: String, required: false, default: "link" },
|
|
32
33
|
format: { type: String, required: false, default: "legacy" },
|
|
34
|
+
hideType: { type: Boolean, required: false, default: false },
|
|
35
|
+
hideAddButton: { type: Boolean, required: false, default: false },
|
|
33
36
|
modelValue: { type: Array, required: false, default: () => [] },
|
|
34
37
|
defaultFirst: { type: Boolean, required: false, default: false },
|
|
38
|
+
defaultType: { type: String, required: false },
|
|
35
39
|
showCounter: { type: Boolean, required: false, default: false },
|
|
36
|
-
limit: { type: Number, required: false, default: 0 }
|
|
40
|
+
limit: { type: Number, required: false, default: 0 },
|
|
41
|
+
label: { type: String, required: false, default: "\u0E0A\u0E48\u0E2D\u0E07\u0E17\u0E32\u0E07\u0E01\u0E32\u0E23\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E2D\u0E37\u0E48\u0E19" }
|
|
37
42
|
});
|
|
38
43
|
const emit = defineEmits(["update:modelValue"]);
|
|
39
44
|
const listSocial = [
|
|
@@ -167,13 +172,14 @@ watch(
|
|
|
167
172
|
},
|
|
168
173
|
{ deep: true }
|
|
169
174
|
);
|
|
175
|
+
const findSocial = (name) => listSocial.find((item) => item.name.toLowerCase() === name?.toLowerCase());
|
|
170
176
|
const rules = (v, linkName) => {
|
|
171
177
|
if (!v) return true;
|
|
172
|
-
const socialItem =
|
|
178
|
+
const socialItem = findSocial(linkName);
|
|
173
179
|
if (socialItem && socialItem.regex) {
|
|
174
180
|
if (!socialItem.regex.test(v)) {
|
|
175
|
-
if (
|
|
176
|
-
return `\u0E23\u0E39\u0E1B\u0E41\u0E1A\u0E1A\u0E25\u0E34\u0E07\u0E04\u0E4C ${
|
|
181
|
+
if (socialItem.name === "Email") return "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E01\u0E23\u0E2D\u0E01\u0E2D\u0E35\u0E40\u0E21\u0E25\u0E17\u0E35\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07";
|
|
182
|
+
return `\u0E23\u0E39\u0E1B\u0E41\u0E1A\u0E1A\u0E25\u0E34\u0E07\u0E04\u0E4C ${socialItem.name} \u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07`;
|
|
177
183
|
}
|
|
178
184
|
return true;
|
|
179
185
|
}
|
|
@@ -181,7 +187,7 @@ const rules = (v, linkName) => {
|
|
|
181
187
|
return regex.test(v) || "\u0E23\u0E39\u0E1B\u0E41\u0E1A\u0E1A\u0E25\u0E34\u0E07\u0E04\u0E4C\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07";
|
|
182
188
|
};
|
|
183
189
|
const getPlaceholder = (name) => {
|
|
184
|
-
return
|
|
190
|
+
return findSocial(name)?.example || "";
|
|
185
191
|
};
|
|
186
192
|
const listOption = computed(() => {
|
|
187
193
|
const arr = listSocial.map((item) => {
|
|
@@ -200,7 +206,7 @@ onMounted(() => {
|
|
|
200
206
|
});
|
|
201
207
|
const addLink = () => {
|
|
202
208
|
const link = {
|
|
203
|
-
name: "Email",
|
|
209
|
+
name: props.defaultType || "Email",
|
|
204
210
|
link: ""
|
|
205
211
|
};
|
|
206
212
|
if (!Array.isArray(linkValue.value)) {
|
|
@@ -2,8 +2,10 @@ import type { InputLinkItem, ContactChannel, InputLinkProps } from "#pukaad-ui/t
|
|
|
2
2
|
type __VLS_Props = InputLinkProps & {
|
|
3
3
|
modelValue?: InputLinkItem[] | ContactChannel[];
|
|
4
4
|
defaultFirst?: boolean;
|
|
5
|
+
defaultType?: string;
|
|
5
6
|
showCounter?: boolean;
|
|
6
7
|
limit?: number;
|
|
8
|
+
label?: string;
|
|
7
9
|
};
|
|
8
10
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
9
11
|
hasError: () => boolean;
|
|
@@ -12,11 +14,14 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {
|
|
|
12
14
|
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
15
|
"onUpdate:modelValue"?: ((value: InputLinkItem[] | ContactChannel[]) => any) | undefined;
|
|
14
16
|
}>, {
|
|
17
|
+
label: string;
|
|
15
18
|
name: string;
|
|
16
19
|
modelValue: InputLinkItem[] | ContactChannel[];
|
|
17
20
|
limit: number;
|
|
18
21
|
showCounter: boolean;
|
|
19
22
|
format: "legacy" | "contact_channel";
|
|
23
|
+
hideType: boolean;
|
|
24
|
+
hideAddButton: boolean;
|
|
20
25
|
defaultFirst: boolean;
|
|
21
26
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
27
|
declare const _default: typeof __VLS_export;
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
<div class="flex items-start gap-[8px] font-body-large">
|
|
23
23
|
<InputSelect
|
|
24
|
+
v-if="!props.hideType"
|
|
24
25
|
:name="`${props.name}-type`"
|
|
25
26
|
:class="props.selectClass"
|
|
26
27
|
:options="props.options"
|
|
@@ -55,7 +56,8 @@ const props = defineProps({
|
|
|
55
56
|
limit: { type: Number, required: false, default: 0 },
|
|
56
57
|
selectClass: { type: null, required: false, default: "w-[172px]" },
|
|
57
58
|
fieldClass: { type: null, required: false },
|
|
58
|
-
resetOnTypeChange: { type: Boolean, required: false, default: true }
|
|
59
|
+
resetOnTypeChange: { type: Boolean, required: false, default: true },
|
|
60
|
+
hideType: { type: Boolean, required: false }
|
|
59
61
|
});
|
|
60
62
|
const emit = defineEmits(["typeChange", "change"]);
|
|
61
63
|
const type = defineModel("type", { type: String, ...{ default: "" } });
|