Skip to content

Commit

Permalink
feat: add PeriodInput on event form on crm (#884)
Browse files Browse the repository at this point in the history
* RM#90595
  • Loading branch information
vhu-axelor authored Feb 11, 2025
1 parent 6e23346 commit e36df4e
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 24 deletions.
5 changes: 5 additions & 0 deletions changelogs/unreleased/90595.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Event form: replace start and end dates inputs by PeriodInput component",
"type": "refactor",
"packages": "crm"
}
5 changes: 5 additions & 0 deletions changelogs/unreleased/90595_PeriodInput_DateConfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "PeriodInput: add props dateInputMode and nullable on date config",
"type": "feat",
"packages": "core"
}
5 changes: 5 additions & 0 deletions changelogs/unreleased/90595_PeriodInput_Error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "PeriodInput: add new props to detect error from outside",
"type": "feat",
"packages": "core"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2025 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React from 'react';
import {StyleSheet} from 'react-native';
import {PeriodInput} from '@axelor/aos-mobile-core';

interface EventPeriodInputProps {
defaultValue?: any;
onChange?: (value: any) => void;
}

const EventPeriodInputAux = ({
defaultValue = null,
onChange,
}: EventPeriodInputProps) => {
const handleValueChange = (field: string, value: any) => {
if (value !== defaultValue[field]) {
onChange({
...defaultValue,
[field]: value,
});
}
};

return (
<PeriodInput
style={styles.periodInput}
horizontal={false}
startDateConfig={{
dateInputMode: 'datetime',
nullable: false,
date: defaultValue.startDateTime,
onDateChange: date => handleValueChange('startDateTime', date),
}}
endDateConfig={{
dateInputMode: 'datetime',
nullable: false,
date: defaultValue.endDateTime,
onDateChange: date => handleValueChange('endDateTime', date),
}}
onPeriodErrorChange={isError => handleValueChange('isError', isError)}
/>
);
};

const styles = StyleSheet.create({
periodInput: {
alignSelf: 'center',
},
});

const EventPeriodInput = ({
defaultValue = null,
onChange,
}: EventPeriodInputProps) => {
return (
<EventPeriodInputAux defaultValue={defaultValue} onChange={onChange} />
);
};

export default EventPeriodInput;
1 change: 1 addition & 0 deletions packages/apps/crm/src/components/organisms/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export {default as DropdownEventView} from './DropdownEventView/DropdownEventVie
export {default as DropdownGeneralView} from './DropdownGeneralView/DropdownGeneralView';
export {default as DropdownOpportunityView} from './DropdownOpportunityView/DropdownOpportunityView';
export {default as EditButton} from './EditButton/EditButton';
export {default as EventPeriodInput} from './EventPeriodInput/EventPeriodInput';
export {default as TourItineraryButton} from './TourItineraryButton/TourItineraryButton';
export {default as TourLineActionCard} from './TourLineActionCard/TourLineActionCard';
export {default as TourLineEventPopup} from './TourLineEventPopup/TourLineEventPopup';
Expand Down
30 changes: 22 additions & 8 deletions packages/apps/crm/src/models/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
CivilityPicker,
ClientProspectSearchBar,
ContactSearchBar,
EventPeriodInput,
EventStatusPicker,
EventTypePicker,
FunctionSearchBar,
Expand Down Expand Up @@ -470,15 +471,28 @@ export const crm_formsRegister: FormConfigs = {
showTitle: true,
},
},
startDateTime: {
titleKey: 'Crm_StartDate',
type: 'datetime',
widget: 'date',
perdiodDateTime: {
type: 'object',
widget: 'custom',
customComponent: EventPeriodInput,
},
endDateTime: {
titleKey: 'Crm_EndDate',
type: 'datetime',
widget: 'date',
perdiodDateTimeError: {
type: 'string',
validationOptions: {
required: {
customErrorKey: 'Base_PeriodError',
},
},
dependsOn: {
perdiodDateTime: ({newValue}) => {
if (newValue.isError) {
return '';
} else {
return 'OK';
}
},
},
hideIf: () => true,
},
allDay: {
titleKey: 'Crm_AllDay',
Expand Down
28 changes: 24 additions & 4 deletions packages/apps/crm/src/screens/event/EventFormScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ const EventFormScreen = ({navigation, route}) => {
const _default = {
typeSelect: Event?.typeSelect.Meeting,
statusSelect: Event?.statusSelect.Planned,
startDateTime: _defaultStartDate.toISOString(),
endDateTime: _defaultEndDate.toISOString(),
perdiodDateTime: {
startDateTime: _defaultStartDate,
endDateTime: _defaultEndDate,
isError: false,
},
user: user,
};

Expand Down Expand Up @@ -101,6 +104,11 @@ const EventFormScreen = ({navigation, route}) => {
? {
...creationDefaultValue,
...event,
perdiodDateTime: {
startDateTime: new Date(event.startDateTime),
endDateTime: new Date(event.endDateTime),
isError: false,
},
}
: null,
[event, creationDefaultValue],
Expand All @@ -110,7 +118,11 @@ const EventFormScreen = ({navigation, route}) => {
(_event, dispatch) => {
dispatch(
createEvent({
event: _event,
event: {
..._event,
startDateTime: _event.perdiodDateTime.startDateTime.toISOString(),
endDateTime: _event.perdiodDateTime.endDateTime.toISOString(),
},
tourlineData: tourlineData,
}),
);
Expand All @@ -121,7 +133,15 @@ const EventFormScreen = ({navigation, route}) => {

const updateEventAPI = useCallback(
(_event, dispatch) => {
dispatch(updateEvent({event: _event}));
dispatch(
updateEvent({
event: {
..._event,
startDateTime: _event.perdiodDateTime.startDateTime.toISOString(),
endDateTime: _event.perdiodDateTime.endDateTime.toISOString(),
},
}),
);
navigation.pop();
},
[navigation],
Expand Down
43 changes: 31 additions & 12 deletions packages/core/src/components/templates/PeriodInput/PeriodInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,32 @@ const DATE_INPUT_MODE = {
};

interface dateInputConfig {
dateInputMode?: 'date' | 'datetime' | 'time';
nullable?: boolean;
date?: Date;
onDateChange: (date: Date) => void;
readonly?: boolean;
required?: boolean;
}

interface PeriodInputProps {
style?: any;
horizontal?: boolean;
showTitle?: boolean;
startDateConfig: dateInputConfig;
endDateConfig: dateInputConfig;
showTitle?: boolean;
horizontal?: boolean;
style?: any;
defaultIntervalHours?: number;
onPeriodErrorChange?: (isPeriodError: boolean) => void;
}

const PeriodInput = ({
style,
horizontal = true,
showTitle = true,
startDateConfig,
endDateConfig,
showTitle = true,
horizontal = true,
style,
defaultIntervalHours = null,
onPeriodErrorChange,
}: PeriodInputProps) => {
const I18n = useTranslator();

Expand Down Expand Up @@ -86,10 +90,23 @@ const PeriodInput = ({
}, [startDate, endDate, interval, startDateConfig, endDateConfig]);

useEffect(() => {
setIsPeriodError(
startDate && endDate && getStartOfDay(startDate) > getEndOfDay(endDate),
);
}, [startDate, endDate]);
const _startDate =
startDateConfig.dateInputMode === 'date'
? getStartOfDay(startDate)
: startDate;
const _endDate =
endDateConfig.dateInputMode === 'date' ? getEndOfDay(endDate) : endDate;

const isError = startDate && endDate && _startDate > _endDate;
setIsPeriodError(isError);
onPeriodErrorChange(isError);
}, [
startDate,
endDate,
startDateConfig.dateInputMode,
endDateConfig.dateInputMode,
onPeriodErrorChange,
]);

const styles = useMemo(() => {
return getStyles(horizontal);
Expand Down Expand Up @@ -143,13 +160,15 @@ const PeriodInput = ({
const translationKey = isStartDate ? 'Base_StartDate' : 'Base_EndDate';
const date = isStartDate ? startDate : endDate;
const dateConfig = isStartDate ? startDateConfig : endDateConfig;
const nullable =
dateConfig.nullable || dateConfig.nullable == null ? true : false;

return (
<DateInput
style={styles.dateInput}
title={showTitle && I18n.t(translationKey)}
mode="date"
nullable
mode={dateConfig.dateInputMode ?? 'date'}
nullable={nullable}
popup={horizontal}
defaultDate={date}
onDateChange={_date => handleDateChange(isStartDate, _date)}
Expand Down

0 comments on commit e36df4e

Please sign in to comment.