@material-ui/pickers#KeyboardDatePicker TypeScript Examples
The following examples show how to use
@material-ui/pickers#KeyboardDatePicker.
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: DateSelector.tsx From backstage with Apache License 2.0 | 6 votes |
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 #2
Source File: SideDrawerField.tsx From firetable with Apache License 2.0 | 5 votes |
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 #3
Source File: TableCell.tsx From firetable with Apache License 2.0 | 5 votes |
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 #4
Source File: index.tsx From aqualink-app with MIT License | 5 votes |
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 #5
Source File: FilterControls.tsx From clearflask with Apache License 2.0 | 5 votes |
FilterControlDatePicker = (props: {
name: string;
value?: Date;
onChanged: (val?: Date) => void;
KeyboardDatePickerProps?: Partial<React.ComponentProps<typeof KeyboardDatePicker>>;
type: 'past' | 'future';
}) => {
const classes = useStyles();
return (
<KeyboardDatePicker
shouldDisableDate={(date) => {
if (!date) return true;
if (props.type === 'past') {
if (date.isAfter(moment().endOf('day'))) return true;
} else if (props.type === 'future') {
if (date.isBefore(moment().endOf('day'))) return true;
}
return false
}}
variant='inline'
inputVariant='standard'
size='small'
views={['year', 'date']}
format='YYYY/MM/DD'
autoOk
keyboardIcon={(
<CalendarIcon className={classes.dateIcon} fontSize='inherit' />)}
InputProps={{
disableUnderline: true,
}}
InputAdornmentProps={{ position: 'start' }}
disableToolbar
initialFocusedDate={new Date()}
placeholder={props.name}
value={props.value || null}
onChange={val => {
props.onChanged(val?.toDate());
}}
{...props.KeyboardDatePickerProps}
/>
);
}
Example #6
Source File: Calendar.tsx From glific-frontend with GNU Affero General Public License v3.0 | 5 votes |
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 #7
Source File: date-picker.tsx From keycaplendar with MIT License | 4 votes |
DatePicker = ({
pickerProps,
modalProps,
value,
fallbackValue,
onChange,
month,
allowQuarter,
showNowButton,
saveOnClose,
required,
helpTextProps = {},
...props
}: DatePickerProps) => {
const device = useAppSelector(selectDevice);
const useInline = device === "desktop";
const orientation = useAppSelector(selectOrientation);
const landscape = orientation === "landscape";
const [touched, setTouched] = useState(false);
const invalid = touched
? invalidDate(value, {
allowQuarter,
disableFuture: pickerProps?.disableFuture,
month,
required,
})
: false;
const validFallback = invalidDate(fallbackValue || "") ? "" : fallbackValue;
const views: KeyboardDatePickerProps["views"] = month
? ["year", "month"]
: undefined;
const openTo: KeyboardDatePickerProps["openTo"] = month ? "month" : "date";
const minDate = pickerProps?.minDate || "2000-01-01";
const maxDate = pickerProps?.disableFuture
? DateTime.now().toFormat(month ? "yyyy-MM" : "yyyy-MM-dd")
: pickerProps?.maxDate
? pickerProps.maxDate
: DateTime.now()
.plus({ years: 2 })
.toFormat(month ? "yyyy-MM" : "yyyy-MM-dd");
const rifm = useRifm({
accept: allowQuarter ? /\d|\s|Q/g : /\d/g,
format: formatDateWithAppend(month, allowQuarter),
onChange,
value,
});
const [open, setOpen] = useState(false);
const [dialogVal, setDialogVal] = useState(value);
useEffect(() => {
if (dialogVal !== value) {
setDialogVal(value || validFallback || DateTime.now().toISODate());
}
}, [value, fallbackValue]);
const confirmVal = useInline && !saveOnClose ? onChange : setDialogVal;
const handleDatePickerChange: KeyboardDatePickerProps["onChange"] = (
date,
value
) => {
const finalValue =
(month ? date?.toFormat("yyyy-MM") : date?.toISODate()) || value || "";
confirmVal(finalValue);
};
const setNow = () => {
confirmVal(DateTime.now().toFormat(month ? "yyyy-MM" : "yyyy-MM-dd"));
};
const closeDialog = () => {
setOpen(false);
};
const confirmDialog = () => {
onChange(
dialogVal ||
validFallback ||
DateTime.now().toFormat(month ? "yyyy-MM" : "yyyy-MM-dd")
);
closeDialog();
};
const modal = useInline ? (
<MenuSurface
{...modalProps}
anchorCorner="bottomLeft"
className={bemClasses("modal", { open }, [modalProps?.className || ""])}
onClose={saveOnClose ? confirmDialog : undefined}
open={open && (!allowQuarter || value.charAt(0) !== "Q")}
>
<KeyboardDatePicker
maxDate={maxDate}
minDate={minDate}
onChange={handleDatePickerChange}
openTo={openTo}
orientation="portrait"
value={
saveOnClose
? dialogVal
: value || validFallback || DateTime.now().toISODate()
}
variant="static"
views={views}
{...pickerProps}
/>
{showNowButton ? (
<div className={bemClasses("buttons")}>
<Button
label={month ? "This month" : "Today"}
onClick={setNow}
type="button"
/>
</div>
) : null}
</MenuSurface>
) : (
<Dialog
{...modalProps}
className={bemClasses("modal", { open }, [modalProps?.className || ""])}
onClose={closeDialog}
open={open}
renderToPortal
>
<KeyboardDatePicker
maxDate={maxDate}
minDate={minDate}
onChange={handleDatePickerChange}
openTo={openTo}
orientation={orientation}
value={dialogVal || validFallback || DateTime.now().toISODate()}
variant="static"
views={views}
{...pickerProps}
/>
<ConditionalWrapper
condition={landscape}
wrapper={(children) => (
<div className={bemClasses("bottom-bar")}>{children}</div>
)}
>
<DialogActions>
{showNowButton ? (
<Button
className={bemClasses("show-now-button")}
label={month ? "This month" : "Today"}
onClick={setNow}
type="button"
/>
) : null}
<DialogButton isDefaultAction label="Cancel" onClick={closeDialog} />
<DialogButton label="Confirm" onClick={confirmDialog} />
</DialogActions>
</ConditionalWrapper>
</Dialog>
);
return (
<ConditionalWrapper
condition={useInline}
wrapper={(children) => (
<MenuSurfaceAnchor className={bemClasses("anchor")}>
{children}
</MenuSurfaceAnchor>
)}
>
<TextField
{...props}
className={bemClasses("field")}
helpText={{
children: invalid
? capitalise(invalid)
: `Format: ${month ? "YYYY-MM" : "YYYY-MM-DD"}${
allowQuarter ? " or Q1-4 YYYY" : ""
}`,
persistent: true,
validationMsg: true,
...helpTextProps,
}}
inputMode="numeric"
invalid={!!invalid}
onBlur={() => {
if (!touched) {
setTouched(true);
}
if (useInline) {
setOpen(false);
}
}}
onChange={rifm.onChange}
onFocus={() => {
if (touched) {
setTouched(false);
}
if (useInline) {
setOpen(true);
}
}}
pattern={`^\\d{4}-\\d{1,2}${!month ? "-\\d{1,2}" : ""}$${
allowQuarter ? "|^Q[1-4]{1} \\d{4}$" : ""
}`}
required={required}
trailingIcon={
useInline
? undefined
: withTooltip(
<IconButton
icon={iconObject(<Event />)}
onClick={() => setOpen(true)}
/>,
"Date picker"
)
}
value={rifm.value}
/>
{modal}
</ConditionalWrapper>
);
}
Example #8
Source File: index.tsx From aqualink-app with MIT License | 4 votes |
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 #9
Source File: index.tsx From aqualink-app with MIT License | 4 votes |
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'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 #10
Source File: index.tsx From aqualink-app with MIT License | 4 votes |
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 #11
Source File: chart-filters.tsx From backstage with Apache License 2.0 | 4 votes |
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>
);
}