1
0
Fork 0
mirror of https://github.com/plankanban/planka.git synced 2025-07-18 20:59:44 +02:00
planka/client/src/components/StopwatchEditStep/StopwatchEditStep.jsx

193 lines
5.3 KiB
React
Raw Normal View History

2020-08-20 15:35:46 +05:00
import { dequal } from 'dequal';
import React, { useCallback, useEffect, useRef } from 'react';
2019-08-31 04:07:25 +05:00
import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next';
import { Button, Form } from 'semantic-ui-react';
import { useToggle } from '../../lib/hooks';
2019-08-31 04:07:25 +05:00
import { Input, Popup } from '../../lib/custom-ui';
import { useForm } from '../../hooks';
import {
createStopwatch,
getStopwatchParts,
startStopwatch,
stopStopwatch,
updateStopwatch,
} from '../../utils/stopwatch';
import styles from './StopwatchEditStep.module.scss';
const createData = (stopwatch) => {
if (!stopwatch) {
2019-08-31 04:07:25 +05:00
return {
hours: '0',
minutes: '0',
seconds: '0',
};
}
const { hours, minutes, seconds } = getStopwatchParts(stopwatch);
2019-08-31 04:07:25 +05:00
return {
hours: `${hours}`,
minutes: `${minutes}`,
seconds: `${seconds}`,
};
};
const StopwatchEditStep = React.memo(({ defaultValue, onUpdate, onBack, onClose }) => {
2019-08-31 04:07:25 +05:00
const [t] = useTranslation();
const [data, handleFieldChange, setData] = useForm(() => createData(defaultValue));
2022-06-20 18:27:39 +02:00
const [isEditing, toggleEditing] = useToggle();
2019-08-31 04:07:25 +05:00
const hoursField = useRef(null);
const minutesField = useRef(null);
const secondsField = useRef(null);
const handleStartClick = useCallback(() => {
onUpdate(startStopwatch(defaultValue));
2019-08-31 04:07:25 +05:00
onClose();
}, [defaultValue, onUpdate, onClose]);
const handleStopClick = useCallback(() => {
onUpdate(stopStopwatch(defaultValue));
2019-08-31 04:07:25 +05:00
}, [defaultValue, onUpdate]);
const handleClearClick = useCallback(() => {
2019-08-31 04:07:25 +05:00
if (defaultValue) {
onUpdate(null);
}
onClose();
}, [defaultValue, onUpdate, onClose]);
2022-06-20 18:27:39 +02:00
const handleToggleEditingClick = useCallback(() => {
2019-08-31 04:07:25 +05:00
setData(createData(defaultValue));
2022-06-20 18:27:39 +02:00
toggleEditing();
}, [defaultValue, setData, toggleEditing]);
2019-08-31 04:07:25 +05:00
const handleSubmit = useCallback(() => {
2019-08-31 04:07:25 +05:00
const parts = {
hours: parseInt(data.hours, 10),
minutes: parseInt(data.minutes, 10),
seconds: parseInt(data.seconds, 10),
};
if (Number.isNaN(parts.hours)) {
hoursField.current.select();
return;
}
if (Number.isNaN(parts.minutes) || parts.minutes > 60) {
minutesField.current.select();
return;
}
if (Number.isNaN(parts.seconds) || parts.seconds > 60) {
secondsField.current.select();
return;
}
if (defaultValue) {
if (!dequal(parts, getStopwatchParts(defaultValue))) {
onUpdate(updateStopwatch(defaultValue, parts));
2019-08-31 04:07:25 +05:00
}
} else {
onUpdate(createStopwatch(parts));
2019-08-31 04:07:25 +05:00
}
onClose();
}, [defaultValue, onUpdate, onClose, data]);
useEffect(() => {
if (isEditing) {
hoursField.current.select();
}
}, [isEditing]);
return (
<>
<Popup.Header onBack={onBack}>
{t('common.editStopwatch', {
2019-08-31 04:07:25 +05:00
context: 'title',
})}
</Popup.Header>
<Popup.Content>
<Form onSubmit={handleSubmit}>
<div className={styles.fieldWrapper}>
<div className={styles.fieldBox}>
<div className={styles.text}>{t('common.hours')}</div>
<Input.Mask
2019-08-31 04:07:25 +05:00
ref={hoursField}
name="hours"
value={data.hours}
mask="9999"
maskChar={null}
disabled={!isEditing}
onChange={handleFieldChange}
/>
</div>
<div className={styles.fieldBox}>
<div className={styles.text}>{t('common.minutes')}</div>
<Input.Mask
2019-08-31 04:07:25 +05:00
ref={minutesField}
name="minutes"
value={data.minutes}
mask="99"
maskChar={null}
disabled={!isEditing}
onChange={handleFieldChange}
/>
</div>
<div className={styles.fieldBox}>
<div className={styles.text}>{t('common.seconds')}</div>
<Input.Mask
2019-08-31 04:07:25 +05:00
ref={secondsField}
name="seconds"
value={data.seconds}
mask="99"
maskChar={null}
disabled={!isEditing}
onChange={handleFieldChange}
/>
</div>
<Button
type="button"
icon={isEditing ? 'close' : 'edit'}
className={styles.iconButton}
2022-06-20 18:27:39 +02:00
onClick={handleToggleEditingClick}
2019-08-31 04:07:25 +05:00
/>
</div>
{isEditing && <Button positive content={t('action.save')} />}
</Form>
{!isEditing &&
(defaultValue && defaultValue.startedAt ? (
2019-08-31 04:07:25 +05:00
<Button positive content={t('action.stop')} icon="pause" onClick={handleStopClick} />
) : (
<Button positive content={t('action.start')} icon="play" onClick={handleStartClick} />
))}
<Button
negative
content={t('action.remove')}
className={styles.deleteButton}
onClick={handleClearClick}
/>
</Popup.Content>
</>
);
});
StopwatchEditStep.propTypes = {
2019-08-31 04:07:25 +05:00
defaultValue: PropTypes.object, // eslint-disable-line react/forbid-prop-types
onUpdate: PropTypes.func.isRequired,
onBack: PropTypes.func,
onClose: PropTypes.func.isRequired,
};
StopwatchEditStep.defaultProps = {
2019-08-31 04:07:25 +05:00
defaultValue: undefined,
onBack: undefined,
};
export default StopwatchEditStep;