@material-ui/pickers#MuiPickersUtilsProvider TypeScript Examples

The following examples show how to use @material-ui/pickers#MuiPickersUtilsProvider. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: TestContext.tsx    From office-booker with MIT License 6 votes vote down vote up
TestContext: React.FC<{ user?: User; config?: Config }> = ({
  children,
  user,
  config,
}) => (
  <StylesProvider injectFirst>
    <StyledThemeProvider theme={MaterialTheme}>
      <MaterialThemeProvider theme={MaterialTheme}>
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
          <AppProvider initialState={{ user, config }}>
            <Structure>{children}</Structure>
          </AppProvider>
        </MuiPickersUtilsProvider>
      </MaterialThemeProvider>
    </StyledThemeProvider>
  </StylesProvider>
)
Example #2
Source File: Root.tsx    From office-booker with MIT License 6 votes vote down vote up
Root: React.FC = () => (
  <StylesProvider injectFirst>
    <StyledThemeProvider theme={MaterialTheme}>
      <MaterialThemeProvider theme={MaterialTheme}>
        <CssBaseline />
        <StyledGlobal />

        <MuiPickersUtilsProvider utils={DateFnsUtils}>
          <ErrorBoundary>
            <AppProvider>
              <Structure>
                <Routes />
              </Structure>
            </AppProvider>
          </ErrorBoundary>
        </MuiPickersUtilsProvider>
      </MaterialThemeProvider>
    </StyledThemeProvider>
  </StylesProvider>
)
Example #3
Source File: root.tsx    From keycaplendar with MIT License 6 votes vote down vote up
Root = () => (
  <Provider store={store}>
    <MuiPickersUtilsProvider utils={LocalizedUtils}>
      <ThemeProvider>
        <RMWCProvider tooltip={{ align: "bottom", enterDelay: 500 }}>
          <App />
        </RMWCProvider>
      </ThemeProvider>
    </MuiPickersUtilsProvider>
  </Provider>
)
Example #4
Source File: DatePickerElement.test.tsx    From react-hook-form-mui with MIT License 6 votes vote down vote up
it('renders without crashing', () => {
  const div = document.createElement('div')
  ReactDOM.render(
    <MuiPickersUtilsProvider utils={LocalizedUtils}>
      <FormContainer
        onSuccess={() => console.log('success')}
        defaultValues={''}
      >
        <DatePickerElement
          label="The DatePickerElement label"
          name={'basic date picker'}
          fullWidth
          openTo="year"
        />
      </FormContainer>
    </MuiPickersUtilsProvider>,
    div
  )
  ReactDOM.unmountComponentAtNode(div)
})
Example #5
Source File: DateSelector.tsx    From backstage with Apache License 2.0 6 votes vote down vote up
DateSelector = ({ name, control, setValue }: Props) => {
  const label = `${
    name.charAt(0).toLocaleUpperCase('en-US') + name.slice(1, name.indexOf('D'))
  } date`;

  return (
    <Controller
      name={name}
      control={control}
      render={({ field }) => (
        <FormControl>
          <MuiPickersUtilsProvider utils={LuxonUtils}>
            <KeyboardDatePicker
              disableToolbar
              format="dd-MM-yyyy"
              label={label}
              value={field.value}
              onChange={date => {
                setValue(name, date?.toISO());
              }}
              InputProps={{
                endAdornment: (
                  <IconButton onClick={() => setValue(name, null)}>
                    <ClearIcon />
                  </IconButton>
                ),
              }}
              InputAdornmentProps={{
                position: 'start',
              }}
            />
          </MuiPickersUtilsProvider>
        </FormControl>
      )}
    />
  );
}
Example #6
Source File: TableCell.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
export default function Date_({
  rowIdx,
  column,
  value,
  onSubmit,
  disabled,
}: IHeavyCellProps) {
  const classes = useStyles();
  const { dataGridRef } = useFiretableContext();

  const transformedValue = transformValue(value);

  const [handleDateChange] = useDebouncedCallback<DatePickerProps["onChange"]>(
    (date) => {
      const sanitized = sanitizeValue(date);
      if (sanitized === undefined) return;

      onSubmit(sanitized);
      if (dataGridRef?.current?.selectCell)
        dataGridRef.current.selectCell({ rowIdx, idx: column.idx });
    },
    500
  );

  if (disabled)
    return (
      <div className={classes.disabledCell}>
        <BasicCell
          value={value}
          type={(column as any).type}
          name={column.key}
        />
      </div>
    );

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <KeyboardDatePicker
        value={transformedValue}
        onChange={handleDateChange}
        onClick={(e) => e.stopPropagation()}
        format={column.config?.format ?? DATE_FORMAT}
        fullWidth
        clearable
        keyboardIcon={<DateIcon />}
        className={clsx("cell-collapse-padding", classes.root)}
        inputVariant="standard"
        InputProps={{
          disableUnderline: true,
          classes: { root: classes.inputBase, input: classes.input },
        }}
        InputAdornmentProps={{
          position: "start",
          classes: { root: classes.inputAdornment },
        }}
        KeyboardButtonProps={{
          size: "small",
          classes: { root: !disabled ? "row-hover-iconButton" : undefined },
        }}
        DialogProps={{ onClick: (e) => e.stopPropagation() }}
        disabled={disabled}
      />
    </MuiPickersUtilsProvider>
  );
}
Example #7
Source File: TimePicker.tsx    From glific-frontend with GNU Affero General Public License v3.0 5 votes vote down vote up
TimePicker: React.SFC<TimePickerProps> = ({
  variant = 'inline',
  inputVariant = 'outlined',
  field,
  form: { setFieldValue, touched, errors },
  placeholder,
  disabled = false,
  helperText,
}) => {
  moment.defaultFormat = 'Thh:mm:ss';
  const dateValue = field.value ? moment(field.value, moment.defaultFormat).toDate() : null;
  const [open, setOpen] = useState(false);

  const errorText = getIn(errors, field.name);
  const touchedVal = getIn(touched, field.name);
  const hasError = touchedVal && errorText !== undefined;

  const handleDateChange = (time: Date | null) => {
    const value = time ? moment(time).format('THH:mm:ss') : null;
    setFieldValue(field.name, value);
  };

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <Grid className={styles.TimePicker}>
        <KeyboardTimePicker
          error={hasError}
          autoOk
          open={open}
          variant={variant}
          inputVariant={inputVariant}
          label={placeholder}
          data-testid="time-picker"
          mask="__:__ _M"
          value={dateValue}
          onClick={() => !disabled && setOpen(true)}
          onClose={() => setOpen(false)}
          disabled={disabled}
          onChange={(date) => handleDateChange(date)}
          keyboardIcon={<ScheduleIcon />}
          helperText={hasError ? errorText : ''}
          className={styles.picker}
        />
        {helperText && (
          <div id="helper-text" className={styles.HelperText}>
            {helperText}
          </div>
        )}
      </Grid>
    </MuiPickersUtilsProvider>
  );
}
Example #8
Source File: DateTimePicker.tsx    From glific-frontend with GNU Affero General Public License v3.0 5 votes vote down vote up
DateTimePicker: React.SFC<DateTimePickerProps> = ({
  variant = 'inline',
  inputVariant = 'outlined',
  format = 'dd/MM/yyyy hh:mm a',
  field,
  form: { touched, errors, setFieldValue },
  placeholder,
  minDate,
  onChange,
}) => {
  const errorText = getIn(errors, field.name);
  const touchedVal = getIn(touched, field.name);
  const hasError = touchedVal && errorText !== undefined;
  const dateValue = field.value ? field.value : null;

  const handleDateChange = (date: Date | null | string) => {
    const value = date && date.toString() !== 'Invalid Date' ? date : null;
    setFieldValue(field.name, value);
    if (onChange) onChange(value);
  };

  const icon = <CalenderIcon />;
  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <Grid className={styles.DateTimePicker}>
        <KeyboardDateTimePicker
          className={styles.Text}
          error={hasError}
          autoOk
          variant={variant}
          inputVariant={inputVariant}
          format={format}
          data-testid="date-picker-inline"
          label={placeholder}
          value={dateValue}
          onChange={handleDateChange}
          helperText={hasError ? errorText : ''}
          minDate={minDate}
          keyboardIcon={icon}
        />
      </Grid>
    </MuiPickersUtilsProvider>
  );
}
Example #9
Source File: Calendar.tsx    From glific-frontend with GNU Affero General Public License v3.0 5 votes vote down vote up
Calendar: React.SFC<CalendarProps> = ({
  variant = 'inline',
  inputVariant = 'outlined',
  format = 'MM/dd/yyyy',
  field,
  disabled = false,
  form: { touched, errors, setFieldValue },
  placeholder,
  minDate,
}) => {
  const errorText = getIn(errors, field.name);
  const touchedVal = getIn(touched, field.name);
  const hasError = touchedVal && errorText !== undefined;
  const dateValue = field.value ? field.value : null;
  const [open, setOpen] = useState(false);

  const handleDateChange = (date: Date | null | string) => {
    if (date) {
      if (date !== 'Invalid Date') setFieldValue(field.name, date);
    } else {
      setFieldValue(field.name, null);
    }
  };

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <Grid className={styles.Calendar}>
        <KeyboardDatePicker
          error={hasError}
          autoOk
          open={open}
          variant={variant}
          inputVariant={inputVariant}
          format={format}
          className={styles.CalendarInput}
          disabled={disabled}
          data-testid="date-picker-inline"
          label={placeholder}
          value={dateValue}
          onClick={() => !disabled && setOpen(true)}
          onClose={() => setOpen(false)}
          onChange={handleDateChange}
          helperText={hasError ? errorText : ''}
          minDate={minDate}
        />
      </Grid>
    </MuiPickersUtilsProvider>
  );
}
Example #10
Source File: DatePickerComponent.web.tsx    From react-native-jigsaw with MIT License 5 votes vote down vote up
DatePickerComponent: React.FC<Props & { theme: typeof Theme }> = ({
  value,
  onChange,
  mode,
  toggleVisibility,
  isVisible,
  theme,
}) => {
  const internalTheme = createMuiTheme({
    palette: {
      primary: {
        main: theme?.colors?.primary ?? Theme.colors.primary,
      },
      secondary: {
        main: theme?.colors?.secondary ?? Theme.colors.secondary,
      },
    },
  });

  const Picker =
    mode === "date"
      ? DatePicker
      : mode === "time"
      ? TimePicker
      : DateTimePicker;

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <ThemeProvider theme={internalTheme}>
        <Picker
          value={value}
          open={isVisible}
          onChange={(d) => {
            toggleVisibility();
            onChange(null, d);
          }}
          onClose={() => toggleVisibility()}
          variant="dialog"
          TextFieldComponent={() => null}
        />
      </ThemeProvider>
    </MuiPickersUtilsProvider>
  );
}
Example #11
Source File: FilterControls.tsx    From clearflask with Apache License 2.0 5 votes vote down vote up
FilterControlDateRange = (props: {
  valueFrom?: Date;
  onFromChanged: (val?: Date) => void;
  valueTo?: Date;
  onToChanged: (val?: Date) => void;
}) => {
  const classes = useStyles();

  // const prefilledDates: Array<{
  //   label: string,
  //   start?: Date,
  //   end?: Date,
  // }> = [
  //     { label: 'Today', start: moment().startOf('day').toDate(), end: moment().endOf('day').toDate() },
  //     { label: 'This week', start: moment().startOf('week').toDate(), end: moment().endOf('week').toDate() },
  //     { label: 'This month', start: moment().startOf('month').toDate(), end: moment().endOf('month').toDate() },
  //     { label: 'All time' },
  //     { label: 'Past week', start: moment().startOf('week').toDate(), end: moment().endOf('week').toDate() },
  //     { label: 'Past month', start: moment().startOf('month').toDate(), end: moment().endOf('month').toDate() },
  //   ];
  return (
    <MuiPickersUtilsProvider utils={MomentUtils} locale='en'>
      <div className={classes.group}>
        <FilterControlTitle name='Range' />
        <div className={classes.datesVertical}>
          <FilterControlDatePicker
            name='From'
            value={props.valueFrom}
            onChanged={props.onFromChanged}
            type='past'
          />
          <FilterControlDatePicker
            name='To'
            value={props.valueTo}
            onChanged={props.onToChanged}
            type='past'
          />
        </div>
        {/* <div className={this.props.classes.dateButtons}>
        {prefilledDates.map((prefilledDate, index) => {
          const checked = prefilledDate.start?.getTime() === from?.getTime() && prefilledDate.end?.getTime() === to?.getTime();
          return (
            <Button
              key={`prefilledDate-${prefilledDate.label}`}
              className={this.props.classes.dateButton}
              variant='text'
              color={!!checked ? 'primary' : undefined}
              onClick={e => {
                const newSearch: Admin.IdeaSearchAdmin = {
                  ...this.props.search,
                  filterCreatedStart: prefilledDate.start,
                  filterCreatedEnd: prefilledDate.end,
                }
                this.props.onSearchChanged(newSearch);
              }}
            >
              {prefilledDate.label}
            </Button>
          )
        })}
      </div> */}
      </div>
    </MuiPickersUtilsProvider>
  );
}
Example #12
Source File: index.tsx    From aqualink-app with MIT License 5 votes vote down vote up
DatePicker = ({
  value,
  dateName,
  dateNameTextVariant,
  pickerSize,
  autoOk,
  timeZone,
  onChange,
  classes,
}: DatePickerProps) => {
  return (
    <Grid item>
      <Box display="flex" alignItems="flex-end">
        <Typography variant={dateNameTextVariant || "h6"} color="textSecondary">
          {`${dateName || "Date"}:`}
        </Typography>
        <div className={classes.datePicker}>
          <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <KeyboardDatePicker
              size={pickerSize}
              className={classes.textField}
              helperText=""
              disableToolbar
              format="MM/dd/yyyy"
              name="datePicker"
              maxDate={moment()
                .tz(timeZone || "UTC")
                .format("YYYY/MM/DD")}
              minDate={moment(0).format("YYYY/MM/DD")}
              autoOk={autoOk}
              showTodayButton
              value={value || null}
              onChange={onChange}
              InputProps={{
                className: classes.textField,
                inputProps: { className: classes.smallPadding },
              }}
              inputVariant="standard"
              KeyboardButtonProps={{ className: classes.calendarButton }}
              keyboardIcon={<CalendarTodayIcon fontSize="small" />}
            />
          </MuiPickersUtilsProvider>
        </div>
      </Box>
    </Grid>
  );
}
Example #13
Source File: TableCell.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
export default function DateTime({
  rowIdx,
  column,
  value,
  onSubmit,
  disabled,
}: IHeavyCellProps) {
  const classes = useStyles();
  const { dataGridRef } = useFiretableContext();

  const transformedValue = transformValue(value);

  const [handleDateChange] = useDebouncedCallback<DatePickerProps["onChange"]>(
    (date) => {
      const sanitized = sanitizeValue(date);
      if (sanitized === undefined) return;

      onSubmit(sanitized);
      if (dataGridRef?.current?.selectCell)
        dataGridRef.current.selectCell({ rowIdx, idx: column.idx });
    },
    500
  );

  if (disabled)
    return (
      <div className={classes.disabledCell}>
        <BasicCell
          value={value}
          type={(column as any).type}
          name={column.key}
        />
      </div>
    );

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <KeyboardDateTimePicker
        value={transformedValue}
        onChange={handleDateChange}
        onClick={(e) => e.stopPropagation()}
        format={DATE_TIME_FORMAT}
        fullWidth
        clearable
        keyboardIcon={<DateTimeIcon />}
        className={clsx("cell-collapse-padding", classes.root)}
        inputVariant="standard"
        InputProps={{
          disableUnderline: true,
          classes: { root: classes.inputBase, input: classes.input },
        }}
        InputAdornmentProps={{
          position: "start",
          classes: { root: classes.inputAdornment },
        }}
        KeyboardButtonProps={{
          size: "small",
          classes: { root: "row-hover-iconButton" },
        }}
        DialogProps={{ onClick: (e) => e.stopPropagation() }}
        dateRangeIcon={<DateRangeIcon className={classes.dateTabIcon} />}
        timeIcon={<TimeIcon className={classes.dateTabIcon} />}
      />
    </MuiPickersUtilsProvider>
  );
}
Example #14
Source File: SideDrawerField.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
export default function DateTime({
  column,
  control,
  docRef,
  disabled,
  ...props
}: IDateTimeProps) {
  const theme = useTheme();

  return (
    <Controller
      control={control}
      name={column.key}
      render={({ onChange, onBlur, value }) => {
        const transformedValue = transformValue(value);

        const handleChange = (date: Date | null) => {
          const sanitized = sanitizeValue(date);
          if (sanitized === undefined) return;
          onChange(sanitized);
        };

        return (
          <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <KeyboardDateTimePicker
              variant="inline"
              inputVariant="filled"
              fullWidth
              margin="none"
              format={DATE_TIME_FORMAT}
              placeholder={DATE_TIME_FORMAT}
              InputAdornmentProps={{
                style: { marginRight: theme.spacing(-1) },
              }}
              keyboardIcon={<TimeIcon />}
              {...props}
              value={transformedValue}
              onChange={handleChange}
              onBlur={onBlur}
              label=""
              hiddenLabel
              id={`sidedrawer-field-${column.key}`}
              dateRangeIcon={
                <DateRangeIcon
                  style={{ color: theme.palette.primary.contrastText }}
                />
              }
              timeIcon={
                <TimeIcon
                  style={{ color: theme.palette.primary.contrastText }}
                />
              }
              disabled={disabled}
            />
          </MuiPickersUtilsProvider>
        );
      }}
    />
  );
}
Example #15
Source File: SideDrawerField.tsx    From firetable with Apache License 2.0 5 votes vote down vote up
export default function Date_({
  column,
  control,
  docRef,
  disabled,
  ...props
}: IDateProps) {
  const theme = useTheme();

  return (
    <MuiPickersUtilsProvider utils={DateFnsUtils}>
      <Controller
        control={control}
        name={column.key}
        render={({ onChange, onBlur, value }) => {
          const transformedValue = transformValue(value);

          const handleChange = (date: Date | null) => {
            const sanitized = sanitizeValue(date);
            if (sanitized === undefined) return;
            onChange(sanitized);
          };

          return (
            <KeyboardDatePicker
              variant="inline"
              inputVariant="filled"
              fullWidth
              margin="none"
              format={column.config?.format ?? DATE_FORMAT}
              placeholder={column.config?.format ?? DATE_FORMAT}
              InputAdornmentProps={{
                style: { marginRight: theme.spacing(-1) },
              }}
              {...props}
              value={transformedValue}
              onChange={handleChange}
              onBlur={onBlur}
              label=""
              hiddenLabel
              // TODO: move this out to side drawer
              id={`sidedrawer-field-${column.key}`}
              disabled={disabled}
            />
          );
        }}
      />
    </MuiPickersUtilsProvider>
  );
}
Example #16
Source File: ShiftOverrideModal.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
ShiftOverrideModal = ({
  scheduleId,
  shift,
  refetchOnCallSchedules,
  isModalOpened,
  setIsModalOpened,
}: {
  scheduleId: number;
  shift: Shift;
  refetchOnCallSchedules: () => void;
  isModalOpened: boolean;
  setIsModalOpened: (isModalOpened: boolean) => void;
}) => {
  const [
    { isLoading, users, user, start, end },
    { setUser, setStart, setEnd, setIsLoading },
  ] = useShiftOverride(shift, isModalOpened);
  const ilertApi = useApi(ilertApiRef);
  const alertApi = useApi(alertApiRef);
  const classes = useStyles();

  const handleClose = () => {
    setIsModalOpened(false);
  };

  const handleOverride = () => {
    if (!shift || !shift.user) {
      return;
    }
    setIsLoading(true);
    setTimeout(async () => {
      try {
        const success = await ilertApi.overrideShift(
          scheduleId,
          user.id,
          start,
          end,
        );
        if (success) {
          alertApi.post({ message: 'Shift overridden.' });
          refetchOnCallSchedules();
        }
      } catch (err) {
        alertApi.post({ message: err, severity: 'error' });
      }
      setIsModalOpened(false);
    }, 250);
  };

  if (!shift) {
    return null;
  }

  return (
    <Dialog
      open={isModalOpened}
      onClose={handleClose}
      aria-labelledby="override-shift-form-title"
    >
      <DialogTitle id="override-shift-form-title">Shift override</DialogTitle>
      <DialogContent>
        <MuiPickersUtilsProvider utils={LuxonUtils}>
          <Autocomplete
            disabled={isLoading}
            options={users}
            value={user}
            classes={{
              root: classes.formControl,
              option: classes.option,
            }}
            onChange={(_event: any, newValue: any) => {
              setUser(newValue);
            }}
            autoHighlight
            getOptionLabel={a => ilertApi.getUserInitials(a)}
            renderOption={a => (
              <div className={classes.optionWrapper}>
                <Typography noWrap>{ilertApi.getUserInitials(a)}</Typography>
              </div>
            )}
            renderInput={params => (
              <TextField
                {...params}
                label="User"
                variant="outlined"
                fullWidth
                inputProps={{
                  ...params.inputProps,
                  autoComplete: 'new-password', // disable autocomplete and autofill
                }}
              />
            )}
          />
          <DateTimePicker
            label="Start"
            inputVariant="outlined"
            fullWidth
            margin="normal"
            ampm={false}
            value={start}
            className={classes.formControl}
            onChange={date => {
              setStart(date ? date.toISO() : '');
            }}
          />
          <DateTimePicker
            label="End"
            inputVariant="outlined"
            fullWidth
            margin="normal"
            ampm={false}
            value={end}
            className={classes.formControl}
            onChange={date => {
              setEnd(date ? date.toISO() : '');
            }}
          />
        </MuiPickersUtilsProvider>
      </DialogContent>
      <DialogActions>
        <Button
          disabled={isLoading}
          onClick={handleOverride}
          color="primary"
          variant="contained"
        >
          Override
        </Button>
        <Button disabled={isLoading} onClick={handleClose} color="primary">
          Cancel
        </Button>
      </DialogActions>
    </Dialog>
  );
}
Example #17
Source File: chart-filters.tsx    From backstage with Apache License 2.0 4 votes vote down vote up
export function ChartFilters(props: ChartFiltersProps) {
  const {
    analysis,
    cicdConfiguration,
    initialFetchFilter,
    currentFetchFilter,
    onChangeFetchFilter,
    updateFetchFilter,
    initialViewOptions,
    onChangeViewOptions,
  } = props;

  const classes = useStyles();

  const [internalRef] = useState<InternalRef>({ first: true });

  const [useNowAsToDate, setUseNowAsToDate] = useState(true);
  const [toDate, setToDate] = useState(initialFetchFilter.toDate);
  const [fromDate, setFromDate] = useState(initialFetchFilter.fromDate);

  const [branch, setBranch] = useState(initialFetchFilter.branch);

  const statusValues: ReadonlyArray<StatusSelection> =
    cicdConfiguration.availableStatuses;
  const [selectedStatus, setSelectedStatus] = useState(
    initialFetchFilter.status,
  );

  const [viewOptions, setViewOptions] = useState(initialViewOptions);

  const setLowercaseNames = useCallback(
    (lowercaseNames: boolean) => {
      setViewOptions(old => ({ ...old, lowercaseNames }));
    },
    [setViewOptions],
  );

  const setNormalizeTimeRange = useCallback(
    (normalizeTimeRange: boolean) => {
      setViewOptions(old => ({ ...old, normalizeTimeRange }));
    },
    [setViewOptions],
  );

  const setHideLimit = useCallback(
    (value: number) => {
      setViewOptions(old => ({ ...old, hideLimit: value }));
    },
    [setViewOptions],
  );

  const setCollapseLimit = useCallback(
    (value: number) => {
      setViewOptions(old => ({ ...old, collapsedLimit: value }));
    },
    [setViewOptions],
  );

  const setChartType = useCallback(
    (statusType: FilterStatusType, chartTypes: ChartTypes) => {
      setViewOptions(old => ({
        ...old,
        chartTypes: { ...old.chartTypes, [statusType]: chartTypes },
      }));
    },
    [setViewOptions],
  );
  const setChartTypeSpecific = useMemo(
    () =>
      Object.fromEntries(
        statusTypes.map(
          status =>
            [
              status,
              (chartTypes: ChartTypes) => setChartType(status, chartTypes),
            ] as const,
        ),
      ),
    [setChartType],
  );

  useEffect(() => {
    onChangeViewOptions(viewOptions);
  }, [onChangeViewOptions, viewOptions]);

  useEffect(() => {
    if (internalRef.first) {
      // Skip calling onChangeFetchFilter first time
      internalRef.first = false;
      return;
    }
    onChangeFetchFilter({
      toDate,
      fromDate,
      branch,
      status: selectedStatus,
    });
  }, [
    internalRef,
    toDate,
    fromDate,
    branch,
    selectedStatus,
    onChangeFetchFilter,
  ]);

  const toggleUseNowAsDate = useCallback(() => {
    setUseNowAsToDate(!useNowAsToDate);
    if (!DateTime.fromJSDate(toDate).hasSame(DateTime.now(), 'day')) {
      setToDate(new Date());
    }
  }, [useNowAsToDate, toDate]);

  const hasFetchFilterChanges = useMemo(
    () =>
      !currentFetchFilter ||
      !isSameChartFilter(
        {
          toDate,
          fromDate,
          branch,
          status: selectedStatus,
        },
        currentFetchFilter,
      ),
    [toDate, fromDate, branch, selectedStatus, currentFetchFilter],
  );

  const updateFilter = useCallback(() => {
    updateFetchFilter({
      toDate,
      fromDate,
      branch,
      status: selectedStatus,
    });
  }, [toDate, fromDate, branch, selectedStatus, updateFetchFilter]);

  const inrefferedStatuses = analysis?.statuses ?? selectedStatus;

  return (
    <MuiPickersUtilsProvider utils={LuxonUtils}>
      <Card className={classes.rootCard}>
        <CardHeader
          action={
            <Button
              size="small"
              color="secondary"
              variant="contained"
              onClick={updateFilter}
              disabled={!hasFetchFilterChanges}
            >
              Update
            </Button>
          }
          title={
            <Typography variant="subtitle2" className={classes.header}>
              Fetching options
            </Typography>
          }
        />
        <CardContent>
          <Typography
            variant="subtitle2"
            className={`${classes.title} ${classes.title}`}
          >
            Date range
          </Typography>
          <KeyboardDatePicker
            autoOk
            variant="inline"
            inputVariant="outlined"
            label="From date"
            format="yyyy-MM-dd"
            value={fromDate}
            InputAdornmentProps={{ position: 'start' }}
            onChange={date => setFromDate(date?.toJSDate() ?? new Date())}
          />
          <br />
          <FormControl component="fieldset">
            <FormGroup>
              <FormControlLabel
                control={
                  <Switch
                    checked={useNowAsToDate}
                    onChange={toggleUseNowAsDate}
                  />
                }
                label={<Label>To today</Label>}
              />
              {useNowAsToDate ? null : (
                <KeyboardDatePicker
                  autoOk
                  variant="inline"
                  inputVariant="outlined"
                  label="To date"
                  format="yyyy-MM-dd"
                  value={toDate}
                  InputAdornmentProps={{ position: 'start' }}
                  onChange={date => setToDate(date?.toJSDate() ?? new Date())}
                />
              )}
            </FormGroup>
          </FormControl>
          <Typography
            variant="subtitle2"
            className={`${classes.title} ${classes.title}`}
          >
            Branch
          </Typography>
          <ButtonSwitch<string>
            values={branchValues}
            selection={branch}
            onChange={setBranch}
          />
          <Typography
            variant="subtitle2"
            className={`${classes.title} ${classes.title}`}
          >
            Status
          </Typography>
          <ButtonSwitch<string>
            values={statusValues}
            multi
            vertical
            selection={selectedStatus}
            onChange={setSelectedStatus}
          />
        </CardContent>
      </Card>
      <Card className={classes.rootCard}>
        <CardHeader
          title={
            <Typography variant="subtitle2" className={classes.header}>
              View options
            </Typography>
          }
        />
        <CardContent>
          <Toggle
            checked={viewOptions.lowercaseNames}
            setChecked={setLowercaseNames}
          >
            <Tooltip
              arrow
              title={
                'Lowercasing names can reduce duplications ' +
                'when stage names have changed casing'
              }
            >
              <Label>Lowercase names</Label>
            </Tooltip>
          </Toggle>
          <Toggle
            checked={viewOptions.normalizeTimeRange}
            setChecked={setNormalizeTimeRange}
          >
            <Tooltip
              arrow
              title={
                'All charts will use the same x-axis. ' +
                'This reduces confusion when stages have been altered over time ' +
                'and only appear in a part of the time range.'
              }
            >
              <Label>Normalize time range</Label>
            </Tooltip>
          </Toggle>
          <DurationSlider
            header="Hide under peak"
            value={viewOptions.hideLimit}
            setValue={setHideLimit}
          />
          <DurationSlider
            header="Collapse under peak"
            value={viewOptions.collapsedLimit}
            setValue={setCollapseLimit}
          />
          <Typography
            variant="subtitle2"
            className={`${classes.title} ${classes.title}`}
          >
            Chart styles
          </Typography>
          {inrefferedStatuses.map(status => (
            <Grid key={status} container spacing={0}>
              <Grid item>
                <ButtonSwitch<ChartType>
                  values={chartTypeValues}
                  selection={viewOptions.chartTypes[status as FilterStatusType]}
                  onChange={setChartTypeSpecific[status]}
                  multi
                />
              </Grid>
              <Grid item className={classes.buttonDescription}>
                <div>{status}</div>
              </Grid>
            </Grid>
          ))}
        </CardContent>
      </Card>
    </MuiPickersUtilsProvider>
  );
}
Example #18
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
Form = ({
  siteName,
  application,
  agreed,
  handleFormSubmit,
  classes,
}: FormProps) => {
  const [installationSchedule, setInstallationSchedule] = useState<Date | null>(
    null
  );

  useEffect(() => {
    if (application?.installationSchedule) {
      setInstallationSchedule(new Date(application.installationSchedule));
    }
  }, [application]);

  const { register, errors, handleSubmit } = useForm({
    reValidateMode: "onSubmit",
  });

  const handleInstalationChange = (date: Date | null) => {
    if (date) {
      setInstallationSchedule(date);
    }
  };

  const formSubmit = useCallback(
    (data: any) => {
      const params: SiteApplyParams = {
        fundingSource: data.fundingSource,
        permitRequirements: data.permitRequirements,
        installationResources: data.installationResources,
        installationSchedule: new Date(data.installationSchedule).toISOString(),
      };
      handleFormSubmit(data.siteName, params);
    },
    [handleFormSubmit]
  );

  return (
    <form className={classes.form} onSubmit={handleSubmit(formSubmit)}>
      <Typography className={classes.formTitle} variant="h3">
        Your Site
      </Typography>

      <TextField
        className={`${classes.formField} ${classes.textField}`}
        variant="outlined"
        inputProps={{ className: classes.textField }}
        fullWidth
        placeholder="Site Name e.g. 'Sombrero Site'"
        disabled
        defaultValue={siteName}
        name="siteName"
        inputRef={register({
          required: "This is a required field",
        })}
        error={!!errors.siteName}
        helperText={errors?.siteName?.message || ""}
      />

      <Typography className={classes.additionalInfo}>
        Please provide some additional information for each site:
      </Typography>

      <Typography>Permitting</Typography>
      <TextField
        className={`${classes.formField} ${classes.textField}`}
        variant="outlined"
        inputProps={{ className: classes.textField }}
        fullWidth
        multiline
        rows={2}
        defaultValue={application?.permitRequirements || null}
        placeholder="Please describe the permitting requirements. Please be sure to mention the authority having jurisdiction"
        name="permitRequirements"
        inputRef={register({
          required: "This is a required field",
        })}
        error={!!errors.permitRequirements}
        helperText={errors?.permitRequirements?.message || ""}
      />

      <Typography>Funding Source</Typography>
      <TextField
        className={`${classes.formField} ${classes.textField}`}
        variant="outlined"
        inputProps={{ className: classes.textField }}
        fullWidth
        multiline
        rows={2}
        defaultValue={application?.fundingSource || null}
        placeholder="Funding source for import duties and shipping. Please describe the funding source for the import duties and shipping costs"
        name="fundingSource"
        inputRef={register({
          required: "This is a required field",
        })}
        error={!!errors.fundingSource}
        helperText={errors?.fundingSource?.message || ""}
      />

      <Typography>Schedule for installation</Typography>
      <Typography className={classes.scheduleDescription}>
        What is the soonest date you could install the Smart Buoy and conduct a
        survey?
      </Typography>
      <MuiPickersUtilsProvider utils={DateFnsUtils}>
        <KeyboardDatePicker
          className={classes.formField}
          disableToolbar
          format="MM/dd/yyyy"
          id="installationSchedule"
          name="installationSchedule"
          autoOk
          showTodayButton
          helperText={errors?.installationSchedule?.message || ""}
          inputRef={register({
            required: "This is a required field",
            validate: {
              validDate: (value) =>
                moment(value, "MM/DD/YYYY", true).isValid() || "Invalid date",
            },
          })}
          error={!!errors.installationSchedule}
          value={installationSchedule}
          onChange={handleInstalationChange}
          KeyboardButtonProps={{
            "aria-label": "change date",
          }}
          inputProps={{
            className: classes.textField,
          }}
          inputVariant="outlined"
        />
      </MuiPickersUtilsProvider>

      <Typography>
        Installation, survey and maintenance personnel and equipment
      </Typography>
      <TextField
        className={`${classes.formField} ${classes.textField}`}
        variant="outlined"
        inputProps={{ className: classes.textField }}
        fullWidth
        multiline
        rows={4}
        defaultValue={application?.installationResources || null}
        placeholder="Please provide a description of the people that will be able to conduct periodic surveys and maintenance of the buoy. Please also include a description of the equipment (e.g. a boat, cameras) that are available."
        name="installationResources"
        inputRef={register({
          required: "This is a required field",
        })}
        error={!!errors.installationResources}
        helperText={errors?.installationResources?.message || ""}
      />

      <Button
        disabled={!agreed}
        type="submit"
        color="primary"
        variant="contained"
      >
        Submit
      </Button>
    </form>
  );
}
Example #19
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
ExclusionDatesDialog = ({
  dialogType,
  open,
  token,
  timeZone,
  siteId,
  onClose,
  classes,
}: ExclusionDatesDialogProps) => {
  const dispatch = useDispatch();

  // State variables for deploy dialog
  const [deployDateTime, setDeployDateTime] = useState<Date | null>(null);
  const [deployLoading, setDeployLoading] = useState(false);
  const [deployError, setDeployError] = useState<string>();
  const [pickerError, setPickerError] = useState("");

  // State variables for maintain dialog
  const [maintainStartDateTime, setMaintainStartDateTime] =
    useState<Date | null>(null);
  const [maintainEndDateTime, setMaintainEndDateTime] = useState<Date | null>(
    null
  );
  const [maintainLoading, setMaintainLoading] = useState(false);
  const [maintainError, setMaintainError] = useState<string>();
  const [startPickerError, setStartPickerError] = useState("");
  const [endPickerError, setEndPickerError] = useState("");
  const [isConfirmationDialogOpen, setIsConfirmationDialogOpen] =
    useState(false);
  const isMaintainDisabled =
    !maintainStartDateTime || !maintainEndDateTime || maintainLoading;

  useEffect(() => {
    switch (dialogType) {
      case "deploy":
        if (deployDateTime) {
          setPickerError("");
        }
        break;
      case "maintain":
        if (maintainStartDateTime) {
          setStartPickerError("");
        }
        if (maintainEndDateTime) {
          setEndPickerError("");
        }
        break;
      default:
        break;
    }
  }, [deployDateTime, dialogType, maintainEndDateTime, maintainStartDateTime]);

  const onDeployDialogClose = () => {
    setDeployLoading(false);
    setDeployDateTime(null);
    setDeployError(undefined);
    setPickerError("");
    onClose();
  };

  const onMaintainDialogClose = () => {
    setMaintainLoading(false);
    setMaintainStartDateTime(null);
    setMaintainEndDateTime(null);
    setMaintainError(undefined);
    setStartPickerError("");
    setEndPickerError("");
    onClose();
  };

  const onDeploy = () => {
    const localDate = setTimeZone(deployDateTime, timeZone);
    if (localDate) {
      setDeployLoading(true);
      siteServices
        .deploySpotter(siteId, { endDate: localDate.toString() }, token)
        .then(() => {
          setPickerError("");
          onDeployDialogClose();
          dispatch(siteRequest(`${siteId}`));
          dispatch(liveDataRequest(`${siteId}`));
        })
        .catch((err) =>
          setDeployError(err?.response?.data?.message || "Something went wrong")
        )
        .finally(() => setDeployLoading(false));
    } else {
      setPickerError("Cannot be empty");
    }
  };

  const onMaintainAdd = () => {
    const localStartDate = setTimeZone(maintainStartDateTime, timeZone);
    const localEndDate = setTimeZone(maintainEndDateTime, timeZone);

    if (!localStartDate) {
      setStartPickerError("Cannot be empty");
    }
    if (!localEndDate) {
      setEndPickerError("Cannot be empty");
    }
    if (localStartDate && localEndDate) {
      setMaintainLoading(true);
      siteServices
        .maintainSpotter(
          siteId,
          {
            endDate: localEndDate,
            startDate: localStartDate,
          },
          token
        )
        .then(() => {
          setStartPickerError("");
          setEndPickerError("");
          onMaintainDialogClose();
          dispatch(clearTimeSeriesData());
          dispatch(clearTimeSeriesDataRange());
          dispatch(setSelectedSite(undefined));
          dispatch(siteRequest(`${siteId}`));
          dispatch(liveDataRequest(`${siteId}`));
        })
        .catch((err) =>
          setMaintainError(
            err?.response?.data?.message || "Something went wrong"
          )
        )
        .finally(() => {
          setMaintainLoading(false);
          onConfirmationDialogClose();
        });
    }
  };

  const confirmActionButtonText = () => {
    switch (dialogType) {
      case "deploy":
        return deployLoading ? "Deploying..." : "Deploy";
      case "maintain":
        return "Add Period";
      default:
        return "";
    }
  };

  const onConfirmationDialogOpen = () => setIsConfirmationDialogOpen(true);
  const onConfirmationDialogClose = () => setIsConfirmationDialogOpen(false);

  const actions: Action[] = [
    {
      action:
        dialogType === "deploy" ? onDeployDialogClose : onMaintainDialogClose,
      color: "secondary",
      size: "small",
      text: "Cancel",
      variant: "outlined",
    },
    {
      action: dialogType === "deploy" ? onDeploy : onConfirmationDialogOpen,
      color: "primary",
      size: "small",
      text: confirmActionButtonText(),
      variant: "outlined",
      disabled: dialogType === "deploy" ? deployLoading : isMaintainDisabled,
    },
  ];

  return (
    <>
      <ConfirmationDialog
        open={isConfirmationDialogOpen}
        isConfirmLoading={maintainLoading}
        onClose={onConfirmationDialogClose}
        handleMaintainPeriodAddition={onMaintainAdd}
        start={maintainStartDateTime || undefined}
        end={maintainEndDateTime || undefined}
        timeZone={timeZone || "UTC"}
      />
      <Dialog
        open={open}
        actions={actions}
        header={
          dialogType === "deploy" ? "Mark as deployed" : "Data Exclusion Dates"
        }
        onClose={
          dialogType === "deploy" ? onDeployDialogClose : onMaintainDialogClose
        }
        content={
          <div className={classes.dialogContent}>
            <Box mb="20px">
              <Alert severity="info">
                {dialogType === "deploy"
                  ? "Spotter data before this date will be deleted."
                  : "Spotter data between these dates will be deleted."}{" "}
                Note: The dates below are in the site&apos;s local timezone (
                {timeZone || "UTC"}).
              </Alert>
            </Box>
            <Box mb="5px">
              {(deployError || maintainError) && (
                <Alert severity="error">{deployError || maintainError}</Alert>
              )}
            </Box>
            <Typography
              className={classes.dateTitle}
              color="textSecondary"
              variant="h5"
            >
              {dialogType === "deploy" ? "Activation Date" : "Start"}
            </Typography>
            <Grid
              className={
                dialogType === "maintain"
                  ? classes.startDateContainer
                  : undefined
              }
              container
              item
              spacing={1}
            >
              <Grid item xs={12} sm={6}>
                <MuiPickersUtilsProvider utils={DateFnsUtils}>
                  <KeyboardDatePicker
                    className={classes.textField}
                    disableToolbar
                    format="MM/dd/yyyy"
                    autoOk
                    size="small"
                    fullWidth
                    showTodayButton
                    value={
                      dialogType === "deploy"
                        ? deployDateTime
                        : maintainStartDateTime
                    }
                    onChange={
                      dialogType === "deploy"
                        ? setDeployDateTime
                        : setMaintainStartDateTime
                    }
                    KeyboardButtonProps={{
                      "aria-label": "change date",
                    }}
                    inputProps={{
                      className: classes.textField,
                    }}
                    inputVariant="outlined"
                    error={
                      dialogType === "deploy"
                        ? pickerError !== ""
                        : startPickerError !== ""
                    }
                    helperText={
                      dialogType === "deploy" ? pickerError : startPickerError
                    }
                  />
                </MuiPickersUtilsProvider>
              </Grid>
              <Grid item xs={12} sm={6}>
                <MuiPickersUtilsProvider utils={DateFnsUtils}>
                  <KeyboardTimePicker
                    className={classes.textField}
                    id="time-picker"
                    name="diveTime"
                    size="small"
                    autoOk
                    fullWidth
                    format="HH:mm"
                    value={
                      dialogType === "deploy"
                        ? deployDateTime
                        : maintainStartDateTime
                    }
                    onChange={
                      dialogType === "deploy"
                        ? setDeployDateTime
                        : setMaintainStartDateTime
                    }
                    KeyboardButtonProps={{
                      "aria-label": "change time",
                    }}
                    InputProps={{
                      className: classes.textField,
                    }}
                    keyboardIcon={<AccessTimeIcon />}
                    inputVariant="outlined"
                    error={
                      dialogType === "deploy"
                        ? pickerError !== ""
                        : startPickerError !== ""
                    }
                    helperText={
                      dialogType === "deploy" ? pickerError : startPickerError
                    }
                  />
                </MuiPickersUtilsProvider>
              </Grid>
            </Grid>
            {dialogType === "maintain" && (
              <>
                <Typography
                  className={classes.dateTitle}
                  color="textSecondary"
                  variant="h5"
                >
                  End
                </Typography>
                <Grid container item spacing={1}>
                  <Grid item xs={12} sm={6}>
                    <MuiPickersUtilsProvider utils={DateFnsUtils}>
                      <KeyboardDatePicker
                        className={classes.textField}
                        disableToolbar
                        format="MM/dd/yyyy"
                        size="small"
                        autoOk
                        fullWidth
                        showTodayButton
                        value={maintainEndDateTime}
                        onChange={setMaintainEndDateTime}
                        KeyboardButtonProps={{
                          "aria-label": "change date",
                        }}
                        inputProps={{
                          className: classes.textField,
                        }}
                        inputVariant="outlined"
                        error={endPickerError !== ""}
                        helperText={endPickerError}
                      />
                    </MuiPickersUtilsProvider>
                  </Grid>
                  <Grid item xs={12} sm={6}>
                    <MuiPickersUtilsProvider utils={DateFnsUtils}>
                      <KeyboardTimePicker
                        className={classes.textField}
                        id="time-picker"
                        name="diveTime"
                        size="small"
                        autoOk
                        fullWidth
                        format="HH:mm"
                        value={maintainEndDateTime}
                        onChange={setMaintainEndDateTime}
                        KeyboardButtonProps={{
                          "aria-label": "change time",
                        }}
                        InputProps={{
                          className: classes.textField,
                        }}
                        keyboardIcon={<AccessTimeIcon />}
                        inputVariant="outlined"
                        error={endPickerError !== ""}
                        helperText={endPickerError}
                      />
                    </MuiPickersUtilsProvider>
                  </Grid>
                </Grid>
              </>
            )}
          </div>
        }
      />
    </>
  );
}
Example #20
Source File: DateInput.tsx    From halstack-react with Apache License 2.0 4 votes vote down vote up
DxcDateInput = React.forwardRef<RefType, DateInputPropsType>(
  (
    {
      label,
      name,
      defaultValue = "",
      value,
      format = "dd-MM-yyyy",
      helperText,
      placeholder = false,
      clearable,
      disabled,
      optional,
      onChange,
      onBlur,
      error,
      autocomplete,
      margin,
      size,
      tabIndex,
    },
    ref
  ) => {
    const [innerValue, setInnerValue] = useState(defaultValue);
    const [isOpen, setIsOpen] = useState(false);
    const [anchorEl, setAnchorEl] = useState(null);

    const colorsTheme = useTheme();
    const translatedLabels = useTranslatedLabels();
    const refDate = ref || useRef(null);

    const handleCalendarOnKeyDown = (event) => {
      switch (event.keyCode) {
        case 27: // Esc
          event.preventDefault();
          setIsOpen(false);
          break;
      }
    };
    const handleCalendarOnClick = (newDate) => {
      const newValue = dayjs(newDate).format(format.toUpperCase());
      value ?? setInnerValue(newValue);
      newDate?.toJSON()
        ? onChange?.({
            value: newValue,
            date: newDate,
          })
        : onChange?.({
            value: newValue,
          });
    };
    const handleIOnChange = ({ value: newValue, error: inputError }) => {
      value ?? setInnerValue(newValue);
      const dayjsDate = dayjs(newValue, format.toUpperCase(), true);
      const invalidDateMessage =
        newValue !== "" && !dayjsDate.isValid() && translatedLabels.dateInput.invalidDateErrorMessage;
      const callbackParams =
        inputError || invalidDateMessage
          ? { value: newValue, error: inputError || invalidDateMessage }
          : { value: newValue };
      dayjsDate.isValid()
        ? onChange?.({
            ...callbackParams,
            date: dayjsDate.toDate(),
          })
        : onChange?.(callbackParams);
    };
    const handleIOnBlur = ({ value, error: inputError }) => {
      const dayjsDate = dayjs(value, format.toUpperCase(), true);
      const invalidDateMessage =
        value !== "" && !dayjsDate.isValid() && translatedLabels.dateInput.invalidDateErrorMessage;
      const callbackParams =
        inputError || invalidDateMessage ? { value, error: inputError || invalidDateMessage } : { value };
      dayjsDate.isValid()
        ? onBlur?.({
            ...callbackParams,
            date: dayjsDate.toDate(),
          })
        : onBlur?.(callbackParams);
    };

    const openCalendar = () => {
      const dateBtn = refDate.current.getElementsByTagName("button")[0];
      setIsOpen(!isOpen);
      setAnchorEl(dateBtn);
    };
    const closeCalendar = () => {
      setIsOpen(false);
    };

    const calendarAction = {
      onClick: openCalendar,
      icon: (
        <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24" fill="currentColor">
          <path d="M0 0h24v24H0z" fill="none" />
          <path d="M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z" />
        </svg>
      ),
    };

    const dateTheme = createMuiTheme({
      overrides: {
        MuiTypography: {
          root: {
            fontFamily: `${colorsTheme.dateInput.pickerFontFamily} !important`,
          },
        },
        MuiPickersYearSelection: {
          container: {
            color: colorsTheme.dateInput.pickerYearFontColor,
            "&::-webkit-scrollbar": {
              width: "3px",
            },

            "&::-webkit-scrollbar-track": {
              backgroundColor: "#D9D9D9",
              borderRadius: "3px",
            },

            "&::-webkit-scrollbar-thumb": {
              backgroundColor: "#666666",
              borderRadius: "3px",
            },
          },
        },
        MuiPickersToolbar: {
          toolbar: {
            backgroundColor: colorsTheme.dateInput.pickerBackgroundColor,
            color: colorsTheme.dateInput.pickerDayFontColor,
          },
        },
        MuiIconButton: {
          root: {
            height: "36px",
            width: "36px",
            padding: "0px",
          },
        },
        MuiTouchRipple: {
          child: {
            opacity: "0",
          },
        },
        MuiButtonBase: {
          root: {
            "&:focus": {
              outline: colorsTheme.dateInput.pickerFocusColor + " solid 2px",
            },
          },
        },
        MuiPickersBasePicker: {
          pickerView: {
            minWidth: "unset",
            maxWidth: "unset",
            minHeight: "unset",
            padding: "0px 10px",
            height: colorsTheme.dateInput.pickerHeight,
            width: colorsTheme.dateInput.pickerWidth,
            backgroundColor: colorsTheme.dateInput.pickerBackgroundColor,
            fontFamily: colorsTheme.dateInput.pickerFontFamily,
          },
        },
        MuiPickersToolbarText: {
          toolbarTxt: {
            color: colorsTheme.dateInput.pickerActualDateFontColor,
            fontFamily: colorsTheme.dateInput.pickerFontFamily,
            fontSize: "2rem",
          },
          toolbarBtnSelected: {
            color: colorsTheme.dateInput.pickerActualDateFontColor,
          },
        },
        MuiPickersCalendarHeader: {
          transitionContainer: {
            color: colorsTheme.dateInput.pickerMonthFontColor,
          },
          dayLabel: {
            color: colorsTheme.dateInput.pickerWeekFontColor,
            fontFamily: colorsTheme.dateInput.pickerFontFamily,
          },
          switchHeader: {
            backgroundColor: "#ffffff",
            color: colorsTheme.dateInput.pickerDayFontColor,
          },
          iconButton: {
            backgroundColor: colorsTheme.dateInput.pickerMonthArrowsBackgroundColor,
            "&:hover": {
              backgroundColor: colorsTheme.dateInput.pickerMonthArrowsBackgroundColor,
            },
          },
        },
        MuiPickersCalendar: {
          week: {
            marginBottom: "2px",
          },
        },
        MuiPickersDay: {
          current: {
            color: colorsTheme.dateInput.pickerDayFontColor,
          },
          day: {
            fontFamily: colorsTheme.dateInput.pickerFontFamily,
            color: colorsTheme.dateInput.pickerDayFontColor,
            "&:hover": {
              backgroundColor: colorsTheme.dateInput.pickerHoverDateBackgroundColor,
              color: colorsTheme.dateInput.pickerHoverDateFontColor,
            },
          },
          daySelected: {
            backgroundColor: colorsTheme.dateInput.pickerSelectedDateBackgroundColor,
            color: colorsTheme.dateInput.pickerSelectedDateColor,
            "&:hover": {
              backgroundColor: colorsTheme.dateInput.pickerSelectedDateBackgroundColor,
              color: colorsTheme.dateInput.pickerSelectedDateColor,
              opacity: "1",
            },
          },
        },
        MuiPickersYear: {
          yearSelected: {
            color: colorsTheme.dateInput.pickerSelectedDateColor,
            backgroundColor: colorsTheme.dateInput.pickerSelectedDateBackgroundColor,
            margin: "0px 100px",
            borderRadius: "20px",
          },
          root: {
            "&:focus": {
              color: colorsTheme.dateInput.pickerHoverDateFontColor,
              backgroundColor: colorsTheme.dateInput.pickerHoverDateBackgroundColor,
            },
          },
        },
        MuiPickersModal: {
          dialogAction: {
            color: "pink",
          },
        },
      },
    });

    return (
      <ThemeProvider theme={colorsTheme}>
        <MuiThemeProvider theme={dateTheme}>
          <MuiPickersUtilsProvider utils={DayjsUtils}>
            <StyledDPicker>
              <DxcTextInput
                label={label}
                name={name}
                defaultValue={defaultValue}
                value={value ?? innerValue}
                helperText={helperText}
                placeholder={placeholder ? format.toUpperCase() : null}
                action={calendarAction}
                clearable={clearable}
                disabled={disabled}
                optional={optional}
                onChange={handleIOnChange}
                onBlur={handleIOnBlur}
                error={error}
                autocomplete={autocomplete}
                margin={margin}
                size={size}
                tabIndex={tabIndex}
                ref={refDate}
              />
              <Popover
                onKeyDown={handleCalendarOnKeyDown}
                open={isOpen}
                anchorEl={anchorEl}
                anchorOrigin={{
                  vertical: "bottom",
                  horizontal: "left",
                }}
                transformOrigin={{
                  vertical: "top",
                  horizontal: "center",
                }}
                PaperProps={{
                  style: {
                    marginTop: "10px",
                  },
                }}
              >
                <ClickAwayListener onClickAway={closeCalendar}>
                  <Paper role="dialog" aria-modal="true">
                    <DatePicker
                      variant="static"
                      value={getValueForPicker(value ?? innerValue, format)}
                      onChange={(date) => handleCalendarOnClick(date)}
                      format={format}
                      disabled={disabled}
                    />
                  </Paper>
                </ClickAwayListener>
              </Popover>
            </StyledDPicker>
          </MuiPickersUtilsProvider>
        </MuiThemeProvider>
      </ThemeProvider>
    );
  }
)
Example #21
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
SurveyForm = ({
  siteId,
  timeZone,
  onSubmit,
  classes,
}: SurveyFormProps) => {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("xs"));
  const diveLocation = useSelector(diveLocationSelector);
  const [diveDateTime, setDiveDateTime] = useState<Date | null>(null);
  const [weather, setWeather] =
    useState<SurveyData["weatherConditions"]>("calm");
  const itemsSize = isMobile ? "small" : "medium";
  const iconSize = isMobile ? "small" : "default";

  const { register, errors, handleSubmit, reset } = useForm({
    reValidateMode: "onSubmit",
  });

  const handleDiveDateTimeChange = (date: Date | null) => {
    if (date) {
      setDiveDateTime(date);
    }
  };

  const handleWeatherChange = (event: ChangeEvent<{ value: unknown }>) => {
    setWeather(event.target.value as SurveyData["weatherConditions"]);
  };

  const nativeSubmit = useCallback(
    (data: { comments: string }) => {
      if (diveDateTime) {
        const dateTime = new Date(
          setTimeZone(diveDateTime, timeZone) || diveDateTime
        ).toISOString();
        const weatherConditions = weather;
        const { comments } = data;
        onSubmit(dateTime, diveLocation, weatherConditions, comments);
      }
    },
    [onSubmit, diveDateTime, timeZone, weather, diveLocation]
  );

  const resetForm = () => {
    reset({
      diveTime: null,
      diveDate: null,
      comments: null,
    });
    setDiveDateTime(null);
    setWeather("calm");
  };

  return (
    <form onSubmit={handleSubmit(nativeSubmit)}>
      {/* Dive Date and Time */}
      <Grid
        className={classes.section}
        container
        justify="space-between"
        spacing={2}
      >
        <Grid item xs={12} sm={6}>
          <Typography variant="h6" gutterBottom>
            Dive Date
          </Typography>
          <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <KeyboardDatePicker
              className={classes.textField}
              disableToolbar
              format="MM/dd/yyyy"
              fullWidth
              id="dive-date"
              name="diveDate"
              autoOk
              showTodayButton
              size={itemsSize}
              helperText={errors?.diveDate?.message || ""}
              inputRef={register({
                required: "This is a required field",
                validate: {
                  validDate: (value) =>
                    moment(value, "MM/DD/YYYY", true).isValid() ||
                    "Invalid date",
                },
              })}
              error={!!errors.diveDate}
              value={diveDateTime}
              onChange={handleDiveDateTimeChange}
              KeyboardButtonProps={{
                "aria-label": "change date",
              }}
              inputProps={{
                className: classes.textField,
              }}
              inputVariant="outlined"
              keyboardIcon={<EventIcon fontSize={iconSize} />}
            />
          </MuiPickersUtilsProvider>
        </Grid>
        <Grid item xs={12} sm={6}>
          <Typography variant="h6" gutterBottom>
            Dive Local Time
          </Typography>
          <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <KeyboardTimePicker
              className={classes.textField}
              id="time-picker"
              name="diveTime"
              fullWidth
              autoOk
              size={itemsSize}
              helperText={errors?.diveTime?.message || ""}
              inputRef={register({
                required: "This is a required field",
                pattern: {
                  value: /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/,
                  message: "Invalid time format",
                },
              })}
              error={!!errors.diveTime}
              format="HH:mm"
              value={diveDateTime}
              onChange={handleDiveDateTimeChange}
              KeyboardButtonProps={{
                "aria-label": "change time",
              }}
              InputProps={{
                className: classes.textField,
              }}
              keyboardIcon={<AccessTimeIcon fontSize={iconSize} />}
              inputVariant="outlined"
            />
          </MuiPickersUtilsProvider>
        </Grid>
      </Grid>
      <Typography variant="h6" gutterBottom>
        Dive Location
      </Typography>
      <Grid className={classes.section} container spacing={2}>
        <Grid item xs={12} sm={6}>
          <TextField
            variant="outlined"
            inputProps={{ className: classes.textField }}
            fullWidth
            placeholder="LAT"
            label="Latitude"
            value={diveLocation?.lat || ""}
            disabled
            size={itemsSize}
          />
        </Grid>
        <Grid item xs={12} sm={6}>
          <TextField
            variant="outlined"
            inputProps={{ className: classes.textField }}
            fullWidth
            placeholder="LONG"
            label="Longitude"
            value={diveLocation?.lng || ""}
            disabled
            size={itemsSize}
          />
        </Grid>
      </Grid>
      {/* Weather Conditions */}
      <Grid item xs={12}>
        <Typography variant="h6" gutterBottom>
          Weather Conditions
        </Typography>
      </Grid>
      <Grid className={classes.extraMargin} item xs={12}>
        <TextField
          className={classes.textField}
          select
          id="weather"
          name="weather"
          value={weather}
          onChange={handleWeatherChange}
          placeholder="Select One"
          fullWidth
          variant="outlined"
          size={itemsSize}
          inputProps={{
            className: classes.textField,
          }}
        >
          <MenuItem className={classes.textField} value="calm">
            Calm
          </MenuItem>
          <MenuItem className={classes.textField} value="waves">
            Waves
          </MenuItem>
          <MenuItem className={classes.textField} value="storm">
            Stormy
          </MenuItem>
        </TextField>
      </Grid>
      <Grid item xs={12}>
        <Typography variant="h6" gutterBottom>
          Comments
        </Typography>
      </Grid>
      <Grid className={classes.extraMargin} item xs={12}>
        <TextField
          className={classes.textField}
          variant="outlined"
          multiline
          name="comments"
          placeholder="Did anything stand out during this survey"
          inputRef={register()}
          fullWidth
          size={itemsSize}
          inputProps={{
            className: classes.textField,
          }}
        />
      </Grid>
      {/* SUBMIT */}
      <Grid
        className={classes.section}
        container
        justify="flex-end"
        item
        spacing={2}
      >
        <Grid item>
          <Button
            component={Link}
            to={`/sites/${siteId}`}
            onClick={resetForm}
            color="primary"
            variant="outlined"
            size={itemsSize}
          >
            Cancel
          </Button>
        </Grid>
        <Grid item>
          <Button
            size={itemsSize}
            onClick={resetForm}
            color="primary"
            variant="outlined"
          >
            Clear
          </Button>
        </Grid>
        <Grid item>
          <Button
            size={itemsSize}
            type="submit"
            color="primary"
            variant="contained"
          >
            Next
          </Button>
        </Grid>
      </Grid>
    </form>
  );
}
Example #22
Source File: DatePicker.tsx    From UsTaxes with GNU Affero General Public License v3.0 4 votes vote down vote up
export function DatePicker<TFormValues>(
  props: DatePickerProps<TFormValues>
): ReactElement {
  const {
    label,
    required = false,
    name,
    minDate = new Date(1900, 0, 1),
    maxDate,
    useGrid = true,
    sizes = { xs: 12 }
  } = props

  const classes = useStyles()
  const {
    control,
    formState: { isSubmitted }
  } = useFormContext<TFormValues>()

  return (
    <ConditionallyWrap
      condition={useGrid}
      wrapper={(children) => (
        <Grid item {...sizes}>
          {children}
        </Grid>
      )}
    >
      <Controller
        name={name}
        control={control}
        rules={{
          required
        }}
        render={({ field: { value, onChange } }) => {
          const forceError: boolean | undefined =
            (isSubmitted &&
              required &&
              ((value as string | undefined | null) ?? undefined) ===
                undefined) ||
            value === ''

          const forceErrorProps = forceError
            ? {
                helperText: 'Input is required',
                error: true
              }
            : {}

          return (
            <div className={classes.root}>
              <FormControl component="fieldset">
                <MuiPickersUtilsProvider utils={DateFnsUtils}>
                  <MuiDatePicker
                    {...forceErrorProps}
                    data-testid={name}
                    label={label}
                    InputLabelProps={{
                      shrink: true
                    }}
                    inputVariant="filled"
                    minDate={minDate}
                    maxDate={maxDate}
                    maxDateMessage={`Date cannot be after ${maxDate.toLocaleDateString()}`}
                    minDateMessage={`Date cannot be before ${minDate.toLocaleDateString()}`}
                    // invalid date message can be shown once user has attempted to submit
                    invalidDateMessage={
                      isSubmitted ? 'Invalid date format' : undefined
                    }
                    value={(value as string | undefined) ?? null}
                    placeholder="mm/dd/yyyy"
                    onChange={onChange}
                    format="MM/dd/yyyy"
                  />
                </MuiPickersUtilsProvider>
              </FormControl>
            </div>
          )
        }}
      />
    </ConditionallyWrap>
  )
}
Example #23
Source File: RightSideBar.tsx    From projectboard with MIT License 4 votes vote down vote up
RightSideBar: React.FC<Props> = ({ showMenu, onCloseMenu }) => {

  const ref = useRef<HTMLDivElement>() as RefObject<HTMLDivElement>;
  const { task } = useSelector((state: RootState) => state.taskDetail);
  const { error, loading, success } = useSelector((state: RootState) => state.updateTask);
  const dispatch = useDispatch();
  const params = useParams<URLParams>();
  const { getAccessTokenSilently } = useAuth0();
  const classes = classNames(
    `absolute lg:static inset-0 transform duration-300 lg:relative lg:translate-x-0 bg-white flex flex-col flex-shrink-0 w-80 font-sans text-sm text-gray-700 border-l border-gray-100 lg:shadow-none justify-items-start h-screen`,
    {
      '-translate-x-full ease-out shadow-none': !showMenu,
      'translate-x-0 ease-in shadow-xl': showMenu
    }
  );
  const [startDate, setStartDate] = useState<MaterialUiPickersDate>(task.startDate);
  const [dueDate, setDueDate] = useState<MaterialUiPickersDate>(task.dueDate);
  const [priority, setPriority] = useState(task.priority);
  const [label, setLabel] = useState(task.label);
  const [status, setStatus] = useState(task.status);
  const [assignee, setAssignee] = useState<Member>(task.assignee);
  const [edited, setEdited] = useState(false);

  // Date Pickers
  const [isOpenStartDate, setIsOpenStartDate] = useState(false);
  const [isOpenDueDate, setIsOpenDueDate] = useState(false);

  const onStartDatePick = () => {
    setIsOpenStartDate(true);
  };
  const onDueDatePick = () => {
    setIsOpenDueDate(true);
  };


  let ready = false;
  useClickOutside(ref, () => {
    if (ready && showMenu && onCloseMenu)
      onCloseMenu();
  });

  const onCancel = useCallback(() => {
    setPriority(task.priority);
    setLabel(task.label);
    setDueDate(task.dueDate);
    setStartDate(task.startDate);
    setAssignee(task.assignee);
    setStatus(task.status);
    setEdited(false);
  }, [task]);
  const onSave = async () => {
    const fieldsToUpdate = {
      status: task.status !== status,
      priority: task.priority !== priority,
      startDate: task.startDate !== startDate,
      dueDate: task.dueDate !== dueDate,
      label: task.label !== label,
      assignee: task?.assignee?.user?._id !== assignee?.user?._id
    };
    const body: any = {};
    if (fieldsToUpdate.dueDate) body.dueDate = dueDate;
    if (fieldsToUpdate.startDate) body.startDate = startDate;
    if (fieldsToUpdate.assignee) body.assignee = assignee._id;
    if (fieldsToUpdate.priority) body.priority = priority;
    if (fieldsToUpdate.status) body.status = status;
    if (fieldsToUpdate.label) body.label = label;

    const token = await getAccessTokenSilently();
    dispatch(updateTaskMicroProperties(params.taskId, params.projectId, token, body));
  };

  useEffect(() => {
    // eslint-disable-next-line react-hooks/exhaustive-deps
    setTimeout(() => ready = true, 300);
  });
  useEffect(() => {
    if (priority !== task.priority) setEdited(true);
    if (label !== task.label) setEdited(true);
    if (status !== task.status) setEdited(true);
    if (startDate !== task.startDate) setEdited(true);
    if (dueDate !== task.dueDate) setEdited(true);
    if (assignee?.user?._id !== task?.assignee?.user?._id) setEdited(true);
  }, [priority, label, status, assignee, edited, task.priority, task.label, task.status, task.startDate, task.dueDate, startDate, dueDate, task?.assignee?.user?._id]);

  useEffect(() => {
    if (error) {
      showError('Please try again later.', 'Unable to Update Task.');
      onCancel();
      dispatch({ type: UPDATE_TASK_MICRO_PROPS_CLEAR });
    }
    if (success) {
      showInfo('', 'Task Updated Successfully');
      setEdited(false);
      getAccessTokenSilently().then(token => {
        dispatch(getTaskDetail(token, params.projectId, params.taskId));
        dispatch({ type: UPDATE_TASK_MICRO_PROPS_CLEAR });
      });
    }
  }, [success, error, onCancel, dispatch, getAccessTokenSilently, params]);

  return (
    <>
      <div className={classes} style={{ zIndex: 3 }} ref={ref}>
        <button
          className='flex-shrink-0 px-5 ml-2 lg:hidden h-14 focus:outline-none'
          onClick={onCloseMenu}
        >
          <CloseIcon className='w-4' />
        </button>

        {/* Top menu*/}
        {loading ? <div className='flex items-center justify-center flex-1'><CircularProgress color="primary" /></div> : <div className='flex flex-col flex-grow-0 flex-shrink-0 px-5 py-3 pt-10'>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Status</p>
            <div className='flex items-center mr-auto'>
              <StatusMenu
                id='status-menu'
                button={<button className='flex items-center justify-center w-6 h-6 border-none rounded focus:outline-none hover:bg-gray-100'><StatusIcon status={status} /></button>}
                onSelect={(st) => {
                  setStatus(st);
                }}
              />
              <p className='text-gray-500 ml-2'>{getStatusText(status)}</p>
            </div>
          </div>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Priority</p>
            <div className='flex items-center mr-auto'>
              <PriorityMenu
                // id='priority-menu'
                button={<button
                  className='inline-flex items-center h-6 px-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'
                >
                  {priority && <PriorityIcon priority={priority} />}
                </button>}
                onSelect={(val) => setPriority(val)}
              />
              <p className='text-gray-500 ml-2'>{getPriorityString(priority)}</p>
            </div>
          </div>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Assignee</p>
            <div className='flex items-center mr-auto'>
              <AssigneeMenu
                button={<button className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {!assignee ? <><OwnerIcon className='w-3.5 h-3.5 mr-2' />
                    <span>Unassigned</span></> : <><OwnerIcon className='w-3.5 h-3.5 mr-2' />
                    <span>{`${assignee?.user?.firstName} ${assignee?.user?.lastName}`}</span></>}
                </button>}
                onSelect={(assignee: Member) => setAssignee(assignee)}
              />
            </div>
          </div>
          <div className='flex justify-between items-center mb-6'>
            <p className='text-gray-400 font-medium w-28'>Label</p>
            <div className='flex items-center mr-auto'>
              <LabelMenu
                id='label-menu'
                onSelect={(label: Label) => setLabel(label.name)}
                button={<button className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {label === 'No Label' ? <><LabelIcon className='w-3.5 h-3.5  mr-2' /> <span>No Label</span> </> : <><div className="w-2.5 h-2.5 rounded-full mr-2" style={{ background: getLabelObj(label)?.color }}></div> <span>{getLabelObj(label)?.name}</span> </>}
                </button>} />
            </div>
          </div>
          <MuiPickersUtilsProvider utils={DateFnsUtils}>

            <div className='flex justify-between items-center mb-6'>
              <p className='text-gray-400 font-medium w-28'>Start Date</p>
              <div className='flex items-center mr-auto'>
                <DatePicker
                  disablePast
                  open={isOpenStartDate}
                  onOpen={() => setIsOpenStartDate(true)}
                  onClose={() => setIsOpenStartDate(false)}
                  TextFieldComponent={() => null}
                  variant='dialog'
                  onChange={(date: MaterialUiPickersDate) => setStartDate(date)}
                  value={startDate}
                />
                <button onClick={onStartDatePick} className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {startDate ? `${formatDate(startDate)}` : "Start Date"}
                </button>
              </div>
            </div>
            <div className='flex justify-between items-center mb-6'>
              <p className='text-gray-400 font-medium w-28'>Due Date</p>
              <div className='flex items-center mr-auto'>
                <DatePicker
                  disablePast
                  open={isOpenDueDate}
                  onOpen={() => setIsOpenDueDate(true)}
                  onClose={() => setIsOpenDueDate(false)}
                  TextFieldComponent={() => null}
                  variant='dialog'
                  onChange={(date: MaterialUiPickersDate) => setDueDate(date)}
                  value={dueDate}
                />
                <button onClick={onDueDatePick} className='inline-flex items-center h-6 px-2 mr-2 text-gray-500 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700'>
                  {dueDate ? `${formatDate(dueDate)}` : "Due Date"}
                </button>
              </div>
            </div>
            <div className='flex justify-around mt-4'>
              {edited && <><button onClick={onCancel} className='inline-flex items-center justify-center px-4 py-2 transition-all rounded-md border border-gray-200 text-gray-500 hover:bg-gray-100 rouned hover:text-gray-700 w-28'>Cancel</button>
                <button onClick={onSave} className='ml-3 inline-flex items-center justify-center px-4 py-2 transition-all duration-400 bg-indigo-700 rounded-md  hover:bg-indigo-800 rouned w-5/12 text-white'>Save</button></>}
            </div>
          </MuiPickersUtilsProvider>
        </div>}
      </div>
    </>
  );
}
Example #24
Source File: CreateTask.tsx    From projectboard with MIT License 4 votes vote down vote up
CreateTask: React.FC<Props> = ({ match, history, location }) => {
    const [showMenu, setShowMenu] = useState(false);
    const [title, setTitle] = useState('');
    const [description, setDescription] = useState('');
    const [priority, setPriority] = useState(Priority.NO_PRIORITY);
    const [status, setStatus] = useState(location?.state?.status || Status.BACKLOG);
    const [label, setLabel] = useState(DEFAULT_LABLES[3]);
    const [assignee, setAssignee] = useState<Member>();
    const [dueDate, setDueDate] = useState<MaterialUiPickersDate>(() => {
        const date = new Date();
        const newDate = new Date(Number(date));
        newDate.setDate(date.getDate() + 10);
        return newDate;
    });
    const [startDate, setStartDate] = useState<MaterialUiPickersDate>(new Date());

    // Date Pickers
    const [isOpenStartDate, setIsOpenStartDate] = useState(false);
    const [isOpenDueDate, setIsOpenDueDate] = useState(false);

    const { projectData } = useSelector((state: RootState) => state.currentProject);
    const { memberList } = useSelector((state: RootState) => state);
    const memberIds = memberList.members.map((member: Member) => member._id);

    const { getAccessTokenSilently } = useAuth0();

    const onAssigneeSelect = (member: Member) => {
        setAssignee(member);
    };

    const onStartDatePick = () => {
        setIsOpenStartDate(true);
    };
    const onDueDatePick = () => {
        setIsOpenDueDate(true);
    };

    const handleSubmit = async () => {
        if (title === '') {
            showWarning('Please enter a title before submiting', 'Title required');
            return;
        }
        const body = {
            title,
            priority,
            status,
            label: label.name,
            assignee: assignee?._id,
            description,
            startDate,
            dueDate
        };
        try {
            showWarning('Please wait!', 'Creating Task...');
            const token = await getAccessTokenSilently();

            const { data } = await axios({
                url: `${baseURL}${endpoints.projects}/${match.params.projectId}${endpoints.tasks}`,
                method: 'POST',
                data: body,
                headers: {
                    Authorization: `Bearer ${token}`
                }
            });
            socket.emit('create_task_update', { newTask: data, member: projectData._id, memberIds });
        } catch (e) {
            showError('', 'Error Creating Task.');
        }
        setTitle('');
        setDescription('');
        setPriority(Priority.NO_PRIORITY);
        setStatus(Status.BACKLOG);
        showInfo('You created new task.', 'Task created');

        history.push(`/projects/${projectData.project._id}/tasks`);
    };

    useEffect(() => {
        const buyCoffee = document.getElementById('bmc-wbtn');
        if (buyCoffee) {
            buyCoffee.style.opacity = '0';
            buyCoffee.style.visibility = 'hidden';
        }
        return () => {
            const buyCoffee = document.getElementById('bmc-wbtn');
            if (buyCoffee) {
                buyCoffee.style.opacity = '1';
                buyCoffee.style.visibility = 'visible';
            }
        };
    }, []);

    return (
        <>
            <LeftSideBar showMenu={showMenu} onCloseMenu={() => setShowMenu(false)} />
            <div className="flex flex-col flex-grow">
                <div className="flex flex-col w-full py-4 flex-1">
                    {/* header */}
                    <div className="flex items-center justify-between flex-shrink-0 px-4">
                        <div className="flex items-center">
                            <span className="inline-flex items-center p-1 text-gray-400 bg-gray-100 rounded">
                                <GitIssueIcon className="w-3 mr-1" />
                                <span>{projectData.project.title}</span>
                            </span>
                            <span className="ml-2 font-normal text-gray-700">› New Task</span>
                        </div>
                        <div className="flex items-center">
                            <Link
                                to={`/projects/${projectData.project._id}/tasks`}
                                className="inline-flex items-center justify-center ml-2 text-gray-500 h-7 w-7 hover:bg-gray-100 rouned hover:text-gray-700"
                            >
                                <CloseIcon className="w-4" />
                            </Link>
                        </div>
                    </div>
                    <div className="flex flex-col flex-1 pb-3.5 overflow-y-auto">
                        {/* Task title */}
                        <div className="flex items-center w-full mt-1.5 px-4">
                            <StatusMenu
                                id="status-menu"
                                button={
                                    <button className="flex items-center justify-center w-6 h-6 border-none rounded focus:outline-none hover:bg-gray-100">
                                        <StatusIcon status={status} />
                                    </button>
                                }
                                onSelect={st => {
                                    setStatus(st);
                                }}
                            />
                            <input
                                className="w-full ml-1.5 text-lg font-semibold placeholder-gray-400 border-none h-7 focus:outline-none"
                                placeholder="Task title"
                                value={title}
                                onChange={e => setTitle(e.target.value)}
                            />
                        </div>

                        {/* Task description editor */}
                        <div className="flex px-4">
                            <MarkdownStyles>
                                <Editor
                                    autoFocus
                                    id="editor"
                                    defaultValue={description}
                                    onChange={value => setDescription(value())}
                                    className="mt-4 ml-5 font-normal border-none appearance-none min-h-12 text-md focus:outline-none"
                                    placeholder="Add description..."
                                />
                            </MarkdownStyles>
                        </div>
                    </div>

                    {/* Task labels & priority */}
                    <div className="flex items-center px-4 pb-3 mt-1 border-b border-gray-200 flex-wrap">
                        <PriorityMenu
                            // id='priority-menu'
                            button={
                                <button className="mt-2 inline-flex items-center h-6 px-2 text-gray-500 bg-gray-200 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700 mr-2">
                                    <PriorityIcon priority={priority} className="mr-2" />
                                    <span>{getPriorityString(priority)}</span>
                                </button>
                            }
                            onSelect={val => setPriority(val)}
                        />

                        <AssigneeMenu
                            button={
                                <button className="mt-2 inline-flex items-center h-6 px-2 mr-2 text-gray-500 bg-gray-200 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700">
                                    {!assignee ? (
                                        <>
                                            <OwnerIcon className="w-3.5 h-3.5 mr-2" />
                                            <span>Assignee</span>
                                        </>
                                    ) : (
                                        <>
                                            <OwnerIcon className="w-3.5 h-3.5 mr-2" />
                                            <span>{`${assignee.user.firstName} ${assignee.user.lastName}`}</span>
                                        </>
                                    )}
                                </button>
                            }
                            onSelect={onAssigneeSelect}
                        />

                        <LabelMenu
                            id="label-menu"
                            onSelect={(label: Label) => setLabel(label)}
                            button={
                                <button className="mt-2 inline-flex items-center h-6 px-2 mr-2 text-gray-500 bg-gray-200 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700">
                                    {label.name === 'No Label' ? (
                                        <>
                                            <LabelIcon className="w-3.5 h-3.5  mr-2" /> <span>No Label</span>{' '}
                                        </>
                                    ) : (
                                        <>
                                            <div
                                                className="w-2.5 h-2.5 rounded-full mr-2"
                                                style={{ background: label.color }}
                                            ></div>{' '}
                                            <span>{label.name}</span>{' '}
                                        </>
                                    )}
                                </button>
                            }
                        />

                        <MuiPickersUtilsProvider utils={DateFnsUtils}>
                            <DatePicker
                                disablePast
                                open={isOpenStartDate}
                                onOpen={() => setIsOpenStartDate(true)}
                                onClose={() => setIsOpenStartDate(false)}
                                TextFieldComponent={() => null}
                                variant="dialog"
                                onChange={(date: MaterialUiPickersDate) => setStartDate(date)}
                                value={startDate}
                            />
                            <button
                                onClick={onStartDatePick}
                                className="mt-2 inline-flex items-center h-6 px-2 mr-2 text-gray-500 bg-gray-200 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700"
                            >
                                {startDate ? `Start Date: ${formatDate(startDate)}` : 'Start Date'}
                            </button>
                            <DatePicker
                                disablePast
                                open={isOpenDueDate}
                                onOpen={() => setIsOpenDueDate(true)}
                                onClose={() => setIsOpenDueDate(false)}
                                TextFieldComponent={() => null}
                                variant="dialog"
                                onChange={(date: MaterialUiPickersDate) => setDueDate(date)}
                                value={dueDate}
                            />
                            <button
                                onClick={onDueDatePick}
                                className="mt-2 inline-flex items-center h-6 px-2 mr-2 text-gray-500 bg-gray-200 border-none rounded focus:outline-none hover:bg-gray-100 hover:text-gray-700"
                            >
                                {dueDate ? `Due Date: ${formatDate(dueDate)}` : 'Due Date'}
                            </button>
                        </MuiPickersUtilsProvider>
                    </div>
                    {/* Footer */}
                    <div className="flex items-center justify-between flex-shrink-0 px-4 pt-3 w-full">
                        <div className="flex items-center w-full">
                            <button
                                className="px-3 ml-2 text-white bg-indigo-600 rounded hover:bg-indigo-700 h-7 focus:outline-none ml-auto"
                                onClick={handleSubmit}
                            >
                                Save Task
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </>
    );
}