4646 </template >
4747 </NcActionInput >
4848 </template >
49+ <template v-else-if =" answerType .pickerType === ' time' " #actions >
50+ <NcActionCheckbox
51+ :model-value =" timeRange"
52+ @update:model-value =" onTimeRangeChange" >
53+ {{ t('forms', 'Use time range') }}
54+ </NcActionCheckbox >
55+ <NcActionInput
56+ type =" time"
57+ is-native-picker
58+ :model-value =" timeMin"
59+ :label =" t('forms', 'Earliest time')"
60+ hide-label
61+ :max =" timeMax"
62+ @update:model-value =" onTimeMinChange" >
63+ <template #icon >
64+ <NcIconSvgWrapper
65+ :svg =" svgClockArrowUp"
66+ :name =" t('forms', 'Earliest time')" />
67+ </template >
68+ </NcActionInput >
69+ <NcActionInput
70+ type =" time"
71+ is-native-picker
72+ :model-value =" timeMax"
73+ :label =" t('forms', 'Latest time')"
74+ hide-label
75+ :min =" timeMin"
76+ @update:model-value =" onTimeMaxChange" >
77+ <template #icon >
78+ <NcIconSvgWrapper
79+ :svg =" svgClockArrowDown"
80+ :name =" t('forms', 'Latest time')" />
81+ </template >
82+ </NcActionInput >
83+ </template >
4984 <div class =" question__content" >
5085 <NcDateTimePicker
5186 :value =" time"
5287 :disabled =" !readOnly"
5388 :formatter =" formatter"
5489 :placeholder =" datetimePickerPlaceholder"
5590 :show-second =" false"
56- :type =" answerType.pickerType "
91+ :type =" dateTimePickerType "
5792 :disabled-date =" disabledDates"
93+ :disabled-time =" disabledTimes"
5894 :input-attr =" inputAttr"
59- :range =" extraSettings?.dateRange"
6095 range-separator =" - "
6196 @change =" onValueChange" />
6297 </div >
6398 </Question >
6499</template >
65100
66101<script >
102+ import svgClockArrowDown from ' ../../../img/clock_arrow_down.svg?raw'
103+ import svgClockArrowUp from ' ../../../img/clock_arrow_up.svg?raw'
67104import svgEventIcon from ' ../../../img/event.svg?raw'
68105import svgTodayIcon from ' ../../../img/today.svg?raw'
69106
@@ -96,6 +133,8 @@ export default {
96133 stringify: this .stringifyDate ,
97134 parse: this .parseTimestampToDate ,
98135 },
136+ svgClockArrowDown,
137+ svgClockArrowUp,
99138 svgEventIcon,
100139 svgTodayIcon,
101140 }
@@ -104,15 +143,21 @@ export default {
104143 computed: {
105144 datetimePickerPlaceholder () {
106145 if (this .readOnly ) {
107- return this .extraSettings ? .dateRange
146+ return this .extraSettings ? .dateRange || this . extraSettings ? . timeRange
108147 ? this .answerType .submitPlaceholderRange
109148 : this .answerType .submitPlaceholder
110149 }
111- return this .extraSettings ? .dateRange
150+ return this .extraSettings ? .dateRange || this . extraSettings ? . timeRange
112151 ? this .answerType .createPlaceholderRange
113152 : this .answerType .createPlaceholder
114153 },
115154
155+ dateTimePickerType () {
156+ return this .extraSettings ? .dateRange || this .extraSettings ? .timeRange
157+ ? this .answerType .pickerType + ' -range'
158+ : this .answerType .pickerType
159+ },
160+
116161 /**
117162 * All non-exposed props onto datepicker input-element.
118163 *
@@ -126,7 +171,7 @@ export default {
126171 },
127172
128173 time () {
129- if (this .extraSettings ? .dateRange ) {
174+ if (this .extraSettings ? .dateRange || this . extraSettings ? . timeRange ) {
130175 return this .values
131176 ? [this .parse (this .values [0 ]), this .parse (this .values [1 ])]
132177 : null
@@ -155,6 +200,34 @@ export default {
155200 dateRange () {
156201 return this .extraSettings ? .dateRange ?? false
157202 },
203+
204+ /**
205+ * The maximum allowable time for the time input field
206+ */
207+ timeMax () {
208+ return this .extraSettings ? .timeMax
209+ ? moment (
210+ this .extraSettings .timeMax ,
211+ this .answerType .storageFormat ,
212+ ).toDate ()
213+ : new Date (new Date ().setHours (24 , 0 , 0 , 0 ))
214+ },
215+
216+ /**
217+ * The minimum allowable time for the time input field
218+ */
219+ timeMin () {
220+ return this .extraSettings ? .timeMin
221+ ? moment (
222+ this .extraSettings .timeMin ,
223+ this .answerType .storageFormat ,
224+ ).toDate ()
225+ : new Date (new Date ().setHours (0 , 0 , 0 , 0 ))
226+ },
227+
228+ timeRange () {
229+ return this .extraSettings ? .timeRange ?? false
230+ },
158231 },
159232
160233 methods: {
@@ -216,13 +289,54 @@ export default {
216289 this .onExtraSettingsChange ({ dateRange: value === true ?? null })
217290 },
218291
292+ /**
293+ * Handles the change event for the maximum time input.
294+ * Updates the maximum allowable date based on the provided value.
295+ *
296+ * @param {string | Date} value - The new maximum date value. Can be a string or a Date object.
297+ */
298+ onTimeMaxChange (value ) {
299+ this .onExtraSettingsChange ({
300+ timeMax:
301+ value === null || value === new Date (new Date ().setHours (24 , 0 , 0 , 0 ))
302+ ? null
303+ : moment (value).format (this .answerType .storageFormat ),
304+ })
305+ },
306+
307+ /**
308+ * Handles the change event for the minimum date input.
309+ * Updates the minimum allowable date based on the provided value.
310+ *
311+ * @param {string | Date} value - The new minimum date value. Can be a string or a Date object.
312+ */
313+ onTimeMinChange (value ) {
314+ this .onExtraSettingsChange ({
315+ timeMin:
316+ value === null || value === new Date (new Date ().setHours (0 , 0 , 0 , 0 ))
317+ ? null
318+ : moment (value).format (this .answerType .storageFormat ),
319+ })
320+ },
321+
322+ /**
323+ * Handles the change event for the date range selection.
324+ * Updates the extra settings with the new date range value.
325+ *
326+ * @param {boolean} value - The new value of the date range selection.
327+ * If true, the date range is enabled; otherwise, null.
328+ */
329+ onTimeRangeChange (value ) {
330+ this .onExtraSettingsChange ({ timeRange: value === true ?? null })
331+ },
332+
219333 /**
220334 * Store Value
221335 *
222336 * @param {Date|Array<Date>} date The date or date range to store
223337 */
224338 onValueChange (date ) {
225- if (this .extraSettings ? .dateRange ) {
339+ if (this .extraSettings ? .dateRange || this . extraSettings ? . timeRange ) {
226340 this .$emit (' update:values' , [
227341 moment (date[0 ]).format (this .answerType .storageFormat ),
228342 moment (date[1 ]).format (this .answerType .storageFormat ),
@@ -247,6 +361,19 @@ export default {
247361 )
248362 },
249363
364+ /**
365+ * Determines if a given time should be disabled.
366+ *
367+ * @param {Date} time - The time to check.
368+ * @return {boolean} - Returns true if the time should be disabled, otherwise false.
369+ */
370+ disabledTimes (time ) {
371+ return (
372+ (this .timeMin && time < this .timeMin )
373+ || (this .timeMax && time > this .timeMax )
374+ )
375+ },
376+
250377 /**
251378 * Datepicker timestamp to string
252379 *
0 commit comments