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

Commit 181641b

Browse files
committed
Ctrl+Enter hotkey to save time range edit
1 parent 34b79ea commit 181641b

File tree

3 files changed

+125
-106
lines changed

3 files changed

+125
-106
lines changed
Lines changed: 115 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useCallback, useEffect, useState } from 'react';
22
import { Button, Col, Form, Input, Modal, Row, TimePicker } from 'antd';
33
import { Moment } from 'moment/moment';
44
import moment from 'moment';
@@ -25,116 +25,128 @@ interface TimeRangeModalProps {
2525
onClose: () => void;
2626
}
2727

28-
export default observer(function TimeRangeModal({
29-
taskTime,
30-
visible,
31-
onClose,
32-
}: TimeRangeModalProps) {
33-
const [valid, setValid] = useState<boolean>(false);
34-
const [description, setDescription] = useState<string>('');
35-
const [timeRange, setTimeRange] = useState<Undefined<ITimeRangeModel>>();
36-
const timeInProgress = !taskTime?.time.end;
28+
const TimeRangeModal = observer(
29+
({ taskTime, visible, onClose }: TimeRangeModalProps) => {
30+
const [valid, setValid] = useState<boolean>(false);
31+
const [description, setDescription] = useState<string>('');
32+
const [timeRange, setTimeRange] = useState<Undefined<ITimeRangeModel>>();
33+
const timeInProgress = !taskTime?.time.end;
3734

38-
useEffect(() => {
39-
setValid(
40-
!!timeRange?.start ||
41-
!!(
42-
timeRange?.start &&
43-
timeRange?.end &&
44-
isBefore(timeRange?.start, timeRange?.end)
45-
)
46-
);
47-
}, [timeRange]);
35+
const handleOk = useCallback(() => {
36+
if (taskTime?.task && timeRange?.start) {
37+
const { task, index } = taskTime;
38+
timeRange.description = description;
39+
tasksStore.setTime(task, index, timeRange);
40+
}
41+
onClose();
42+
}, [description, onClose, taskTime, timeRange]);
4843

49-
useEffect(() => {
50-
if (taskTime) {
51-
setTimeRange({ ...taskTime.time });
52-
setDescription(taskTime.time.description || '');
53-
}
54-
}, [taskTime]);
44+
useEffect(() => {
45+
function keyupHandler(e: KeyboardEvent) {
46+
// Hotkey: Ctrl+Enter
47+
if (e.ctrlKey && e.key === 'Enter') {
48+
handleOk();
49+
}
50+
}
5551

56-
function handleOk() {
57-
if (taskTime?.task && timeRange?.start) {
58-
const { task, index } = taskTime;
59-
if (description) {
60-
timeRange.description = description;
52+
document.addEventListener('keyup', keyupHandler);
53+
return () => {
54+
document.removeEventListener('keyup', keyupHandler);
55+
};
56+
}, [handleOk]);
57+
58+
useEffect(() => {
59+
setValid(
60+
!!timeRange?.start ||
61+
!!(
62+
timeRange?.start &&
63+
timeRange?.end &&
64+
isBefore(timeRange?.start, timeRange?.end)
65+
)
66+
);
67+
}, [timeRange]);
68+
69+
useEffect(() => {
70+
if (taskTime) {
71+
setTimeRange({ ...taskTime.time });
72+
setDescription(taskTime.time.description || '');
6173
}
62-
tasksStore.setTime(task, index, timeRange);
63-
}
64-
onClose();
65-
}
74+
}, [taskTime]);
6675

67-
function handleDelete() {
68-
if (taskTime) {
69-
tasksStore.deleteTime(taskTime.task, taskTime.index);
76+
function handleDelete() {
77+
if (taskTime) {
78+
tasksStore.deleteTime(taskTime.task, taskTime.index);
79+
}
80+
onClose();
7081
}
71-
onClose();
72-
}
7382

74-
function handleCancel() {
75-
onClose();
76-
}
83+
function handleCancel() {
84+
onClose();
85+
}
7786

78-
function onChange(field: RangeField) {
79-
return (value: Moment | null) => {
80-
const newTimeRange = {
81-
...timeRange,
82-
[field]: value?.toDate() || undefined,
87+
function onChange(field: RangeField) {
88+
return (value: Moment | null) => {
89+
const newTimeRange = {
90+
...timeRange,
91+
[field]: value?.toDate() || undefined,
92+
};
93+
setTimeRange(newTimeRange as ITimeRangeModel);
8394
};
84-
setTimeRange(newTimeRange as ITimeRangeModel);
85-
};
95+
}
96+
97+
return (
98+
<Modal
99+
title="Edit time range"
100+
visible={visible}
101+
okButtonProps={{ disabled: !valid }}
102+
onOk={handleOk}
103+
onCancel={handleCancel}
104+
okText="Save"
105+
>
106+
<Form colon>
107+
<Form.Item label="Task">
108+
<div>{taskTime?.task.title}</div>
109+
</Form.Item>
110+
<Form.Item label="Description">
111+
<Input
112+
placeholder="Type description..."
113+
value={description}
114+
onChange={(e) => setDescription(e.target.value)}
115+
/>
116+
</Form.Item>
117+
<Row>
118+
<Col span={8}>
119+
<Form.Item label="Start" labelCol={{ span: 24 }}>
120+
<TimePicker
121+
format="HH:mm"
122+
value={timeRange?.start && moment(timeRange?.start)}
123+
onChange={onChange(RangeField.start)}
124+
/>
125+
</Form.Item>
126+
</Col>
127+
<Col span={8}>
128+
<Form.Item label="End" labelCol={{ span: 24 }}>
129+
<TimePicker
130+
format="HH:mm"
131+
value={timeRange?.end && moment(timeRange?.end)}
132+
onChange={onChange(RangeField.end)}
133+
disabled={timeInProgress}
134+
/>
135+
</Form.Item>
136+
</Col>
137+
<Col span={8}>
138+
<Form.Item label="Duration" labelCol={{ span: 24 }}>
139+
<TimeRangeDuration timeRange={timeRange} />
140+
</Form.Item>
141+
</Col>
142+
</Row>
143+
<Button icon={<DeleteFilled />} onClick={handleDelete}>
144+
Remove
145+
</Button>
146+
</Form>
147+
</Modal>
148+
);
86149
}
150+
);
87151

88-
return (
89-
<Modal
90-
title="Edit time range"
91-
visible={visible}
92-
okButtonProps={{ disabled: !valid }}
93-
onOk={handleOk}
94-
onCancel={handleCancel}
95-
okText="Save"
96-
>
97-
<Form colon>
98-
<Form.Item label="Task">
99-
<div>{taskTime?.task.title}</div>
100-
</Form.Item>
101-
<Form.Item label="Description">
102-
<Input
103-
placeholder="Type description..."
104-
value={description}
105-
onChange={(e) => setDescription(e.target.value)}
106-
/>
107-
</Form.Item>
108-
<Row>
109-
<Col span={8}>
110-
<Form.Item label="Start" labelCol={{ span: 24 }}>
111-
<TimePicker
112-
format="HH:mm"
113-
value={timeRange?.start && moment(timeRange?.start)}
114-
onChange={onChange(RangeField.start)}
115-
/>
116-
</Form.Item>
117-
</Col>
118-
<Col span={8}>
119-
<Form.Item label="End" labelCol={{ span: 24 }}>
120-
<TimePicker
121-
format="HH:mm"
122-
value={timeRange?.end && moment(timeRange?.end)}
123-
onChange={onChange(RangeField.end)}
124-
disabled={timeInProgress}
125-
/>
126-
</Form.Item>
127-
</Col>
128-
<Col span={8}>
129-
<Form.Item label="Duration" labelCol={{ span: 24 }}>
130-
<TimeRangeDuration timeRange={timeRange} />
131-
</Form.Item>
132-
</Col>
133-
</Row>
134-
<Button icon={<DeleteFilled />} onClick={handleDelete}>
135-
Remove
136-
</Button>
137-
</Form>
138-
</Modal>
139-
);
140-
});
152+
export default TimeRangeModal;

src/screens/projects/components/ProjectModals/EditProjectModal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@ interface EditProjectModalProps {
1414
onClose: () => void;
1515
}
1616

17-
export default observer(function EditProjectModal({
18-
project,
19-
}: EditProjectModalProps) {
17+
const EditProjectModal = observer(({ project }: EditProjectModalProps) => {
2018
const [title, setTitle] = useState<string>('');
2119
const [color, setColor] = useState<string>('');
2220

@@ -79,3 +77,5 @@ export default observer(function EditProjectModal({
7977
</Modal>
8078
);
8179
});
80+
81+
export default EditProjectModal;

src/screens/projects/components/TaskInput.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,20 @@ export default observer(function TaskInput() {
99
const [text, setText] = useState('');
1010

1111
function handleKeyPress(event: KeyboardEvent) {
12+
// Hotkey: Enter
1213
if (event.key === 'Enter') {
1314
const { tasksStore, projectStore } = rootStore;
1415
tasksStore.add(
1516
new TaskModel({
1617
key: String(Date.now()),
1718
title: text,
1819
projectId: projectStore.activeProject,
20+
active: false,
21+
time: [],
22+
checked: false,
23+
children: [],
24+
datesInProgress: [],
25+
details: [],
1926
})
2027
);
2128
setText('');

0 commit comments

Comments
 (0)