import { computed, SetupContext, ref } from 'vue';
import { TimeSelectProps, useTimeSelectFn, Time, TimeListType } from './time-select-types';
export function useTimeSelect(props: TimeSelectProps, ctx: SetupContext): useTimeSelectFn {
const select = ref();
const padTime = (time: number | string) => {
return `${time}`.padStart(2, '0');
};
const parseTimeToNumber = (time: string): null | Time => {
const timeArr = (time || '').split(':');
if (timeArr.length < 2) {
return null;
}
const hour = Number.parseInt(timeArr[0], 10);
const minute = Number.parseInt(timeArr[1], 10);
return {
hour,
minute,
};
};
const formatTime = (time: Time) => {
return `${padTime(time.hour)}:${padTime(time.minute)}`;
};
const nextTime = (time: string, step: string): string => {
const timeValue = parseTimeToNumber(time);
const stepValue = parseTimeToNumber(step);
const nextTimeObj: Time = {
hour: timeValue.hour,
minute: timeValue.minute,
};
nextTimeObj.minute += stepValue.minute;
nextTimeObj.hour += stepValue.hour;
nextTimeObj.hour += Math.floor(nextTimeObj.minute / 60);
nextTimeObj.minute = nextTimeObj.minute % 60;
return formatTime(nextTimeObj);
};
const start = computed(() => {
const startTime = parseTimeToNumber(props.start);
return startTime ? formatTime(startTime) : '00:00';
});
const end = computed(() => {
const endTime = parseTimeToNumber(props.end);
return endTime ? formatTime(endTime) : '24:00';
});
const step = computed(() => {
const stepTime = parseTimeToNumber(props.step);
if (stepTime && stepTime.hour >= 0 && stepTime.minute >= 0 && stepTime.hour + stepTime.minute > 0) {
return formatTime(stepTime);
}
return '00:30';
});
const minTime = computed(() => {
const min = parseTimeToNumber(props.minTime);
return min ? formatTime(min) : null;
});
const maxTime = computed(() => {
const max = parseTimeToNumber(props.maxTime);
return max ? formatTime(max) : null;
});
const compareTime = (time1: string, time2: string): number => {
const time1Obj = parseTimeToNumber(time1);
const time2Obj = parseTimeToNumber(time2);
const minutes01 = time1Obj.minute + time1Obj.hour * 60;
const minutes02 = time2Obj.minute + time2Obj.hour * 60;
if (minutes01 === minutes02) {
return 0;
}
return minutes01 > minutes02 ? 1 : -1;
};
const options = computed(() => {
const list = [];
if (props.start && props.end && props.step) {
let current = start.value;
let currentTime;
while (compareTime(current, end.value) <= 0) {
currentTime = current;
list.push({
value: currentTime,
name: currentTime,
disabled: compareTime(current, minTime.value || '-1:-1') < 0 || compareTime(current, maxTime.value || '24:00') > 0,
});
current = nextTime(current, step.value);
}
}
return list;
});
const changeData = (data: TimeListType) => {
ctx.emit('update:modelValue', data.value);
ctx.emit('change', data.value);
};
const clearData = (value: string) => {
ctx.emit('update:modelValue', value);
};
const focusFun = (e: FocusEvent) => {
ctx.emit('focus', e);
};
const blurFun = (e: FocusEvent) => {
ctx.emit('blur', e);
};
return {
options,
changeData,
select,
clearData,
focusFun,
blurFun,
};
}