Skip to content

Commit 3117b1a

Browse files
authored
Merge pull request #1721 from wix/infra/Agenda_types_fix
Agenda - types fix
2 parents c293f63 + f52bac8 commit 3117b1a

File tree

7 files changed

+178
-166
lines changed

7 files changed

+178
-166
lines changed

example/src/screens/agenda.tsx

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
11
import React, {Component} from 'react';
22
import {Alert, StyleSheet, Text, View, TouchableOpacity} from 'react-native';
3-
// @ts-expect-error
4-
import {Agenda} from 'react-native-calendars';
3+
import {Agenda, DateData, AgendaEntry, AgendaSchedule} from 'react-native-calendars';
54
import testIDs from '../testIDs';
65

7-
export default class AgendaScreen extends Component {
8-
state = {
9-
items: {}
6+
interface State {
7+
items?: AgendaSchedule;
8+
}
9+
10+
export default class AgendaScreen extends Component<State> {
11+
state: State = {
12+
items: undefined
1013
};
1114

1215
render() {
1316
return (
1417
<Agenda
1518
testID={testIDs.agenda.CONTAINER}
1619
items={this.state.items}
17-
loadItemsForMonth={this.loadItems.bind(this)}
20+
loadItemsForMonth={this.loadItems}
1821
selected={'2017-05-16'}
19-
renderItem={this.renderItem.bind(this)}
20-
renderEmptyDate={this.renderEmptyDate.bind(this)}
21-
rowHasChanged={this.rowHasChanged.bind(this)}
22+
renderItem={this.renderItem}
23+
renderEmptyDate={this.renderEmptyDate}
24+
rowHasChanged={this.rowHasChanged}
2225
showClosingKnob={true}
2326
// markingType={'period'}
2427
// markedDates={{
@@ -38,57 +41,66 @@ export default class AgendaScreen extends Component {
3841
);
3942
}
4043

41-
loadItems(day) {
44+
loadItems = (day: DateData) => {
45+
const items = this.state.items || {};
46+
4247
setTimeout(() => {
4348
for (let i = -15; i < 85; i++) {
4449
const time = day.timestamp + i * 24 * 60 * 60 * 1000;
4550
const strTime = this.timeToString(time);
46-
if (!this.state.items[strTime]) {
47-
this.state.items[strTime] = [];
51+
52+
if (!items[strTime]) {
53+
items[strTime] = [];
54+
4855
const numItems = Math.floor(Math.random() * 3 + 1);
4956
for (let j = 0; j < numItems; j++) {
50-
this.state.items[strTime].push({
57+
items[strTime].push({
5158
name: 'Item for ' + strTime + ' #' + j,
52-
height: Math.max(50, Math.floor(Math.random() * 150))
59+
height: Math.max(50, Math.floor(Math.random() * 150)),
60+
day: strTime
5361
});
5462
}
5563
}
5664
}
57-
const newItems = {};
58-
Object.keys(this.state.items).forEach(key => {
59-
newItems[key] = this.state.items[key];
65+
66+
const newItems: AgendaSchedule = {};
67+
Object.keys(items).forEach(key => {
68+
newItems[key] = items[key];
6069
});
6170
this.setState({
6271
items: newItems
6372
});
6473
}, 1000);
6574
}
6675

67-
renderItem(item) {
76+
renderItem = (reservation: AgendaEntry, isFirst: boolean) => {
77+
const fontSize = isFirst ? 16 : 14;
78+
const color = isFirst ? 'black' : '#43515c';
79+
6880
return (
6981
<TouchableOpacity
7082
testID={testIDs.agenda.ITEM}
71-
style={[styles.item, {height: item.height}]}
72-
onPress={() => Alert.alert(item.name)}
83+
style={[styles.item, {height: reservation.height}]}
84+
onPress={() => Alert.alert(reservation.name)}
7385
>
74-
<Text>{item.name}</Text>
86+
<Text style={{fontSize, color}}>{reservation.name}</Text>
7587
</TouchableOpacity>
7688
);
7789
}
7890

79-
renderEmptyDate() {
91+
renderEmptyDate = () => {
8092
return (
8193
<View style={styles.emptyDate}>
8294
<Text>This is empty date!</Text>
8395
</View>
8496
);
8597
}
8698

87-
rowHasChanged(r1, r2) {
99+
rowHasChanged = (r1: AgendaEntry, r2: AgendaEntry) => {
88100
return r1.name !== r2.name;
89101
}
90102

91-
timeToString(time) {
103+
timeToString(time: number) {
92104
const date = new Date(time);
93105
return date.toISOString().split('T')[0];
94106
}

src/agenda/index.tsx

Lines changed: 41 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,45 +21,35 @@ import {weekDayNames, sameDate, sameMonth} from '../dateutils';
2121
import {AGENDA_CALENDAR_KNOB} from '../testIDs';
2222
import {VelocityTracker} from '../velocityTracker';
2323
import {DateData} from '../types';
24+
import {getCalendarDateString} from '../services';
2425
import styleConstructor from './style';
26+
import {AgendaSchedule} from '../types';
2527
import CalendarList, {CalendarListProps} from '../calendar-list';
2628
import ReservationList, {ReservationListProps} from './reservation-list';
2729

2830

2931
const HEADER_HEIGHT = 104;
3032
const KNOB_HEIGHT = 24;
3133

32-
export type ReservationItemType = {
33-
name: string;
34-
height: number;
35-
day: XDate;
36-
};
37-
38-
export type ReservationsType = {
39-
[date: string]: ReservationItemType[];
40-
};
41-
4234
export type AgendaProps = CalendarListProps & ReservationListProps & {
4335
/** the list of items that have to be displayed in agenda. If you want to render item as empty date
4436
the value of date key has to be an empty array []. If there exists no value for date key it is
4537
considered that the date in question is not yet loaded */
46-
items: ReservationsType;
38+
items?: AgendaSchedule;
4739
/** callback that gets called when items for a certain month should be loaded (month became visible) */
48-
loadItemsForMonth?: (data: any) => DateData;
40+
loadItemsForMonth?: (data: DateData) => void;
4941
/** callback that fires when the calendar is opened or closed */
5042
onCalendarToggled?: (enabled: boolean) => void;
51-
/** callback that gets called on day press */
52-
onDayPress?: (data: DateData) => void;
5343
/** callback that gets called when day changes while scrolling agenda list */
54-
onDayChange?: (data: any) => void;
44+
onDayChange?: (data: DateData) => void;
5545
/** specify how agenda knob should look like */
5646
renderKnob?: () => JSX.Element;
5747
/** initially selected day */
58-
selected: boolean; //TODO: Should be renamed 'selectedDay'
48+
selected?: string; //TODO: Should be renamed 'selectedDay'
5949
/** Hide knob button. Default = false */
60-
hideKnob: boolean;
50+
hideKnob?: boolean;
6151
/** When `true` and `hideKnob` prop is `false`, the knob will always be visible and the user will be able to drag the knob up and close the calendar. Default = false */
62-
showClosingKnob: boolean;
52+
showClosingKnob?: boolean;
6353
}
6454

6555
type State = {
@@ -94,8 +84,6 @@ export default class Agenda extends Component<AgendaProps, State> {
9484
loadItemsForMonth: PropTypes.func,
9585
/** callback that fires when the calendar is opened or closed */
9686
onCalendarToggled: PropTypes.func,
97-
/** callback that gets called on day press */
98-
onDayPress: PropTypes.func,
9987
/** callback that gets called when day changes while scrolling agenda list */
10088
onDayChange: PropTypes.func,
10189
/** specify how agenda knob should look like */
@@ -111,14 +99,14 @@ export default class Agenda extends Component<AgendaProps, State> {
11199
private style: {[key: string]: ViewStyle};
112100
private viewHeight: number;
113101
private viewWidth: number;
114-
private scrollTimeout: any;
102+
private scrollTimeout?: ReturnType<typeof setTimeout>;
115103
private headerState: string;
116104
private currentMonth: XDate;
117-
private knobTracker: any;
105+
private knobTracker: VelocityTracker;
118106
private _isMounted: boolean | undefined;
119107
private scrollPad: React.RefObject<any> = React.createRef();
120108
private calendar: React.RefObject<CalendarList> = React.createRef();
121-
private knob: React.RefObject<any> = React.createRef();
109+
private knob: React.RefObject<View> = React.createRef();
122110
public list: React.RefObject<ReservationList> = React.createRef();
123111

124112
constructor(props: AgendaProps) {
@@ -170,7 +158,6 @@ export default class Agenda extends Component<AgendaProps, State> {
170158
if (nextProps.items) {
171159
return {firstReservationLoad: false};
172160
}
173-
174161
return null;
175162
}
176163

@@ -198,10 +185,8 @@ export default class Agenda extends Component<AgendaProps, State> {
198185
};
199186

200187
enableCalendarScrolling(enable = true) {
201-
this.setState({
202-
calendarScrollable: enable
203-
});
204-
188+
this.setState({calendarScrollable: enable});
189+
205190
this.props.onCalendarToggled?.(enable);
206191

207192
// Enlarge calendarOffset here as a workaround on iOS to force repaint.
@@ -217,22 +202,19 @@ export default class Agenda extends Component<AgendaProps, State> {
217202

218203
loadReservations(props: AgendaProps) {
219204
if ((!props.items || !Object.keys(props.items).length) && !this.state.firstReservationLoad) {
220-
this.setState(
221-
{
222-
firstReservationLoad: true
223-
},
205+
this.setState({firstReservationLoad: true},
224206
() => {
225207
this.props.loadItemsForMonth?.(xdateToData(this.state.selectedDay));
226208
}
227209
);
228210
}
229211
}
230212

231-
chooseDayFromCalendar = (d: any) => {
213+
onDayPress = (d: DateData) => {
232214
this.chooseDay(d, !this.state.calendarScrollable);
233215
};
234216

235-
chooseDay(d: any, optimisticScroll: boolean) {
217+
chooseDay(d: DateData, optimisticScroll: boolean) {
236218
const day = parseDate(d);
237219

238220
this.setState({
@@ -243,9 +225,7 @@ export default class Agenda extends Component<AgendaProps, State> {
243225
this.props.onCalendarToggled?.(false);
244226

245227
if (!optimisticScroll) {
246-
this.setState({
247-
topDay: day.clone()
248-
});
228+
this.setState({topDay: day.clone()});
249229
}
250230

251231
this.setScrollPadPosition(this.initialScrollPadPosition(), true);
@@ -255,14 +235,16 @@ export default class Agenda extends Component<AgendaProps, State> {
255235
this.props.onDayPress?.(xdateToData(day));
256236
}
257237

258-
generateMarkings = memoize((selectedDay, markedDates, items = {}) => {
238+
generateMarkings = memoize((selectedDay, markedDates, items) => {
259239
if (!markedDates) {
260240
markedDates = {};
261-
Object.keys(items).forEach(key => {
262-
if (items[key] && items[key].length) {
263-
markedDates[key] = {marked: true};
264-
}
265-
});
241+
if (items) {
242+
Object.keys(items).forEach(key => {
243+
if (items[key] && items[key].length) {
244+
markedDates[key] = {marked: true};
245+
}
246+
});
247+
}
266248
}
267249

268250
const key = toMarkingFormat(selectedDay);
@@ -326,7 +308,9 @@ export default class Agenda extends Component<AgendaProps, State> {
326308
this.props.onVisibleMonthsChange?.(months);
327309

328310
if (this.props.items && !this.state.firstReservationLoad) {
329-
clearTimeout(this.scrollTimeout);
311+
if (this.scrollTimeout) {
312+
clearTimeout(this.scrollTimeout);
313+
}
330314

331315
this.scrollTimeout = setTimeout(() => {
332316
if (this._isMounted) {
@@ -336,16 +320,13 @@ export default class Agenda extends Component<AgendaProps, State> {
336320
}
337321
};
338322

339-
onDayChange = (day: any) => {
340-
const newDate = parseDate(day);
341-
const withAnimation = sameMonth(newDate, this.state.selectedDay);
342-
323+
onDayChange = (day: XDate) => {
324+
const withAnimation = sameMonth(day, this.state.selectedDay);
343325
this.calendar?.current?.scrollToDay(day, this.calendarOffset(), withAnimation);
344-
this.setState({
345-
selectedDay: newDate
346-
});
326+
327+
this.setState({selectedDay: day});
347328

348-
this.props.onDayChange?.(xdateToData(newDate));
329+
this.props.onDayChange?.(xdateToData(day));
349330
};
350331

351332
renderReservations() {
@@ -355,7 +336,6 @@ export default class Agenda extends Component<AgendaProps, State> {
355336
<ReservationList
356337
{...reservationListProps}
357338
ref={this.list}
358-
reservations={this.props.items}
359339
selectedDay={this.state.selectedDay}
360340
topDay={this.state.topDay}
361341
onDayChange={this.onDayChange}
@@ -372,13 +352,13 @@ export default class Agenda extends Component<AgendaProps, State> {
372352
<CalendarList
373353
{...calendarListProps}
374354
ref={this.calendar}
375-
current={this.currentMonth}
355+
current={getCalendarDateString(this.currentMonth.toString())}
376356
markedDates={this.generateMarkings(this.state.selectedDay, markedDates, items)}
377357
calendarWidth={this.viewWidth}
378358
scrollEnabled={this.state.calendarScrollable}
379359
hideExtraDays={shouldHideExtraDays}
380360
onLayout={this.onCalendarListLayout}
381-
onDayPress={this.chooseDayFromCalendar}
361+
onDayPress={this.onDayPress}
382362
onVisibleMonthsChange={this.onVisibleMonthsChange}
383363
/>
384364
);
@@ -401,7 +381,12 @@ export default class Agenda extends Component<AgendaProps, State> {
401381

402382
renderWeekDaysNames = memoize((weekDaysNames: string[]) => {
403383
return weekDaysNames.map((day, index) => (
404-
<Text allowFontScaling={false} key={day + index} style={this.style.weekday} numberOfLines={1}>
384+
<Text
385+
key={day + index}
386+
style={this.style.weekday}
387+
allowFontScaling={false}
388+
numberOfLines={1}
389+
>
405390
{day}
406391
</Text>
407392
));

0 commit comments

Comments
 (0)