pukaad-ui-lib 1.370.0 → 1.372.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.
Files changed (35) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/card/card-opening-hours.d.vue.ts +16 -0
  3. package/dist/runtime/components/card/card-opening-hours.vue +90 -0
  4. package/dist/runtime/components/card/card-opening-hours.vue.d.ts +16 -0
  5. package/dist/runtime/components/card/card-place-detail.vue +28 -85
  6. package/dist/runtime/components/card/card-profile-header.d.vue.ts +1 -1
  7. package/dist/runtime/components/card/card-profile-header.vue.d.ts +1 -1
  8. package/dist/runtime/components/card/card-reaction.d.vue.ts +1 -1
  9. package/dist/runtime/components/card/card-reaction.vue.d.ts +1 -1
  10. package/dist/runtime/components/card/card-review.d.vue.ts +5 -5
  11. package/dist/runtime/components/card/card-review.vue.d.ts +5 -5
  12. package/dist/runtime/components/display/display-image-place.d.vue.ts +1 -1
  13. package/dist/runtime/components/display/display-image-place.vue.d.ts +1 -1
  14. package/dist/runtime/components/drawer/drawer-profile-network.d.vue.ts +1 -1
  15. package/dist/runtime/components/drawer/drawer-profile-network.vue.d.ts +1 -1
  16. package/dist/runtime/components/input/input-autocomplete.d.vue.ts +1 -1
  17. package/dist/runtime/components/input/input-autocomplete.vue.d.ts +1 -1
  18. package/dist/runtime/components/input/input-file.d.vue.ts +1 -1
  19. package/dist/runtime/components/input/input-file.vue.d.ts +1 -1
  20. package/dist/runtime/components/input/input-localized-name.d.vue.ts +1 -1
  21. package/dist/runtime/components/input/input-localized-name.vue.d.ts +1 -1
  22. package/dist/runtime/components/input/input-tag.d.vue.ts +1 -1
  23. package/dist/runtime/components/input/input-tag.vue.d.ts +1 -1
  24. package/dist/runtime/components/input/input-typed-field.d.vue.ts +1 -1
  25. package/dist/runtime/components/input/input-typed-field.vue.d.ts +1 -1
  26. package/dist/runtime/components/modal/modal-media-view.d.vue.ts +1 -1
  27. package/dist/runtime/components/modal/modal-media-view.vue.d.ts +1 -1
  28. package/dist/runtime/components/modal/suggest-edit-place/modal-suggest-edit-place.vue +154 -69
  29. package/dist/runtime/components/modal/suggest-edit-place/place-dateopening.vue +5 -78
  30. package/dist/runtime/components/timeline.d.vue.ts +14 -0
  31. package/dist/runtime/components/timeline.vue +29 -10
  32. package/dist/runtime/components/timeline.vue.d.ts +14 -0
  33. package/dist/runtime/utils/opening-hours.d.ts +21 -0
  34. package/dist/runtime/utils/opening-hours.js +20 -0
  35. package/package.json +1 -1
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pukaad-ui-lib",
3
3
  "configKey": "pukaadUI",
4
- "version": "1.370.0",
4
+ "version": "1.372.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "3.6.1"
@@ -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;
@@ -30,50 +30,13 @@
30
30
  props.item.open_status === 'temporarily_closed' ? 'text-destructive' : 'text-primary '
31
31
  ]"
32
32
  />
33
- <div v-if="businessHours.length" class="flex flex-col gap-[4px] flex-1">
34
- <div
35
- v-if="props.item.open_status === 'temporarily_closed'"
36
- class="font-body-large-prominent text-error"
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,25 +48,27 @@
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
- <div class="flex gap-[12px]">
89
- <Icon
90
- name="lucide:shield-check"
91
- :size="20"
92
- class="text-primary shrink-0 mt-[2px]"
93
- />
94
- <div class="font-body-large">หากคุณเป็นเจ้าของธุรกิจนี้</div>
95
- </div>
96
- <div
97
- class="flex gap-[12px] hover:cursor-pointer"
98
- @click="isOpenModalSuggestEdit = true"
99
- >
100
- <Icon
101
- name="lucide:square-pen"
102
- :size="20"
103
- class="text-primary shrink-0 mt-[2px]"
104
- />
105
- <div class="font-body-large">แนะนำให้แก้ไข</div>
106
- </div>
51
+ <template v-if="!props.item.owner_profile_id">
52
+ <div class="flex gap-[12px]">
53
+ <Icon
54
+ name="lucide:shield-check"
55
+ :size="20"
56
+ class="text-primary shrink-0 mt-[2px]"
57
+ />
58
+ <div class="font-body-large">หากคุณเป็นเจ้าของธุรกิจนี้</div>
59
+ </div>
60
+ <div
61
+ class="flex gap-[12px] hover:cursor-pointer"
62
+ @click="isOpenModalSuggestEdit = true"
63
+ >
64
+ <Icon
65
+ name="lucide:square-pen"
66
+ :size="20"
67
+ class="text-primary shrink-0 mt-[2px]"
68
+ />
69
+ <div class="font-body-large">แนะนำให้แก้ไข</div>
70
+ </div>
71
+ </template>
107
72
  <Divider />
108
73
 
109
74
  <div v-if="socialLinks.length" class="flex flex-col gap-[8px]">
@@ -127,6 +92,7 @@
127
92
  </div>
128
93
  </div>
129
94
  <ModalSuggestEditPlace
95
+ v-if="!props.item.owner_profile_id"
130
96
  v-model="isOpenModalSuggestEdit"
131
97
  :item="props.item"
132
98
  />
@@ -153,35 +119,12 @@ const toArray = (value) => Array.isArray(value) ? value : [];
153
119
  const categoryText = computed(
154
120
  () => props.item.categories?.map((c) => c.category_name).join(", ") ?? ""
155
121
  );
156
- const getTimeLines = (isOpen, timeSlots, isAllDay) => {
157
- if (!isOpen) return ["\u0E2B\u0E22\u0E38\u0E14\u0E17\u0E33\u0E01\u0E32\u0E23"];
158
- const slots = toArray(timeSlots);
159
- if (isAllDay || slots.length === 0) return ["\u0E40\u0E1B\u0E34\u0E14\u0E15\u0E25\u0E2D\u0E14 24 \u0E0A\u0E21."];
160
- return slots.map((t) => `${t.start} - ${t.end} \u0E19.`);
161
- };
162
- const businessHours = computed(
163
- () => toArray(props.item.opening_hours).filter((h) => !!h).map((h) => ({
164
- day: DAY_NAMES[h.day] ?? "",
165
- time_lines: getTimeLines(h.isOpen, h.timeSlots, h.isAllDay)
166
- }))
167
- );
168
122
  const socialLinks = computed(
169
123
  () => toArray(props.item.contact_channels).filter((ch) => ch?.value).map((ch) => ({
170
124
  name: ch.channel_type ?? "link",
171
125
  link: ch.value
172
126
  }))
173
127
  );
174
- const sortedSpecialDays = computed(() => {
175
- const today = dayjs().startOf("day");
176
- const maxDate = today.add(30, "day").endOf("day");
177
- 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());
178
- });
179
- const upcomingSpecialDays = computed(
180
- () => sortedSpecialDays.value.map((s) => ({
181
- date_label: s.date.locale("th").format("D MMMM BBBB"),
182
- time_lines: getTimeLines(s.isOpen, s.timeSlots)
183
- }))
184
- );
185
128
  const onClickLink = (link) => {
186
129
  window.open(link, "_blank");
187
130
  };
@@ -7,9 +7,9 @@ declare const __VLS_export: import("vue").DefineComponent<CardProfileAboutProps,
7
7
  onChat?: (() => any) | undefined;
8
8
  }>, {
9
9
  type: "article" | "media" | "sale-info";
10
+ preview: boolean;
10
11
  optionMenuButtonType: "solid" | "text";
11
12
  actionsHidden: boolean;
12
- preview: boolean;
13
13
  disabledPadding: boolean;
14
14
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
15
  declare const _default: typeof __VLS_export;
@@ -7,9 +7,9 @@ declare const __VLS_export: import("vue").DefineComponent<CardProfileAboutProps,
7
7
  onChat?: (() => any) | undefined;
8
8
  }>, {
9
9
  type: "article" | "media" | "sale-info";
10
+ preview: boolean;
10
11
  optionMenuButtonType: "solid" | "text";
11
12
  actionsHidden: boolean;
12
- preview: boolean;
13
13
  disabledPadding: boolean;
14
14
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
15
  declare const _default: typeof __VLS_export;
@@ -24,8 +24,8 @@ type __VLS_Props = {
24
24
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
25
25
  disabled: boolean;
26
26
  id: string;
27
- disabledPadding: boolean;
28
27
  state: string;
28
+ disabledPadding: boolean;
29
29
  itemCount: Count;
30
30
  itemActive: Reacted;
31
31
  padding: string | number;
@@ -24,8 +24,8 @@ type __VLS_Props = {
24
24
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
25
25
  disabled: boolean;
26
26
  id: string;
27
- disabledPadding: boolean;
28
27
  state: string;
28
+ disabledPadding: boolean;
29
29
  itemCount: Count;
30
30
  itemActive: Reacted;
31
31
  padding: string | number;
@@ -36,17 +36,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
36
36
  "onReply-delete"?: ((item: CardReviewProps) => any) | undefined;
37
37
  }>, {
38
38
  item: CardReviewProps;
39
- disabledMenu: boolean;
40
- isProfile: boolean;
41
- disabledLike: boolean;
42
- allowReply: boolean;
43
- replyAvatar: string;
44
39
  place: {
45
40
  id: string | number;
46
41
  name?: string;
47
42
  address?: string;
48
43
  cover?: string;
49
44
  };
45
+ disabledMenu: boolean;
46
+ isProfile: boolean;
47
+ disabledLike: boolean;
48
+ allowReply: boolean;
49
+ replyAvatar: string;
50
50
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
51
  declare const _default: typeof __VLS_export;
52
52
  export default _default;
@@ -36,17 +36,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
36
36
  "onReply-delete"?: ((item: CardReviewProps) => any) | undefined;
37
37
  }>, {
38
38
  item: CardReviewProps;
39
- disabledMenu: boolean;
40
- isProfile: boolean;
41
- disabledLike: boolean;
42
- allowReply: boolean;
43
- replyAvatar: string;
44
39
  place: {
45
40
  id: string | number;
46
41
  name?: string;
47
42
  address?: string;
48
43
  cover?: string;
49
44
  };
45
+ disabledMenu: boolean;
46
+ isProfile: boolean;
47
+ disabledLike: boolean;
48
+ allowReply: boolean;
49
+ replyAvatar: string;
50
50
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
51
51
  declare const _default: typeof __VLS_export;
52
52
  export default _default;
@@ -15,9 +15,9 @@ type __VLS_Props = {
15
15
  };
16
16
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
17
17
  title: string;
18
- state: "personal" | "office" | "business";
19
18
  photos: MediaItem[];
20
19
  videos: MediaItem[];
20
+ state: "personal" | "office" | "business";
21
21
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
22
  declare const _default: typeof __VLS_export;
23
23
  export default _default;
@@ -15,9 +15,9 @@ type __VLS_Props = {
15
15
  };
16
16
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
17
17
  title: string;
18
- state: "personal" | "office" | "business";
19
18
  photos: MediaItem[];
20
19
  videos: MediaItem[];
20
+ state: "personal" | "office" | "business";
21
21
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
22
  declare const _default: typeof __VLS_export;
23
23
  export default _default;
@@ -30,9 +30,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
30
30
  "onExplore-places"?: (() => any) | undefined;
31
31
  "onRequire-auth"?: (() => any) | undefined;
32
32
  }>, {
33
- isMyProfile: boolean;
34
33
  profileId: string;
35
34
  defaultTab: "followers" | "following" | "favorites";
35
+ isMyProfile: boolean;
36
36
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
37
37
  declare const _default: typeof __VLS_export;
38
38
  export default _default;
@@ -30,9 +30,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
30
30
  "onExplore-places"?: (() => any) | undefined;
31
31
  "onRequire-auth"?: (() => any) | undefined;
32
32
  }>, {
33
- isMyProfile: boolean;
34
33
  profileId: string;
35
34
  defaultTab: "followers" | "following" | "favorites";
35
+ isMyProfile: boolean;
36
36
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
37
37
  declare const _default: typeof __VLS_export;
38
38
  export default _default;
@@ -48,11 +48,11 @@ 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;
53
52
  labelKey: string;
54
53
  placeholder: string;
55
54
  limit: number;
55
+ options: AutocompleteOption[] | string[] | number[];
56
56
  disabledErrorMessage: boolean;
57
57
  disabledBorder: boolean;
58
58
  showCounter: boolean;
@@ -48,11 +48,11 @@ 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;
53
52
  labelKey: string;
54
53
  placeholder: string;
55
54
  limit: number;
55
+ options: AutocompleteOption[] | string[] | number[];
56
56
  disabledErrorMessage: boolean;
57
57
  disabledBorder: boolean;
58
58
  showCounter: 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;
@@ -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;
@@ -11,9 +11,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
11
11
  label: string;
12
12
  name: string;
13
13
  modelValue: LocalizedNameItem[];
14
- options: InputSelectItem[];
15
14
  placeholder: string;
16
15
  limit: number;
16
+ options: InputSelectItem[];
17
17
  showCounter: boolean;
18
18
  addLabel: string;
19
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -11,9 +11,9 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
11
11
  label: string;
12
12
  name: string;
13
13
  modelValue: LocalizedNameItem[];
14
- options: InputSelectItem[];
15
14
  placeholder: string;
16
15
  limit: number;
16
+ options: InputSelectItem[];
17
17
  showCounter: boolean;
18
18
  addLabel: string;
19
19
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -25,8 +25,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
25
25
  "onUpdate:modelValue"?: ((value: SelectedTag[]) => any) | undefined;
26
26
  }>, {
27
27
  name: string;
28
- state: "user" | "admin";
29
28
  placeholder: string;
29
+ state: "user" | "admin";
30
30
  limit: number;
31
31
  ignore: string[];
32
32
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -25,8 +25,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
25
25
  "onUpdate:modelValue"?: ((value: SelectedTag[]) => any) | undefined;
26
26
  }>, {
27
27
  name: string;
28
- state: "user" | "admin";
29
28
  placeholder: string;
29
+ state: "user" | "admin";
30
30
  limit: number;
31
31
  ignore: string[];
32
32
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -19,8 +19,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
19
19
  }>, {
20
20
  name: string;
21
21
  required: boolean;
22
- options: import("../../../types/components/input/input-select.js").InputSelectItem[];
23
22
  limit: number;
23
+ options: import("../../../types/components/input/input-select.js").InputSelectItem[];
24
24
  showCounter: boolean;
25
25
  selectClass: import("vue").HTMLAttributes["class"];
26
26
  resetOnTypeChange: boolean;
@@ -19,8 +19,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
19
19
  }>, {
20
20
  name: string;
21
21
  required: boolean;
22
- options: import("../../../types/components/input/input-select.js").InputSelectItem[];
23
22
  limit: number;
23
+ options: import("../../../types/components/input/input-select.js").InputSelectItem[];
24
24
  showCounter: boolean;
25
25
  selectClass: import("vue").HTMLAttributes["class"];
26
26
  resetOnTypeChange: boolean;
@@ -23,8 +23,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
23
23
  }>, {
24
24
  title: string;
25
25
  items: CarouselItem[];
26
- startIndex: number;
27
26
  uploaderLabel: string;
27
+ startIndex: number;
28
28
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
29
29
  declare const _default: typeof __VLS_export;
30
30
  export default _default;
@@ -23,8 +23,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {},
23
23
  }>, {
24
24
  title: string;
25
25
  items: CarouselItem[];
26
- startIndex: number;
27
26
  uploaderLabel: string;
27
+ startIndex: number;
28
28
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
29
29
  declare const _default: typeof __VLS_export;
30
30
  export default _default;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <Modal class="w-[512px]" v-model="isOpen" :loading="false" @submit="onSubmit">
2
+ <Modal class="w-[512px]" v-model="isOpen" :loading="isSubmitting" @submit="onSubmit">
3
3
  <template #header>
4
4
  <div v-if="activeField === 'list'" class="font-title-medium-prominent">
5
5
  แนะนำให้แก้ไข
@@ -396,79 +396,164 @@ const openLinkEditField = (channel) => {
396
396
  const cancelEdit = () => {
397
397
  activeField.value = "list";
398
398
  };
399
- const onSubmit = () => {
400
- if (activeField.value === "place_name") {
401
- emit("submit-field", {
402
- field: "place_name",
403
- editType: editType.value,
404
- value: newName.value,
405
- localizedNames: localizedNames.value
406
- });
407
- }
408
- if (activeField.value === "address") {
409
- emit("submit-field", {
410
- field: "address",
411
- editType: addressEditType.value,
412
- addressValue: addressValue.value,
413
- latLng: addressLatLng.value
414
- });
415
- }
416
- if (activeField.value === "category") {
417
- emit("submit-field", {
418
- field: "category",
419
- editType: categoryEditType.value,
420
- categories: categories.value
421
- });
422
- }
423
- if (activeField.value === "description") {
424
- emit("submit-field", {
425
- field: "description",
426
- editType: descriptionEditType.value,
427
- value: descriptionValue.value
428
- });
429
- }
430
- if (activeField.value === "dateopening") {
431
- emit("submit-field", {
432
- field: "dateopening",
433
- editType: dateOpeningEditType.value,
434
- openingHours: newOpeningHours.value,
435
- specialDays: newSpecialDays.value
436
- });
437
- }
438
- if (activeField.value === "phone") {
439
- emit("submit-field", {
440
- field: "phone",
441
- value: phoneValue.value
442
- });
399
+ const isSubmitting = ref(false);
400
+ const buildSuggestEditBody = () => {
401
+ switch (activeField.value) {
402
+ case "place_name":
403
+ return {
404
+ topic_key: "name",
405
+ edit_type: editType.value,
406
+ name: newName.value,
407
+ localized_names: localizedNames.value.filter((r) => r.editType === "new" && r.newName.trim()).map((r) => ({ language: r.language, name: r.newName }))
408
+ };
409
+ case "address":
410
+ return {
411
+ topic_key: "address",
412
+ edit_type: addressEditType.value,
413
+ address: addressValue.value,
414
+ latLng: addressLatLng.value ?? void 0
415
+ };
416
+ case "category":
417
+ return {
418
+ topic_key: "category",
419
+ edit_type: categoryEditType.value,
420
+ categories: categories.value
421
+ };
422
+ case "description":
423
+ return {
424
+ topic_key: "description",
425
+ edit_type: descriptionEditType.value,
426
+ description: descriptionValue.value
427
+ };
428
+ case "dateopening":
429
+ return {
430
+ topic_key: "opening_hours",
431
+ edit_type: dateOpeningEditType.value,
432
+ opening_hours: newOpeningHours.value,
433
+ special_days: newSpecialDays.value
434
+ };
435
+ case "phone":
436
+ return {
437
+ topic_key: "phone",
438
+ edit_type: "add",
439
+ value: phoneValue.value
440
+ };
441
+ case "phone_edit":
442
+ return {
443
+ topic_key: "phone",
444
+ edit_type: phoneEditType.value,
445
+ target_value: editingPhone.value,
446
+ value: editPhoneValue.value
447
+ };
448
+ case "link":
449
+ return {
450
+ topic_key: "contact_channels",
451
+ edit_type: "add",
452
+ contact_channels: newContactChannels.value
453
+ };
454
+ case "link_edit":
455
+ return {
456
+ topic_key: "contact_channels",
457
+ edit_type: linkEditType.value,
458
+ target_channel_id: editingChannel.value?.id,
459
+ target_value: editingChannel.value?.value,
460
+ value: editChannelValue.value
461
+ };
462
+ default:
463
+ return null;
443
464
  }
444
- if (activeField.value === "phone_edit") {
445
- emit("submit-field", {
446
- field: "phone_edit",
447
- currentPhone: editingPhone.value,
448
- editType: phoneEditType.value,
449
- value: editPhoneValue.value
465
+ };
466
+ const onSubmit = async () => {
467
+ const body = buildSuggestEditBody();
468
+ if (!body || isSubmitting.value) return;
469
+ isSubmitting.value = true;
470
+ try {
471
+ await api(`/suggest-places/${props.item.id}/suggest-edits`, {
472
+ method: "post",
473
+ body
450
474
  });
451
- }
452
- if (activeField.value === "link") {
453
- emit("submit-field", {
454
- field: "link",
455
- channels: newContactChannels.value
475
+ if (activeField.value === "place_name") {
476
+ emit("submit-field", {
477
+ field: "place_name",
478
+ editType: editType.value,
479
+ value: newName.value,
480
+ localizedNames: localizedNames.value
481
+ });
482
+ }
483
+ if (activeField.value === "address") {
484
+ emit("submit-field", {
485
+ field: "address",
486
+ editType: addressEditType.value,
487
+ addressValue: addressValue.value,
488
+ latLng: addressLatLng.value
489
+ });
490
+ }
491
+ if (activeField.value === "category") {
492
+ emit("submit-field", {
493
+ field: "category",
494
+ editType: categoryEditType.value,
495
+ categories: categories.value
496
+ });
497
+ }
498
+ if (activeField.value === "description") {
499
+ emit("submit-field", {
500
+ field: "description",
501
+ editType: descriptionEditType.value,
502
+ value: descriptionValue.value
503
+ });
504
+ }
505
+ if (activeField.value === "dateopening") {
506
+ emit("submit-field", {
507
+ field: "dateopening",
508
+ editType: dateOpeningEditType.value,
509
+ openingHours: newOpeningHours.value,
510
+ specialDays: newSpecialDays.value
511
+ });
512
+ }
513
+ if (activeField.value === "phone") {
514
+ emit("submit-field", {
515
+ field: "phone",
516
+ value: phoneValue.value
517
+ });
518
+ }
519
+ if (activeField.value === "phone_edit") {
520
+ emit("submit-field", {
521
+ field: "phone_edit",
522
+ currentPhone: editingPhone.value,
523
+ editType: phoneEditType.value,
524
+ value: editPhoneValue.value
525
+ });
526
+ }
527
+ if (activeField.value === "link") {
528
+ emit("submit-field", {
529
+ field: "link",
530
+ channels: newContactChannels.value
531
+ });
532
+ }
533
+ if (activeField.value === "link_edit") {
534
+ emit("submit-field", {
535
+ field: "link_edit",
536
+ currentChannel: editingChannel.value,
537
+ editType: linkEditType.value,
538
+ value: editChannelValue.value
539
+ });
540
+ }
541
+ activeField.value = "list";
542
+ $alert.show({
543
+ type: "success",
544
+ title: "\u0E02\u0E2D\u0E1A\u0E04\u0E38\u0E13\u0E17\u0E35\u0E48\u0E41\u0E08\u0E49\u0E07\u0E43\u0E2B\u0E49\u0E40\u0E23\u0E32\u0E17\u0E23\u0E32\u0E1A !",
545
+ description: "\u0E40\u0E23\u0E32\u0E08\u0E30\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E25\u0E32\u0E2A\u0E2D\u0E07\u0E2A\u0E32\u0E21\u0E27\u0E31\u0E19\u0E43\u0E19\u0E01\u0E32\u0E23\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E23\u0E32\u0E22\u0E07\u0E32\u0E19\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13"
456
546
  });
457
- }
458
- if (activeField.value === "link_edit") {
459
- emit("submit-field", {
460
- field: "link_edit",
461
- currentChannel: editingChannel.value,
462
- editType: linkEditType.value,
463
- value: editChannelValue.value
547
+ } catch (error) {
548
+ console.error(error);
549
+ $alert.show({
550
+ type: "error",
551
+ title: "\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14",
552
+ description: "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07 !"
464
553
  });
554
+ } finally {
555
+ isSubmitting.value = false;
465
556
  }
466
- activeField.value = "list";
467
- $alert.show({
468
- type: "success",
469
- title: "\u0E02\u0E2D\u0E1A\u0E04\u0E38\u0E13\u0E17\u0E35\u0E48\u0E41\u0E08\u0E49\u0E07\u0E43\u0E2B\u0E49\u0E40\u0E23\u0E32\u0E17\u0E23\u0E32\u0E1A !",
470
- description: "\u0E40\u0E23\u0E32\u0E08\u0E30\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E25\u0E32\u0E2A\u0E2D\u0E07\u0E2A\u0E32\u0E21\u0E27\u0E31\u0E19\u0E43\u0E19\u0E01\u0E32\u0E23\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E23\u0E32\u0E22\u0E07\u0E32\u0E19\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13"
471
- });
472
557
  };
473
558
  const canSubmit = computed(() => {
474
559
  switch (activeField.value) {
@@ -6,51 +6,11 @@
6
6
  </div>
7
7
  <div class="flex flex-col gap-[8px]">
8
8
  <div class="font-body-large-prominent text-gray">วัน เวลาทำการเดิม</div>
9
- <div v-if="businessHours.length" class="flex flex-col gap-[4px]">
10
- <div
11
- v-if="props.currentOpenStatus === 'temporarily_closed'"
12
- class="font-body-large-prominent text-error"
13
- >
14
- ปิดชั่วคราว
15
- </div>
16
- <div
17
- v-for="(hour, index) in businessHours"
18
- :key="index"
19
- class="flex items-start justify-between font-body-large"
20
- >
21
- <span>{{ hour.day }}</span>
22
- <div class="flex flex-col items-end">
23
- <span v-for="(line, li) in hour.time_lines" :key="li">{{
24
- line
25
- }}</span>
26
- </div>
27
- </div>
28
-
29
- <template v-if="upcomingSpecialDays.length">
30
- <div class="font-body-large-prominent text-warning">
31
- วันทำการพิเศษ
32
- </div>
33
- <div
34
- v-for="(special, index) in upcomingSpecialDays"
35
- :key="index"
36
- class="flex items-start justify-between text-warning font-body-large"
37
- >
38
- <span>{{ special.date_label }}</span>
39
- <div class="flex flex-col items-end">
40
- <span v-for="(line, li) in special.time_lines" :key="li">{{
41
- line
42
- }}</span>
43
- </div>
44
- </div>
45
- </template>
46
- </div>
47
- <div
48
- v-else-if="props.currentOpenStatus === 'temporarily_closed'"
49
- class="font-body-large-prominent text-destructive"
50
- >
51
- ปิดชั่วคราว
52
- </div>
53
- <div v-else class="text-cloud">ไม่มีข้อมูลเวลาทำการ</div>
9
+ <CardOpeningHours
10
+ :items="props.currentOpeningHours"
11
+ :special-days="props.currentSpecialDays"
12
+ :open-status="props.currentOpenStatus"
13
+ />
54
14
  </div>
55
15
 
56
16
  <InputSelect
@@ -92,39 +52,6 @@ const editTypeOptions = [
92
52
  { label: "\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E43\u0E2B\u0E21\u0E48", value: "new" },
93
53
  { label: "\u0E44\u0E21\u0E48\u0E17\u0E23\u0E32\u0E1A \u0E41\u0E15\u0E48\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E44\u0E21\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07", value: "incorrect" }
94
54
  ];
95
- const DAY_NAMES = [
96
- "\u0E27\u0E31\u0E19\u0E2D\u0E32\u0E17\u0E34\u0E15\u0E22\u0E4C",
97
- "\u0E27\u0E31\u0E19\u0E08\u0E31\u0E19\u0E17\u0E23\u0E4C",
98
- "\u0E27\u0E31\u0E19\u0E2D\u0E31\u0E07\u0E04\u0E32\u0E23",
99
- "\u0E27\u0E31\u0E19\u0E1E\u0E38\u0E18",
100
- "\u0E27\u0E31\u0E19\u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35",
101
- "\u0E27\u0E31\u0E19\u0E28\u0E38\u0E01\u0E23\u0E4C",
102
- "\u0E27\u0E31\u0E19\u0E40\u0E2A\u0E32\u0E23\u0E4C"
103
- ];
104
- const toArray = (value) => Array.isArray(value) ? value : [];
105
- const getTimeLines = (isOpen, timeSlots, isAllDay) => {
106
- if (!isOpen) return ["\u0E2B\u0E22\u0E38\u0E14\u0E17\u0E33\u0E01\u0E32\u0E23"];
107
- const slots = toArray(timeSlots);
108
- if (isAllDay || slots.length === 0) return ["\u0E40\u0E1B\u0E34\u0E14\u0E15\u0E25\u0E2D\u0E14 24 \u0E0A\u0E21."];
109
- return slots.map((t) => `${t.start} - ${t.end} \u0E19.`);
110
- };
111
- const businessHours = computed(
112
- () => toArray(props.currentOpeningHours).filter((h) => !!h).map((h) => ({
113
- day: DAY_NAMES[h.day] ?? "",
114
- time_lines: getTimeLines(h.isOpen, h.timeSlots, h.isAllDay)
115
- }))
116
- );
117
- const sortedSpecialDays = computed(() => {
118
- const today = dayjs().startOf("day");
119
- const maxDate = today.add(30, "day").endOf("day");
120
- return toArray(props.currentSpecialDays).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());
121
- });
122
- const upcomingSpecialDays = computed(
123
- () => sortedSpecialDays.value.map((s) => ({
124
- date_label: s.date.locale("th").format("D MMMM BBBB"),
125
- time_lines: getTimeLines(s.isOpen, s.timeSlots)
126
- }))
127
- );
128
55
  const isNewOpeningHoursCompleted = computed(
129
56
  () => Array.isArray(newOpeningHours.value) && newOpeningHours.value.some((s) => s.isOpen)
130
57
  );
@@ -1,9 +1,18 @@
1
+ import type { OpeningHour, SpecialDay } from "#pukaad-ui/runtime/components/card/card-opening-hours.vue";
1
2
  export interface TimelineItem {
2
3
  id?: string | number;
3
4
  avatar?: string;
4
5
  name?: string;
5
6
  time?: string | Date;
6
7
  description?: string;
8
+ value?: string;
9
+ suggested_value?: string;
10
+ hours?: OpeningHour[];
11
+ opening_hours?: OpeningHour[];
12
+ suggested_hours?: OpeningHour[];
13
+ special_days?: SpecialDay[];
14
+ suggested_special_days?: SpecialDay[];
15
+ [key: string]: any;
7
16
  }
8
17
  type __VLS_Props = {
9
18
  items: TimelineItem[];
@@ -11,9 +20,14 @@ type __VLS_Props = {
11
20
  declare var __VLS_1: {
12
21
  item: TimelineItem;
13
22
  index: number;
23
+ }, __VLS_8: {
24
+ item: TimelineItem;
25
+ index: number;
14
26
  };
15
27
  type __VLS_Slots = {} & {
16
28
  content?: (props: typeof __VLS_1) => any;
29
+ } & {
30
+ description?: (props: typeof __VLS_8) => any;
17
31
  };
18
32
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
33
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,9 +1,9 @@
1
1
  <template>
2
- <div class="flex flex-col">
2
+ <div class="flex flex-col w-full">
3
3
  <div
4
4
  v-for="(item, index) in props.items"
5
5
  :key="item.id ?? index"
6
- class="flex gap-[8px]"
6
+ class="flex gap-[8px] w-full"
7
7
  >
8
8
  <!-- dot + connecting line (โครงของ component เอง) -->
9
9
  <div class="flex flex-col items-center w-[8px]">
@@ -15,22 +15,40 @@
15
15
 
16
16
  <!-- เนื้อหา — ปล่อยให้ผู้ใช้ครอบเองผ่าน slot ได้ ถ้าไม่ส่งมาใช้ default นี้ -->
17
17
  <div
18
- class="flex flex-col gap-[8px]"
18
+ class="flex flex-col gap-[8px] flex-1 min-w-0"
19
19
  :class="index < props.items.length - 1 ? 'pb-[16px]' : ''"
20
20
  >
21
21
  <slot name="content" :item="item" :index="index">
22
- <div class="flex gap-[8px]">
22
+ <div class="flex gap-[8px] w-full">
23
23
  <Avatar :src="item.avatar" :alt="item.name" :size="30" />
24
- <div class="flex flex-col gap-[8px]">
24
+ <div class="flex flex-col gap-[8px] flex-1 min-w-0">
25
25
  <div class="flex flex-col gap-[4px]">
26
26
  <span class="font-body-large text-gray">{{ item.name }}</span>
27
- <span class="font-body-small text-gray"
28
- >{{ convertDateTime(item.time) }} น.</span
27
+ <span
28
+ v-if="item.time"
29
+ class="font-body-small text-gray"
29
30
  >
31
+ {{ convertDateTime(item.time) }} น.
32
+ </span>
30
33
  </div>
31
- <p class="font-body-large text-gray">
32
- {{ item.description }}
33
- </p>
34
+ <slot name="description" :item="item" :index="index">
35
+ <CardOpeningHours
36
+ v-if="
37
+ item.opening_hours || item.suggested_hours || item.hours
38
+ "
39
+ :items="
40
+ item.opening_hours || item.suggested_hours || item.hours
41
+ "
42
+ :special-days="
43
+ item.special_days || item.suggested_special_days
44
+ "
45
+ :open-status="item.open_status"
46
+ class="text-gray w-full"
47
+ />
48
+ <p v-else class="font-body-large text-gray">
49
+ {{ item.description }}
50
+ </p>
51
+ </slot>
34
52
  </div>
35
53
  </div>
36
54
  </slot>
@@ -41,6 +59,7 @@
41
59
 
42
60
  <script setup>
43
61
  import { useConvert } from "#pukaad-ui/runtime/composables/useConvert";
62
+ import CardOpeningHours from "#pukaad-ui/runtime/components/card/card-opening-hours.vue";
44
63
  const props = defineProps({
45
64
  items: { type: Array, required: true }
46
65
  });
@@ -1,9 +1,18 @@
1
+ import type { OpeningHour, SpecialDay } from "#pukaad-ui/runtime/components/card/card-opening-hours.vue";
1
2
  export interface TimelineItem {
2
3
  id?: string | number;
3
4
  avatar?: string;
4
5
  name?: string;
5
6
  time?: string | Date;
6
7
  description?: string;
8
+ value?: string;
9
+ suggested_value?: string;
10
+ hours?: OpeningHour[];
11
+ opening_hours?: OpeningHour[];
12
+ suggested_hours?: OpeningHour[];
13
+ special_days?: SpecialDay[];
14
+ suggested_special_days?: SpecialDay[];
15
+ [key: string]: any;
7
16
  }
8
17
  type __VLS_Props = {
9
18
  items: TimelineItem[];
@@ -11,9 +20,14 @@ type __VLS_Props = {
11
20
  declare var __VLS_1: {
12
21
  item: TimelineItem;
13
22
  index: number;
23
+ }, __VLS_8: {
24
+ item: TimelineItem;
25
+ index: number;
14
26
  };
15
27
  type __VLS_Slots = {} & {
16
28
  content?: (props: typeof __VLS_1) => any;
29
+ } & {
30
+ description?: (props: typeof __VLS_8) => any;
17
31
  };
18
32
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
19
33
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -0,0 +1,21 @@
1
+ export interface TimeSlot {
2
+ start: string;
3
+ end: string;
4
+ }
5
+ export interface OpeningHour {
6
+ day: number;
7
+ isOpen: boolean;
8
+ isAllDay?: boolean;
9
+ timeSlots?: TimeSlot[];
10
+ }
11
+ export interface SpecialDay {
12
+ date: string | Date;
13
+ isOpen: boolean;
14
+ timeSlots?: TimeSlot[];
15
+ }
16
+ export declare const DAY_NAMES: string[];
17
+ export declare const getTimeLines: (isOpen: boolean, timeSlots?: TimeSlot[], isAllDay?: boolean) => string[];
18
+ export declare const toDayLines: (hours?: OpeningHour[]) => {
19
+ day: string;
20
+ time_lines: string[];
21
+ }[];
@@ -0,0 +1,20 @@
1
+ export const DAY_NAMES = [
2
+ "\u0E27\u0E31\u0E19\u0E2D\u0E32\u0E17\u0E34\u0E15\u0E22\u0E4C",
3
+ "\u0E27\u0E31\u0E19\u0E08\u0E31\u0E19\u0E17\u0E23\u0E4C",
4
+ "\u0E27\u0E31\u0E19\u0E2D\u0E31\u0E07\u0E04\u0E32\u0E23",
5
+ "\u0E27\u0E31\u0E19\u0E1E\u0E38\u0E18",
6
+ "\u0E27\u0E31\u0E19\u0E1E\u0E24\u0E2B\u0E31\u0E2A\u0E1A\u0E14\u0E35",
7
+ "\u0E27\u0E31\u0E19\u0E28\u0E38\u0E01\u0E23\u0E4C",
8
+ "\u0E27\u0E31\u0E19\u0E40\u0E2A\u0E32\u0E23\u0E4C"
9
+ ];
10
+ const toArray = (value) => Array.isArray(value) ? value : [];
11
+ export const getTimeLines = (isOpen, timeSlots, isAllDay) => {
12
+ if (!isOpen) return ["\u0E2B\u0E22\u0E38\u0E14\u0E17\u0E33\u0E01\u0E32\u0E23"];
13
+ const slots = toArray(timeSlots);
14
+ if (isAllDay || slots.length === 0) return ["\u0E40\u0E1B\u0E34\u0E14\u0E15\u0E25\u0E2D\u0E14 24 \u0E0A\u0E21."];
15
+ return slots.map((t) => `${t.start} - ${t.end} \u0E19.`);
16
+ };
17
+ export const toDayLines = (hours) => toArray(hours).filter((h) => !!h).map((h) => ({
18
+ day: DAY_NAMES[h.day] ?? "",
19
+ time_lines: getTimeLines(h.isOpen, h.timeSlots, h.isAllDay)
20
+ }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pukaad-ui-lib",
3
- "version": "1.370.0",
3
+ "version": "1.372.0",
4
4
  "description": "pukaad-ui for MeMSG",
5
5
  "repository": {
6
6
  "type": "git",