diff --git a/README.md b/README.md
index a91c623..cec2212 100644
--- a/README.md
+++ b/README.md
@@ -67,7 +67,7 @@ We use for generic UI components
## TODO upgrade
+- Refactor EventDetail and EventList to functional components
- Make stripe work again
- Fix icons
- Fix colors in native base theme
-- Refactor EventDetail and EventList to functional components
diff --git a/src/Navigation.js b/src/Navigation.js
index 57ead87..ffcf2a0 100644
--- a/src/Navigation.js
+++ b/src/Navigation.js
@@ -5,7 +5,7 @@ import { createNativeStackNavigator } from '@react-navigation/native-stack';
import Icon from 'react-native-vector-icons/SimpleLineIcons';
import EventListScreen from './screens/EventListScreen';
-import EventDetailScreen from './screens/EventDetailScreen';
+import EventDetail from './modules/events/EventDetail';
import Membership from './modules/membership/Membership';
import Login from './modules/login/Login';
@@ -24,8 +24,8 @@ const EventStackScreen = () => (
/>
({ title: route.params.item.title.decoded })}
+ component={EventDetail}
+ options={({ route }) => ({ title: route.params.event.title.decoded })}
/>
);
diff --git a/src/modules/events/EventDetail.js b/src/modules/events/EventDetail.js
index 0264bd2..3c9913d 100644
--- a/src/modules/events/EventDetail.js
+++ b/src/modules/events/EventDetail.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React from 'react';
import { Linking, StyleSheet, ScrollView, Text, Platform, View, Image, TouchableOpacity } from 'react-native';
import HTMLView from 'react-native-htmlview';
import moment from 'moment';
@@ -10,230 +10,192 @@ moment.locale('nb');
const CHATEAU_NEUF_ADDRESS = 'Chateau Neuf, Slemdalsveien 15, 0369 Oslo';
-export default class EventDetail extends Component {
- _formatTime(time) {
- return moment(time).format('HH:mm');
+const FORMAT_TIME = 'HH:mm';
+const FORMAT_MONTH = 'MMM';
+const FORMAT_DAY = 'DD.';
+const FORMAT_LOCAL_DAY = 'ddd';
+const FORMAT_YEAR = 'YYYY';
+
+const formatRelative = (time) => moment(time).fromNow();
+
+const format = (time, formatString = FORMAT_TIME) => moment(time).format(formatString);
+
+const formatTicketText = (event) => {
+ /* FIXME: This should be handled by API */
+ let regularPrice = '';
+ let memberPrice = '';
+ if (event.price_regular === '0') {
+ event.price_regular = 'Gratis';
+ }
+ if (event.price_member === '0') {
+ event.price_member = 'Gratis';
+ }
+ if (event.price_regular !== 'Gratis') {
+ regularPrice = ' kr';
+ }
+ if (event.price_member !== 'Gratis') {
+ memberPrice = ' kr';
}
- _formatMonth(time) {
- return moment(time).format('MMM');
+ let text = '';
+ if (event.price_regular && event.price_member) {
+ text = `Pris: ${event.price_regular}${regularPrice} / Medlemmer: ${event.price_member}${memberPrice}`;
+ } else if (event.price_regular) {
+ text = `Pris: ${event.price_regular}${regularPrice}`;
+ } else if (event.price_member) {
+ text = `Pris (Medlemmer): ${event.price_member}${memberPrice}`;
+ } else {
+ return '';
+ }
+ return text;
+};
+
+const onFacebookUrlPress = (link) => {
+ const fbEventPattern = /https?:\/\/www\.facebook\.com\/events\/(\d+)\/?/i;
+ const matches = fbEventPattern.exec(link);
+ let iosURL = link;
+ if (matches && matches.length) {
+ iosURL = `fb://event/?id=${matches[1]}`;
+ }
+ const url = Platform.select({
+ ios: iosURL,
+ android: link,
+ });
+ Linking.canOpenURL(url)
+ .then((supported) => {
+ if (!supported) {
+ return Linking.openURL(link);
+ }
+ return Linking.openURL(url);
+ })
+ .catch((err) => console.error('An error occurred', err));
+};
+
+const onLocationPress = (venue) => {
+ if (venue !== 'Annetsteds') {
+ Linking.openURL(`https://www.google.com/maps/dir/?api=1&destination=${CHATEAU_NEUF_ADDRESS}`);
+ }
+};
+
+const VenueLocation = ({ venue }) => (venue !== 'Annetsteds' ? CHATEAU_NEUF_ADDRESS : 'Ukjent adresse');
+
+const PriceAndTicket = ({ event }) => {
+ const text = formatTicketText(event);
+
+ if (text === '') {
+ return null;
}
- _formatDay(time) {
- return moment(time).format('DD.');
- }
-
- _formatLocalDay(time) {
- return moment(time).format('ddd');
- }
-
- _formatYear(time) {
- return moment(time).format('YYYY');
- }
-
- _formatRelative(time) {
- return moment(time).fromNow();
- }
-
- _formatLocation() {
- if (this.props.item.venue !== 'Annetsteds') {
- return CHATEAU_NEUF_ADDRESS;
- }
- return 'Ukjent adresse';
- }
-
- _formatTicketText() {
- /* FIXME: This should be handled by API */
- const { item } = this.props;
- let regularPrice = '';
- let memberPrice = '';
- if (item.price_regular === '0') {
- item.price_regular = 'Gratis';
- }
- if (item.price_member === '0') {
- item.price_member = 'Gratis';
- }
- if (item.price_regular !== 'Gratis') {
- regularPrice = ' kr';
- }
- if (item.price_member !== 'Gratis') {
- memberPrice = ' kr';
- }
-
- let text = '';
- if (item.price_regular && item.price_member) {
- text = `Pris: ${item.price_regular}${regularPrice} / Medlemmer: ${item.price_member}${memberPrice}`;
- } else if (item.price_regular) {
- text = `Pris: ${item.price_regular}${regularPrice}`;
- } else if (item.price_member) {
- text = `Pris (Medlemmer): ${item.price_member}${memberPrice}`;
- } else {
- return '';
- }
- return text;
- }
-
- onTicketUrlPress(link) {
- Linking.openURL(link);
- }
-
- onFacebookUrlPress(link) {
- const fbEventPattern = /https?:\/\/www\.facebook\.com\/events\/(\d+)\/?/i;
- const matches = fbEventPattern.exec(link);
- let iosURL = link;
- if (matches && matches.length) {
- iosURL = `fb://event/?id=${matches[1]}`;
- }
- const url = Platform.select({
- ios: iosURL,
- android: link,
- });
- Linking.canOpenURL(url)
- .then((supported) => {
- if (!supported) {
- return Linking.openURL(link);
- }
- return Linking.openURL(url);
- })
- .catch((err) => console.error('An error occurred', err));
- }
-
- onLocationPress(venue) {
- if (venue !== 'Annetsteds') {
- Linking.openURL(`https://www.google.com/maps/dir/?api=1&destination=${CHATEAU_NEUF_ADDRESS}`);
- }
- }
-
- showPriceAndTicket() {
- const { item } = this.props;
- const text = this._formatTicketText();
-
- if (text === '') {
- return null;
- }
-
- if (item.ticket_url) {
- return (
- this.onTicketUrlPress(item.ticket_url)}>
-
-
-
-
- {text}
- Kjøp billett
-
-
- );
- }
-
+ if (event.ticket_url) {
return (
-
+ Linking.openURL(event.ticket_url)}>
{text}
- Billett i døra
-
-
- );
- }
-
- showFacebutton() {
- const { item } = this.props;
- if (!item.facebook_url) {
- return null;
- }
-
- return (
- this.onFacebookUrlPress(item.facebook_url)} style={styles.metaInner}>
-
-
-
-
- På Facebook
+ Kjøp billett
);
}
- showImage() {
- const { item } = this.props;
-
- if (item.thumbnail.medium_large) {
- return ;
- }
+ return (
+
+
+
+
+
+ {text}
+ Billett i døra
+
+
+ );
+};
+const FaceButton = ({ event }) => {
+ if (!event.facebook_url) {
return null;
}
- showYear() {
- const { item } = this.props;
-
- if (moment().year() !== moment(item.start_time).year()) {
- return {this._formatYear(item.start_time)};
- }
+ return (
+ onFacebookUrlPress(event.facebook_url)} style={styles.metaInner}>
+
+
+
+
+ På Facebook
+
+
+ );
+};
+const Year = ({ startTime }) => {
+ if (moment().year() === moment(startTime).year()) {
return null;
}
+ return {format(startTime, FORMAT_YEAR)};
+};
- formatTimeFull(item) {
- const endTime = item.end_time ? ` - ${this._formatTime(item.end_time)}` : '';
- const startTime = `${this._formatLocalDay(item.start_time)} kl. ${this._formatTime(item.start_time)}`;
- return `${startTime}${endTime}`;
- }
+const formatTimeFull = (event) => {
+ const endTime = event.end_time ? ` - ${format(event.end_time, FORMAT_TIME)}` : '';
+ const startTime = `${format(event.start_time, FORMAT_LOCAL_DAY)} kl. ${format(event.start_time, FORMAT_TIME)}`;
+ return `${startTime}${endTime}`;
+};
- render() {
- const { item } = this.props;
- return (
-
- {this.showImage()}
-
- {/* Date and title */}
-
-
-
- {this._formatDay(item.start_time)}
- {this._formatMonth(item.start_time)}
- {this.showYear()}
-
-
-
-
- {item.title.decoded}
-
-
+const EventDetail = ({
+ route: {
+ params: { event },
+ },
+}) => (
+
+ {event.thumbnail.medium_large && }
+
+ {/* Date and title */}
+
+
+
+ {format(event.start_time, FORMAT_DAY)}
+ {format(event.start_time, FORMAT_MONTH)}
+
- {/* Time and calendar */}
-
-
-
-
-
- {this.formatTimeFull(item)}
- {this._formatRelative(item.start_time)}
-
-
- {/* Location and maps */}
- this.onLocationPress(item.venue)}>
-
-
-
-
- {item.venue}
-
- {this._formatLocation()}
-
-
-
- {this.showPriceAndTicket()}
- {this.showFacebutton()}
-
-
- );
- }
-}
+
+
+ {event.title.decoded}
+
+
+
+ {/* Time and calendar */}
+
+
+
+
+
+ {formatTimeFull(event)}
+ {formatRelative(event.start_time)}
+
+
+ {/* Location and maps */}
+ onLocationPress(event.venue)}>
+
+
+
+
+ {event.venue}
+
+
+
+
+
+
+
+
+
+
+);
+
+export default EventDetail;
const styles = StyleSheet.create({
dateAndTitle: {
diff --git a/src/screens/EventDetailScreen.js b/src/screens/EventDetailScreen.js
deleted file mode 100644
index 7dd81d5..0000000
--- a/src/screens/EventDetailScreen.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from 'react';
-
-import EventDetail from '../modules/events/EventDetail';
-
-const EventDetailScreen = ({ route }) => ;
-
-export default EventDetailScreen;
diff --git a/src/screens/EventListScreen.js b/src/screens/EventListScreen.js
index 31024c7..1e3d6dd 100644
--- a/src/screens/EventListScreen.js
+++ b/src/screens/EventListScreen.js
@@ -7,8 +7,8 @@ const EventListScreen = () => {
const { navigate } = useNavigation();
return (
{
- navigate('EventDetail', { item });
+ showEvent={(event) => {
+ navigate('EventDetail', { event });
}}
/>
);