feat: redesign task due date manager
This commit is contained in:
@ -126,4 +126,8 @@ export default createGlobalStyle`
|
||||
}
|
||||
|
||||
${mixin.placeholderColor(color.textLight)}
|
||||
|
||||
.picker-hidden {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
@ -793,12 +793,12 @@ const ProjectBoard: React.FC<ProjectBoardProps> = ({ projectID, onCardLabelClick
|
||||
<DueDateManager
|
||||
task={task}
|
||||
onRemoveDueDate={t => {
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: null } });
|
||||
hidePopup();
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: null, hasTime: false } });
|
||||
// hidePopup();
|
||||
}}
|
||||
onDueDateChange={(t, newDueDate) => {
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
|
||||
hidePopup();
|
||||
onDueDateChange={(t, newDueDate, hasTime) => {
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate, hasTime } });
|
||||
// hidePopup();
|
||||
}}
|
||||
onCancel={NOOP}
|
||||
/>
|
||||
|
@ -632,12 +632,12 @@ const Details: React.FC<DetailsProps> = ({
|
||||
<DueDateManager
|
||||
task={task}
|
||||
onRemoveDueDate={t => {
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: null } });
|
||||
hidePopup();
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: null, hasTime: false } });
|
||||
// hidePopup();
|
||||
}}
|
||||
onDueDateChange={(t, newDueDate) => {
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate } });
|
||||
hidePopup();
|
||||
onDueDateChange={(t, newDueDate, hasTime) => {
|
||||
updateTaskDueDate({ variables: { taskID: t.id, dueDate: newDueDate, hasTime } });
|
||||
// hidePopup();
|
||||
}}
|
||||
onCancel={NOOP}
|
||||
/>
|
||||
|
@ -2,6 +2,8 @@ import styled from 'styled-components';
|
||||
import Button from 'shared/components/Button';
|
||||
import { mixin } from 'shared/utils/styles';
|
||||
import Input from 'shared/components/Input';
|
||||
import ControlledInput from 'shared/components/ControlledInput';
|
||||
import { Clock } from 'shared/icons';
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
display: flex
|
||||
@ -17,6 +19,11 @@ display: flex
|
||||
z-index: 10000;
|
||||
margin-top: 0;
|
||||
}
|
||||
& .react-datepicker__close-icon::after {
|
||||
background: none;
|
||||
font-size: 16px;
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
}
|
||||
|
||||
& .react-datepicker-time__header {
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
@ -91,6 +98,24 @@ display: flex
|
||||
border-bottom: 1px solid ${props => props.theme.colors.border};
|
||||
}
|
||||
|
||||
& .react-datepicker__input-container input {
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-color: ${props => props.theme.colors.alternate};
|
||||
background: #262c49;
|
||||
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0.15);
|
||||
padding: 0.7rem;
|
||||
color: #c2c6dc;
|
||||
position: relative;
|
||||
border-radius: 5px;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
padding: 0 12px;
|
||||
&:focus {
|
||||
box-shadow: 0 3px 10px 0 rgba(0, 0, 0, 0.15);
|
||||
border: 1px solid rgba(115, 103, 240);
|
||||
background: ${props => props.theme.colors.bg.primary};
|
||||
}
|
||||
`;
|
||||
|
||||
export const DueDatePickerWrapper = styled.div`
|
||||
@ -110,6 +135,44 @@ export const RemoveDueDate = styled(Button)`
|
||||
margin: 0 0 0 4px;
|
||||
`;
|
||||
|
||||
export const AddDateRange = styled.div`
|
||||
opacity: 0.6;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: ${props => mixin.rgba(props.theme.colors.primary, 0.8)};
|
||||
&:hover {
|
||||
color: ${props => mixin.rgba(props.theme.colors.primary, 1)};
|
||||
text-decoration: underline;
|
||||
}
|
||||
`;
|
||||
|
||||
export const DateRangeInputs = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-left: -4px;
|
||||
& > div:first-child,
|
||||
& > div:last-child {
|
||||
flex: 1 1 92px;
|
||||
margin-bottom: 4px;
|
||||
margin-left: 4px;
|
||||
min-width: 92px;
|
||||
width: initial;
|
||||
}
|
||||
& > ${AddDateRange} {
|
||||
margin-left: 4px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
& > .react-datepicker-wrapper input {
|
||||
padding-bottom: 4px;
|
||||
padding-top: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CancelDueDate = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -119,15 +182,86 @@ export const CancelDueDate = styled.div`
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
export const DueDateInput = styled(Input)`
|
||||
export const DueDateInput = styled(ControlledInput)`
|
||||
margin-top: 15px;
|
||||
margin-bottom: 5px;
|
||||
padding-right: 10px;
|
||||
`;
|
||||
|
||||
export const ActionWrapper = styled.div`
|
||||
padding-top: 8px;
|
||||
export const ActionsSeparator = styled.div`
|
||||
margin-top: 8px;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background: #414561;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
`;
|
||||
export const ActionsWrapper = styled.div`
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
& .react-datepicker-wrapper {
|
||||
margin-left: auto;
|
||||
width: 82px;
|
||||
}
|
||||
& .react-datepicker__input-container input {
|
||||
padding-bottom: 4px;
|
||||
padding-top: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ActionClock = styled(Clock)`
|
||||
align-self: center;
|
||||
fill: ${props => props.theme.colors.primary};
|
||||
margin: 0 8px;
|
||||
flex: 0 0 auto;
|
||||
`;
|
||||
|
||||
export const ActionLabel = styled.div`
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
`;
|
||||
|
||||
export const ActionIcon = styled.div`
|
||||
height: 36px;
|
||||
min-height: 36px;
|
||||
min-width: 36px;
|
||||
width: 36px;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
margin-right: 8px;
|
||||
svg {
|
||||
fill: ${props => props.theme.colors.text.primary};
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border, box-shadow, fill;
|
||||
}
|
||||
&:hover svg {
|
||||
fill: ${props => props.theme.colors.text.secondary};
|
||||
}
|
||||
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
export const ClearButton = styled.div`
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
padding: 0 12px;
|
||||
margin-left: auto;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
border-radius: 6px;
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
transition-duration: 0.2s;
|
||||
transition-property: background, border, box-shadow, color, fill;
|
||||
color: ${props => props.theme.colors.text.primary};
|
||||
&:hover {
|
||||
color: ${props => props.theme.colors.text.secondary};
|
||||
}
|
||||
`;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, forwardRef } from 'react';
|
||||
import React, { useState, useEffect, forwardRef, useRef, useCallback } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import styled from 'styled-components';
|
||||
import DatePicker from 'react-datepicker';
|
||||
@ -8,11 +8,27 @@ 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';
|
||||
import {
|
||||
Wrapper,
|
||||
RemoveDueDate,
|
||||
DueDateInput,
|
||||
DueDatePickerWrapper,
|
||||
ConfirmAddDueDate,
|
||||
DateRangeInputs,
|
||||
AddDateRange,
|
||||
ActionIcon,
|
||||
ActionsWrapper,
|
||||
ClearButton,
|
||||
ActionsSeparator,
|
||||
ActionClock,
|
||||
ActionLabel,
|
||||
} from './Styles';
|
||||
import { Clock, Cross } from 'shared/icons';
|
||||
import Select from 'react-select/src/Select';
|
||||
|
||||
type DueDateManagerProps = {
|
||||
task: Task;
|
||||
onDueDateChange: (task: Task, newDueDate: Date) => void;
|
||||
onDueDateChange: (task: Task, newDueDate: Date, hasTime: boolean) => void;
|
||||
onRemoveDueDate: (task: Task) => void;
|
||||
onCancel: () => void;
|
||||
};
|
||||
@ -52,14 +68,20 @@ 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;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
& option {
|
||||
color: #c2c6dc;
|
||||
background: ${props => props.theme.colors.bg.primary};
|
||||
}
|
||||
|
||||
& option:hover {
|
||||
background: ${props => props.theme.colors.bg.secondary};
|
||||
border: 1px solid ${props => props.theme.colors.primary};
|
||||
outline: none !important;
|
||||
@ -110,15 +132,34 @@ const HeaderActions = styled.div`
|
||||
`;
|
||||
|
||||
const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange, onRemoveDueDate, onCancel }) => {
|
||||
const now = dayjs();
|
||||
const currentDueDate = task.dueDate ? dayjs(task.dueDate).toDate() : null;
|
||||
const { register, handleSubmit, errors, setValue, setError, formState, control } = useForm<DueDateFormData>();
|
||||
const [startDate, setStartDate] = useState(new Date());
|
||||
|
||||
const [startDate, setStartDate] = useState<Date | null>(currentDueDate);
|
||||
const [endDate, setEndDate] = useState<Date | null>(currentDueDate);
|
||||
const [hasTime, enableTime] = useState(task.hasTime ?? false);
|
||||
const firstRun = useRef<boolean>(true);
|
||||
|
||||
const debouncedFunctionRef = useRef((newDate: Date | null, nowHasTime: boolean) => {
|
||||
if (!firstRun.current) {
|
||||
if (newDate) {
|
||||
onDueDateChange(task, newDate, nowHasTime);
|
||||
} else {
|
||||
onRemoveDueDate(task);
|
||||
enableTime(false);
|
||||
}
|
||||
} else {
|
||||
firstRun.current = false;
|
||||
}
|
||||
});
|
||||
const debouncedChange = useCallback(
|
||||
_.debounce((newDate, nowHasTime) => debouncedFunctionRef.current(newDate, nowHasTime), 500),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const newDate = dayjs(startDate).format('YYYY-MM-DD');
|
||||
setValue('endDate', newDate);
|
||||
}, [startDate]);
|
||||
|
||||
debouncedChange(startDate, hasTime);
|
||||
}, [startDate, hasTime]);
|
||||
const years = _.range(2010, getYear(new Date()) + 10, 1);
|
||||
const months = [
|
||||
'January',
|
||||
@ -134,19 +175,21 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
|
||||
'November',
|
||||
'December',
|
||||
];
|
||||
const saveDueDate = (data: any) => {
|
||||
const newDate = dayjs(`${data.endDate} ${dayjs(data.endTime).format('h:mm A')}`, 'YYYY-MM-DD h:mm A');
|
||||
if (newDate.isValid()) {
|
||||
onDueDateChange(task, newDate.toDate());
|
||||
}
|
||||
|
||||
const onChange = (dates: any) => {
|
||||
const [start, end] = dates;
|
||||
setStartDate(start);
|
||||
setEndDate(end);
|
||||
};
|
||||
const CustomTimeInput = forwardRef(({ value, onClick }: any, $ref: any) => {
|
||||
const [isRange, setIsRange] = useState(false);
|
||||
|
||||
const CustomTimeInput = forwardRef(({ value, onClick, onChange, onBlur, onFocus }: any, $ref: any) => {
|
||||
return (
|
||||
<DueDateInput
|
||||
id="endTime"
|
||||
value={value}
|
||||
name="endTime"
|
||||
ref={$ref}
|
||||
onChange={onChange}
|
||||
width="100%"
|
||||
variant="alternate"
|
||||
label="Time"
|
||||
@ -154,114 +197,119 @@ const DueDateManager: React.FC<DueDateManagerProps> = ({ task, onDueDateChange,
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Form onSubmit={handleSubmit(saveDueDate)}>
|
||||
<FormField>
|
||||
<DueDateInput
|
||||
id="endDate"
|
||||
name="endDate"
|
||||
width="100%"
|
||||
variant="alternate"
|
||||
label="Date"
|
||||
defaultValue={now.format('YYYY-MM-DD')}
|
||||
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 />}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormField>
|
||||
<DueDatePickerWrapper>
|
||||
<DateRangeInputs>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => setStartDate(date)}
|
||||
popperClassName="picker-hidden"
|
||||
dateFormat="yyyy-MM-dd"
|
||||
disabledKeyboardNavigation
|
||||
isClearable
|
||||
placeholderText="Select due date"
|
||||
/>
|
||||
{isRange ? (
|
||||
<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))}
|
||||
>
|
||||
{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);
|
||||
}
|
||||
}}
|
||||
isClearable
|
||||
onChange={date => setStartDate(date)}
|
||||
popperClassName="picker-hidden"
|
||||
dateFormat="yyyy-MM-dd"
|
||||
placeholderText="Select from date"
|
||||
/>
|
||||
</DueDatePickerWrapper>
|
||||
<ActionWrapper>
|
||||
<ConfirmAddDueDate type="submit" onClick={NOOP}>
|
||||
Save
|
||||
</ConfirmAddDueDate>
|
||||
<RemoveDueDate
|
||||
variant="outline"
|
||||
color="danger"
|
||||
) : (
|
||||
<AddDateRange>Add date range</AddDateRange>
|
||||
)}
|
||||
</DateRangeInputs>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => setStartDate(date)}
|
||||
startDate={startDate}
|
||||
useWeekdaysShort
|
||||
renderCustomHeader={({
|
||||
date,
|
||||
changeYear,
|
||||
changeMonth,
|
||||
decreaseMonth,
|
||||
increaseMonth,
|
||||
prevMonthButtonDisabled,
|
||||
nextMonthButtonDisabled,
|
||||
}) => (
|
||||
<HeaderActions>
|
||||
<HeaderButton onClick={decreaseMonth} disabled={prevMonthButtonDisabled}>
|
||||
Prev
|
||||
</HeaderButton>
|
||||
<HeaderSelectLabel>
|
||||
{months[date.getMonth()]}
|
||||
<HeaderSelect
|
||||
value={months[getMonth(date)]}
|
||||
onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}
|
||||
>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</HeaderSelect>
|
||||
</HeaderSelectLabel>
|
||||
<HeaderSelectLabel>
|
||||
{date.getFullYear()}
|
||||
<HeaderSelect value={getYear(date)} onChange={({ target: { value } }) => changeYear(parseInt(value, 10))}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</HeaderSelect>
|
||||
</HeaderSelectLabel>
|
||||
|
||||
<HeaderButton onClick={increaseMonth} disabled={nextMonthButtonDisabled}>
|
||||
Next
|
||||
</HeaderButton>
|
||||
</HeaderActions>
|
||||
)}
|
||||
inline
|
||||
/>
|
||||
<ActionsSeparator />
|
||||
{hasTime && (
|
||||
<ActionsWrapper>
|
||||
<ActionClock width={16} height={16} />
|
||||
<ActionLabel>Due Time</ActionLabel>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => {
|
||||
setStartDate(date);
|
||||
}}
|
||||
showTimeSelect
|
||||
showTimeSelectOnly
|
||||
timeIntervals={15}
|
||||
timeCaption="Time"
|
||||
dateFormat="h:mm aa"
|
||||
/>
|
||||
<ActionIcon onClick={() => enableTime(false)}>
|
||||
<Cross width={16} height={16} />
|
||||
</ActionIcon>
|
||||
</ActionsWrapper>
|
||||
)}
|
||||
<ActionsWrapper>
|
||||
{!hasTime && (
|
||||
<ActionIcon
|
||||
onClick={() => {
|
||||
onRemoveDueDate(task);
|
||||
if (startDate === null) {
|
||||
const today = new Date();
|
||||
today.setHours(12, 30, 0);
|
||||
setStartDate(today);
|
||||
}
|
||||
enableTime(true);
|
||||
}}
|
||||
>
|
||||
Remove
|
||||
</RemoveDueDate>
|
||||
</ActionWrapper>
|
||||
</Form>
|
||||
<Clock width={16} height={16} />
|
||||
</ActionIcon>
|
||||
)}
|
||||
<ClearButton onClick={() => setStartDate(null)}>{hasTime ? 'Clear all' : 'Clear'}</ClearButton>
|
||||
</ActionsWrapper>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
@ -341,7 +341,9 @@ const TaskDetails: React.FC<TaskDetailsProps> = ({
|
||||
}}
|
||||
>
|
||||
{task.dueDate ? (
|
||||
<SidebarButtonText>{dayjs(task.dueDate).format('MMM D [at] h:mm A')}</SidebarButtonText>
|
||||
<SidebarButtonText>
|
||||
{dayjs(task.dueDate).format(task.hasTime ? 'MMM D [at] h:mm A' : 'MMMM D')}
|
||||
</SidebarButtonText>
|
||||
) : (
|
||||
<SidebarButtonText>No due date</SidebarButtonText>
|
||||
)}
|
||||
|
@ -215,6 +215,7 @@ export type Task = {
|
||||
position: Scalars['Float'];
|
||||
description?: Maybe<Scalars['String']>;
|
||||
dueDate?: Maybe<Scalars['Time']>;
|
||||
hasTime: Scalars['Boolean'];
|
||||
complete: Scalars['Boolean'];
|
||||
completedAt?: Maybe<Scalars['Time']>;
|
||||
assigned: Array<Member>;
|
||||
@ -883,6 +884,7 @@ export type UpdateTaskLocationPayload = {
|
||||
|
||||
export type UpdateTaskDueDate = {
|
||||
taskID: Scalars['UUID'];
|
||||
hasTime: Scalars['Boolean'];
|
||||
dueDate?: Maybe<Scalars['Time']>;
|
||||
};
|
||||
|
||||
@ -1451,7 +1453,7 @@ export type FindTaskQuery = (
|
||||
{ __typename?: 'Query' }
|
||||
& { findTask: (
|
||||
{ __typename?: 'Task' }
|
||||
& Pick<Task, 'id' | 'name' | 'description' | 'dueDate' | 'position' | 'complete'>
|
||||
& Pick<Task, 'id' | 'name' | 'description' | 'dueDate' | 'position' | 'complete' | 'hasTime'>
|
||||
& { taskGroup: (
|
||||
{ __typename?: 'TaskGroup' }
|
||||
& Pick<TaskGroup, 'id' | 'name'>
|
||||
@ -2314,6 +2316,7 @@ export type UpdateTaskDescriptionMutation = (
|
||||
export type UpdateTaskDueDateMutationVariables = Exact<{
|
||||
taskID: Scalars['UUID'];
|
||||
dueDate?: Maybe<Scalars['Time']>;
|
||||
hasTime: Scalars['Boolean'];
|
||||
}>;
|
||||
|
||||
|
||||
@ -2321,7 +2324,7 @@ export type UpdateTaskDueDateMutation = (
|
||||
{ __typename?: 'Mutation' }
|
||||
& { updateTaskDueDate: (
|
||||
{ __typename?: 'Task' }
|
||||
& Pick<Task, 'id' | 'dueDate'>
|
||||
& Pick<Task, 'id' | 'dueDate' | 'hasTime'>
|
||||
) }
|
||||
);
|
||||
|
||||
@ -3017,6 +3020,7 @@ export const FindTaskDocument = gql`
|
||||
dueDate
|
||||
position
|
||||
complete
|
||||
hasTime
|
||||
taskGroup {
|
||||
id
|
||||
name
|
||||
@ -4692,10 +4696,13 @@ export type UpdateTaskDescriptionMutationHookResult = ReturnType<typeof useUpdat
|
||||
export type UpdateTaskDescriptionMutationResult = ApolloReactCommon.MutationResult<UpdateTaskDescriptionMutation>;
|
||||
export type UpdateTaskDescriptionMutationOptions = ApolloReactCommon.BaseMutationOptions<UpdateTaskDescriptionMutation, UpdateTaskDescriptionMutationVariables>;
|
||||
export const UpdateTaskDueDateDocument = gql`
|
||||
mutation updateTaskDueDate($taskID: UUID!, $dueDate: Time) {
|
||||
updateTaskDueDate(input: {taskID: $taskID, dueDate: $dueDate}) {
|
||||
mutation updateTaskDueDate($taskID: UUID!, $dueDate: Time, $hasTime: Boolean!) {
|
||||
updateTaskDueDate(
|
||||
input: {taskID: $taskID, dueDate: $dueDate, hasTime: $hasTime}
|
||||
) {
|
||||
id
|
||||
dueDate
|
||||
hasTime
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -4716,6 +4723,7 @@ export type UpdateTaskDueDateMutationFn = ApolloReactCommon.MutationFunction<Upd
|
||||
* variables: {
|
||||
* taskID: // value for 'taskID'
|
||||
* dueDate: // value for 'dueDate'
|
||||
* hasTime: // value for 'hasTime'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
@ -5167,4 +5175,4 @@ export function useUsersLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOp
|
||||
}
|
||||
export type UsersQueryHookResult = ReturnType<typeof useUsersQuery>;
|
||||
export type UsersLazyQueryHookResult = ReturnType<typeof useUsersLazyQuery>;
|
||||
export type UsersQueryResult = ApolloReactCommon.QueryResult<UsersQuery, UsersQueryVariables>;
|
||||
export type UsersQueryResult = ApolloReactCommon.QueryResult<UsersQuery, UsersQueryVariables>;
|
@ -6,6 +6,7 @@ query findTask($taskID: UUID!) {
|
||||
dueDate
|
||||
position
|
||||
complete
|
||||
hasTime
|
||||
taskGroup {
|
||||
id
|
||||
name
|
||||
|
@ -1,11 +1,13 @@
|
||||
mutation updateTaskDueDate($taskID: UUID!, $dueDate: Time) {
|
||||
mutation updateTaskDueDate($taskID: UUID!, $dueDate: Time, $hasTime: Boolean!) {
|
||||
updateTaskDueDate (
|
||||
input: {
|
||||
taskID: $taskID
|
||||
dueDate: $dueDate
|
||||
hasTime: $hasTime
|
||||
}
|
||||
) {
|
||||
id
|
||||
dueDate
|
||||
hasTime
|
||||
}
|
||||
}
|
||||
|
1
frontend/src/types.d.ts
vendored
1
frontend/src/types.d.ts
vendored
@ -102,6 +102,7 @@ type Task = {
|
||||
name: string;
|
||||
badges?: TaskBadges;
|
||||
position: number;
|
||||
hasTime?: boolean;
|
||||
dueDate?: string;
|
||||
complete?: boolean;
|
||||
completedAt?: string | null;
|
||||
|
Reference in New Issue
Block a user