diff --git a/src/components/Table/Columns/index.ts b/src/components/Table/Columns/index.ts
index babb1fd..ee6776a 100755
--- a/src/components/Table/Columns/index.ts
+++ b/src/components/Table/Columns/index.ts
@@ -3,6 +3,7 @@ import { Rule } from 'antd/lib/form'
import { ColumnProps } from 'antd/lib/table'
export { makeDateColumn } from './date'
+export { makeTimeColumn } from './time'
export {
RegExpIsFloat,
makeNumericRender,
diff --git a/src/components/Table/Columns/time.tsx b/src/components/Table/Columns/time.tsx
new file mode 100644
index 0000000..7b7144e
--- /dev/null
+++ b/src/components/Table/Columns/time.tsx
@@ -0,0 +1,26 @@
+import { ReactNode } from 'react'
+
+import { formatTime } from '@utils/datetime'
+
+import { makeColumn, columnPropsOther } from '.'
+import { makeTimeSorter, TimePickerWrapper, TimePickerWrapperProps } from '..'
+
+export const makeTimeColumn = (
+ title: ReactNode,
+ key: string,
+ utc?: boolean,
+ format?: string,
+ other?: columnPropsOther,
+ pickerOther?: TimePickerWrapperProps,
+) => makeColumn(title, key, {
+ ...other,
+ render: (time) => (
+
+ {formatTime(time, utc, format) ?? '-'}
+
+ ),
+ sorter: makeTimeSorter(key),
+ input: ,
+})
+
+export default makeTimeColumn
diff --git a/src/components/Table/TimePickerWrapper.tsx b/src/components/Table/TimePickerWrapper.tsx
new file mode 100644
index 0000000..6ebe6a9
--- /dev/null
+++ b/src/components/Table/TimePickerWrapper.tsx
@@ -0,0 +1,31 @@
+import { Moment } from 'moment'
+import { TimePicker, TimePickerProps } from 'antd'
+import { memo, useCallback, useMemo } from 'react'
+
+import { defaultTimeFormat, momentToTimeOnly, timeOnlyToMoment } from '@utils/datetime'
+import { TimeOnly } from '@api'
+
+export type TimePickerWrapperProps = Omit, 'onChange'> & {
+ value?: TimeOnly,
+ onChange?: (date: TimeOnly | null) => any
+ isUTC?: boolean
+}
+
+export const TimePickerWrapper = memo(({ value, onChange, isUTC, ...other }) => {
+ const time = useMemo(() => value ? timeOnlyToMoment(value, isUTC) : null, [value, isUTC])
+
+ const onTimeChange = useCallback((time: Moment | null) => onChange?.(time ? momentToTimeOnly(time) : null), [onChange])
+
+ return (
+
+ )
+})
+
+export default TimePickerWrapper
diff --git a/src/components/Table/index.tsx b/src/components/Table/index.tsx
index ddf735d..715c2d2 100755
--- a/src/components/Table/index.tsx
+++ b/src/components/Table/index.tsx
@@ -1,6 +1,7 @@
-export { makeDateSorter, makeNumericSorter, makeStringSorter } from './sorters'
+export { makeDateSorter, makeNumericSorter, makeStringSorter, makeTimeSorter } from './sorters'
export { EditableTable, makeActionHandler } from './EditableTable'
export { DatePickerWrapper } from './DatePickerWrapper'
+export { TimePickerWrapper } from './TimePickerWrapper'
export { DateRangeWrapper } from './DateRangeWrapper'
export { Table } from './Table'
export {
@@ -8,6 +9,7 @@ export {
timezoneOptions,
TimezoneSelect,
makeDateColumn,
+ makeTimeColumn,
makeGroupColumn,
makeColumn,
makeColumnsPlanFact,
@@ -36,6 +38,7 @@ export type {
} from './Columns'
export type { DateRangeWrapperProps } from './DateRangeWrapper'
export type { DatePickerWrapperProps } from './DatePickerWrapper'
+export type { TimePickerWrapperProps } from './TimePickerWrapper'
export type { BaseTableColumn, TableColumns, TableContainer } from './Table'
export const defaultPagination = {
diff --git a/src/components/Table/sorters.ts b/src/components/Table/sorters.ts
index bbccbbd..2592300 100755
--- a/src/components/Table/sorters.ts
+++ b/src/components/Table/sorters.ts
@@ -1,4 +1,6 @@
+import { timeOnlyToMoment } from '@utils/datetime'
import { isRawDate } from '@utils'
+import { TimeOnly } from '@api'
import { DataType } from './Columns'
@@ -23,3 +25,14 @@ export const makeDateSorter = (key: keyof DataType) => (a:
return date.getTime() - new Date(bdate).getTime()
}
+
+export const makeTimeSorter = (key: keyof DataType) => (a: DataType, b: DataType) => {
+ const elma = a[key]
+ const elmb = b[key]
+
+ if (!elma && !elmb) return 0
+ if (!elma) return 1
+ if (!elmb) return -1
+
+ return timeOnlyToMoment(elma).diff(timeOnlyToMoment(elmb))
+}
diff --git a/src/utils/datetime.ts b/src/utils/datetime.ts
index e72f63c..cb92700 100755
--- a/src/utils/datetime.ts
+++ b/src/utils/datetime.ts
@@ -1,10 +1,11 @@
-import moment from 'moment'
+import moment, { Moment } from 'moment'
-import { SimpleTimezoneDto } from '@api'
+import { SimpleTimezoneDto, TimeOnly } from '@api'
export type RawDate = number | string | Date
export const defaultFormat: Readonly = 'DD.MM.YYYY HH:mm'
+export const defaultTimeFormat: Readonly = 'HH:mm:ss'
export enum timeInS {
millisecond = 0.001,
@@ -19,12 +20,25 @@ export function isRawDate(value: unknown): value is RawDate {
return !isNaN(Date.parse(String(value)))
}
+export function isTimeOnly(value: unknown): value is TimeOnly {
+ if (!value || typeof value !== 'object')
+ return false
+ const keys = Object.keys(value)
+ return ['hour', 'minute', 'second'].every((key) => keys.includes(key))
+}
+
export const formatDate = (date: unknown, utc: boolean = false, format: string = defaultFormat) => {
if (!isRawDate(date)) return null
const out = utc ? moment.utc(date).local() : moment(date)
return out.format(format)
}
+export const formatTime = (time: unknown, utc: boolean = false, format: string = defaultTimeFormat) => {
+ if(!isTimeOnly(time)) return
+ const out = timeOnlyToMoment(time, utc, format)
+ return out.format(format)
+}
+
export const periodToString = (time?: number) => {
if (!time || time <= 0) return '00:00:00'
const days = Math.floor(time / timeInS.day)
@@ -77,3 +91,16 @@ export const isTimezoneId = (value: unknown): value is TimezoneId => !!value &&
export const findTimezoneId = (value: SimpleTimezoneDto): TimezoneId =>
(isTimezoneId(value.timezoneId) && value.timezoneId) ||
(Object.keys(rawTimezones) as TimezoneId[]).find(id => rawTimezones[id] === value.hours) as TimezoneId
+
+export const timeOnlyToMoment = (time?: TimeOnly | null, isUtc?: boolean, format: string = defaultTimeFormat): Moment => {
+ const input = `${time?.hour ?? 0}:${time?.minute ?? 0}:${time?.second ?? 0}`
+ return isUtc ? moment.utc(input, format).local() : moment(input, format)
+}
+
+export const momentToTimeOnly = (time?: Moment | null): TimeOnly => ({
+ hour: time?.hour() ?? 0,
+ minute: time?.minute() ?? 0,
+ second: time?.second() ?? 0,
+ millisecond: 0,
+ ticks: 0,
+})