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,56 @@ 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
302+ || value === new Date (new Date ().setHours (24 , 0 , 0 , 0 ))
303+ ? null
304+ : moment (value).format (this .answerType .storageFormat ),
305+ })
306+ },
307+
308+ /**
309+ * Handles the change event for the minimum date input.
310+ * Updates the minimum allowable date based on the provided value.
311+ *
312+ * @param {string | Date} value - The new minimum date value. Can be a string or a Date object.
313+ */
314+ onTimeMinChange (value ) {
315+ this .onExtraSettingsChange ({
316+ timeMin:
317+ value === null
318+ || value === new Date (new Date ().setHours (0 , 0 , 0 , 0 ))
319+ ? null
320+ : moment (value).format (this .answerType .storageFormat ),
321+ })
322+ },
323+
324+ /**
325+ * Handles the change event for the date range selection.
326+ * Updates the extra settings with the new date range value.
327+ *
328+ * @param {boolean} value - The new value of the date range selection.
329+ * If true, the date range is enabled; otherwise, null.
330+ */
331+ onTimeRangeChange (value ) {
332+ this .onExtraSettingsChange ({ timeRange: value === true ?? null })
333+ },
334+
219335 /**
220336 * Store Value
221337 *
222338 * @param {Date|Array<Date>} date The date or date range to store
223339 */
224340 onValueChange (date ) {
225- if (this .extraSettings ? .dateRange ) {
341+ if (this .extraSettings ? .dateRange || this . extraSettings ? . timeRange ) {
226342 this .$emit (' update:values' , [
227343 moment (date[0 ]).format (this .answerType .storageFormat ),
228344 moment (date[1 ]).format (this .answerType .storageFormat ),
@@ -247,6 +363,19 @@ export default {
247363 )
248364 },
249365
366+ /**
367+ * Determines if a given time should be disabled.
368+ *
369+ * @param {Date} time - The time to check.
370+ * @return {boolean} - Returns true if the time should be disabled, otherwise false.
371+ */
372+ disabledTimes (time ) {
373+ return (
374+ (this .timeMin && time < this .timeMin )
375+ || (this .timeMax && time > this .timeMax )
376+ )
377+ },
378+
250379 /**
251380 * Datepicker timestamp to string
252381 *
0 commit comments