@webitel/ui-sdk 26.8.44 → 26.8.46

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 (22) hide show
  1. package/dist/{clients-EyPsBurj.js → clients-DBqdsc05.js} +2 -2
  2. package/dist/{components-DZ-mqx3y.js → components-CfX8XNuf.js} +3 -3
  3. package/dist/ui-sdk.css +1 -1
  4. package/dist/ui-sdk.js +1 -1
  5. package/dist/ui-sdk.umd.cjs +360 -360
  6. package/dist/{wt-chat-emoji-DxGSTYd8.js → wt-chat-emoji-PSwoA5FA.js} +1 -1
  7. package/dist/{wt-datepicker-C5LuZK-R.js → wt-datepicker-D5Af57PB.js} +7 -5
  8. package/dist/{wt-display-chip-items-DicXPtf3.js → wt-display-chip-items-CIXM-Ohl.js} +1 -1
  9. package/dist/{wt-send-message-popup-qzdEoZPK.js → wt-send-message-popup-3yRiBsoN.js} +2 -2
  10. package/dist/{wt-status-select-B-N9Fvz4.js → wt-status-select-DL1bOn9G.js} +2 -6
  11. package/dist/{wt-type-extension-value-input-BUf4t1jl.js → wt-type-extension-value-input-DArCroNk.js} +2 -2
  12. package/dist/{wt-vidstack-player-Bv_bhxih.js → wt-vidstack-player-BGnQxLI3.js} +1 -1
  13. package/package.json +1 -1
  14. package/src/components/wt-datepicker/wt-datepicker.vue +8 -5
  15. package/src/components/wt-status-select/__tests__/WtStatusSelect.spec.js +65 -0
  16. package/src/components/wt-status-select/wt-status-select.vue +6 -20
  17. package/src/modules/AgentStatusSelect/components/__tests__/wt-cc-agent-status-select.spec.js +97 -1
  18. package/src/modules/AgentStatusSelect/components/wt-cc-agent-status-select.vue +1 -23
  19. package/src/validations/config/errors/customZodErrorsHandler.ts +32 -4
  20. package/types/.tsbuildinfo +1 -1
  21. package/types/components/wt-datepicker/wt-datepicker.vue.d.ts +2 -0
  22. package/types/components/wt-status-select/wt-status-select.vue.d.ts +0 -2
@@ -1,4 +1,4 @@
1
- import "./components-DZ-mqx3y.js";
1
+ import "./components-CfX8XNuf.js";
2
2
  import { t as e } from "./_plugin-vue_export-helper-B3ysoDQm.js";
3
3
  import { l as t } from "./enums-De8CDKZ1.js";
4
4
  import { t as n } from "./wt-button-B7B7qITq.js";
@@ -208,6 +208,7 @@ var W = { class: "wt-datepicker" }, G = { class: "wt-datepicker__button-bar" },
208
208
  Boolean
209
209
  ] },
210
210
  customValidators: { default: () => [] },
211
+ regleValidation: {},
211
212
  modelValue: {},
212
213
  defaultValue: {},
213
214
  name: {},
@@ -320,9 +321,10 @@ var W = { class: "wt-datepicker" }, G = { class: "wt-datepicker__button-bar" },
320
321
  }, 0);
321
322
  }, X = () => {
322
323
  B();
323
- }, Z = f(() => o.required ? `${o.label}*` : o.label), { v: ne, customValidators: re } = j(o), { isValidation: ie, invalid: Q, validationText: $, validationTextColor: ae } = d({
324
+ }, Z = f(() => o.required ? `${o.label}*` : o.label), { v: ne, customValidators: re, regleValidation: ie } = j(o), { isValidation: ae, invalid: Q, validationText: $, validationTextColor: oe } = d({
324
325
  v: ne,
325
- customValidators: re
326
+ customValidators: re,
327
+ regleValidation: ie
326
328
  });
327
329
  return (a, o) => {
328
330
  let s = k("wt-label"), l = k("wt-button"), u = k("wt-icon-btn"), d = k("wt-message");
@@ -438,9 +440,9 @@ var W = { class: "wt-datepicker" }, G = { class: "wt-datepicker__button-bar" },
438
440
  "show-clear",
439
441
  "onBlur"
440
442
  ]),
441
- M(ie) && M($) ? (D(), p(d, {
443
+ M(ae) && M($) ? (D(), p(d, {
442
444
  key: 0,
443
- color: M(ae),
445
+ color: M(oe),
444
446
  variant: M(i).SIMPLE,
445
447
  size: M(r).SM
446
448
  }, {
@@ -454,6 +456,6 @@ var W = { class: "wt-datepicker" }, G = { class: "wt-datepicker__button-bar" },
454
456
  ]);
455
457
  };
456
458
  }
457
- }), [["__scopeId", "data-v-e763bd8a"]]);
459
+ }), [["__scopeId", "data-v-4c2f4f33"]]);
458
460
  //#endregion
459
461
  export { X as default };
@@ -1,4 +1,4 @@
1
- import { C as e, i as t } from "./components-DZ-mqx3y.js";
1
+ import { C as e, i as t } from "./components-CfX8XNuf.js";
2
2
  import { t as n } from "./_plugin-vue_export-helper-B3ysoDQm.js";
3
3
  import { t as r } from "./displayText-CtaxzaBz.js";
4
4
  import { Fragment as i, computed as a, createCommentVNode as o, createElementBlock as s, createTextVNode as c, createVNode as l, defineComponent as u, openBlock as d, renderList as f, renderSlot as p, toDisplayString as m, unref as h, withCtx as g } from "vue";
@@ -1,6 +1,6 @@
1
1
  import { t as e } from "./rolldown-runtime-BEcgMyyN.js";
2
- import { n as t, r as n } from "./clients-EyPsBurj.js";
3
- import { T as r, n as i, w as a } from "./components-DZ-mqx3y.js";
2
+ import { n as t, r as n } from "./clients-DBqdsc05.js";
3
+ import { T as r, n as i, w as a } from "./components-CfX8XNuf.js";
4
4
  import { t as o } from "./vue-i18n-Db_oYfO8.js";
5
5
  import { n as s } from "./useEventBus-B-ZeklLu.js";
6
6
  import { createBlock as c, createTextVNode as l, createVNode as u, defineComponent as d, mergeProps as f, onMounted as p, openBlock as m, ref as h, resolveComponent as g, toDisplayString as _, unref as v, withCtx as y } from "vue";
@@ -31,18 +31,15 @@ var f = [
31
31
  statusDuration: { default: 0 },
32
32
  options: {}
33
33
  },
34
- emits: ["change", "closed"],
34
+ emits: ["change"],
35
35
  setup(s, { emit: p }) {
36
36
  let m = s, h = p, { t: g } = n(), _ = i(() => m.options ? m.options : f.map((e) => ({
37
37
  ...e,
38
38
  text: g(e.locale)
39
- }))), v = i(() => _.value.find((e) => e.value === m.status)), y = i(() => _.value.reduce((e, n) => (m.status === n.value && n.value !== t.PAUSE || n.value === t.BREAK_OUT || e.push(n), e), [])), b = i(() => typeof m.statusDuration == "string" ? m.statusDuration : m.statusDuration === void 0 ? v.value?.text ?? "" : r(m.statusDuration));
39
+ }))), v = i(() => _.value.find((e) => e.value === m.status)), y = i(() => _.value.filter((e) => e.value !== t.BREAK_OUT && (e.value !== t.OFFLINE || m.status !== t.OFFLINE))), b = i(() => typeof m.statusDuration == "string" ? m.statusDuration : m.statusDuration === void 0 ? v.value?.text ?? "" : r(m.statusDuration));
40
40
  function x(e) {
41
41
  h("change", e.value);
42
42
  }
43
- function S(e) {
44
- h("closed", e);
45
- }
46
43
  return (t, n) => {
47
44
  let r = l("wt-indicator"), i = l("wt-single-select");
48
45
  return c(), a(i, {
@@ -53,7 +50,6 @@ var f = [
53
50
  class: "wt-status-select",
54
51
  "data-key": "value",
55
52
  size: u(e).SM,
56
- onClosed: S,
57
53
  "onUpdate:modelValue": x
58
54
  }, {
59
55
  value: d(() => [o(r, {
@@ -1,5 +1,5 @@
1
- import { t as e } from "./clients-EyPsBurj.js";
2
- import { a as t, o as n, r, s as i } from "./components-DZ-mqx3y.js";
1
+ import { t as e } from "./clients-DBqdsc05.js";
2
+ import { a as t, o as n, r, s as i } from "./components-CfX8XNuf.js";
3
3
  import { t as a } from "./enums-De8CDKZ1.js";
4
4
  import { t as o } from "./vue-i18n-Db_oYfO8.js";
5
5
  import { computed as s, createBlock as c, createCommentVNode as l, createVNode as u, defineComponent as d, mergeModels as f, mergeProps as p, openBlock as m, renderSlot as h, resolveComponent as g, unref as _, useModel as v } from "vue";
@@ -1,4 +1,4 @@
1
- import { E as e } from "./components-DZ-mqx3y.js";
1
+ import { E as e } from "./components-CfX8XNuf.js";
2
2
  import { t } from "./_plugin-vue_export-helper-B3ysoDQm.js";
3
3
  import { l as n } from "./enums-De8CDKZ1.js";
4
4
  import "./wt-button-B7B7qITq.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webitel/ui-sdk",
3
- "version": "26.8.44",
3
+ "version": "26.8.46",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "npm run docs:dev",
@@ -55,7 +55,7 @@
55
55
  >
56
56
  <template #buttonbar="{ todayCallback, clearCallback }">
57
57
  <div class="wt-datepicker__button-bar">
58
- <wt-button
58
+ <wt-button
59
59
  :color="ButtonColor.SECONDARY"
60
60
  :variant="ButtonVariant.OUTLINED"
61
61
  :size="ComponentSize.SM"
@@ -63,7 +63,7 @@
63
63
  >
64
64
  {{ t('reusable.today') }}
65
65
  </wt-button>
66
- <wt-button
66
+ <wt-button
67
67
  v-show="clearable && modelValue"
68
68
  :color="ButtonColor.SECONDARY"
69
69
  :variant="ButtonVariant.OUTLINED"
@@ -76,14 +76,14 @@
76
76
  </template>
77
77
 
78
78
  <template #prevbutton="{ actionCallback }">
79
- <wt-icon-btn
79
+ <wt-icon-btn
80
80
  icon="arrow-left"
81
81
  @click="actionCallback"
82
82
  />
83
83
  </template>
84
84
 
85
85
  <template #nextbutton="{ actionCallback }">
86
- <wt-icon-btn
86
+ <wt-icon-btn
87
87
  icon="arrow-right"
88
88
  @click="actionCallback"
89
89
  />
@@ -133,6 +133,7 @@
133
133
  </template>
134
134
 
135
135
  <script setup lang="ts">
136
+ import type { SuperCompatibleRegleFieldStatus } from '@regle/core';
136
137
  import { fromZonedTime, toZonedTime } from 'date-fns-tz';
137
138
  import PDatepicker, {
138
139
  DatePickerEmitsOptions,
@@ -167,6 +168,7 @@ interface Props extends DatePickerProps {
167
168
  timezone?: string;
168
169
  v?: VuelidateFieldLike;
169
170
  customValidators?: CompatCustomValidator[];
171
+ regleValidation?: SuperCompatibleRegleFieldStatus;
170
172
  }
171
173
 
172
174
  const props = withDefaults(defineProps<Props>(), {
@@ -257,12 +259,13 @@ const requiredLabel = computed(() => {
257
259
  });
258
260
 
259
261
  // https://stackoverflow.com/questions/72408463/use-props-in-composables-vue3
260
- const { v, customValidators } = toRefs(props);
262
+ const { v, customValidators, regleValidation } = toRefs(props);
261
263
 
262
264
  const { isValidation, invalid, validationText, validationTextColor } =
263
265
  useValidation({
264
266
  v,
265
267
  customValidators,
268
+ regleValidation,
266
269
  });
267
270
  </script>
268
271
 
@@ -1,5 +1,6 @@
1
1
  import { shallowMount } from '@vue/test-utils';
2
2
 
3
+ import AgentStatus from '../../../enums/AgentStatus/AgentStatus.enum';
3
4
  import WtSingleSelect from '../../wt-single-select/wt-single-select.vue';
4
5
  import WtStatusSelect from '../wt-status-select.vue';
5
6
 
@@ -13,6 +14,70 @@ describe('WtStatusSelect', () => {
13
14
  expect(wrapper.classes('wt-status-select')).toBe(true);
14
15
  });
15
16
 
17
+ it('keeps "online" option in the list when it is the current status', () => {
18
+ const wrapper = shallowMount(WtStatusSelect, {
19
+ props: {
20
+ status: AgentStatus.ONLINE,
21
+ },
22
+ stubs: {
23
+ WtSingleSelect,
24
+ },
25
+ });
26
+ expect(
27
+ wrapper.vm.availableOptions.some(
28
+ (opt) => opt.value === AgentStatus.ONLINE,
29
+ ),
30
+ ).toBe(true);
31
+ });
32
+
33
+ it('keeps "pause" option in the list when it is the current status', () => {
34
+ const wrapper = shallowMount(WtStatusSelect, {
35
+ props: {
36
+ status: AgentStatus.PAUSE,
37
+ },
38
+ stubs: {
39
+ WtSingleSelect,
40
+ },
41
+ });
42
+ expect(
43
+ wrapper.vm.availableOptions.some(
44
+ (opt) => opt.value === AgentStatus.PAUSE,
45
+ ),
46
+ ).toBe(true);
47
+ });
48
+
49
+ it('removes "offline" option from the list when it is the current status', () => {
50
+ const wrapper = shallowMount(WtStatusSelect, {
51
+ props: {
52
+ status: AgentStatus.OFFLINE,
53
+ },
54
+ stubs: {
55
+ WtSingleSelect,
56
+ },
57
+ });
58
+ expect(
59
+ wrapper.vm.availableOptions.some(
60
+ (opt) => opt.value === AgentStatus.OFFLINE,
61
+ ),
62
+ ).toBe(false);
63
+ });
64
+
65
+ it('always removes "break_out" option from the list', () => {
66
+ const wrapper = shallowMount(WtStatusSelect, {
67
+ props: {
68
+ status: AgentStatus.BREAK_OUT,
69
+ },
70
+ stubs: {
71
+ WtSingleSelect,
72
+ },
73
+ });
74
+ expect(
75
+ wrapper.vm.availableOptions.some(
76
+ (opt) => opt.value === AgentStatus.BREAK_OUT,
77
+ ),
78
+ ).toBe(false);
79
+ });
80
+
16
81
  it('correctly represents duration', () => {
17
82
  const wrapper = shallowMount(WtStatusSelect, {
18
83
  stubs: {
@@ -7,7 +7,6 @@
7
7
  class="wt-status-select"
8
8
  data-key="value"
9
9
  :size="ComponentSize.SM"
10
- @closed="closedHandler"
11
10
  @update:model-value="inputHandler"
12
11
  >
13
12
  <template #value>
@@ -55,9 +54,6 @@ const emit = defineEmits<{
55
54
  change: [
56
55
  value: string,
57
56
  ];
58
- closed: [
59
- event: Event,
60
- ];
61
57
  }>();
62
58
 
63
59
  const { t } = useI18n();
@@ -76,18 +72,12 @@ const selectedOption = computed<StatusOption | undefined>(() =>
76
72
  );
77
73
 
78
74
  const availableOptions = computed<StatusOption[]>(() =>
79
- statusOptions.value.reduce<StatusOption[]>((options, opt) => {
80
- // PAUSE option is always passed
81
- if (
82
- (props.status === opt.value && opt.value !== AgentStatus.PAUSE) ||
83
- opt.value === AgentStatus.BREAK_OUT
84
- ) {
85
- // skip breakout option
86
- return options;
87
- }
88
- options.push(opt);
89
- return options;
90
- }, []),
75
+ statusOptions.value.filter(
76
+ (opt) =>
77
+ opt.value !== AgentStatus.BREAK_OUT &&
78
+ (opt.value !== AgentStatus.OFFLINE ||
79
+ props.status !== AgentStatus.OFFLINE),
80
+ ),
91
81
  );
92
82
 
93
83
  const duration = computed<string>(() => {
@@ -105,8 +95,4 @@ const duration = computed<string>(() => {
105
95
  function inputHandler(value: StatusOption) {
106
96
  emit('change', value.value);
107
97
  }
108
-
109
- function closedHandler(event: Event) {
110
- emit('closed', event);
111
- }
112
98
  </script>
@@ -1,4 +1,4 @@
1
- import { mount, shallowMount } from '@vue/test-utils';
1
+ import { flushPromises, mount, shallowMount } from '@vue/test-utils';
2
2
  import { createStore } from 'vuex';
3
3
 
4
4
  import AgentStatus from '../../../../enums/AgentStatus/AgentStatus.enum.js';
@@ -28,6 +28,19 @@ vi.spyOn(AgentStatusAPIFactory, 'default').mockImplementation(() => ({
28
28
  patch: agentStatusMock,
29
29
  }));
30
30
 
31
+ const onlineSkillsGetListMock = vi.fn(() => ({
32
+ items: [
33
+ {
34
+ id: 'default',
35
+ },
36
+ ],
37
+ }));
38
+ vi.mock('@webitel/api-services/api', () => ({
39
+ OnlineSkillsAPI: {
40
+ getList: (...args) => onlineSkillsGetListMock(...args),
41
+ },
42
+ }));
43
+
31
44
  const agent = {
32
45
  status: '',
33
46
  agentId: 1,
@@ -46,9 +59,17 @@ const mountOptions = {
46
59
  shallow: true,
47
60
  };
48
61
 
62
+ function emitStatusChange(wrapper, value) {
63
+ wrapper
64
+ .findComponent('.wt-cc-agent-status-select__status-select')
65
+ .vm.$emit('change', value);
66
+ }
67
+
49
68
  describe('Wt Cc Agent Status Select', () => {
50
69
  beforeEach(() => {
51
70
  getAgentPauseCausesMock.mockClear();
71
+ agentStatusMock.mockClear();
72
+ onlineSkillsGetListMock.mockClear();
52
73
  });
53
74
  it('renders a component', () => {
54
75
  const wrapper = shallowMount(WtCcAgentStatusSelect, mountOptions);
@@ -76,4 +97,79 @@ describe('Wt Cc Agent Status Select', () => {
76
97
  };
77
98
  expect(agentStatusMock).toHaveBeenCalledWith(reqPayload);
78
99
  });
100
+
101
+ it(`at repeated "online" selection (already active status), if online skills
102
+ exist, opens the activity-type popup instead of updating status`, async () => {
103
+ onlineSkillsGetListMock.mockReturnValueOnce({
104
+ items: [
105
+ {
106
+ id: 'default',
107
+ },
108
+ {
109
+ id: 'skill1',
110
+ name: 'Skill 1',
111
+ },
112
+ ],
113
+ });
114
+ const wrapper = mount(WtCcAgentStatusSelect, {
115
+ ...mountOptions,
116
+ props: {
117
+ ...mountOptions.props,
118
+ status: AgentStatus.ONLINE,
119
+ },
120
+ });
121
+ emitStatusChange(wrapper, AgentStatus.ONLINE);
122
+ await flushPromises();
123
+ expect(
124
+ wrapper
125
+ .findComponent({
126
+ name: 'activity-type-popup',
127
+ })
128
+ .exists(),
129
+ ).toBe(true);
130
+ expect(agentStatusMock).not.toHaveBeenCalled();
131
+ });
132
+
133
+ it(`at repeated "online" selection (already active status), if no online
134
+ skills exist, does not open a popup and does not update status`, async () => {
135
+ const wrapper = mount(WtCcAgentStatusSelect, {
136
+ ...mountOptions,
137
+ props: {
138
+ ...mountOptions.props,
139
+ status: AgentStatus.ONLINE,
140
+ },
141
+ });
142
+ emitStatusChange(wrapper, AgentStatus.ONLINE);
143
+ await flushPromises();
144
+ expect(onlineSkillsGetListMock).toHaveBeenCalled();
145
+ expect(
146
+ wrapper
147
+ .findComponent({
148
+ name: 'activity-type-popup',
149
+ })
150
+ .exists(),
151
+ ).toBe(false);
152
+ expect(agentStatusMock).not.toHaveBeenCalled();
153
+ });
154
+
155
+ it(`at repeated "pause" selection (already active status), if pause causes
156
+ exist, opens the pause-cause popup instead of updating status`, async () => {
157
+ const wrapper = mount(WtCcAgentStatusSelect, {
158
+ ...mountOptions,
159
+ props: {
160
+ ...mountOptions.props,
161
+ status: AgentStatus.PAUSE,
162
+ },
163
+ });
164
+ emitStatusChange(wrapper, AgentStatus.PAUSE);
165
+ await flushPromises();
166
+ expect(
167
+ wrapper
168
+ .findComponent({
169
+ name: 'pause-cause-popup',
170
+ })
171
+ .exists(),
172
+ ).toBe(true);
173
+ expect(agentStatusMock).not.toHaveBeenCalled();
174
+ });
79
175
  });
@@ -12,8 +12,7 @@
12
12
  :key="status"
13
13
  :status="status"
14
14
  :status-duration="statusDuration"
15
- @closed="handleClosed"
16
- @change="handleSelectInput"
15
+ @change="handleStatus"
17
16
  class="wt-cc-agent-status-select__status-select"
18
17
  />
19
18
  <activity-type-popup
@@ -89,7 +88,6 @@ const { t } = useI18n();
89
88
  const isPauseCausePopup = ref(false);
90
89
  const pauseCauses = ref<EngineForAgentPauseCause[]>([]);
91
90
  const error = ref(null);
92
- const chosenStatus = ref('');
93
91
 
94
92
  const isActivityTypePopup = ref(false);
95
93
  const activityTypes = ref<ActivityType[]>([]);
@@ -203,26 +201,6 @@ async function handleStatus(status: string) {
203
201
  });
204
202
  }
205
203
 
206
- function handleSelectInput(newStatus: string) {
207
- handleStatus(newStatus);
208
- chosenStatus.value = newStatus;
209
- // we need to save changes which come from input, because sometimes we want
210
- // to choose 'pause' repeatedly and have to check the previous status
211
- }
212
-
213
- function handleClosed(event: { value: string }) {
214
- // sometimes we want to choose 'pause' repeatedly
215
- // but 'change' event from wt-status-select can't give us the same value,
216
- // in this case we have to use value from 'closed' event to choose 'pause' status
217
- if (
218
- (event.value === chosenStatus.value || !chosenStatus.value) && // if closed status the same as chosen, or chosen status is empty
219
- event.value === AgentStatus.PAUSE
220
- ) {
221
- // and only for 'pause' status
222
- handleStatus(event.value);
223
- }
224
- }
225
-
226
204
  function handleActivityTypeInput(activityType: ActivityType) {
227
205
  const payload =
228
206
  activityType.id === defaultActivityTypeOption.value?.id
@@ -3,6 +3,11 @@ import type { z } from 'zod/v4';
3
3
 
4
4
  import { isEmpty } from '../../../scripts';
5
5
 
6
+ const isMissingValue = (value: unknown) => {
7
+ if (typeof value === 'number') return false;
8
+ return isEmpty(value) as boolean;
9
+ };
10
+
6
11
  export const customZodErrorsHandler =
7
12
  (t: I18nComposerTranslation) => (issue: z.core.$ZodRawIssue) => {
8
13
  switch (issue.code) {
@@ -14,7 +19,7 @@ export const customZodErrorsHandler =
14
19
  case 'invalid_type':
15
20
  return handleInvalid(issue);
16
21
  case 'invalid_union':
17
- return t('validation.invalid');
22
+ return handleInvalidUnion(issue);
18
23
  case 'custom':
19
24
  return handleCustom(issue);
20
25
  default:
@@ -40,8 +45,7 @@ export const customZodErrorsHandler =
40
45
  return t('validation.required');
41
46
  };
42
47
 
43
- // if empty, show "required" error
44
- if (isEmpty(issue.input) as boolean) {
48
+ if (isMissingValue(issue.input)) {
45
49
  return showRequiredMsg();
46
50
  }
47
51
 
@@ -52,6 +56,13 @@ export const customZodErrorsHandler =
52
56
  });
53
57
  }
54
58
 
59
+ // if date, show formatted date in the "value" error
60
+ if (issue.origin === 'date') {
61
+ return t('validation.minValue', {
62
+ min: new Date(issue.minimum as number).toLocaleString(),
63
+ });
64
+ }
65
+
55
66
  // else, show "value" error
56
67
  return t('validation.minValue', {
57
68
  min: issue.minimum,
@@ -66,6 +77,13 @@ export const customZodErrorsHandler =
66
77
  });
67
78
  }
68
79
 
80
+ // if date, show formatted date in the "value" error
81
+ if (issue.origin === 'date') {
82
+ return t('validation.maxValue', {
83
+ max: new Date(issue.maximum as number).toLocaleString(),
84
+ });
85
+ }
86
+
69
87
  // else, show "value" error
70
88
  return t('validation.maxValue', {
71
89
  max: issue.maximum,
@@ -77,10 +95,20 @@ export const customZodErrorsHandler =
77
95
  | z.core.$ZodRawIssue<z.core.$ZodIssueInvalidType>
78
96
  | z.core.$ZodRawIssue<z.core.$ZodIssueInvalidValue>,
79
97
  ) {
80
- if (isEmpty(issue.input)) {
98
+ if (isMissingValue(issue.input)) {
81
99
  return t('validation.required');
82
100
  }
83
101
 
84
102
  console.error('Unknown Invalid Zod issue:', issue);
85
103
  }
104
+
105
+ function handleInvalidUnion(
106
+ issue: z.core.$ZodRawIssue<z.core.$ZodIssueInvalidUnion>,
107
+ ) {
108
+ if (isMissingValue(issue.input)) {
109
+ return t('validation.required');
110
+ }
111
+
112
+ return t('validation.invalid');
113
+ }
86
114
  };