Skip to content

Commit 0c8b8a9

Browse files
authored
Merge pull request #3243 from bluewave-labs/feat/v2-create-maintenance
feat: v2 create maintenance
2 parents d74d79c + dfe62bd commit 0c8b8a9

File tree

21 files changed

+704
-763
lines changed

21 files changed

+704
-763
lines changed
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
2+
import type { DatePickerProps } from "@mui/x-date-pickers/DatePicker";
3+
import type { Dayjs } from "dayjs";
4+
import { useTheme } from "@mui/material/styles";
5+
import Stack from "@mui/material/Stack";
6+
import Typography from "@mui/material/Typography";
7+
import { FieldLabel } from "./FieldLabel";
8+
import { Calendar } from "lucide-react";
9+
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
10+
import { LocalizationProvider } from "@mui/x-date-pickers";
11+
12+
interface DatePickerComponentProps extends Omit<DatePickerProps<Dayjs>, "label"> {
13+
fieldLabel?: string;
14+
required?: boolean;
15+
error?: boolean;
16+
helperText?: string;
17+
}
18+
19+
export const DatePickerComponent = ({
20+
fieldLabel,
21+
required,
22+
error,
23+
helperText,
24+
...props
25+
}: DatePickerComponentProps) => {
26+
const theme = useTheme();
27+
28+
const picker = (
29+
<LocalizationProvider dateAdapter={AdapterDayjs}>
30+
<DatePicker
31+
{...props}
32+
slots={{
33+
openPickerIcon: () => (
34+
<Calendar
35+
size={20}
36+
stroke={theme.palette.text.secondary}
37+
/>
38+
),
39+
...props.slots,
40+
}}
41+
slotProps={{
42+
switchViewButton: { sx: { display: "none" } },
43+
nextIconButton: { sx: { ml: theme.spacing(2) } },
44+
day: {
45+
sx: {
46+
"&.MuiPickersDay-root.Mui-disabled": {
47+
color: theme.palette.text.disabled,
48+
},
49+
},
50+
},
51+
field: {
52+
sx: {
53+
width: "fit-content",
54+
"& > .MuiOutlinedInput-root": {
55+
flexDirection: "row-reverse",
56+
},
57+
"& input": {
58+
minHeight: 34,
59+
p: 0,
60+
pl: theme.spacing(3),
61+
pr: theme.spacing(5),
62+
},
63+
"& fieldset": {
64+
borderColor: error ? theme.palette.error.main : theme.palette.divider,
65+
borderRadius: theme.shape.borderRadius,
66+
},
67+
"&:not(:has(.Mui-disabled)):not(:has(.Mui-error)) .MuiOutlinedInput-root:not(:has(input:focus)):hover fieldset":
68+
{
69+
borderColor: error ? theme.palette.error.main : theme.palette.divider,
70+
},
71+
},
72+
},
73+
inputAdornment: { sx: { ml: 0 } },
74+
openPickerButton: {
75+
sx: {
76+
py: 0,
77+
mr: 0,
78+
},
79+
},
80+
...props.slotProps,
81+
}}
82+
/>
83+
</LocalizationProvider>
84+
);
85+
86+
return (
87+
<Stack spacing={theme.spacing(2)}>
88+
{fieldLabel && <FieldLabel required={required}>{fieldLabel}</FieldLabel>}
89+
{picker}
90+
{helperText && (
91+
<Typography
92+
variant="caption"
93+
color={error ? "error" : "text.secondary"}
94+
>
95+
{helperText}
96+
</Typography>
97+
)}
98+
</Stack>
99+
);
100+
};
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { MobileTimePicker } from "@mui/x-date-pickers/MobileTimePicker";
2+
import type { MobileTimePickerProps } from "@mui/x-date-pickers/MobileTimePicker";
3+
import type { Dayjs } from "dayjs";
4+
import { useTheme } from "@mui/material/styles";
5+
import Stack from "@mui/material/Stack";
6+
import { FieldLabel } from "./FieldLabel";
7+
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
8+
import { LocalizationProvider } from "@mui/x-date-pickers";
9+
10+
interface TimePickerComponentProps extends Omit<MobileTimePickerProps<Dayjs>, "label"> {
11+
fieldLabel?: string;
12+
required?: boolean;
13+
}
14+
15+
export const TimePickerComponent = ({
16+
fieldLabel,
17+
required,
18+
...props
19+
}: TimePickerComponentProps) => {
20+
const theme = useTheme();
21+
22+
const picker = (
23+
<LocalizationProvider dateAdapter={AdapterDayjs}>
24+
<MobileTimePicker
25+
{...props}
26+
slotProps={{
27+
field: {
28+
sx: {
29+
width: "fit-content",
30+
"& input": {
31+
minHeight: 34,
32+
p: 0,
33+
px: theme.spacing(5),
34+
},
35+
"& fieldset": {
36+
borderColor: theme.palette.divider,
37+
borderRadius: theme.shape.borderRadius,
38+
},
39+
"&:not(:has(.Mui-disabled)):not(:has(.Mui-error)) .MuiOutlinedInput-root:not(:has(input:focus)):hover fieldset":
40+
{
41+
borderColor: theme.palette.divider,
42+
},
43+
},
44+
},
45+
...props.slotProps,
46+
}}
47+
/>
48+
</LocalizationProvider>
49+
);
50+
51+
if (fieldLabel) {
52+
return (
53+
<Stack spacing={theme.spacing(2)}>
54+
<FieldLabel required={required}>{fieldLabel}</FieldLabel>
55+
{picker}
56+
</Stack>
57+
);
58+
}
59+
60+
return picker;
61+
};

client/src/Components/v2/inputs/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@ export * from "./Switch";
1414
export * from "./Slider";
1515
export * from "./ImageUpload";
1616
export * from "./ColorPicker";
17+
export { DatePickerComponent as DatePicker } from "./DatePicker";
18+
export { TimePickerComponent as TimePicker } from "./TimePicker";
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { useMemo } from "react";
2+
import dayjs from "dayjs";
3+
import {
4+
maintenanceWindowSchema,
5+
repeatOptions,
6+
type MaintenanceWindowFormData,
7+
} from "@/Validation/maintenanceWindow";
8+
import type { MaintenanceWindow } from "@/Types/MaintenanceWindow";
9+
10+
interface UseMaintenanceWindowFormOptions {
11+
data?: MaintenanceWindow | null;
12+
}
13+
14+
const getRepeatId = (repeatMs: number): string => {
15+
const option = repeatOptions.find((opt) => opt.value === repeatMs);
16+
return option?.id ?? "none";
17+
};
18+
19+
export const useMaintenanceWindowForm = ({
20+
data = null,
21+
}: UseMaintenanceWindowFormOptions = {}) => {
22+
return useMemo(() => {
23+
let defaults: MaintenanceWindowFormData;
24+
25+
if (data) {
26+
const startDate = dayjs(data.start);
27+
28+
defaults = {
29+
name: data.name,
30+
repeat: getRepeatId(data.repeat),
31+
startDate: startDate.format("YYYY-MM-DD"),
32+
startTime: startDate.format("HH:mm"),
33+
duration: data.duration ?? 0,
34+
durationUnit: data.durationUnit ?? "minutes",
35+
monitors: [data.monitorId],
36+
};
37+
} else {
38+
const now = dayjs();
39+
defaults = {
40+
name: "",
41+
repeat: "none",
42+
startDate: now.format("YYYY-MM-DD"),
43+
startTime: now.format("HH:mm"),
44+
duration: 0,
45+
durationUnit: "minutes",
46+
monitors: [],
47+
};
48+
}
49+
50+
return { schema: maintenanceWindowSchema, defaults };
51+
}, [data]);
52+
};

client/src/Pages/Maintenance/CreateMaintenance/Components/ConfigSelect/index.jsx

Lines changed: 0 additions & 38 deletions
This file was deleted.

client/src/Pages/Maintenance/CreateMaintenance/Components/MonitorList/index.jsx

Lines changed: 0 additions & 71 deletions
This file was deleted.

0 commit comments

Comments
 (0)