Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.

Commit 8a2a14a

Browse files
committed
Start, duration, gaps, estimatedEnd
1 parent db81ba4 commit 8a2a14a

File tree

3 files changed

+93
-15
lines changed

3 files changed

+93
-15
lines changed

src/helpers/DateTime.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { ITimeRangeModel } from '../models/TaskModel';
2+
import { format } from 'date-fns';
3+
import { mapPrevCurrent } from './MapPrevCurrent';
24

35
function timePad(time: number): string {
46
return String(time).padStart(2, '0');
@@ -42,3 +44,34 @@ export function calcDuration(taskTime: ITimeRangeModel[]): number {
4244
return prev + timeRange.end.getTime() - timeRange.start.getTime();
4345
}, 0);
4446
}
47+
48+
export function calcDurationGaps(taskTime: ITimeRangeModel[]): number {
49+
let result = 0;
50+
mapPrevCurrent(taskTime, (prev, cur) => {
51+
if (prev?.end) {
52+
result += cur.start.getTime() - prev.end.getTime();
53+
}
54+
});
55+
return result;
56+
}
57+
58+
const TIME_FORMAT = 'HH:mm';
59+
const NO_TIME = '--:--';
60+
61+
export function getTime(date: Date | undefined) {
62+
if (!date) {
63+
return NO_TIME;
64+
}
65+
return format(date, TIME_FORMAT);
66+
}
67+
68+
const EIGHT_HOURS = 8 * 60 * 60 * 1000;
69+
70+
export function estimateWorkingTimeEnd(
71+
startDate: Date | undefined,
72+
restTimeMs: number
73+
): Date | undefined {
74+
return startDate
75+
? new Date(startDate.getTime() + restTimeMs + EIGHT_HOURS)
76+
: undefined;
77+
}

src/hooks/TaskHooks.ts

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { useCallback, useEffect, useRef, useState } from 'react';
1+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2+
import { isBefore } from 'date-fns';
23

3-
import { calcDuration, msToTime } from '../helpers/DateTime';
4+
import { calcDuration, calcDurationGaps, msToTime } from '../helpers/DateTime';
45
import TaskModel, { ITimeRangeModel } from '../models/TaskModel';
56
import TaskTimeItemModel from '../models/TaskTimeItemModel';
67

@@ -31,25 +32,33 @@ export function useTaskDuration(model: TaskModel | undefined) {
3132
return duration;
3233
}
3334

34-
export function useTimeItemsDuration(
35-
taskTime: TaskTimeItemModel[],
36-
showSeconds: boolean = false
37-
) {
38-
const [duration, setDuration] = useState<string>('');
35+
export function useTimeItemsDuration(taskTime: TaskTimeItemModel[]) {
36+
const [durationMs, setDurationMs] = useState<number>(0);
37+
const [gapsMs, setGapsMs] = useState<number>(0);
3938
const intervalRef = useRef<NodeJS.Timeout>();
4039

4140
const calcTaskDuration = useCallback(
42-
() => msToTime(calcDuration(taskTime.map((t) => t.time)), showSeconds),
43-
[showSeconds, taskTime]
41+
() => calcDuration(taskTime.map((t) => t.time)),
42+
[taskTime]
43+
);
44+
45+
const calcTaskGapsDuration = useCallback(
46+
() => calcDurationGaps(taskTime.map((t) => t.time)),
47+
[taskTime]
4448
);
4549

50+
const setTimes = useCallback(() => {
51+
setDurationMs(calcTaskDuration());
52+
setGapsMs(calcTaskGapsDuration());
53+
}, [calcTaskDuration, calcTaskGapsDuration]);
54+
4655
useEffect(() => {
47-
setDuration(calcTaskDuration());
56+
setTimes();
4857

4958
const haveActiveTime = taskTime.some((t) => !t.time.end);
5059
if (haveActiveTime) {
5160
intervalRef.current = setInterval(() => {
52-
setDuration(calcTaskDuration());
61+
setTimes();
5362
}, 1000);
5463
}
5564

@@ -58,9 +67,12 @@ export function useTimeItemsDuration(
5867
clearInterval(intervalRef.current);
5968
}
6069
};
61-
}, [calcTaskDuration, taskTime]);
70+
}, [setTimes, taskTime]);
6271

63-
return duration;
72+
return {
73+
durationMs,
74+
gapsMs,
75+
};
6476
}
6577

6678
export function useTimeRangeDuration(timeRange: ITimeRangeModel | undefined) {
@@ -93,3 +105,17 @@ export function useTimeRangeDuration(timeRange: ITimeRangeModel | undefined) {
93105

94106
return duration;
95107
}
108+
109+
export function useStartWorkingTime(
110+
timeItems: TaskTimeItemModel[]
111+
): Date | undefined {
112+
return useMemo(() => {
113+
let minTime: Date | undefined;
114+
timeItems.forEach((time) => {
115+
if (!minTime || isBefore(time.time.start, minTime)) {
116+
minTime = time.time.start;
117+
}
118+
});
119+
return minTime;
120+
}, [timeItems]);
121+
}
Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,33 @@
11
import React from 'react';
22
import { observer } from 'mobx-react';
3+
import { Space } from 'antd';
34

45
import * as TaskHooks from '../../../../hooks/TaskHooks';
56
import TaskTimeItemModel from '../../../../models/TaskTimeItemModel';
7+
import {
8+
estimateWorkingTimeEnd,
9+
getTime,
10+
msToTime,
11+
} from '../../../../helpers/DateTime';
612

713
interface TotalHoursProps {
814
timeItems: TaskTimeItemModel[];
915
}
1016

1117
export default observer(function TotalHours({ timeItems }: TotalHoursProps) {
12-
const duration = TaskHooks.useTimeItemsDuration(timeItems);
13-
return <div>{duration}</div>;
18+
const { durationMs, gapsMs } = TaskHooks.useTimeItemsDuration(timeItems);
19+
const startWorkingTime = TaskHooks.useStartWorkingTime(timeItems);
20+
const estimatedWorkingTimeEnd = estimateWorkingTimeEnd(
21+
startWorkingTime,
22+
gapsMs
23+
);
24+
25+
return (
26+
<Space>
27+
<span>{getTime(startWorkingTime)}</span>
28+
<span>{msToTime(durationMs, false)}</span>
29+
<span>{msToTime(gapsMs, false)}</span>
30+
<span>{getTime(estimatedWorkingTimeEnd)}</span>
31+
</Space>
32+
);
1433
});

0 commit comments

Comments
 (0)