Skip to content

Commit

Permalink
Feature: fixed-week behavior (#75)
Browse files Browse the repository at this point in the history
* Create FixedWeekView.js as copy of WeekView.js

* Create FixedWeek component

* Update README and changelog

* Update README (minor)

* Remove FixedWeekView component and replace by prop

* Update README and changelog

* Update changelog

* Remove old reference to FixedWeekView

* Fix README (minor)

* Undo unnecessary changes

* Fix linter issues
  • Loading branch information
pdpino authored May 21, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 5a8f551 commit b3e9760
Showing 5 changed files with 122 additions and 20 deletions.
94 changes: 81 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -3,26 +3,37 @@
![weekView](images/gif.gif)


## Basic Usage
## Basic usage

```js
import WeekView from 'react-native-week-view';

const myEvents = [
// ...
{
id: 1,
description: 'Event',
startDate: new Date(2021, 3, 15, 12, 0),
endDate: new Date(2021, 3, 15, 12, 30),
color: 'blue',
// ... more properties if needed,
},
// More events...
];

const MyComponent = () => (
<WeekView
events={myEvents}
selectedDate={new Date()}
selectedDate={new Date(2021, 3, 15)}
numberOfDays={7}
/>
);

```

## Props
* **`events`** _(Array)_ - Events to display, in `Event Object` format (see below)
## Full API

### Props
* **`events`** _(Array)_ - Events to display, in `Event Object` format (see [sub-section below](#event-object))
* **`onEventPress`** _(Function)_ - Callback when event item is clicked
* **`numberOfDays`** _(Number)_ - Set number of days to show in view, can be `1`, `3`, `5`, `7`.
* **`formatDateHeader`** _(String)_ - Format for dates of header, default is `MMM D`
@@ -42,25 +53,26 @@ const MyComponent = () => (
* `pressEvent` _(Object)_ - object passed by the [TouchableWithoutFeedback.onPress() method](https://reactnative.dev/docs/touchablewithoutfeedback#onpress) (and not an event object as defined below)
* `startHour` _(Number)_ - hour clicked (as integer)
* `date` _(Date)_ - date object indicating day clicked (the hour is not relevant)
* **`EventComponent`** _(React.Component)_ - Component rendered inside an event. By default, is a `Text` with the `event.description`. See below for details on the component.
* **`EventComponent`** _(React.Component)_ - Custom component rendered inside an event. By default, is a `Text` with the `event.description`. See [sub-section below](#custom-eventcomponent) for details on the component.
* **`showNowLine`** _(Boolean)_ - If `true`, displays a line indicating the time right now. Defaults to `false`.
* **`nowLineColor`** _(String)_ - Color used for the now-line. Defaults to a red `#e53935`.
* **`rightToLeft`** _(Boolean)_ - If `true`, render older days to the right and more recent days to the left.
* **`fixedHorizontally`** _(Boolean)_ - If `true`, the component can be used to display a single fixed week. See example in [sub-section below](#fixed-week).
* **`prependMostRecent`** _(Boolean)_ - If `true`, the horizontal prepending is done in the most recent dates. See [issue #39](https://github.com/hoangnm/react-native-week-view/issues/39) for more details. Default is `false`.

## Event Object
### Event Object
```js
{
id: 1,
description: 'Event',
startDate: new Date(),
endDate: new Date(),
startDate: new Date(2021, 3, 15, 12, 0),
endDate: new Date(2021, 3, 15, 12, 30),
color: 'blue',
// ... more properties if needed,
}
```

## Methods
### Methods

To use the component methods save a reference to it:
```js
@@ -75,8 +87,8 @@ To use the component methods save a reference to it:
* **`goToPrevPage(animated = true)`**: the component navigates to the previous page (to the past). Note: if `prependMostRecent` is `false` (the default), and the component is near the first page rendered, there may be a delay on the animation.


## Custom `EventComponent`
The component will be rendered inside a `TouchableOpacity`, which has the background color set to `event.color`, and is placed with absolute position in the grid. The component receives two props:
### Custom `EventComponent`
The custom component will be rendered inside a `TouchableOpacity`, which has the background color set to `event.color`, and is placed with absolute position in the grid. The component receives two props:
* **`event`** _(Event)_ - Event object as described before.
* **`position`**: _(Object)_ - object containing `top`, `left`, `height` and `width` values in pixels.

@@ -97,7 +109,8 @@ const MyEventComponent = ({ event, position }) => (
/>
```

## Locales customization
### Locales customization

There's a `addLocale` function to add customized locale for the component. The component depends on `momentjs`, you can refer to https://momentjs.com/docs/#/customization/ for more information.

Example:
@@ -112,6 +125,61 @@ addLocale('fr', {
});
```

## Other example usages

### Fixed week

The `WeekView` component can be used to display a fixed week (as a timetable):

* Use the prop `fixedHorizontally={true}`. This prop should not be changed after the first render

* To set `startDate` and `endDate` in each event, you should use the function provided: `createFixedWeekDate(day, hour, minutes=0, seconds=0)`, where:
* `day`: _(Number|String)_ - specify day of the week as number (1 is monday, 2 is tuesday, etc) or as string (will be parsed with the current locale, e.g. `"Monday"`, `"Tuesday"`, etc. for english).
* `hour`: _(Number)_ - specify hour of the day as number (from 0 to 23)
* `minutes`: _(Number)_ - specify minutes of the day as number (from 0 to 59), defaults to 0
* `seconds`: _(Number)_ - specify seconds of the day as number (from 0 to 59), defaults to 0

If you choose to not use `createFixedWeekDate()`, make sure that `startDate` and `endDate` are `Date` objects within this week, otherwise the events will not be displayed correctly in the timetable.


* If the `numberOfDays` is other than 7, will display the first days of the week. E.g. if `numberOfDays === 5`, will display from monday to friday.


```js
import WeekView, { createFixedWeekDate } from 'react-native-week-view';

const myEvents = [
{
id: 1,
description: 'Event 1',
startDate: createFixedWeekDate('Monday', 12), // Day may be passed as string
endDate: createFixedWeekDate(1, 14), // Or as number, 1 = monday
color: 'blue',
},
{
id: 2,
description: 'Event 2',
startDate: createFixedWeekDate('wed', 16),
endDate: createFixedWeekDate(3, 16, 30),
color: 'red',
},
];

const MyComponent = () => (
<WeekView
events={myEvents}
fixedHorizontally={true}
// Recommended props:
showTitle={false} // if true, shows this month and year
numberOfDays={7}
formatDateHeader="ddd" // display short name days, e.g. Mon, Tue, etc
// ... other props
/>
);
```



## TODO
- [x] allow to swipe between weeks or days.
- [x] header should be swipeable with columns.
30 changes: 26 additions & 4 deletions example/App.js
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
import React from 'react';
import {SafeAreaView, StyleSheet, StatusBar, Alert} from 'react-native';

import WeekView from 'react-native-week-view';
import WeekView, {createFixedWeekDate} from 'react-native-week-view';

const generateDates = (hours, minutes) => {
const date = new Date();
@@ -44,9 +44,29 @@ const sampleEvents = [
},
];

const sampleFixedEvents = [
{
id: 1,
description: 'Event 1',
startDate: createFixedWeekDate('Monday', 12),
endDate: createFixedWeekDate(1, 14),
color: 'blue',
},
{
id: 2,
description: 'Event 2',
startDate: createFixedWeekDate('wed', 16),
endDate: createFixedWeekDate(3, 17, 30),
color: 'red',
},
];

// For debugging purposes
const showFixedComponent = true;

class App extends React.Component {
state = {
events: sampleEvents,
events: showFixedComponent ? sampleFixedEvents : sampleEvents,
selectedDate: new Date(),
};

@@ -74,17 +94,19 @@ class App extends React.Component {
}}
events={events}
selectedDate={selectedDate}
numberOfDays={3}
numberOfDays={7}
onEventPress={this.onEventPress}
onGridClick={this.onGridClick}
headerStyle={styles.header}
headerTextStyle={styles.headerText}
hourTextStyle={styles.hourText}
eventContainerStyle={styles.eventContainer}
formatDateHeader="MMM D"
formatDateHeader={showFixedComponent ? 'ddd' : 'ddd DD'}
hoursInDisplay={12}
timeStep={60}
startHour={8}
fixedHorizontally={showFixedComponent}
showTitle={!showFixedComponent}
showNowLine
/>
</SafeAreaView>
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { default } from './src/WeekView/WeekView';
export { addLocale } from './src/utils';
export { addLocale, createFixedWeekDate } from './src/utils';
8 changes: 6 additions & 2 deletions src/WeekView/WeekView.js
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ export default class WeekView extends Component {
props.selectedDate,
props.numberOfDays,
props.prependMostRecent,
props.fixedHorizontally,
);
this.state = {
// currentMoment should always be the first date of the current page
@@ -257,10 +258,10 @@ export default class WeekView extends Component {
this.header = ref;
};

calculatePagesDates = (currentMoment, numberOfDays, prependMostRecent) => {
calculatePagesDates = (currentMoment, numberOfDays, prependMostRecent, fixedHorizontally) => {
const initialDates = [];
const centralDate = moment(currentMoment);
if (numberOfDays === 7) {
if (numberOfDays === 7 || fixedHorizontally) {
// Start week on monday
centralDate.startOf('isoWeek');
}
@@ -335,6 +336,7 @@ export default class WeekView extends Component {
EventComponent,
prependMostRecent,
rightToLeft,
fixedHorizontally,
showNowLine,
nowLineColor,
} = this.props;
@@ -399,6 +401,7 @@ export default class WeekView extends Component {
getItemLayout={(_, index) => this.getListItemLayout(index)}
keyExtractor={(item) => item}
initialScrollIndex={this.pageOffset}
scrollEnabled={!fixedHorizontally}
renderItem={({ item }) => {
return (
<Events
@@ -464,6 +467,7 @@ WeekView.propTypes = {
EventComponent: PropTypes.elementType,
showTitle: PropTypes.bool,
rightToLeft: PropTypes.bool,
fixedHorizontally: PropTypes.bool,
prependMostRecent: PropTypes.bool,
showNowLine: PropTypes.bool,
nowLineColor: PropTypes.string,
8 changes: 8 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -44,3 +44,11 @@ export const calculateDaysArray = (date, numberOfDays, rightToLeft) => {
}
return rightToLeft ? dates.reverse() : dates;
};

export const createFixedWeekDate = (day, hours, minutes=0, seconds=0) => {
const date = moment();
date.isoWeekday(day);
date.hours(hours);
date.minutes(minutes);
return date.toDate();
};

0 comments on commit b3e9760

Please sign in to comment.