Skip to content

Commit e595a16

Browse files
adjust frontend to update task time
1 parent 96dd729 commit e595a16

File tree

6 files changed

+95
-14
lines changed

6 files changed

+95
-14
lines changed

frontend/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
"@testing-library/react": "^9.3.2",
1010
"@testing-library/user-event": "^7.1.2",
1111
"apollo-link-context": "^1.0.19",
12-
"format-duration": "^1.3.1",
1312
"formik": "^2.1.1",
1413
"grommet": "^2.9.0",
1514
"grommet-icons": "^4.4.0",

frontend/src/helpers/tasks.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { DateTime, Duration } from 'luxon'
2+
3+
const secondsToMillis = time => time * 1000
4+
5+
export const timerRunning = timerStatus => timerStatus === 'running'
6+
export const elapsedTime = ({ time, timerStartedAt, timerStatus }) => {
7+
return secondsToMillis(time) + (timerRunning(timerStatus) ? DateTime.utc().diff(DateTime.fromISO(timerStartedAt)) : 0)
8+
}
9+
10+
export const formatDuration = (timeInMillis) =>
11+
Duration.fromMillis(timeInMillis).toFormat('hh:mm')

frontend/src/pages/Home/TaskList.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react'
22
import { gql, useMutation } from '@apollo/client'
33
import { Box, Text } from 'grommet'
4-
import formatDuration from 'format-duration'
54
import styled from 'styled-components'
5+
import { formatDuration } from '../../helpers/tasks'
66
import Task from './Task'
77

88
const edgeSize = () => ({ theme}) => theme.global.edgeSize.xsmall

frontend/src/pages/Home/TaskModal.js

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
11
import React from 'react'
2-
import { Layer, Form, TextArea, Button, Box, FormField } from 'grommet'
2+
import { Layer, Form, TextArea, Button, Box, FormField, MaskedInput } from 'grommet'
33
import { Checkmark, Trash } from 'grommet-icons'
44
import { gql, useMutation } from '@apollo/client'
55
import { useFormik } from 'formik'
66
import * as Yup from 'yup'
7+
import styled from 'styled-components'
8+
import { Duration } from 'luxon'
79
import useSelectedProjectId from '../../hooks/useSelectedProjectId'
10+
import { formatDuration, timerRunning } from '../../helpers/tasks'
11+
12+
const TimeFormField = styled(FormField)`
13+
flex-direction: row;
14+
> label {
15+
flex-grow: 2;
16+
display: flex;
17+
align-items: center;
18+
justify-content: flex-end;
19+
font-weight: 600;
20+
}
21+
`
22+
23+
const TimeMaskedInput = styled(MaskedInput)`
24+
width: 100px;
25+
&:disabled {
26+
opacity: ${({ theme }) => theme.textInput.disabled.opacity
27+
}
28+
`
29+
830

931
const CREATE_TASK = gql`
1032
mutation CreateTaskMutation($projectId:ID!, $description: String!) {
@@ -36,15 +58,45 @@ const validationSchema = Yup.object().shape({
3658
.required('Required')
3759
})
3860

61+
const createInitialValues = (task) => {
62+
if(!task) return { time: '00:00' }
63+
64+
const { description } = task
65+
const time = formatDuration(task.time * 1000)
66+
return {
67+
description,
68+
time
69+
}
70+
}
71+
72+
const formattedDurationToSeconds = (stringDuration) => {
73+
const [hours, minutes] = stringDuration.split(':')
74+
return Duration.fromObject({ hours, minutes }).as('seconds')
75+
}
76+
3977
function TaskModal({ onClose, onTaskSaved, onTaskDeleted, task }) {
4078
const [createTask] = useMutation(CREATE_TASK)
4179
const [updateTask] = useMutation(UPDATE_TASK)
4280
const [deleteTask] = useMutation(DELETE_TASK)
4381

82+
const updateVars = (task, formValues) => {
83+
const { description, time } = formValues
84+
const { id: taskId } = task
85+
86+
return {
87+
variables: {
88+
taskId,
89+
description,
90+
...(timerRunning(task.timerStatus) ? {} : { time: formattedDurationToSeconds(time) })
91+
}
92+
}
93+
}
94+
95+
const createVars = ({ description, time }) => ({ projectId, description, time })
96+
4497
const projectId = useSelectedProjectId()
45-
const onSubmit = async ({ description }) => {
46-
const variables = { variables: { ...(task ? { taskId: task.id } : { projectId } ), description } }
47-
task ? await updateTask(variables) : await createTask(variables)
98+
const onSubmit = async (values) => {
99+
task ? await updateTask(updateVars(task, values)) : await createTask(createVars(values))
48100
onClose()
49101
onTaskSaved()
50102
}
@@ -53,7 +105,7 @@ function TaskModal({ onClose, onTaskSaved, onTaskDeleted, task }) {
53105
onClose()
54106
onTaskDeleted()
55107
}
56-
const form = useFormik({ initialValues: task || {}, validationSchema, onSubmit })
108+
const form = useFormik({ initialValues: createInitialValues(task), validationSchema, onSubmit })
57109

58110
return (
59111
<Layer
@@ -66,6 +118,26 @@ function TaskModal({ onClose, onTaskSaved, onTaskDeleted, task }) {
66118
<TextArea onChange={form.handleChange} placeholder='Type the task description' rows={4} name='description' value={form.values.description} />
67119
</FormField>
68120

121+
<TimeFormField error={form.touched.time && form.errors.time} label='Duration'>
122+
<TimeMaskedInput
123+
onChange={form.handleChange}
124+
placeholder='00:00'
125+
name='time'
126+
value={form.values.time}
127+
disabled={task && timerRunning(task.timerStatus)}
128+
mask={[
129+
{ length: [1,2], regexp: /^[0-9]*$/, placeholder: 'hh' },
130+
{ fixed: ':' },
131+
{
132+
length: 2,
133+
options: ['00', '05', '10', '15', '30', '45'],
134+
regexp: /^[0-5][0-9]$|^[0-9]$/,
135+
placeholder: 'mm',
136+
},
137+
]}
138+
/>
139+
</TimeFormField>
140+
69141
<Box justify='between' direction='row'>
70142
{task && (
71143
<Button

frontend/src/pages/Home/Timer.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
import React, { useState, useEffect } from 'react'
22
import { Box, Text } from 'grommet'
3-
import { DateTime } from 'luxon'
4-
import formatDuration from 'format-duration'
5-
6-
const secondsToMillis = time => time * 1000
7-
const timerRunning = timerStatus => timerStatus === 'running'
8-
const calcElapsedTime = ({ time, timerStartedAt, timerStatus }) =>
9-
secondsToMillis(time) + (timerRunning(timerStatus) ? DateTime.utc().diff(DateTime.fromISO(timerStartedAt)) : 0)
3+
import { elapsedTime as calcElapsedTime, formatDuration } from '../../helpers/tasks'
104

115
const Timer = ({ task }) => {
126
const [elapsedTime, setElapsedTime] = useState(calcElapsedTime(task))

frontend/src/theme.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,10 @@ export default {
55
size: '18px',
66
height: '20px'
77
}
8+
},
9+
textInput: {
10+
disabled: {
11+
opacity: 0.5
12+
}
813
}
914
}

0 commit comments

Comments
 (0)