diff --git a/controllers/AttendeesListViewController.js b/controllers/AttendeesListViewController.js
index ec1e4e6..a86b7e4 100644
--- a/controllers/AttendeesListViewController.js
+++ b/controllers/AttendeesListViewController.js
@@ -9,6 +9,7 @@
import moment from 'moment';
import React from 'react';
import {FlatList, View, ActivityIndicator} from 'react-native';
+import SegmentedControlTab from 'react-native-segmented-control-tab';
import {inject, observer} from 'mobx-react/native';
import {SearchBar} from 'react-native-elements';
@@ -20,6 +21,14 @@ import TournamentRow from './components/TournamentRow';
const keyExtractor = (item, index) => item.id;
export default class AttendeesListViewController extends MemeleeViewController {
+ state = {
+ selectedIndex: 0
+ };
+
+ swapIndex = (index) => this.setState({
+ selectedIndex: index
+ });
+
renderItem = ({item}) => ()
render() {
@@ -28,7 +37,20 @@ export default class AttendeesListViewController extends MemeleeViewController {
keyExtractor: keyExtractor,
renderItem: this.renderItem
};
+
+ const segmentedProps = {
+ values: ['Players', 'Teams'],
+ borderRadius: 0,
+ activeTabStyle: styles.tournamentInfoActiveTableStyle,
+ tabStyle: styles.tournamentInfoTabsStyle,
+ tabTextStyle: styles.tournamentInfoTabTextStyle,
+ selectedIndex: this.state.selectedIndex,
+ onTabPress: this.swapIndex
+ };
- return
+ return (
+
+
+ );
}
}
diff --git a/controllers/BracketViewController.js b/controllers/BracketViewController.js
index 9247047..4fabba9 100644
--- a/controllers/BracketViewController.js
+++ b/controllers/BracketViewController.js
@@ -11,13 +11,21 @@ import React from 'react';
import {ScrollView, Text, View} from 'react-native';
import {inject, observer} from 'mobx-react/native';
+import styles from '../styles';
+
import MemeleeViewController from './MemeleeViewController';
const Match = ({set, ...rest}) => (
-
- {set.entrant1.name ? set.entrant1.name : ''} {set.entrant1Score}
-
- {set.entrant2.name ? set.entrant2.name : ''} {set.entrant2Score}
+
+
+ {set.entrant1.name ? set.entrant1.name : ''}
+ {set.entrant1Score}
+
+
+
+ {set.entrant2.name ? set.entrant2.name : ''}
+ {set.entrant2Score}
+
);
@@ -33,8 +41,11 @@ export default class BracketViewController extends MemeleeViewController {
{this.props.Events.bracketData[key].map(bracket => (
- {bracket.title}
- {bracket.sets.map(set => )}
+ {bracket.title}
+ {bracket.sets.map(set => {
+ if(set.isGF) console.log(JSON.stringify(set, null, 4));
+ return ;
+ })}
))}
diff --git a/controllers/ContactViewController.js b/controllers/ContactViewController.js
index ec1e4e6..e54b43c 100644
--- a/controllers/ContactViewController.js
+++ b/controllers/ContactViewController.js
@@ -6,29 +6,54 @@
* @copyright Ryan McGrath 2018.
*/
-import moment from 'moment';
import React from 'react';
-import {FlatList, View, ActivityIndicator} from 'react-native';
-import {inject, observer} from 'mobx-react/native';
-import {SearchBar} from 'react-native-elements';
+import {ScrollView, View, Text, StyleSheet} from 'react-native';
+import Markdown from 'react-native-markdown-renderer';
+import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
+import SettingsList, {Header, Item} from 'react-native-settings-list';
import styles from '../styles';
-import Constants from '../utils/Constants';
+import {openURL} from '../utils';
import MemeleeViewController from './MemeleeViewController';
-import TournamentRow from './components/TournamentRow';
-const keyExtractor = (item, index) => item.id;
-
-export default class AttendeesListViewController extends MemeleeViewController {
- renderItem = ({item}) => ()
+export default class ContactViewController extends MemeleeViewController {
+ email = () => { openURL('mailto:' + this.props.data.email); }
+ phone = () => { openURL('tel:' + this.props.data.phone); }
+ twitter = () => { openURL('https://twitter.com/' + this.props.data.twitter); }
render() {
- const props = {
- data: this.props.data,
- keyExtractor: keyExtractor,
- renderItem: this.renderItem
+ const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
+ const ss = {
+ itemWidth: 50,
+ backgroundColor: s.backgroundColor,
+ style: styles.tournamentDetailsEventWrapper,
+ titleStyle: styles.tournamentDetailsEventItem
};
- return
+ return (
+
+ {this.props.data.email ? -
+
+
+ } /> : null}
+ {this.props.data.phone ? -
+
+
+ } /> : null}
+ {this.props.data.twitter ?
-
+
+
+ } /> : null}
+
+
+ {this.props.data.info ?
+
+ {this.props.data.info}
+
+ : null}
+ );
}
}
diff --git a/controllers/LocationViewController.js b/controllers/LocationViewController.js
index ec1e4e6..1c8f3e7 100644
--- a/controllers/LocationViewController.js
+++ b/controllers/LocationViewController.js
@@ -6,29 +6,38 @@
* @copyright Ryan McGrath 2018.
*/
-import moment from 'moment';
import React from 'react';
-import {FlatList, View, ActivityIndicator} from 'react-native';
-import {inject, observer} from 'mobx-react/native';
-import {SearchBar} from 'react-native-elements';
+import {ScrollView, StyleSheet, Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
+import Markdown, {PluginContainer} from 'react-native-markdown-renderer';
+import SettingsList, {Header, Item} from 'react-native-settings-list';
+import openMap from 'react-native-open-maps';
import styles from '../styles';
-import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
-import TournamentRow from './components/TournamentRow';
-
-const keyExtractor = (item, index) => item.id;
-
-export default class AttendeesListViewController extends MemeleeViewController {
- renderItem = ({item}) => ()
+export default class LocationViewController extends MemeleeViewController {
render() {
- const props = {
- data: this.props.data,
- keyExtractor: keyExtractor,
- renderItem: this.renderItem
+ const addy = '\n' + this.props.data.venue.name + '\n' + this.props.data.venue.address + ' ' + this.props.data.venue.city +
+ ' ' + this.props.data.venue.state + ' ' + this.props.data.venue.postalCode + '\n' + this.props.data.venue.country + '\n';
+
+ const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
+ const ss = {
+ itemWidth: 50,
+ backgroundColor: s.backgroundColor,
+ style: styles.tournamentDetailsEventWrapper,
+ titleStyle: styles.tournamentDetailsEventItem
};
- return
+ return (
+
+
- openMap({latitude: this.props.data.map.lat, longitude: this.props.data.map.lng})} />
+
+
+ {this.props.data.gettingThere ?
+
+ {this.props.data.gettingThere}
+
+ : null}
+ );
}
}
diff --git a/controllers/TournamentInfoViewController.js b/controllers/TournamentInfoViewController.js
index 85538bd..c032118 100644
--- a/controllers/TournamentInfoViewController.js
+++ b/controllers/TournamentInfoViewController.js
@@ -9,6 +9,7 @@
import moment from 'moment';
import React from 'react';
import {ScrollView, StyleSheet, Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
+import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import Markdown, {PluginContainer} from 'react-native-markdown-renderer';
import SegmentedControlTab from 'react-native-segmented-control-tab';
import SettingsList, {Header, Item} from 'react-native-settings-list';
@@ -21,16 +22,116 @@ import EventsStore from '../stores/TournamentEventStore';
import MemeleeViewController from './MemeleeViewController';
const w = Dimensions.get('screen').width;
-/*
-
- Register
-
-
- Bookmark
-
-
-*/
+const determineTabs = (tournament) => {
+ const slugs = parseSlugs(tournament, null);
+ const tabs = [
+ // Actually can't do this without using what's pretty clearly a private API. :(
+ // {slug: 'attendees', name: 'Attendees', screen: Constants.Screens.Attendees, adminOnly: false, data: []}
+ {slug: 'attendees', icon: 'link', name: 'Attendees', url: 'https://smash.gg/tournament/' + slugs.tournament + '/attendees/players', adminOnly: false}
+ ];
+
+ if(
+ tournament.gettingThere || tournament.lat || tournament.lng || tournament.mapsPlaceId || tournament.venueName ||
+ tournament.venueAddress || tournament.city || tournament.addrState || tournament.countryCode || tournament.postalCode
+ ) tabs.push({
+ slug: 'location',
+ name: 'Location',
+ icon: 'map-marker',
+ screen: Constants.Screens.Location,
+ adminOnly: false,
+ data: {
+ gettingThere: tournament.gettingThere,
+ map: {
+ lat: tournament.lat,
+ lng: tournament.lng,
+ mapsPlaceId: tournament.mapsPlaceId,
+ },
+ venue: {
+ name: tournament.venueName,
+ address: tournament.venueAddress,
+ city: tournament.city,
+ state: tournament.addrState,
+ country: tournament.countryCode,
+ postalCode: tournament.postalCode
+ }
+ }
+ });
+
+ tabs.push({
+ slug: 'contact',
+ name: 'Contact',
+ icon: 'email',
+ screen: Constants.Screens.Contact,
+ adminOnly: false,
+ data: {
+ email: tournament.contactEmail,
+ info: tournament.contactInfo,
+ phone: tournament.contactPhone,
+ twitter: tournament.contactTwitter
+ }
+ });
+
+ if(tournament.rules && tournament.rules !== '') {
+ if(tournament.rules.startsWith('http://') || tournament.rules.startsWith('https://')) {
+ tabs.push({slug: 'rules', icon: 'link', name: 'Rules', url: tournament.rules, adminOnly: false});
+ } else {
+ tabs.push({slug: 'rules', name: 'Rules', icon: 'file-document-box', info: tournament.rules, adminOnly: false});
+ }
+ }
+
+ if(tournament.prizes && tournament.prizes !== '') {
+ if(tournament.prizes.startsWith('http://') || tournament.prizes.startsWith('https://')) {
+ tabs.push({slug: 'prizes', name: 'Prizes', icon: 'trophy', url: tournament.prizes, adminOnly: false});
+ } else {
+ tabs.push({slug: 'prizes', name: 'Prizes', icon: 'trophy', info: tournament.prizes, adminOnly: false});
+ }
+ }
+
+ if(tournament.publishing && tournament.publishing.fantasy)
+ tabs.push({
+ slug: 'fantasy',
+ name: 'Fantasy',
+ icon: 'chart-timeline',
+ url: 'https://smash.gg/tournament/' + slugs.tournament + '/fantasy/',
+ adminOnly: false
+ });
+
+ const generatedTabs = tournament.generatedTabs;
+ if(generatedTabs) {
+ const objs = Object.keys(generatedTabs).map(key => generatedTabs[key]);
+
+ objs.forEach(tab => {
+ Object.keys(tab).map(key => ({
+ slug: key,
+ name: tab[key].name,
+ adminOnly: tab[key].adminOnly,
+ icon: 'link',
+ url: 'https://smash.gg/tournament/' + slugs.tournament + '/' + key
+ })).filter(tab => !tab.adminOnly || tab.adminOnly === false).forEach(tab => tabs.push(tab));
+ });
+ }
+
+ const links = tournament.links;
+ if(links) {
+ Object.keys(tournament.links).forEach(key => {
+ tabs.push({
+ slug: key,
+ icon: 'link',
+ name: key[0].toUpperCase() + key.substring(1),
+ url: links[key]
+ });
+ });
+ }
+
+ return tabs;
+}
+
+const SIcon = (icon) => (
+
+
+
+);
export default class TournamentInfoViewController extends MemeleeViewController {
state = {
@@ -39,50 +140,9 @@ export default class TournamentInfoViewController extends MemeleeViewController
};
componentWillMount = () => {
- const tabs = [
- {slug: 'attendees', name: 'Attendees', screen: Constants.Screens.Attendees, adminOnly: false},
- {slug: 'location', name: 'Location', screen: Constants.Screens.Location, adminOnly: false},
- {slug: 'contact', name: 'Contact', screen: Constants.Screens.Contact, adminOnly: false}
- ];
-
- if(this.props.tournament.rules && this.props.tournament.rules !== '') {
- if(this.props.tournament.rules.startsWith('http://') || this.props.tournament.rules.startsWith('https://')) {
- tabs.push({slug: 'rules', name: 'Rules', url: this.props.tournament.rules, adminOnly: false});
- } else {
- tabs.push({slug: 'rules', name: 'Rules', info: this.props.tournament.rules, adminOnly: false});
- }
- }
-
- if(this.props.tournament.prizes && this.props.tournament.prizes !== '') {
- if(this.props.tournament.prizes.startsWith('http://') || this.props.tournament.prizes.startsWith('https://')) {
- tabs.push({slug: 'prizes', name: 'Prizes', url: this.props.tournament.prizes, adminOnly: false});
- } else {
- tabs.push({slug: 'prizes', name: 'Prizes', info: this.props.tournament.prizes, adminOnly: false});
- }
- }
-
- if(this.props.tournament.publishing && this.props.tournament.publishing.fantasy)
- tabs.push({
- slug: 'fantasy',
- name: 'Fantasy',
- url: 'https://smash.gg/tournament/' + parseSlugs(this.props.tournament, null).tournament + '/fantasy/',
- adminOnly: false
- });
-
- const generatedTabs = this.props.tournament.generatedTabs;
- if(generatedTabs) {
- const objs = Object.keys(generatedTabs).map(key => generatedTabs[key]);
-
- objs.forEach(tab => {
- Object.keys(tab).map(key => ({
- slug: key,
- name: tab[key].name,
- adminOnly: tab[key].adminOnly
- })).filter(tab => !tab.adminOnly || tab.adminOnly === false).forEach(tab => tabs.push(tab));
- });
- }
-
- this.setState({tabs: tabs});
+ this.setState({
+ tabs: determineTabs(this.props.tournament)
+ });
}
onEventTapped = (evt) => {
@@ -100,7 +160,7 @@ export default class TournamentInfoViewController extends MemeleeViewController
return this.props.navigator.push({
screen: tab.screen,
title: tab.name,
- passProps: {data: []},
+ passProps: {data: tab.data},
navigatorStyle: {tabBarHidden: true}
});
@@ -146,7 +206,7 @@ export default class TournamentInfoViewController extends MemeleeViewController
- {this.state.tabs.map(tab => - this.handleTab(tab)} />)}
+ {this.state.tabs.map(tab =>
- this.handleTab(tab)} />)}
) : null}
diff --git a/controllers/components/TournamentRow.js b/controllers/components/TournamentRow.js
index a6c6f70..86af2e1 100644
--- a/controllers/components/TournamentRow.js
+++ b/controllers/components/TournamentRow.js
@@ -34,7 +34,7 @@ export default class TournamentRow extends React.Component {
- {this.props.tournament.hasOnlineEvents && (!this.props.tournament.city || this.props.tournament.city === '') ? 'Online' : (this.props.tournament.city ? this.props.tournament.city + ', ' : '') + this.props.tournament.addrState}
+ {this.props.tournament.hasOnlineEvents && (!this.props.tournament.city || this.props.tournament.city === '') ? 'Online' : (this.props.tournament.city ? this.props.tournament.city + ', ' : '') + (this.props.tournament.addrState ? this.props.tournament.addrState : '')}
{this.props.tournament.memeleeEventsCount} Events
diff --git a/ios/memelee.xcodeproj/project.xcworkspace/xcuserdata/laika.xcuserdatad/UserInterfaceState.xcuserstate b/ios/memelee.xcodeproj/project.xcworkspace/xcuserdata/laika.xcuserdatad/UserInterfaceState.xcuserstate
index 04176fb..cb36ff7 100644
Binary files a/ios/memelee.xcodeproj/project.xcworkspace/xcuserdata/laika.xcuserdatad/UserInterfaceState.xcuserstate and b/ios/memelee.xcodeproj/project.xcworkspace/xcuserdata/laika.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/package.json b/package.json
index 1714b5b..dae0fa1 100644
--- a/package.json
+++ b/package.json
@@ -31,8 +31,10 @@
"react-native": "0.52.0",
"react-native-elements": "^0.19.0",
"react-native-hyperlink": "0.0.12",
+ "react-native-maps": "^0.21.0",
"react-native-markdown-renderer": "^3.1.0",
"react-native-navigation": "^1.1.426",
+ "react-native-open-maps": "^0.1.4",
"react-native-segmented-control-tab": "^3.2.2",
"react-native-settings-list": "^1.8.0",
"react-native-svg": "^6.3.1",
diff --git a/stores/TournamentEventStore.js b/stores/TournamentEventStore.js
index e44618b..d52dfd9 100644
--- a/stores/TournamentEventStore.js
+++ b/stores/TournamentEventStore.js
@@ -139,6 +139,10 @@ class Store {
*
* @arg bracketID {String or Number} ID for the bracket - SmashGG calls this a phase. Go fig.
*/
+
+//https://smash.gg/api/-/gg_api./tournament/fighter-s-spirit-2018-1;eventSlug=street-fighter-v-arcade-edition-singles;expand=["event","phase","wave","station","stream","entrantCounts","tagsByEntity","ruleset"];mutations=["playerData","profileTaskNotifs"];phaseId=246410;reset=false;slug=fighter-s-spirit-2018-1?returnMeta=true
+
+
fetchBracketData = (bracketID) => {
this.bracketData = {winners: [], losers: []};
this.bracketID = bracketID;
@@ -157,10 +161,15 @@ class Store {
};
const url = api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true'
- console.log(url);
+ //console.log(url);
fetch(
url
).then(response => response.json()).then(data => {
+ if(data.items.resultEntity && data.items.resultEntity === 'groups' && typeof data.items.entities.sets === 'undefined') {
+ this.parseAndStoreGroups(data);
+ return;
+ }
+
const grands = [];
const brackets = {
winners: [],
@@ -176,13 +185,14 @@ class Store {
result.entrant1 = {};
result.entrant2 = {};
- data.items.entities.entrants.forEach(function(entrant) {
- if(entrant.id === result.entrant1Id)
- result.entrant1 = entrant;
+ if(data.items.entities.entrants)
+ data.items.entities.entrants.forEach(function(entrant) {
+ if(entrant.id === result.entrant1Id)
+ result.entrant1 = entrant;
- if(entrant.id === result.entrant2Id)
- result.entrant2 = entrant;
- });
+ if(entrant.id === result.entrant2Id)
+ result.entrant2 = entrant;
+ });
if(result.isGF) {
grands.push(result);
@@ -208,13 +218,11 @@ class Store {
// GFs are technically in the winners bracket, but for presentation purposes they're shoved
// in after to be like how smash.gg presents them.
if(grands.length > 0) {
- grands.forEach(grandFinal => {
- brackets.winners.push({
- title: 'Grand Finals',
- sets: [grandFinal],
- key: v4()
- });
- });
+ grands.forEach(grandFinal => brackets.winners.push({
+ title: 'Grand Finals',
+ sets: [grandFinal],
+ key: v4()
+ }));
}
runInAction('Set Bracket Data', () => {
@@ -222,6 +230,13 @@ class Store {
});
});
}
+
+ parseAndStoreGroups = (data) => {
+ console.warn('Groups!');
+ runInAction('Set Groups Data', () => {
+
+ });
+ }
};
export default new Store();
diff --git a/styles/index.js b/styles/index.js
index 461503c..7a7c294 100644
--- a/styles/index.js
+++ b/styles/index.js
@@ -121,6 +121,37 @@ const stylesheet = StyleSheet.create({
textAlign: 'center',
marginTop: 5,
color: textColor
+ },
+
+ bracketTitle: {
+ fontWeight: 'bold',
+ padding: 5,
+ textAlign: 'center',
+ color: textColor
+ },
+
+ matchWrapper: {
+ backgroundColor: '#3b3b48',
+ borderColor: '#0e0e12',
+ borderWidth: 0.5,
+ borderRadius: 4,
+ marginBottom: 20,
+ overflow: 'hidden'
+ },
+
+ matchEntrant: {
+ flexDirection: 'row',
+ justifyContent: 'space-between'
+ },
+
+ matchEntrantText: {
+ color: '#dbdbde',
+ padding: 5
+ },
+
+ matchSeparator: {
+ borderTopWidth: 0.5,
+ borderTopColor: '#2a2a33'
}
});