pcm-shared-components 2.0.18 → 2.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/NEW_COMPONENT/index.js +2 -1
- package/dist/index.js +1 -3
- package/dist/languages/en/translations.json +4 -0
- package/dist/languages/es/translations.json +4 -0
- package/dist/languages/fr/translations.json +4 -0
- package/dist/styles/tailwind.css +1 -1
- package/package.json +1 -4
- package/dist/app/config/reservation_state.js +0 -89
- package/dist/app/config/yes_no_status.js +0 -72
- package/dist/app/tools/date_formatter.js +0 -141
- package/dist/app/tools/date_overlap.js +0 -177
- package/dist/app/tools/seasonal_dates.js +0 -229
- package/dist/components/Timelines/ReservationTimelineComponent/components/SearchLotsTextBox.js +0 -36
- package/dist/components/Timelines/ReservationTimelineComponent/components/TimelinePopUp.js +0 -11
- package/dist/components/Timelines/ReservationTimelineComponent/css/header.css +0 -98
- package/dist/components/Timelines/ReservationTimelineComponent/css/styles.css +0 -121
- package/dist/components/Timelines/ReservationTimelineComponent/css/styles.old +0 -209
- package/dist/components/Timelines/ReservationTimelineComponent/index.js +0 -966
|
@@ -1,966 +0,0 @@
|
|
|
1
|
-
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
|
-
import React, { useRef, useState, useEffect } from 'react';
|
|
3
|
-
import Timeline, { TimelineMarkers, CustomMarker, TimelineHeaders, DateHeader, SidebarHeader } from 'react-calendar-timeline';
|
|
4
|
-
import 'react-calendar-timeline/lib/Timeline.css';
|
|
5
|
-
import './css/styles.css';
|
|
6
|
-
import './css/header.css';
|
|
7
|
-
import moment from 'moment';
|
|
8
|
-
import Tooltip from 'react-tooltip-lite';
|
|
9
|
-
// import TimelinePopUp from './components/TimelinePopUp'; **************** NOTE NOW USING TimelinePopUpComponent *************************
|
|
10
|
-
import SearchLotsTextBox from './components/SearchLotsTextBox';
|
|
11
|
-
import IconButton from '@mui/material/IconButton';
|
|
12
|
-
import ZoomIn from '@mui/icons-material/ZoomIn';
|
|
13
|
-
import ZoomOut from '@mui/icons-material/ZoomOut';
|
|
14
|
-
import Edit from '@mui/icons-material/Edit';
|
|
15
|
-
import Close from '@mui/icons-material/Close';
|
|
16
|
-
import * as MDIIcon from '@mdi/react';
|
|
17
|
-
import { mdiCursorMove } from '@mdi/js';
|
|
18
|
-
import { DATE_TIME_FORMAT } from 'app/tools/date_formatter';
|
|
19
|
-
import { doDatesConflictWithOtherReservations } from 'app/tools/date_overlap';
|
|
20
|
-
import { makeStyles } from '@mui/styles';
|
|
21
|
-
// import i18next from 'i18next';
|
|
22
|
-
import PropTypes from 'prop-types';
|
|
23
|
-
import { ThemeProvider } from '@mui/system';
|
|
24
|
-
import { createTheme, useTheme } from '@mui/material/styles';
|
|
25
|
-
const ZERO_HOUR = {
|
|
26
|
-
hour: 0
|
|
27
|
-
};
|
|
28
|
-
let focus_debounce, new_res_debounce;
|
|
29
|
-
const newItemId = -1;
|
|
30
|
-
const useStyles = makeStyles(() => ({
|
|
31
|
-
timelineWrapper: {
|
|
32
|
-
fontFamily: 'sans-serif',
|
|
33
|
-
fontSize: 'large',
|
|
34
|
-
textAlign: 'center',
|
|
35
|
-
maxWidth: '100%',
|
|
36
|
-
maxHeight: '90vh !important',
|
|
37
|
-
height: ({
|
|
38
|
-
height
|
|
39
|
-
}) => height,
|
|
40
|
-
padding: ({
|
|
41
|
-
padding
|
|
42
|
-
}) => padding,
|
|
43
|
-
overflow: 'scroll'
|
|
44
|
-
}
|
|
45
|
-
}));
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* ## Importing the component in your project
|
|
49
|
-
*
|
|
50
|
-
```js
|
|
51
|
-
|
|
52
|
-
import {ReservationTimelineComponent} from 'pcm-shared-components';
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
*
|
|
56
|
-
*/
|
|
57
|
-
export const ReservationTimelineComponent = props => {
|
|
58
|
-
//Refs
|
|
59
|
-
let useRefTimeline = useRef();
|
|
60
|
-
|
|
61
|
-
//---------------------------------------------------
|
|
62
|
-
// Props
|
|
63
|
-
//---------------------------------------------------
|
|
64
|
-
//todo addNewProps [onItemDeselect onAddNewReservation]
|
|
65
|
-
const {
|
|
66
|
-
editResId,
|
|
67
|
-
lotData,
|
|
68
|
-
reservationData,
|
|
69
|
-
language,
|
|
70
|
-
defaultTimeStart,
|
|
71
|
-
defaultTimeEnd,
|
|
72
|
-
newReservationPlaceholderTimeStart,
|
|
73
|
-
newReservationPlaceholderTimeEnd,
|
|
74
|
-
allowAddNewReservation,
|
|
75
|
-
showAddNewReservationButtonInPopup,
|
|
76
|
-
updateReservationTimelineResize,
|
|
77
|
-
updateNewReservationTimeLineItem,
|
|
78
|
-
updateReservationTimelineMove,
|
|
79
|
-
beforeItemMoveDifferentLot,
|
|
80
|
-
numberOfReservations,
|
|
81
|
-
onNewResItemDoubleClick,
|
|
82
|
-
onItemDoubleClick,
|
|
83
|
-
onItemDeselect,
|
|
84
|
-
onItemSelect,
|
|
85
|
-
adjustNewResStartEndTime,
|
|
86
|
-
height,
|
|
87
|
-
padding,
|
|
88
|
-
getNewKey,
|
|
89
|
-
lineHeight,
|
|
90
|
-
itemHeightRatio,
|
|
91
|
-
TimelinePopUpComponent,
|
|
92
|
-
i18next,
|
|
93
|
-
theme
|
|
94
|
-
} = props;
|
|
95
|
-
const compTheme = theme ? theme : useTheme();
|
|
96
|
-
const defaultTheme = createTheme(compTheme);
|
|
97
|
-
const classes = useStyles(props);
|
|
98
|
-
|
|
99
|
-
//---------------------------------------------------
|
|
100
|
-
// Hooks
|
|
101
|
-
//---------------------------------------------------
|
|
102
|
-
const [lot_search, setLotSearch] = useState('');
|
|
103
|
-
const [should_focus_on_lot_filter, setFocusOnFilter] = useState(false);
|
|
104
|
-
const getLotNumberFromReservationId = reservationId => {
|
|
105
|
-
try {
|
|
106
|
-
const reservationObject = reservationData.find(rd => Number(rd.reservation_id) === Number(reservationId));
|
|
107
|
-
if (reservationObject) {
|
|
108
|
-
//found the res obj now return the lot number
|
|
109
|
-
return reservationObject.lot_number;
|
|
110
|
-
}
|
|
111
|
-
} catch (error) {
|
|
112
|
-
console.error(error);
|
|
113
|
-
}
|
|
114
|
-
return null;
|
|
115
|
-
};
|
|
116
|
-
const filterLots = (lot_number_to_search = '') => {
|
|
117
|
-
let timeline_items;
|
|
118
|
-
try {
|
|
119
|
-
if (lot_number_to_search.length === 0) {
|
|
120
|
-
timeline_items = lotData.map(item => {
|
|
121
|
-
return {
|
|
122
|
-
...item,
|
|
123
|
-
id: item.lot_id,
|
|
124
|
-
title: item.lot_id
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
} else {
|
|
128
|
-
timeline_items = lotData.filter(filter_me => filter_me.lot_id.toLowerCase().indexOf(lot_number_to_search.toLowerCase()) >= 0).map(item => {
|
|
129
|
-
return {
|
|
130
|
-
...item,
|
|
131
|
-
id: item.lot_id,
|
|
132
|
-
title: item.lot_id
|
|
133
|
-
};
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
if (String(editResId).length > 0) {
|
|
137
|
-
//Okay so make sure we only display the group/lot number that is associated with this reservation id.
|
|
138
|
-
const lotNumber = getLotNumberFromReservationId(editResId);
|
|
139
|
-
if (lotNumber) {
|
|
140
|
-
//found the res obj now filter all lot except for the one associated to this reservation.
|
|
141
|
-
timeline_items = timeline_items.filter(ti => ti.id === lotNumber);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
clearTimeout(focus_debounce);
|
|
145
|
-
focus_debounce = setTimeout(() => {
|
|
146
|
-
//have a little bug where the text box was loosing focus then the timeline lot items are being updated, this is my workaround
|
|
147
|
-
if (should_focus_on_lot_filter && String(editResId).length === 0) {
|
|
148
|
-
document.getElementById('lot_filter_search').focus();
|
|
149
|
-
}
|
|
150
|
-
}, 0.5);
|
|
151
|
-
} catch (error) {}
|
|
152
|
-
return timeline_items;
|
|
153
|
-
};
|
|
154
|
-
const [state, setState] = useState({
|
|
155
|
-
// if having loading issues then do this..
|
|
156
|
-
// groups: filterLots(lot_search),
|
|
157
|
-
canMove: false,
|
|
158
|
-
canResize: false,
|
|
159
|
-
// Think of "items" as "a singular phase" represented in the Timeline
|
|
160
|
-
// It can be a "Think phase item", an "Explore phase item", or any "Build phase item"
|
|
161
|
-
// Each item can be customized - given or requirements, all item configurations are the same
|
|
162
|
-
//loading the data groups/lots here is a must or else I will loose them when I toggle from one viewer to another and back to this one.
|
|
163
|
-
groups: [],
|
|
164
|
-
//only force a lot group refresh if we have not focused on the text box yet that way we only fire it once or else it's getting fired multiple times...
|
|
165
|
-
// groups: should_focus_on_lot_filter?[]:filterLots(lot_search),//only force a lot group refresh if we have not focused on the text box yet that way we only fire it wonce or else it's getting fired multiple times...
|
|
166
|
-
// The only differentiator between items are the "group" they belong to, their "title" and their "start/end times"
|
|
167
|
-
items: []
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
//---------------------------------------------------
|
|
171
|
-
// Use Effect
|
|
172
|
-
//---------------------------------------------------
|
|
173
|
-
useEffect(() => {
|
|
174
|
-
moment.locale(language);
|
|
175
|
-
}, []);
|
|
176
|
-
useEffect(() => {
|
|
177
|
-
//morph the current lot data into what is needed to create the timeline groups
|
|
178
|
-
// need at the minimum id, and title.
|
|
179
|
-
|
|
180
|
-
if (lotData.length > 0) {
|
|
181
|
-
setState(previousState => {
|
|
182
|
-
return {
|
|
183
|
-
...previousState,
|
|
184
|
-
groups: filterLots(lot_search)
|
|
185
|
-
};
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
}, [lotData]);
|
|
189
|
-
useEffect(() => {
|
|
190
|
-
try {
|
|
191
|
-
// if (data.length > 0) {
|
|
192
|
-
//morph the reservation into timeline items.
|
|
193
|
-
setState(previousState => {
|
|
194
|
-
return {
|
|
195
|
-
...previousState,
|
|
196
|
-
items: filterReservation()
|
|
197
|
-
};
|
|
198
|
-
});
|
|
199
|
-
// }
|
|
200
|
-
} catch (error) {}
|
|
201
|
-
}, [reservationData]);
|
|
202
|
-
useEffect(() => {
|
|
203
|
-
setState(previousState => {
|
|
204
|
-
return {
|
|
205
|
-
...previousState,
|
|
206
|
-
groups: filterLots(lot_search),
|
|
207
|
-
items: filterReservation(lot_search)
|
|
208
|
-
};
|
|
209
|
-
});
|
|
210
|
-
focus_debounce = setTimeout(() => {
|
|
211
|
-
//have a little bug where the text box was loosing focus then the timeline lot items are being updated, this is my workaround
|
|
212
|
-
if (should_focus_on_lot_filter && String(editResId) === 0) {
|
|
213
|
-
document.getElementById('lot_filter_search').focus();
|
|
214
|
-
}
|
|
215
|
-
}, 0.05);
|
|
216
|
-
}, [lot_search]);
|
|
217
|
-
useEffect(() => {
|
|
218
|
-
const newItem = state.items.find(item => Number(item.id) === -1);
|
|
219
|
-
let sameDates = false;
|
|
220
|
-
if (newItem) {
|
|
221
|
-
// check to see if the place holder dates match the existing new item
|
|
222
|
-
const start_time = newItem.start_time;
|
|
223
|
-
const end_time = newItem.end_time;
|
|
224
|
-
// When comparing dates involving '==' or '===' should use the '+' prefix
|
|
225
|
-
// it will then compare the dates' millisecond values
|
|
226
|
-
if (+new Date(start_time) === +new Date(newReservationPlaceholderTimeStart) && +new Date(end_time) === +new Date(newReservationPlaceholderTimeEnd)) {
|
|
227
|
-
sameDates = true;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
if (newReservationPlaceholderTimeStart, newReservationPlaceholderTimeEnd && !sameDates) {
|
|
231
|
-
// new res item doesn't exist with the current dates add it...
|
|
232
|
-
addNewReservationItem(getLotNumberFromReservationId(editResId), newReservationPlaceholderTimeStart, getNumberOfNights(newReservationPlaceholderTimeStart, newReservationPlaceholderTimeEnd));
|
|
233
|
-
}
|
|
234
|
-
}, [newReservationPlaceholderTimeStart, newReservationPlaceholderTimeEnd]);
|
|
235
|
-
|
|
236
|
-
//Functions
|
|
237
|
-
|
|
238
|
-
/**
|
|
239
|
-
* filterReservation
|
|
240
|
-
*
|
|
241
|
-
* Used to filter out the reservations that needs to be displayed on the timeline.
|
|
242
|
-
* Note: cancelled and expired reservations are filtered out....
|
|
243
|
-
*
|
|
244
|
-
* @param {string} [lot_number_to_search='']
|
|
245
|
-
* @returns returns the filtered reservation (will not return cancelled reservations and filtered reservations by lot number)
|
|
246
|
-
*/
|
|
247
|
-
const filterReservation = (lot_number_to_search = '') => {
|
|
248
|
-
let timeline_reservations = reservationData.map(res => {
|
|
249
|
-
return {
|
|
250
|
-
...res,
|
|
251
|
-
id: res.reservation_id,
|
|
252
|
-
group: res.lot_number,
|
|
253
|
-
title: res.reservation_id + ' ' + res.client_name,
|
|
254
|
-
start_time: moment(res.arrival_date, DATE_TIME_FORMAT),
|
|
255
|
-
end_time: moment(res.departure_date, DATE_TIME_FORMAT),
|
|
256
|
-
className: timeLineItemClassName(res)
|
|
257
|
-
// className: res.conflict_detected === 'No' ? (parseInt(res.transaction_status_id, 10) === 2 ? 'green_row' : 'yellow_row') : 'item_collision'
|
|
258
|
-
};
|
|
259
|
-
}).filter(res_f => parseInt(res_f.transaction_status_id, 10) <= 2 && parseInt(res_f.reservation_status_id, 10) !== 3);
|
|
260
|
-
try {
|
|
261
|
-
if (lot_number_to_search.length > 0) {
|
|
262
|
-
timeline_reservations = timeline_reservations.filter(filter_me => filter_me.lot_number.toLowerCase().indexOf(lot_number_to_search.toLowerCase()) >= 0);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
//set the number of displayed reservation in the timeline after all filtering....
|
|
266
|
-
numberOfReservations(timeline_reservations.length);
|
|
267
|
-
} catch (error) {}
|
|
268
|
-
return timeline_reservations;
|
|
269
|
-
};
|
|
270
|
-
const getNewReservationStyling = (reservation_data, lot_number, startDate, endDate) => {
|
|
271
|
-
return doDatesConflictWithOtherReservations(reservation_data, lot_number, startDate, endDate) ? 'item_collision' : 'border-dashed bg-gray-400/75';
|
|
272
|
-
};
|
|
273
|
-
const addNewReservationItem = (groupId, startDate, numberNights = 2) => {
|
|
274
|
-
// Used to add an new reservation item on the timeline
|
|
275
|
-
try {
|
|
276
|
-
if (allowAddNewReservation) {
|
|
277
|
-
const {
|
|
278
|
-
newStartTime,
|
|
279
|
-
newEndTime
|
|
280
|
-
} = adjustNewResStartEndTime(startDate, startDate);
|
|
281
|
-
const new_end_date_count = newEndTime.add(numberNights, 'days');
|
|
282
|
-
//Add new reservation item, make sure to also remove the -1 = new res item before adding a new one...
|
|
283
|
-
setState(previousState => {
|
|
284
|
-
return {
|
|
285
|
-
...previousState,
|
|
286
|
-
canResize: true,
|
|
287
|
-
canMove: true,
|
|
288
|
-
items: [...previousState.items.filter(item => Number(item.id) !== -1), {
|
|
289
|
-
id: newItemId,
|
|
290
|
-
group: groupId,
|
|
291
|
-
title: i18next.t('reservation_new.title.new_reservation'),
|
|
292
|
-
start_time: newStartTime,
|
|
293
|
-
end_time: new_end_date_count,
|
|
294
|
-
className: getNewReservationStyling(previousState.items.filter(item => Number(item.id) !== -1), groupId, newStartTime, new_end_date_count)
|
|
295
|
-
}]
|
|
296
|
-
};
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
//Pass up the new reservation from to date changes so I can adjust the parent component accordingly
|
|
300
|
-
updateNewReservationTimeLineItem(newStartTime, new_end_date_count);
|
|
301
|
-
}
|
|
302
|
-
} catch (error) {
|
|
303
|
-
console.error('Error adding new reservation time to timeline:', error);
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
const handleAddNewReservationItem = (groupId, startDate, e) => {
|
|
307
|
-
addNewReservationItem(groupId, startDate);
|
|
308
|
-
};
|
|
309
|
-
const timeLineItemClassName = res => {
|
|
310
|
-
let class_name_collection = '';
|
|
311
|
-
if (res.conflict_detected === 'No') {
|
|
312
|
-
class_name_collection = parseInt(res.transaction_status_id, 10) === 2 ? 'green_row' : 'yellow_row';
|
|
313
|
-
} else {
|
|
314
|
-
class_name_collection = 'item_collision';
|
|
315
|
-
}
|
|
316
|
-
if (String(editResId) === String(res.reservation_id)) {
|
|
317
|
-
class_name_collection += ' edit_res_id';
|
|
318
|
-
}
|
|
319
|
-
return class_name_collection;
|
|
320
|
-
};
|
|
321
|
-
const handleItemResize = (itemId, time) => {
|
|
322
|
-
let res_id;
|
|
323
|
-
let lot_number;
|
|
324
|
-
let new_departure_date;
|
|
325
|
-
let arrival_date;
|
|
326
|
-
|
|
327
|
-
//? this will get the information needed of the item to proceed
|
|
328
|
-
state.items.filter(f_item => f_item.id === itemId).map(item => {
|
|
329
|
-
res_id = item.reservation_id;
|
|
330
|
-
lot_number = item.group;
|
|
331
|
-
//? This will be used as the default snapback time for my hours and minutes.
|
|
332
|
-
//? What ever previous hours and minutes defined as the start time will be used as the default snapback time for the new start drag date time
|
|
333
|
-
const current_time = moment(item.end_time).toDate();
|
|
334
|
-
|
|
335
|
-
//? Need to set and adjust the new start time of the item based on it's previous hours and minutes so it always snaps to the same value
|
|
336
|
-
new_departure_date = moment(moment(time).set({
|
|
337
|
-
hour: current_time.getHours(),
|
|
338
|
-
minute: current_time.getMinutes(),
|
|
339
|
-
second: 0,
|
|
340
|
-
millisecond: 0
|
|
341
|
-
}));
|
|
342
|
-
|
|
343
|
-
//need the current arrival date because the same call is made to the server weather we do a move or a resize
|
|
344
|
-
arrival_date = item.start_time;
|
|
345
|
-
//? note the item start time will not change when the item is resized as I only allow the right part of the item to change
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
if (Number(itemId) > newItemId) {
|
|
349
|
-
// valid reservation item
|
|
350
|
-
//make the same change in redux or store, and also reevaluate the reservations conflicts for all reservations associated to this lot number/res id
|
|
351
|
-
updateReservationTimelineResize(res_id, lot_number, arrival_date, new_departure_date, getTimeDifference(arrival_date, new_departure_date));
|
|
352
|
-
} else {
|
|
353
|
-
// new reservation item
|
|
354
|
-
setState(previousState => {
|
|
355
|
-
return {
|
|
356
|
-
...previousState,
|
|
357
|
-
items: [...previousState.items.map(it => {
|
|
358
|
-
if (Number(it.id) === Number(itemId)) {
|
|
359
|
-
return {
|
|
360
|
-
...it,
|
|
361
|
-
end_time: moment(new_departure_date),
|
|
362
|
-
className: getNewReservationStyling(previousState.items.filter(item => Number(item.id) !== -1), it.group, it.start_time, new_departure_date)
|
|
363
|
-
};
|
|
364
|
-
} else {
|
|
365
|
-
return it;
|
|
366
|
-
}
|
|
367
|
-
})]
|
|
368
|
-
};
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
//Pass up the new reservation from to date changes so I can adjust the parent component accordingly
|
|
372
|
-
updateNewReservationTimeLineItem(arrival_date, new_departure_date);
|
|
373
|
-
}
|
|
374
|
-
};
|
|
375
|
-
const handleItemMove = (itemId, dragTime, newGroupOrder) => {
|
|
376
|
-
let res_id;
|
|
377
|
-
let original_lot_number;
|
|
378
|
-
let new_lot_number = groups[newGroupOrder].lot_id;
|
|
379
|
-
let new_departure_date;
|
|
380
|
-
let new_arrival_date;
|
|
381
|
-
const ARE_WE_MOVING_TO_THE_SAME_LOT_ID = state.items.filter(f_item => f_item.id === itemId).find(gr => gr.group === new_lot_number) ? true : false;
|
|
382
|
-
const moveItem = () => {
|
|
383
|
-
state.items.filter(f_item => f_item.id === itemId).map(item => {
|
|
384
|
-
res_id = item.reservation_id;
|
|
385
|
-
original_lot_number = item.group;
|
|
386
|
-
|
|
387
|
-
//? This will be used as the default snap time for my hours and minutes.
|
|
388
|
-
//? What ever previous hours and minutes defined as the start time will be used as the default snap time for the new start drag date time
|
|
389
|
-
let current_time = moment(item.start_time).toDate();
|
|
390
|
-
|
|
391
|
-
//? Need to set and adjust the new start time of the item based on it's previous hours and minutes so it always snaps to the same value
|
|
392
|
-
new_arrival_date = moment(moment(dragTime).set({
|
|
393
|
-
hour: current_time.getHours(),
|
|
394
|
-
minute: current_time.getMinutes(),
|
|
395
|
-
second: 0,
|
|
396
|
-
millisecond: 0
|
|
397
|
-
}));
|
|
398
|
-
|
|
399
|
-
//? Need to readjust the item end time to compensate the move
|
|
400
|
-
new_departure_date = new_arrival_date + (item.end_time - item.start_time);
|
|
401
|
-
});
|
|
402
|
-
if (Number(itemId) > newItemId) {
|
|
403
|
-
//make the same change in redux, and also reevaluate the reservations conflicts for all reservations associated to this lot number/res id
|
|
404
|
-
updateReservationTimelineMove(res_id, original_lot_number, new_lot_number, new_arrival_date, new_departure_date, getTimeDifference(new_arrival_date, new_departure_date));
|
|
405
|
-
} else {
|
|
406
|
-
// new reservation item
|
|
407
|
-
const {
|
|
408
|
-
newStartTime,
|
|
409
|
-
newEndTime
|
|
410
|
-
} = adjustNewResStartEndTime(new_arrival_date, new_departure_date);
|
|
411
|
-
setState(previousState => {
|
|
412
|
-
return {
|
|
413
|
-
...previousState,
|
|
414
|
-
items: [...previousState.items.map(it => {
|
|
415
|
-
if (Number(it.id) === Number(itemId)) {
|
|
416
|
-
return {
|
|
417
|
-
...it,
|
|
418
|
-
group: new_lot_number,
|
|
419
|
-
start_time: newStartTime,
|
|
420
|
-
end_time: newEndTime,
|
|
421
|
-
className: getNewReservationStyling(previousState.items.filter(item => Number(item.id) !== -1), new_lot_number, newStartTime, newEndTime)
|
|
422
|
-
};
|
|
423
|
-
} else {
|
|
424
|
-
return it;
|
|
425
|
-
}
|
|
426
|
-
})]
|
|
427
|
-
};
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
//Pass up the new reservation from to date changes so I can adjust the parent component accordingly
|
|
431
|
-
updateNewReservationTimeLineItem(newStartTime, newEndTime);
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
if (!ARE_WE_MOVING_TO_THE_SAME_LOT_ID) {
|
|
435
|
-
//This is where we check to see if the lot has a notification. If it does then prompt the user with the message. Else keep trucking...
|
|
436
|
-
// showLotNotificationPopup({ ...groups[newGroupOrder] }, moveItem);
|
|
437
|
-
beforeItemMoveDifferentLot({
|
|
438
|
-
...groups[newGroupOrder]
|
|
439
|
-
}, moveItem);
|
|
440
|
-
} else {
|
|
441
|
-
// We are moving on the same lot number no need to check for lot notification.
|
|
442
|
-
moveItem();
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
|
-
const getTimeDifference = (start_time, end_time, simulate_time_dragging = false) => {
|
|
446
|
-
if (simulate_time_dragging) {
|
|
447
|
-
// Need to set the hours to 24/midnight so it properly simulated with the timeline items are dragged/resized across days. Or else it feels weird when looking at the days increase
|
|
448
|
-
start_time = moment(moment(start_time).set({
|
|
449
|
-
hour: 24,
|
|
450
|
-
minute: 0,
|
|
451
|
-
second: 0,
|
|
452
|
-
millisecond: 0
|
|
453
|
-
}));
|
|
454
|
-
}
|
|
455
|
-
return moment(end_time).diff(start_time, 'days') + 1;
|
|
456
|
-
};
|
|
457
|
-
const getNumberOfNights = (from_date, to_date) => {
|
|
458
|
-
let n_nights = 0;
|
|
459
|
-
try {
|
|
460
|
-
let dt1 = new Date(from_date);
|
|
461
|
-
let dt2 = new Date(to_date);
|
|
462
|
-
n_nights = Math.floor((Date.UTC(dt2.getFullYear(), dt2.getMonth(), dt2.getDate()) - Date.UTC(dt1.getFullYear(), dt1.getMonth(), dt1.getDate())) / (1000 * 60 * 60 * 24));
|
|
463
|
-
if (!Number(n_nights) || n_nights < 0) {
|
|
464
|
-
n_nights = 0;
|
|
465
|
-
}
|
|
466
|
-
} catch (e) {
|
|
467
|
-
return 0;
|
|
468
|
-
// console.error(e.message);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
return n_nights;
|
|
472
|
-
};
|
|
473
|
-
const isNewItemId = id => {
|
|
474
|
-
//Returns true if this id is from a new item id being added to the timeline
|
|
475
|
-
return Number(id) === newItemId;
|
|
476
|
-
};
|
|
477
|
-
/**
|
|
478
|
-
* customItem
|
|
479
|
-
*
|
|
480
|
-
* Used to display the tooltip of the item when resizing it
|
|
481
|
-
*
|
|
482
|
-
* @param {*} { item, itemContext, getItemProps, getResizeProps }
|
|
483
|
-
* @returns
|
|
484
|
-
*/
|
|
485
|
-
const customItem = props => {
|
|
486
|
-
// const { left: leftResizeProps } = getResizeProps();
|
|
487
|
-
const {
|
|
488
|
-
item,
|
|
489
|
-
itemContext,
|
|
490
|
-
getItemProps,
|
|
491
|
-
getResizeProps
|
|
492
|
-
} = props;
|
|
493
|
-
try {
|
|
494
|
-
const {
|
|
495
|
-
right: rightResizeProps
|
|
496
|
-
} = getResizeProps();
|
|
497
|
-
const itemProps = getItemProps(item.itemProps);
|
|
498
|
-
const isPhaseSelected = itemContext.selected && item.group !== 4;
|
|
499
|
-
let followingTooltipsMarkup = null;
|
|
500
|
-
if (isPhaseSelected) {
|
|
501
|
-
const timeDifference = getTimeDifference(item.start_time, itemContext.resizeTime, true);
|
|
502
|
-
const n_nights = i18next.t('reservation_grid.header.number_of_nights');
|
|
503
|
-
const daysTooltipMarkup = itemContext.resizing ? ` ${n_nights} ${timeDifference} ` : null;
|
|
504
|
-
const tooltipMarkup = /*#__PURE__*/React.createElement("div", {
|
|
505
|
-
className: "rct-item-tooltip rct-item-following-indicator ",
|
|
506
|
-
style: {
|
|
507
|
-
position: 'absolute',
|
|
508
|
-
left: itemContext.dimensions.left + itemContext.dimensions.width,
|
|
509
|
-
top: itemContext.dimensions.top,
|
|
510
|
-
height: `${itemContext.dimensions.height}px`
|
|
511
|
-
}
|
|
512
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
513
|
-
className: "rct-item-tooltip-content"
|
|
514
|
-
}, daysTooltipMarkup));
|
|
515
|
-
followingTooltipsMarkup = /*#__PURE__*/React.createElement("div", null, tooltipMarkup);
|
|
516
|
-
}
|
|
517
|
-
const handleRightSide = itemContext.useResizeHandle && isPhaseSelected ? /*#__PURE__*/React.createElement("div", rightResizeProps, /*#__PURE__*/React.createElement("span", {
|
|
518
|
-
className: state.canResize ? 'handle-icon' : ''
|
|
519
|
-
})) : null;
|
|
520
|
-
const handleLeftSide = itemContext.useResizeHandle && isPhaseSelected ? /*#__PURE__*/React.createElement("div", null, state.canMove && /*#__PURE__*/React.createElement(MDIIcon.Icon, {
|
|
521
|
-
path: mdiCursorMove,
|
|
522
|
-
size: 1.5,
|
|
523
|
-
color: "charcoal",
|
|
524
|
-
className: 'move-icon'
|
|
525
|
-
})) : null;
|
|
526
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
527
|
-
className: `rct-item-wrapper ${itemContext.resizing ? 'rct-item--is-resizing' : ''} ${itemContext.selected ? 'rct-item--is-selected' : ''}`
|
|
528
|
-
}, /*#__PURE__*/React.createElement("div", itemProps, /*#__PURE__*/React.createElement(Tooltip, {
|
|
529
|
-
zIndex: 2000,
|
|
530
|
-
content: /*#__PURE__*/React.createElement(TimelinePopUpComponent, {
|
|
531
|
-
res: item,
|
|
532
|
-
showAddNewReservationButtonInPopup: showAddNewReservationButtonInPopup,
|
|
533
|
-
getTimeDifference: getTimeDifference,
|
|
534
|
-
addNewResOnClick: startAddingNewReservation
|
|
535
|
-
}),
|
|
536
|
-
mouseOutDelay: 500
|
|
537
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
538
|
-
className: "rct-item-content cursor-pointer h-full w-full",
|
|
539
|
-
style: {
|
|
540
|
-
maxHeight: `${itemContext.dimensions.height}`
|
|
541
|
-
}
|
|
542
|
-
}, itemContext.title)), handleLeftSide, handleRightSide), followingTooltipsMarkup);
|
|
543
|
-
} catch (error) {
|
|
544
|
-
console.error('Error in timeline custom item:', error);
|
|
545
|
-
}
|
|
546
|
-
};
|
|
547
|
-
const getItemById = id => {
|
|
548
|
-
return state.items.find(item => item.id === id);
|
|
549
|
-
};
|
|
550
|
-
const getLotByGroupId = groupId => {
|
|
551
|
-
//Note groupId is the lot number, it's just how the timeline works.
|
|
552
|
-
return lotData.find(ld => ld.lot_id === groupId);
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
// const getItemById = (itemId) => {
|
|
556
|
-
// return state.items.find((item) => item.id === itemId);
|
|
557
|
-
// };
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
* groupRenderer
|
|
561
|
-
*
|
|
562
|
-
* Changes the styling of the lot number item on the group column
|
|
563
|
-
*
|
|
564
|
-
* @param {*} { group }
|
|
565
|
-
* @returns
|
|
566
|
-
*/
|
|
567
|
-
const groupRenderer = ({
|
|
568
|
-
group
|
|
569
|
-
}) => {
|
|
570
|
-
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
|
571
|
-
style: {
|
|
572
|
-
color: group.title === '106' ? 'red' : 'black'
|
|
573
|
-
}
|
|
574
|
-
}, group.title));
|
|
575
|
-
};
|
|
576
|
-
const toggleTimelineEdit = () => {
|
|
577
|
-
setState({
|
|
578
|
-
...state,
|
|
579
|
-
canMove: !state.canMove,
|
|
580
|
-
canResize: !state.canResize
|
|
581
|
-
});
|
|
582
|
-
};
|
|
583
|
-
const turnOffTimelineEdit = () => {
|
|
584
|
-
setState(previousState => {
|
|
585
|
-
return {
|
|
586
|
-
...previousState,
|
|
587
|
-
canMove: false,
|
|
588
|
-
canResize: false
|
|
589
|
-
};
|
|
590
|
-
});
|
|
591
|
-
};
|
|
592
|
-
const turnOnTimelineEdit = () => {
|
|
593
|
-
setState(previousState => {
|
|
594
|
-
return {
|
|
595
|
-
...previousState,
|
|
596
|
-
canMove: true,
|
|
597
|
-
canResize: true
|
|
598
|
-
};
|
|
599
|
-
});
|
|
600
|
-
};
|
|
601
|
-
const handleRelativeZoomOutClick = () => {
|
|
602
|
-
useRefTimeline.current.changeZoom(1.25);
|
|
603
|
-
};
|
|
604
|
-
const handleRelativeZoomInClick = () => {
|
|
605
|
-
useRefTimeline.current.changeZoom(0.75);
|
|
606
|
-
};
|
|
607
|
-
|
|
608
|
-
// --------------------------------------------
|
|
609
|
-
// Render used to make the month and year sticky scroll sliding
|
|
610
|
-
// --------------------------------------------
|
|
611
|
-
// const isWeekendDay = (intervalContext, data) => {
|
|
612
|
-
// if (data.isMonth) {
|
|
613
|
-
// return false;
|
|
614
|
-
// }
|
|
615
|
-
// const day = intervalContext.interval.startTime.day();
|
|
616
|
-
// return day === 6 || day === 0; // Saturday or Sunday
|
|
617
|
-
// };
|
|
618
|
-
// const isCurrentDay = (intervalContext, data) => {
|
|
619
|
-
// return !data.isMonth && intervalContext.interval.startTime.isSame(data.currentDate, 'day');
|
|
620
|
-
// };
|
|
621
|
-
|
|
622
|
-
// const itemRenderer = ({ item, itemContext, getItemProps }) => {
|
|
623
|
-
// return (
|
|
624
|
-
// <div
|
|
625
|
-
// {...getItemProps({
|
|
626
|
-
// style: {
|
|
627
|
-
// display: 'flex',
|
|
628
|
-
// alignItems: 'center',
|
|
629
|
-
// background: item.start_time.isAfter() ? '#aaa' : '#d32f2f',
|
|
630
|
-
// border: `3px solid ${itemContext.selected ? '#fff700' : 'transparent'}`,
|
|
631
|
-
// borderRadius: '12.5px',
|
|
632
|
-
// boxShadow: 'rgba(0, 0, 0, 0.16) 0 0.3rem 0.6rem'
|
|
633
|
-
// }
|
|
634
|
-
// })}
|
|
635
|
-
// >
|
|
636
|
-
// <div
|
|
637
|
-
// style={{
|
|
638
|
-
// position: 'sticky',
|
|
639
|
-
// left: '0',
|
|
640
|
-
// display: 'inline-block',
|
|
641
|
-
// overflow: 'hidden',
|
|
642
|
-
// padding: '0 1rem',
|
|
643
|
-
// textOverflow: 'ellipsis',
|
|
644
|
-
// whiteSpace: 'nowrap'
|
|
645
|
-
// }}
|
|
646
|
-
// >
|
|
647
|
-
// {itemContext.title}
|
|
648
|
-
// </div>
|
|
649
|
-
// </div>
|
|
650
|
-
// );
|
|
651
|
-
// };
|
|
652
|
-
|
|
653
|
-
// const emptySlotClicked = (groupId, time) => {
|
|
654
|
-
// // console.log('group id : ', groupId, ' time: ',time)
|
|
655
|
-
// };
|
|
656
|
-
|
|
657
|
-
// const onTimeChange = (start, end, updateScrollCanvas) => {
|
|
658
|
-
// // this.setState({ zoom_out_level: 1 });
|
|
659
|
-
// // this.zoom_days = moment(start).diff(end, "days");
|
|
660
|
-
|
|
661
|
-
// // console.log(
|
|
662
|
-
// // "hours: ",
|
|
663
|
-
// // moment(start).diff(end, "hours"),
|
|
664
|
-
// // "days: ",
|
|
665
|
-
// // this.zoom_days,
|
|
666
|
-
// // "months:",
|
|
667
|
-
// // moment(start).diff(end, "months")
|
|
668
|
-
// // );
|
|
669
|
-
// // console.log("start: ", start, " end: ", end);
|
|
670
|
-
|
|
671
|
-
// updateScrollCanvas(start, end);
|
|
672
|
-
// };
|
|
673
|
-
|
|
674
|
-
//Makes the year month at the top of the timeline stick to the left side when scrolling
|
|
675
|
-
//And also bold the weekends and makes the current day red
|
|
676
|
-
const intervalRenderer = ({
|
|
677
|
-
intervalContext,
|
|
678
|
-
getIntervalProps,
|
|
679
|
-
data
|
|
680
|
-
}) => {
|
|
681
|
-
return /*#__PURE__*/React.createElement("div", _extends({}, getIntervalProps(), {
|
|
682
|
-
className: `rct-dateHeader ${data.isMonth ? 'rct-dateHeader-primary' : ''}`,
|
|
683
|
-
onClick: () => {
|
|
684
|
-
return false;
|
|
685
|
-
}
|
|
686
|
-
}), /*#__PURE__*/React.createElement("span", {
|
|
687
|
-
style: {
|
|
688
|
-
position: data.isMonth ? 'sticky' : 'static',
|
|
689
|
-
marginRight: data.isMonth ? 'auto' : 'inherit',
|
|
690
|
-
left: '50%',
|
|
691
|
-
padding: '0 1rem'
|
|
692
|
-
// fontWeight: isWeekendDay(intervalContext, data) || isCurrentDay(intervalContext, data) ? '400' : '300',
|
|
693
|
-
// color: isCurrentDay(intervalContext, data) ? '#d32f2f' : '#000'
|
|
694
|
-
}
|
|
695
|
-
}, intervalContext.intervalText));
|
|
696
|
-
};
|
|
697
|
-
const startAddingNewReservation = () => {
|
|
698
|
-
//Note the new item id will always be -1 because that's what I set it as and there will only ever be one of them.
|
|
699
|
-
|
|
700
|
-
try {
|
|
701
|
-
clearTimeout(new_res_debounce);
|
|
702
|
-
new_res_debounce = setTimeout(() => {
|
|
703
|
-
//Get the group item so I can trace it back to the lot data item
|
|
704
|
-
const groupItem = getItemById(newItemId);
|
|
705
|
-
if (groupItem) {
|
|
706
|
-
//Get the lot object, lot object is needed for the new res panel to know which lot is currently selected.
|
|
707
|
-
const lot_item = getLotByGroupId(groupItem.group);
|
|
708
|
-
const activeResParts = {
|
|
709
|
-
reservation: {
|
|
710
|
-
end_date: groupItem.end_time.format(DATE_TIME_FORMAT),
|
|
711
|
-
start_date: groupItem.start_time.format(DATE_TIME_FORMAT)
|
|
712
|
-
},
|
|
713
|
-
lot: {
|
|
714
|
-
...lot_item
|
|
715
|
-
}
|
|
716
|
-
};
|
|
717
|
-
onNewResItemDoubleClick(activeResParts);
|
|
718
|
-
|
|
719
|
-
//Remove the edit mode on the timeline.
|
|
720
|
-
turnOffTimelineEdit();
|
|
721
|
-
}
|
|
722
|
-
}, 300);
|
|
723
|
-
} catch (error) {
|
|
724
|
-
console.error('Error in startAddingNewReservation: ', error);
|
|
725
|
-
}
|
|
726
|
-
};
|
|
727
|
-
const handleOnItemDoubleClick = resId => {
|
|
728
|
-
try {
|
|
729
|
-
if (String(editResId).length === 0) {
|
|
730
|
-
if (!isNewItemId(resId)) {
|
|
731
|
-
//Valid reservation, Edit the reservation
|
|
732
|
-
onItemDoubleClick(resId);
|
|
733
|
-
} else {
|
|
734
|
-
//New reservation item, start adding the new reservation\
|
|
735
|
-
startAddingNewReservation();
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
} catch (error) {
|
|
739
|
-
console.error('error in handleOnItemDoubleClick', error);
|
|
740
|
-
}
|
|
741
|
-
};
|
|
742
|
-
const {
|
|
743
|
-
items,
|
|
744
|
-
groups
|
|
745
|
-
} = state;
|
|
746
|
-
const todayInMilliseconds = moment().valueOf();
|
|
747
|
-
return /*#__PURE__*/React.createElement(ThemeProvider, {
|
|
748
|
-
theme: defaultTheme
|
|
749
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
750
|
-
key: "timeline_main_1",
|
|
751
|
-
className: classes.timelineWrapper
|
|
752
|
-
}, /*#__PURE__*/React.createElement(Timeline, {
|
|
753
|
-
key: getNewKey ? Math.random() : 'time_line_key' //Used to re-render the timeline each time the default dates change so I see the changes applied
|
|
754
|
-
,
|
|
755
|
-
groups: groups,
|
|
756
|
-
items: items,
|
|
757
|
-
itemsSorted: true,
|
|
758
|
-
canResize: state.canResize,
|
|
759
|
-
canMove: state.canMove,
|
|
760
|
-
itemTouchSendsClick: false,
|
|
761
|
-
stackItems: true,
|
|
762
|
-
defaultTimeStart: defaultTimeStart,
|
|
763
|
-
defaultTimeEnd: defaultTimeEnd,
|
|
764
|
-
minZoom: 16 * 60 * 60 * 1000,
|
|
765
|
-
maxZoom: 1 * 365.24 * 86400 * 1000,
|
|
766
|
-
lineHeight: lineHeight,
|
|
767
|
-
itemHeightRatio: itemHeightRatio,
|
|
768
|
-
onItemResize: handleItemResize,
|
|
769
|
-
onItemMove: handleItemMove,
|
|
770
|
-
onItemDeselect: e => {
|
|
771
|
-
onItemDeselect();
|
|
772
|
-
},
|
|
773
|
-
onItemSelect: resId => {
|
|
774
|
-
if (Number(resId) > newItemId) {
|
|
775
|
-
onItemSelect(resId);
|
|
776
|
-
}
|
|
777
|
-
},
|
|
778
|
-
onItemDoubleClick: handleOnItemDoubleClick,
|
|
779
|
-
onCanvasDoubleClick: handleAddNewReservationItem,
|
|
780
|
-
itemRenderer: customItem
|
|
781
|
-
// groupRenderer={groupRenderer}
|
|
782
|
-
,
|
|
783
|
-
useResizeHandle: true
|
|
784
|
-
// fullUpdate
|
|
785
|
-
// fixedHeader="sticky"
|
|
786
|
-
// stickyOffset={40}
|
|
787
|
-
|
|
788
|
-
// traditionalZoom={false}
|
|
789
|
-
// dragSnap={1000 * 60 * 60 * 24}
|
|
790
|
-
// onCanvasClick={emptySlotClicked}
|
|
791
|
-
// onTimeChange={onTimeChange}
|
|
792
|
-
// onItemSelect={handleItemSelect}
|
|
793
|
-
,
|
|
794
|
-
ref: useRefTimeline
|
|
795
|
-
}, /*#__PURE__*/React.createElement(TimelineHeaders, {
|
|
796
|
-
key: "time_line_headers_1",
|
|
797
|
-
className: "sticky"
|
|
798
|
-
}, /*#__PURE__*/React.createElement(SidebarHeader, {
|
|
799
|
-
key: "today_sidebar_1"
|
|
800
|
-
}, ({
|
|
801
|
-
getRootProps
|
|
802
|
-
}) => {
|
|
803
|
-
return /*#__PURE__*/React.createElement("div", _extends({
|
|
804
|
-
id: "timeline_headers_1"
|
|
805
|
-
}, getRootProps(), {
|
|
806
|
-
className: "left-header"
|
|
807
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
808
|
-
className: "btn-wrapper"
|
|
809
|
-
}, String(editResId).length === 0 && /*#__PURE__*/React.createElement(IconButton, {
|
|
810
|
-
color: "inherit",
|
|
811
|
-
onClick: toggleTimelineEdit,
|
|
812
|
-
className: state.canMove ? 'blink' : ''
|
|
813
|
-
}, /*#__PURE__*/React.createElement(Edit, null)), /*#__PURE__*/React.createElement(IconButton, {
|
|
814
|
-
color: "inherit",
|
|
815
|
-
onClick: handleRelativeZoomInClick
|
|
816
|
-
}, /*#__PURE__*/React.createElement(ZoomIn, null)), /*#__PURE__*/React.createElement(IconButton, {
|
|
817
|
-
color: "inherit",
|
|
818
|
-
onClick: handleRelativeZoomOutClick
|
|
819
|
-
}, /*#__PURE__*/React.createElement(ZoomOut, null)), String(editResId).length === 0 && /*#__PURE__*/React.createElement("div", {
|
|
820
|
-
className: "flex ml-6 "
|
|
821
|
-
}, /*#__PURE__*/React.createElement(SearchLotsTextBox, {
|
|
822
|
-
label: i18next.t('reservation_grid.header.lot_number'),
|
|
823
|
-
lot_search: lot_search,
|
|
824
|
-
setLotSearch: setLotSearch,
|
|
825
|
-
setFocusOnFilter: setFocusOnFilter,
|
|
826
|
-
should_focus_on_lot_filter: should_focus_on_lot_filter
|
|
827
|
-
}), lot_search && lot_search.length > 0 && /*#__PURE__*/React.createElement(IconButton, {
|
|
828
|
-
color: "inherit",
|
|
829
|
-
style: {
|
|
830
|
-
marginTop: 8,
|
|
831
|
-
maxHeight: 46,
|
|
832
|
-
maxWidth: 46
|
|
833
|
-
},
|
|
834
|
-
onClick: () => setLotSearch('')
|
|
835
|
-
}, /*#__PURE__*/React.createElement(Close, null)))));
|
|
836
|
-
}), /*#__PURE__*/React.createElement(DateHeader, {
|
|
837
|
-
key: "primary_date_header",
|
|
838
|
-
unit: "primaryHeader",
|
|
839
|
-
labelFormat: "MMMM YYYY",
|
|
840
|
-
headerData: {
|
|
841
|
-
isMonth: true
|
|
842
|
-
},
|
|
843
|
-
intervalRenderer: intervalRenderer
|
|
844
|
-
}), /*#__PURE__*/React.createElement(DateHeader, {
|
|
845
|
-
key: "secondary_date_header",
|
|
846
|
-
height: 70,
|
|
847
|
-
headerData: {
|
|
848
|
-
isMonth: false
|
|
849
|
-
}
|
|
850
|
-
})), /*#__PURE__*/React.createElement(TimelineMarkers, {
|
|
851
|
-
key: "timeline_markers_2"
|
|
852
|
-
}, /*#__PURE__*/React.createElement(CustomMarker, {
|
|
853
|
-
key: "custom_marker_1",
|
|
854
|
-
date: todayInMilliseconds
|
|
855
|
-
}, ({
|
|
856
|
-
styles
|
|
857
|
-
}) => {
|
|
858
|
-
const customStyles = {
|
|
859
|
-
...styles,
|
|
860
|
-
backgroundColor: 'red',
|
|
861
|
-
width: '1.5px',
|
|
862
|
-
zIndex: 1
|
|
863
|
-
};
|
|
864
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
865
|
-
style: customStyles
|
|
866
|
-
});
|
|
867
|
-
})))));
|
|
868
|
-
};
|
|
869
|
-
export default ReservationTimelineComponent;
|
|
870
|
-
ReservationTimelineComponent.defaultProps = {
|
|
871
|
-
language: 'en',
|
|
872
|
-
editResId: '',
|
|
873
|
-
getNewKey: false,
|
|
874
|
-
allowAddNewReservation: true,
|
|
875
|
-
showAddNewReservationButtonInPopup: true,
|
|
876
|
-
reservationData: [],
|
|
877
|
-
lotData: [],
|
|
878
|
-
lineHeight: 50,
|
|
879
|
-
itemHeightRatio: 0.70,
|
|
880
|
-
height: '90vh !important',
|
|
881
|
-
padding: '0 16px',
|
|
882
|
-
defaultTimeStart: moment(ZERO_HOUR).subtract(7, 'days'),
|
|
883
|
-
defaultTimeEnd: moment(ZERO_HOUR).add(14, 'days'),
|
|
884
|
-
newReservationPlaceholderTimeStart: undefined,
|
|
885
|
-
newReservationPlaceholderTimeEnd: undefined,
|
|
886
|
-
onItemSelect: () => {},
|
|
887
|
-
onItemDeselect: () => {},
|
|
888
|
-
onItemDoubleClick: () => {},
|
|
889
|
-
onNewResItemDoubleClick: () => {},
|
|
890
|
-
updateNewReservationTimeLineItem: () => {},
|
|
891
|
-
updateReservationTimelineMove: () => {},
|
|
892
|
-
numberOfReservations: () => {},
|
|
893
|
-
updateReservationTimelineResize: () => {},
|
|
894
|
-
beforeItemMoveDifferentLot: ({
|
|
895
|
-
...props
|
|
896
|
-
}, onMove) => {
|
|
897
|
-
onMove();
|
|
898
|
-
},
|
|
899
|
-
//Note if this props is not supplied then we simply move the item without doing any additional work
|
|
900
|
-
adjustNewResStartEndTime: (arrivalDate, departureDate) => {
|
|
901
|
-
return {
|
|
902
|
-
newStartTime: moment(arrivalDate),
|
|
903
|
-
newEndTime: moment(departureDate)
|
|
904
|
-
};
|
|
905
|
-
},
|
|
906
|
-
//If no functions defined then it will return the same arrival and departure dates with the same time without any changes
|
|
907
|
-
TimelinePopUpComponent: undefined,
|
|
908
|
-
i18next: undefined,
|
|
909
|
-
theme: undefined
|
|
910
|
-
};
|
|
911
|
-
ReservationTimelineComponent.propTypes = {
|
|
912
|
-
/** This is the component displayed inside of the tooltip when hovering over the timeline items*/
|
|
913
|
-
TimelinePopUpComponent: PropTypes.elementType,
|
|
914
|
-
/** Indicates to the timeline to use a new key value. Useful when I need the timeline to refresh after an action. And bad in some cases where I don't wan the grid to update. Only use when I'm changing the defaultTimeStart and defaultTimeEnd date so the timeline reflect the changes made. Don't use on a standard timeline or else I will lose my focus each time I select an item that is out of the scope of the initial view port*/
|
|
915
|
-
getNewKey: PropTypes.bool,
|
|
916
|
-
/** Allows adding the new reservation item to the timeline*/
|
|
917
|
-
allowAddNewReservation: PropTypes.bool,
|
|
918
|
-
/** Controls if we see the Add New Reservation button in the popup when hovering over the new res item*/
|
|
919
|
-
showAddNewReservationButtonInPopup: PropTypes.bool,
|
|
920
|
-
/** Language string to use for the timeline */
|
|
921
|
-
language: PropTypes.string,
|
|
922
|
-
/** Converts the timeline into a res edit format if a valid reservation id is supplied. Edits are disabled and the reservation is highlighted so we know which item we are focusing on */
|
|
923
|
-
editResId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
924
|
-
/** Reservation objects used to create the item/reservation on the timeline*/
|
|
925
|
-
reservationData: PropTypes.array,
|
|
926
|
-
/** Lot objects used to cerate the groups*/
|
|
927
|
-
lotData: PropTypes.array,
|
|
928
|
-
/** Height of each group*/
|
|
929
|
-
lineHeight: PropTypes.number,
|
|
930
|
-
/** Height ration of each item inside the group based on the group height*/
|
|
931
|
-
itemHeightRatio: PropTypes.number,
|
|
932
|
-
/** Height of the component in plain CSS notation*/
|
|
933
|
-
height: PropTypes.string,
|
|
934
|
-
/** Padding around the component in plain CSS notation*/
|
|
935
|
-
padding: PropTypes.string,
|
|
936
|
-
/** Controls the starting position of the timeline, defaults to today - 7 days */
|
|
937
|
-
defaultTimeStart: PropTypes.oneOfType([PropTypes.instanceOf(moment), PropTypes.instanceOf(Date)]),
|
|
938
|
-
/** Controls the ending position of the timeline, defaults to today + 14 days */
|
|
939
|
-
defaultTimeEnd: PropTypes.oneOfType([PropTypes.instanceOf(moment), PropTypes.instanceOf(Date)]),
|
|
940
|
-
/** Controls the starting position of the new reservation placeholder */
|
|
941
|
-
newReservationPlaceholderTimeStart: PropTypes.instanceOf(Date),
|
|
942
|
-
/** Controls the ending position of the new reservation placeholder */
|
|
943
|
-
newReservationPlaceholderTimeEnd: PropTypes.instanceOf(Date),
|
|
944
|
-
/** Callback when an item is clicked. (resId) is passed to the function */
|
|
945
|
-
onItemSelect: PropTypes.func,
|
|
946
|
-
/** Callback when an item is un-clicked. no props passed to the function*/
|
|
947
|
-
onItemDeselect: PropTypes.func,
|
|
948
|
-
/** Callback when an item is double clicked. (resId) is passed to the function*/
|
|
949
|
-
onItemDoubleClick: PropTypes.func,
|
|
950
|
-
/** Callback to return the number of reservations being displayed in the timeline (number) one prop is return containing the number of reservations */
|
|
951
|
-
numberOfReservations: PropTypes.func,
|
|
952
|
-
/** Callback to pass back upwards the new dates of the new reservation item so we can adjust the parent component's date accordingly (arrivalDate, newDepartureDate)*/
|
|
953
|
-
updateNewReservationTimeLineItem: PropTypes.func,
|
|
954
|
-
/** Callback to save the changes made ot the object in our store. props passed to the callback function (reservation_id, lot_number, arrival_date, departure_date, number_of_nights) */
|
|
955
|
-
updateReservationTimelineResize: PropTypes.func,
|
|
956
|
-
/** Callback to save the changes made ot the object in our store. props passed to the callback function (reservation_id, original_lot_number, new_lot_number, arrival_date, departure_date, number_of_nights) */
|
|
957
|
-
updateReservationTimelineMove: PropTypes.func,
|
|
958
|
-
/** Callback to allow us to hook in some logic before committing to change the lot to the different lot. ({...props from item groups},moveItem()) */
|
|
959
|
-
beforeItemMoveDifferentLot: PropTypes.func,
|
|
960
|
-
/** Callback to allow us to update the arrival and departure time of the arrivalDate departureDate. Used when adding a new reservation so we can use the specified times from the seasonal object. props=(arrivalDate, departureDate) must return the following shape {newStartTime,newEndTime}*/
|
|
961
|
-
adjustNewResStartEndTime: PropTypes.func,
|
|
962
|
-
/** The i18next needs to be passed in by the component or else they will be blank */
|
|
963
|
-
i18next: PropTypes.any,
|
|
964
|
-
/** Theme object to use on this component, if none provided then the MUI5 theme provider theme is used*/
|
|
965
|
-
theme: PropTypes.object
|
|
966
|
-
};
|