taskcafe/frontend/src/shared/components/DueDateManager/index.tsx

270 lines
6.8 KiB
TypeScript
Raw Normal View History

2020-06-16 00:36:59 +02:00
import React, { useState, useEffect, forwardRef } from 'react';
2020-06-13 00:21:58 +02:00
import moment from 'moment';
import styled from 'styled-components';
2020-04-13 00:45:51 +02:00
import DatePicker from 'react-datepicker';
2020-06-13 00:21:58 +02:00
import _ from 'lodash';
2020-04-13 00:45:51 +02:00
import 'react-datepicker/dist/react-datepicker.css';
2020-06-13 00:21:58 +02:00
import { getYear, getMonth } from 'date-fns';
import { useForm, Controller } from 'react-hook-form';
import NOOP from 'shared/utils/noop';
import { Wrapper, ActionWrapper, RemoveDueDate, DueDateInput, DueDatePickerWrapper, ConfirmAddDueDate } from './Styles';
2020-04-13 00:45:51 +02:00
type DueDateManagerProps = {
task: Task;
onDueDateChange: (task: Task, newDueDate: Date) => void;
2020-06-19 01:12:15 +02:00
onRemoveDueDate: (task: Task) => void;
2020-04-13 00:45:51 +02:00
onCancel: () => void;
};
2020-06-13 00:21:58 +02:00
2020-06-16 00:36:59 +02:00
const Form = styled.form`
padding-top: 25px;
`;
const FormField = styled.div`
width: 50%;
display: inline-block;
`;
2020-06-13 00:21:58 +02:00
const HeaderSelectLabel = styled.div`
display: inline-block;
position: relative;
z-index: 9999;
border-radius: 3px;
cursor: pointer;
padding: 6px 10px;
text-decoration: underline;
margin: 6px 0;
font-size: 14px;
line-height: 16px;
margin-left: 0;
margin-right: 0;
padding-left: 4px;
padding-right: 4px;
color: #c2c6dc;
&:hover {
background: rgba(115, 103, 240);
color: #c2c6dc;
}
`;
const HeaderSelect = styled.select`
text-decoration: underline;
font-size: 14px;
text-align: center;
padding: 4px 6px;
background: none;
outline: none;
border: none;
border-radius: 3px;
appearance: none;
&:hover {
background: #262c49;
border: 1px solid rgba(115, 103, 240);
outline: none !important;
box-shadow: none;
color: #c2c6dc;
}
&::-ms-expand {
display: none;
}
cursor: pointer;
position: absolute;
z-index: 9998;
margin: 0;
left: 0;
top: 5px;
opacity: 0;
`;
const HeaderButton = styled.button`
cursor: pointer;
color: #c2c6dc;
text-decoration: underline;
font-size: 14px;
text-align: center;
padding: 6px 10px;
margin: 6px 0;
background: none;
outline: none;
border: none;
border-radius: 3px;
&:hover {
background: rgba(115, 103, 240);
color: #fff;
}
`;
const HeaderActions = styled.div`
position: relative;
text-align: center;
& > button:first-child {
float: left;
}
& > button:last-child {
float: right;
}
`;
2020-06-19 01:12:15 +02:00
const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange, onRemoveDueDate, onCancel }) => {
2020-06-13 00:21:58 +02:00
const now = moment();
const { register, handleSubmit, errors, setValue, setError, formState, control } = useForm<DueDateFormData>();
2020-04-13 00:45:51 +02:00
const [startDate, setStartDate] = useState(new Date());
2020-06-16 00:36:59 +02:00
useEffect(() => {
const newDate = moment(startDate).format('YYYY-MM-DD');
setValue('endDate', newDate);
}, [startDate]);
2020-06-16 00:36:59 +02:00
2020-06-13 00:21:58 +02:00
const years = _.range(2010, getYear(new Date()) + 10, 1);
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December',
];
2020-06-16 00:36:59 +02:00
const saveDueDate = (data: any) => {
const newDate = moment(`${data.endDate} ${moment(data.endTime).format('h:mm A')}`, 'YYYY-MM-DD h:mm A');
2020-06-16 00:36:59 +02:00
if (newDate.isValid()) {
onDueDateChange(task, newDate.toDate());
}
};
const CustomTimeInput = forwardRef(({ value, onClick }: any, $ref: any) => {
return (
<DueDateInput
id="endTime"
value={value}
2020-06-16 00:36:59 +02:00
name="endTime"
ref={$ref}
width="100%"
variant="alternate"
label="Time"
2020-06-16 00:36:59 +02:00
onClick={onClick}
/>
);
});
2020-04-13 00:45:51 +02:00
return (
<Wrapper>
2020-06-16 00:36:59 +02:00
<Form onSubmit={handleSubmit(saveDueDate)}>
<FormField>
<DueDateInput
id="endDate"
name="endDate"
width="100%"
variant="alternate"
label="Date"
defaultValue={now.format('YYYY-MM-DD')}
2020-06-16 00:36:59 +02:00
ref={register({
required: 'End date is required.',
})}
/>
</FormField>
<FormField>
<Controller
control={control}
defaultValue={now.toDate()}
name="endTime"
render={({ onChange, onBlur, value }) => (
<DatePicker
onChange={onChange}
selected={value}
onBlur={onBlur}
showTimeSelect
showTimeSelectOnly
timeIntervals={15}
timeCaption="Time"
dateFormat="h:mm aa"
customInput={<CustomTimeInput />}
/>
)}
2020-06-16 00:36:59 +02:00
/>
</FormField>
<DueDatePickerWrapper>
<DatePicker
useWeekdaysShort
renderCustomHeader={({
date,
changeYear,
changeMonth,
decreaseMonth,
increaseMonth,
prevMonthButtonDisabled,
nextMonthButtonDisabled,
}) => (
<HeaderActions>
<HeaderButton onClick={decreaseMonth} disabled={prevMonthButtonDisabled}>
Prev
</HeaderButton>
<HeaderSelectLabel>
{months[date.getMonth()]}
<HeaderSelect
value={getYear(date)}
onChange={({ target: { value } }) => changeYear(parseInt(value, 10))}
>
2020-06-16 00:36:59 +02:00
{years.map(option => (
<option key={option} value={option}>
{option}
</option>
))}
</HeaderSelect>
</HeaderSelectLabel>
<HeaderSelectLabel>
{date.getFullYear()}
<HeaderSelect
value={months[getMonth(date)]}
onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}
>
{months.map(option => (
<option key={option} value={option}>
{option}
</option>
))}
</HeaderSelect>
</HeaderSelectLabel>
<HeaderButton onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
Next
</HeaderButton>
</HeaderActions>
)}
selected={startDate}
inline
onChange={date => {
if (date) {
setStartDate(date);
}
2020-06-16 00:36:59 +02:00
}}
/>
</DueDatePickerWrapper>
<ActionWrapper>
<ConfirmAddDueDate type="submit" onClick={NOOP}>
2020-06-19 01:12:15 +02:00
Save
</ConfirmAddDueDate>
<RemoveDueDate
variant="outline"
color="danger"
2020-06-16 00:36:59 +02:00
onClick={() => {
2020-06-19 01:12:15 +02:00
onRemoveDueDate(task);
2020-06-16 00:36:59 +02:00
}}
>
2020-06-19 01:12:15 +02:00
Remove
</RemoveDueDate>
2020-06-16 00:36:59 +02:00
</ActionWrapper>
</Form>
2020-04-13 00:45:51 +02:00
</Wrapper>
);
};
export default DueDateManager;