Skip to content

Commit 697c708

Browse files
big review
1 parent f41fe51 commit 697c708

File tree

7 files changed

+185
-191
lines changed

7 files changed

+185
-191
lines changed

package-lock.json

Lines changed: 42 additions & 43 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@mui/icons-material": "^5.16.14",
2424
"@mui/lab": "5.0.0-alpha.175",
2525
"@mui/material": "^5.16.14",
26-
"@mui/x-date-pickers": "^8.1.0",
26+
"@mui/x-date-pickers": "^7.29.1",
2727
"@mui/x-tree-view": "^7.28.1",
2828
"@reduxjs/toolkit": "^2.5.1",
2929
"ag-grid-community": "^33.1.0",
@@ -35,6 +35,7 @@
3535
"react": "^18.3.1",
3636
"react-dom": "^18.3.1",
3737
"react-hook-form": "^7.54.2",
38+
"react-hook-form-mui": "^7.6.0",
3839
"react-intl": "^7.1.6",
3940
"react-redux": "^9.2.0",
4041
"react-router": "^7.4.1",

src/components/App/app-wrapper.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
1515
import { enUS as MuiDatePickersEnUS, frFR as MuiDatePickersFrFR } from '@mui/x-date-pickers/locales';
1616
import { enUS as dateFnsEnUS, fr as dateFnsFr } from 'date-fns/locale';
1717
import {
18+
CardErrorBoundary,
1819
cardErrorBoundaryEn,
1920
cardErrorBoundaryFr,
20-
CardErrorBoundary,
2121
GsLangUser,
2222
GsTheme,
2323
LANG_ENGLISH,
2424
LANG_FRENCH,
2525
LIGHT_THEME,
2626
loginEn,
2727
loginFr,
28+
NotificationsProvider,
2829
SnackbarProvider,
2930
topBarEn,
3031
topBarFr,
31-
NotificationsProvider,
3232
} from '@gridsuite/commons-ui';
3333
import { type IntlConfig, IntlProvider } from 'react-intl';
3434
import { Provider, useSelector } from 'react-redux';
@@ -155,6 +155,7 @@ const AppWrapperRouterLayout: typeof App = (props: Readonly<PropsWithChildren<{}
155155
<ThemeProvider theme={themeCompiled}>
156156
<LocalizationProvider
157157
dateAdapter={AdapterDateFns}
158+
// @ts-expect-error: Error of AdapterDateFns for Locales type in x-date-pickers v7
158159
adapterLocale={intlToDateFnsLocale(computedLanguage)}
159160
>
160161
<SnackbarProvider hideIconVariant={false}>

src/pages/announcements/add-announcement-form.tsx

Lines changed: 82 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5,136 +5,142 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import { CustomFormProvider, SubmitButton, useSnackMessage } from '@gridsuite/commons-ui';
9-
import Grid from '@mui/material/Grid';
10-
import { FormattedMessage, useIntl } from 'react-intl';
118
import { useCallback } from 'react';
12-
import { FormControl, InputLabel, MenuItem, Select, TextField } from '@mui/material';
13-
import { DateTimePicker } from '@mui/x-date-pickers';
14-
import { Announcement, UserAdminSrv } from '../../services';
15-
import { useForm } from 'react-hook-form';
16-
import { yupResolver } from '@hookform/resolvers/yup';
9+
import { Grid } from '@mui/material';
10+
import { useIntl } from 'react-intl';
11+
import { type Option, SubmitButton, useSnackMessage } from '@gridsuite/commons-ui';
1712
import yup from '../../utils/yup-config';
18-
import { useParameterState } from '../../components/parameters';
19-
import { PARAM_LANGUAGE } from '../../utils/config-params';
13+
import { type InferType } from 'yup';
14+
import { type SubmitHandler, useForm } from 'react-hook-form';
15+
import { yupResolver } from '@hookform/resolvers/yup';
16+
import { FormContainer, SelectElement, TextareaAutosizeElement } from 'react-hook-form-mui';
17+
import { DateTimePickerElement, type DateTimePickerElementProps } from 'react-hook-form-mui/date-pickers';
18+
import { TZDate } from '@date-fns/tz';
19+
import { addSeconds } from 'date-fns';
20+
import { UserAdminSrv } from '../../services';
2021
import { getErrorMessage, handleAnnouncementCreationErrors } from '../../utils/error';
2122

2223
export const MESSAGE = 'message';
2324
export const START_DATE = 'startDate';
2425
export const END_DATE = 'endDate';
2526
export const SEVERITY = 'severity';
2627

27-
interface AddAnnouncementProps {
28-
onAnnouncementCreated: () => void;
29-
}
28+
export type AddAnnouncementFormProps = {
29+
onAnnouncementCreated?: () => void;
30+
};
31+
32+
const severitySelect: Option[] = Object.values(UserAdminSrv.AnnouncementSeverity).map((value) => ({
33+
id: value,
34+
label: `announcements.severity.${value}`,
35+
}));
36+
37+
const formSchema = yup
38+
.object()
39+
.shape({
40+
[MESSAGE]: yup.string().trim().min(1).required(),
41+
[START_DATE]: yup.string().datetime({ precision: 0 }).required(),
42+
[END_DATE]: yup.string().datetime({ precision: 0 }).required(),
43+
[SEVERITY]: yup
44+
.string<UserAdminSrv.AnnouncementSeverity>()
45+
.oneOf(Object.values(UserAdminSrv.AnnouncementSeverity))
46+
.required(),
47+
})
48+
.required();
49+
type FormSchema = InferType<typeof formSchema>;
3050

31-
export default function AddAnnouncementForm({ onAnnouncementCreated }: Readonly<AddAnnouncementProps>) {
51+
const datetimePickerTransform: NonNullable<DateTimePickerElementProps<FormSchema>['transform']> = {
52+
input: (value) => (value && new TZDate(value)) || null,
53+
output: (value, context) => value?.toISOString() || '',
54+
};
55+
56+
export default function AddAnnouncementForm({ onAnnouncementCreated }: Readonly<AddAnnouncementFormProps>) {
3257
const intl = useIntl();
33-
const [languageLocal] = useParameterState(PARAM_LANGUAGE);
3458
const { snackError } = useSnackMessage();
3559

36-
const formSchema = yup
37-
.object()
38-
.shape({
39-
[MESSAGE]: yup.string().trim().required(), // TODO not empty
40-
[START_DATE]: yup.string().required(), //TODO date
41-
[END_DATE]: yup.string().required(), // TODO date
42-
[SEVERITY]: yup.string().required(), // TODO enum
43-
})
44-
.required();
45-
const formMethods = useForm({
60+
const formContext = useForm({
4661
resolver: yupResolver(formSchema),
62+
/*TODO defaultValues: {
63+
[MESSAGE]: null,
64+
[START_DATE]: null,
65+
[END_DATE]: null,
66+
[SEVERITY]: null,
67+
},*/
4768
});
48-
const { register, setValue, handleSubmit, formState } = formMethods;
69+
const { register, setValue, handleSubmit, formState, control, getValues } = formContext;
70+
const startDateValue = getValues(START_DATE);
4971

50-
const onSubmit = useCallback(
51-
(params: any) => {
52-
let startDate = new Date(params.startDate).toISOString();
53-
let endDate = new Date(params.endDate).toISOString();
54-
const newAnnouncement = {
55-
id: crypto.randomUUID(),
72+
const onSubmit = useCallback<SubmitHandler<FormSchema>>(
73+
(params) => {
74+
UserAdminSrv.addAnnouncement({
75+
//id: crypto.randomUUID(),
5676
message: params.message,
57-
startDate: startDate,
58-
endDate: endDate,
77+
startDate: params.startDate,
78+
endDate: params.endDate,
5979
severity: params.severity,
60-
} as Announcement;
61-
UserAdminSrv.addAnnouncement(newAnnouncement)
62-
.then(() => onAnnouncementCreated())
80+
})
81+
.then(() => onAnnouncementCreated?.())
6382
.catch((error) => {
6483
let errorMessage = getErrorMessage(error) ?? '';
6584
if (!handleAnnouncementCreationErrors(errorMessage, snackError)) {
66-
snackError({
67-
headerId: 'announcements.form.errCreateAnnouncement',
68-
messageTxt: errorMessage,
69-
});
85+
snackError({ headerId: 'announcements.form.errCreateAnnouncement', messageTxt: errorMessage });
7086
}
7187
});
7288
},
7389
[onAnnouncementCreated, snackError]
7490
);
7591

7692
return (
77-
<CustomFormProvider validationSchema={formSchema} {...formMethods}>
93+
<FormContainer<FormSchema> formContext={formContext} onSuccess={onSubmit}>
94+
<DateTimePickerElement<FormSchema> name={END_DATE} />
7895
<Grid container spacing={1}>
7996
<Grid item xs={4}>
80-
<TextField
81-
{...register('message')}
82-
id="message-input"
97+
<TextareaAutosizeElement<FormSchema>
98+
name={MESSAGE}
8399
label={intl.formatMessage({ id: 'announcements.form.message' })}
84-
multiline
85-
rows={4}
100+
minRows={2}
101+
maxRows={5}
86102
fullWidth
87-
inputProps={{ maxLength: 200 }}
103+
//inputProps={{ maxLength: 200 }}
88104
/>
89105
</Grid>
90106
<Grid item xs={2}>
91-
<DateTimePicker
92-
{...register('startDate')}
107+
<DateTimePickerElement<FormSchema>
93108
name={START_DATE}
94109
label={intl.formatMessage({ id: 'announcements.table.startDate' })}
95-
onChange={(newValue) => setValue('startDate', newValue?.toISOString() ?? '')} //TODO startOf(min)
110+
transform={datetimePickerTransform} //TODO round startOf(min)
96111
timezone="system"
112+
timeSteps={{ hours: 1, minutes: 1, seconds: 0 }}
113+
disablePast
97114
/>
98115
</Grid>
99116
<Grid item xs={2}>
100-
<DateTimePicker
101-
{...register('endDate')}
117+
<DateTimePickerElement<FormSchema>
102118
name={END_DATE}
103119
label={intl.formatMessage({ id: 'announcements.table.endDate' })}
104-
onChange={(newValue) => setValue('endDate', newValue?.toISOString() ?? '')} //TODO endOf(min)
120+
transform={datetimePickerTransform} //TODO round startOf(min)
105121
timezone="system"
122+
timeSteps={{ hours: 1, minutes: 1, seconds: 0 }}
123+
disablePast
124+
minDateTime={startDateValue ? addSeconds(new TZDate(startDateValue), 1) : undefined}
106125
/>
107126
</Grid>
108127
<Grid item xs={2}>
109-
<FormControl fullWidth>
110-
<InputLabel id="severity-input-label">
111-
<FormattedMessage id="announcements.severity" />
112-
</InputLabel>
113-
<Select
114-
{...register('severity')}
115-
name={SEVERITY}
116-
label={intl.formatMessage({ id: 'announcements.severity' })}
117-
fullWidth={true}
118-
defaultValue={''} // TODO default info
119-
>
120-
<MenuItem value={UserAdminSrv.AnnouncementSeverity.INFO}>
121-
{intl.formatMessage({ id: 'announcements.severity.INFO' })}
122-
</MenuItem>
123-
<MenuItem value={UserAdminSrv.AnnouncementSeverity.WARN}>
124-
{intl.formatMessage({ id: 'announcements.severity.WARN' })}
125-
</MenuItem>
126-
</Select>
127-
</FormControl>
128+
<SelectElement<FormSchema>
129+
name={SEVERITY}
130+
label={intl.formatMessage({ id: 'announcements.severity' })}
131+
options={severitySelect}
132+
fullWidth
133+
/>
128134
</Grid>
129135
<Grid item xs={2}>
130136
<SubmitButton
131137
variant="outlined"
132-
onClick={handleSubmit(onSubmit)}
133-
fullWidth={true}
138+
type="submit"
139+
fullWidth
134140
disabled={!formState.isValid || formState.isValidating}
135141
/>
136142
</Grid>
137143
</Grid>
138-
</CustomFormProvider>
144+
</FormContainer>
139145
);
140146
}

0 commit comments

Comments
 (0)