More fixes/patches
This commit is contained in:
parent
1f90ca2575
commit
c02ad19f2b
18 changed files with 582 additions and 239 deletions
34
controllers/AttendeesListViewController.js
Normal file
34
controllers/AttendeesListViewController.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* AttendeesListViewController
|
||||||
|
*
|
||||||
|
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
|
||||||
|
*
|
||||||
|
* @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 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}) => (<View />)
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const props = {
|
||||||
|
data: this.props.data,
|
||||||
|
keyExtractor: keyExtractor,
|
||||||
|
renderItem: this.renderItem
|
||||||
|
};
|
||||||
|
|
||||||
|
return <FlatList {...props} renderItem={this.renderItem} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,9 +9,8 @@
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {ScrollView, Text, View} from 'react-native';
|
import {ScrollView, Text, View} from 'react-native';
|
||||||
import {v4} from 'uuid';
|
import {inject, observer} from 'mobx-react/native';
|
||||||
|
|
||||||
//import SmashGG from '../store';
|
|
||||||
import MemeleeViewController from './MemeleeViewController';
|
import MemeleeViewController from './MemeleeViewController';
|
||||||
|
|
||||||
const Match = ({set, ...rest}) => (
|
const Match = ({set, ...rest}) => (
|
||||||
|
|
@ -22,32 +21,17 @@ const Match = ({set, ...rest}) => (
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@inject('Events') @observer
|
||||||
export default class BracketViewController extends MemeleeViewController {
|
export default class BracketViewController extends MemeleeViewController {
|
||||||
state = {
|
|
||||||
brackets: {
|
|
||||||
winners: [],
|
|
||||||
losers: [],
|
|
||||||
grandFinals: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const evtSlugs = this.props.evt.slug.split('/');
|
this.props.Events.fetchBracketData(this.props.bracket.id);
|
||||||
const evtSlug = evtSlugs.length > 0 ? evtSlugs[evtSlugs.length - 1] : null;
|
|
||||||
const tournamentSlug = this.props.tournament.slugs[0].replace('tournament/', '');
|
|
||||||
|
|
||||||
SmashGG.fetchBracketData(tournamentSlug, evtSlug, this.props.bracket.id).then(this.updateBracketsData).catch(console.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateBracketsData = (brackets) => {
|
|
||||||
this.setState({brackets: brackets});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (<ScrollView style={{flex: 1, backgroundColor: '#21212d'}} contentContainerStyle={{width: 10001}}>
|
return (<ScrollView style={{flex: 1, backgroundColor: '#21212d'}} contentContainerStyle={{width: 10001}}>
|
||||||
{['winners', 'losers'].map(key => (
|
{['winners', 'losers'].map(key => (
|
||||||
<View key={key} style={{backgroundColor: '#21212d', flexDirection: 'row', paddingTop: 20, paddingBottom: 20, paddingLeft: 20}}>
|
<View key={key} style={{backgroundColor: '#21212d', flexDirection: 'row', paddingTop: 20, paddingBottom: 20, paddingLeft: 20}}>
|
||||||
{this.state.brackets[key].map(bracket => (
|
{this.props.Events.bracketData[key].map(bracket => (
|
||||||
<View key={bracket.key} style={{backgroundColor: '#21212d', marginRight: 20, width: 200, flexDirection: 'column'}}>
|
<View key={bracket.key} style={{backgroundColor: '#21212d', marginRight: 20, width: 200, flexDirection: 'column'}}>
|
||||||
<Text>{bracket.title}</Text>
|
<Text>{bracket.title}</Text>
|
||||||
{bracket.sets.map(set => <Match key={set.id} set={set} />)}
|
{bracket.sets.map(set => <Match key={set.id} set={set} />)}
|
||||||
|
|
|
||||||
34
controllers/ContactViewController.js
Normal file
34
controllers/ContactViewController.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* AttendeesListViewController
|
||||||
|
*
|
||||||
|
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
|
||||||
|
*
|
||||||
|
* @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 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}) => (<View />)
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const props = {
|
||||||
|
data: this.props.data,
|
||||||
|
keyExtractor: keyExtractor,
|
||||||
|
renderItem: this.renderItem
|
||||||
|
};
|
||||||
|
|
||||||
|
return <FlatList {...props} renderItem={this.renderItem} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,40 +8,61 @@
|
||||||
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {ScrollView, Image, Text, View, TouchableOpacity} from 'react-native';
|
import {ScrollView, StyleSheet, ActivityIndicator, Image, Text, View, TouchableOpacity} from 'react-native';
|
||||||
|
import {inject, observer} from 'mobx-react/native';
|
||||||
import Markdown from 'react-native-simple-markdown'
|
import Markdown from 'react-native-simple-markdown'
|
||||||
//import SmashGG from '../store';
|
import SegmentedControlTab from 'react-native-segmented-control-tab';
|
||||||
|
import SettingsList, {Header, Item} from 'react-native-settings-list';
|
||||||
|
|
||||||
|
import styles from '../styles';
|
||||||
|
import Constants from '../utils/Constants';
|
||||||
import MemeleeViewController from './MemeleeViewController';
|
import MemeleeViewController from './MemeleeViewController';
|
||||||
|
|
||||||
|
const Loading = (props) => (
|
||||||
|
<View style={{paddingTop: 20}}>
|
||||||
|
<ActivityIndicator animating size="large" />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Standings = (props) => (
|
||||||
|
props.error ? <View style={{padding: 20}}>
|
||||||
|
<Text style={styles.eventsErrorTextHeader}>No Standings Found</Text>
|
||||||
|
<Text style={styles.eventsErrorText}>Matches may not have been played yet.</Text>
|
||||||
|
</View> : <View>
|
||||||
|
<View style={{flexDirection: 'row', backgroundColor: '#010101'}}>
|
||||||
|
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8, paddingLeft: 58, width: 230}}>Players</Text>
|
||||||
|
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8}}>Losses</Text>
|
||||||
|
</View>
|
||||||
|
<ScrollView>
|
||||||
|
{props.standings.map(standing => (
|
||||||
|
<View key={standing.id} style={{flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: 'gray'}}>
|
||||||
|
<Text key={standing.id} style={{padding: 8, width: 50, textAlign: 'center', backgroundColor: 'gray'}}>
|
||||||
|
{standing.standing}
|
||||||
|
</Text>
|
||||||
|
<Text style={{padding: 8, width: 180}}>{standing.name}</Text>
|
||||||
|
<View style={{padding: 8, flex: 1}}>{standing.losses.map(loss => <Text key={standing.id + loss} style={{flexShrink: 1}}>{loss}</Text>)}</View>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
|
||||||
|
const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
|
||||||
|
const Brackets = (props) => (
|
||||||
|
<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
|
||||||
|
{props.brackets.map(bracket => (
|
||||||
|
<Item key={bracket.name} itemWidth={50} title={bracket.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} onPress={() => props.onPress(bracket)} />
|
||||||
|
))}
|
||||||
|
</SettingsList>
|
||||||
|
);
|
||||||
|
|
||||||
|
@inject('Events') @observer
|
||||||
export default class EventInfoViewController extends MemeleeViewController {
|
export default class EventInfoViewController extends MemeleeViewController {
|
||||||
state = {
|
state = {selectedIndex: 0};
|
||||||
standings: [],
|
|
||||||
brackets: []
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
const evtSlugs = this.props.evt.slug.split('/');
|
|
||||||
const evtSlug = evtSlugs.length > 0 ? evtSlugs[evtSlugs.length - 1] : null;
|
|
||||||
const tournamentSlug = this.props.tournament.slugs[0].replace('tournament/', '');
|
|
||||||
|
|
||||||
if((evtSlug && evtSlug !== '') && (tournamentSlug && tournamentSlug != '')) {
|
|
||||||
SmashGG.fetchEventExpanded(tournamentSlug, evtSlug).then(this.updateBracketsData).catch(console.error);
|
|
||||||
SmashGG.fetchEventStandings(tournamentSlug, evtSlug).then(this.updateStandingsData).catch(console.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateBracketsData = (data) => {
|
|
||||||
this.setState({brackets: data});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStandingsData = (data) => {
|
|
||||||
this.setState({standings: data});
|
|
||||||
}
|
|
||||||
|
|
||||||
onBracketPress = (bracket) => {
|
onBracketPress = (bracket) => {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'memelee.bracket',
|
screen: Constants.Screens.Bracket,
|
||||||
title: bracket.name,
|
title: bracket.name,
|
||||||
backButtonTitle: 'Back',
|
backButtonTitle: 'Back',
|
||||||
passProps: {
|
passProps: {
|
||||||
|
|
@ -53,29 +74,25 @@ export default class EventInfoViewController extends MemeleeViewController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
swapIndex = (index) => {
|
||||||
return (<ScrollView>
|
this.setState({selectedIndex: index});
|
||||||
<Text style={{padding: 8, backgroundColor: '#003366', fontSize: 16}}>Brackets</Text>
|
}
|
||||||
{this.state.brackets.map(bracket => (
|
|
||||||
<TouchableOpacity key={bracket.id} onPress={() => this.onBracketPress(bracket)}>
|
|
||||||
<Text style={{padding: 8, backgroundColor: 'gray'}}>{bracket.name}</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<Text style={{padding: 8, marginTop: 20, backgroundColor: '#003366', fontSize: 16}}>Standings</Text>
|
render() {
|
||||||
<View style={{flexDirection: 'row', backgroundColor: '#010101'}}>
|
return (<View>
|
||||||
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8, paddingLeft: 58, width: 230}}>Players</Text>
|
<SegmentedControlTab values={['Standings', 'Brackets']} borderRadius={0} activeTabStyle={styles.tournamentInfoActiveTableStyle} tabStyle={styles.tournamentInfoTabsStyle} tabTextStyle={styles.tournamentInfoTabTextStyle} selectedIndex={this.state.selectedIndex} onTabPress={this.swapIndex} />
|
||||||
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8}}>Losses</Text>
|
|
||||||
</View>
|
{this.state.selectedIndex === 0 ?
|
||||||
{this.state.standings.map(standing => (
|
this.props.Events.fetchingStandingData ?
|
||||||
<View key={standing.id} style={{flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: 'gray'}}>
|
<Loading /> : <Standings standings={this.props.Events.standings} error={this.props.Events.standingsError} />
|
||||||
<Text key={standing.id} style={{padding: 8, width: 50, textAlign: 'center', backgroundColor: 'gray'}}>
|
: null
|
||||||
{standing.finalPlacement}
|
}
|
||||||
</Text>
|
|
||||||
<Text style={{padding: 8, width: 180}}>{standing.name}</Text>
|
{this.state.selectedIndex === 1 ?
|
||||||
<View style={{padding: 8, flex: 1}}>{standing.losses.map(loss => <Text key={standing.id + loss} style={{flexShrink: 1}}>{loss}</Text>)}</View>
|
this.props.Events.fetchingBracketData ?
|
||||||
</View>
|
<Loading /> : <Brackets error={this.props.Events.standingsError} brackets={this.props.Events.phases} onPress={this.onBracketPress} />
|
||||||
))}
|
: null
|
||||||
</ScrollView>);
|
}
|
||||||
|
</View>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
controllers/GenericInfoViewController.js
Normal file
28
controllers/GenericInfoViewController.js
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
/**
|
||||||
|
* AttendeesListViewController
|
||||||
|
*
|
||||||
|
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
|
||||||
|
*
|
||||||
|
* @copyright Ryan McGrath 2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import {ScrollView, View} from 'react-native';
|
||||||
|
import Markdown from 'react-native-markdown-renderer';
|
||||||
|
import Hyperlink from 'react-native-hyperlink';
|
||||||
|
|
||||||
|
import styles from '../styles';
|
||||||
|
import Constants from '../utils/Constants';
|
||||||
|
import MemeleeViewController from './MemeleeViewController';
|
||||||
|
|
||||||
|
export default class GenericInfoViewController extends MemeleeViewController {
|
||||||
|
render = () => (<ScrollView>
|
||||||
|
<View style={styles.tournamentDetailsTextWrapper}>
|
||||||
|
<Hyperlink>
|
||||||
|
<Markdown style={styles.tournamentDetailsText}>
|
||||||
|
{this.props.info && this.props.info !== '' ? this.props.info : ''}
|
||||||
|
</Markdown>
|
||||||
|
</Hyperlink>
|
||||||
|
</View>
|
||||||
|
</ScrollView>);
|
||||||
|
}
|
||||||
34
controllers/LocationViewController.js
Normal file
34
controllers/LocationViewController.js
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* AttendeesListViewController
|
||||||
|
*
|
||||||
|
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
|
||||||
|
*
|
||||||
|
* @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 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}) => (<View />)
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const props = {
|
||||||
|
data: this.props.data,
|
||||||
|
keyExtractor: keyExtractor,
|
||||||
|
renderItem: this.renderItem
|
||||||
|
};
|
||||||
|
|
||||||
|
return <FlatList {...props} renderItem={this.renderItem} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,12 +9,15 @@
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {ScrollView, StyleSheet, Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
|
import {ScrollView, StyleSheet, Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
|
||||||
//import Markdown from 'react-native-simple-markdown'
|
import Markdown, {PluginContainer} from 'react-native-markdown-renderer';
|
||||||
import Markdown from 'react-native-markdown-renderer';
|
|
||||||
import SegmentedControlTab from 'react-native-segmented-control-tab';
|
import SegmentedControlTab from 'react-native-segmented-control-tab';
|
||||||
import SettingsList, {Header, Item} from 'react-native-settings-list';
|
import SettingsList, {Header, Item} from 'react-native-settings-list';
|
||||||
|
import linkify from 'linkify-it';
|
||||||
|
|
||||||
import styles from '../styles';
|
import styles from '../styles';
|
||||||
|
import Constants from '../utils/Constants';
|
||||||
|
import {openURL, parseSlugs} from '../utils';
|
||||||
|
import EventsStore from '../stores/TournamentEventStore';
|
||||||
import MemeleeViewController from './MemeleeViewController';
|
import MemeleeViewController from './MemeleeViewController';
|
||||||
|
|
||||||
const w = Dimensions.get('screen').width;
|
const w = Dimensions.get('screen').width;
|
||||||
|
|
@ -31,41 +34,126 @@ const w = Dimensions.get('screen').width;
|
||||||
|
|
||||||
export default class TournamentInfoViewController extends MemeleeViewController {
|
export default class TournamentInfoViewController extends MemeleeViewController {
|
||||||
state = {
|
state = {
|
||||||
selectedIndex: 0
|
selectedIndex: 0,
|
||||||
|
tabs: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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});
|
||||||
|
}
|
||||||
|
|
||||||
onEventTapped = (evt) => {
|
onEventTapped = (evt) => {
|
||||||
|
EventsStore.loadEventData(this.props.tournament, evt);
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'memelee.tournamentEventInfoScreen',
|
screen: Constants.Screens.TournamentEventInfoScreen,
|
||||||
title: evt.name,
|
title: evt.name,
|
||||||
passProps: {tournament: this.props.tournament, evt: evt},
|
passProps: {tournament: this.props.tournament, evt: evt},
|
||||||
navigatorStyle: {tabBarHidden: true}
|
navigatorStyle: {tabBarHidden: true}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTab = (tab) => {
|
||||||
|
if(tab.screen)
|
||||||
|
return this.props.navigator.push({
|
||||||
|
screen: tab.screen,
|
||||||
|
title: tab.name,
|
||||||
|
passProps: {data: []},
|
||||||
|
navigatorStyle: {tabBarHidden: true}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(tab.url)
|
||||||
|
return openURL(tab.url);
|
||||||
|
|
||||||
|
if(tab.info)
|
||||||
|
return this.props.navigator.push({
|
||||||
|
screen: Constants.Screens.Info,
|
||||||
|
title: tab.name,
|
||||||
|
passProps: {info: tab.info},
|
||||||
|
navigatorStyle: {tabBarHidden: true}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
swapIndex = (index) => {
|
swapIndex = (index) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
selectedIndex: index
|
selectedIndex: index
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins = []
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
|
const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
|
||||||
|
const ss = {
|
||||||
|
itemWidth: 50,
|
||||||
|
backgroundColor: s.backgroundColor,
|
||||||
|
style: styles.tournamentDetailsEventWrapper,
|
||||||
|
titleStyle: styles.tournamentDetailsEventItem
|
||||||
|
};
|
||||||
|
|
||||||
return (<ScrollView>
|
return (<ScrollView>
|
||||||
<Image style={[styles.tournamentInfoHeader, {width: w}]} source={this.props.tournament.memeleePromoImage.msrc} />
|
<Image style={[styles.tournamentInfoHeader, {width: w}]} source={this.props.tournament.memeleePromoImage.msrc} />
|
||||||
|
|
||||||
<SegmentedControlTab values={['Overview', 'Events']} borderRadius={0} activeTabStyle={styles.tournamentInfoActiveTableStyle} tabStyle={styles.tournamentInfoTabsStyle} tabTextStyle={styles.tournamentInfoTabTextStyle} selectedIndex={this.state.selectedIndex} onTabPress={this.swapIndex} />
|
<SegmentedControlTab values={['Overview', 'Events']} borderRadius={0} activeTabStyle={styles.tournamentInfoActiveTableStyle} tabStyle={styles.tournamentInfoTabsStyle} tabTextStyle={styles.tournamentInfoTabTextStyle} selectedIndex={this.state.selectedIndex} onTabPress={this.swapIndex} />
|
||||||
|
|
||||||
{this.state.selectedIndex === 0 ? (<View style={styles.tournamentDetailsTextWrapper}>
|
{this.state.selectedIndex === 0 ? (<View>
|
||||||
<Markdown style={styles.tournamentDetailsText}>
|
<View style={styles.tournamentDetailsTextWrapper}>
|
||||||
|
<Markdown style={styles.tournamentDetailsText} plugins={this.plugins}>
|
||||||
{this.props.tournament.details && this.props.tournament.details !== '' ? this.props.tournament.details : ''}
|
{this.props.tournament.details && this.props.tournament.details !== '' ? this.props.tournament.details : ''}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
</View>) : null}
|
</View>
|
||||||
|
|
||||||
|
<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
|
||||||
|
{this.state.tabs.map(tab => <Item key={tab.slug} {...ss} title={tab.name} onPress={() => this.handleTab(tab)} />)}
|
||||||
|
</SettingsList>
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
|
||||||
{this.state.selectedIndex === 1 ? (<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
|
{this.state.selectedIndex === 1 ? (<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
|
||||||
{this.props.tournament.memeleeEvents.map(evt => (
|
{this.props.tournament.memeleeEvents.map(evt => (
|
||||||
<Item key={evt.id} itemWidth={50} title={evt.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} />
|
<Item key={evt.id} itemWidth={50} title={evt.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} onPress={() => this.onEventTapped(evt)} />
|
||||||
))}
|
))}
|
||||||
</SettingsList>) : null}
|
</SettingsList>) : null}
|
||||||
</ScrollView>);
|
</ScrollView>);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import {inject, observer} from 'mobx-react/native';
|
||||||
import {SearchBar} from 'react-native-elements';
|
import {SearchBar} from 'react-native-elements';
|
||||||
|
|
||||||
import styles from '../styles';
|
import styles from '../styles';
|
||||||
|
import Constants from '../utils/Constants';
|
||||||
import MemeleeViewController from './MemeleeViewController';
|
import MemeleeViewController from './MemeleeViewController';
|
||||||
import TournamentRow from './components/TournamentRow';
|
import TournamentRow from './components/TournamentRow';
|
||||||
|
|
||||||
|
|
@ -26,7 +27,7 @@ export default class UpcomingTournamentsViewController extends MemeleeViewContro
|
||||||
|
|
||||||
onTap = (tournament) => {
|
onTap = (tournament) => {
|
||||||
this.props.navigator.push({
|
this.props.navigator.push({
|
||||||
screen: 'memelee.tournamentInfoScreen',
|
screen: Constants.Screens.TournamentInfoScreen,
|
||||||
title: tournament.name,
|
title: tournament.name,
|
||||||
passProps: {tournament: tournament},
|
passProps: {tournament: tournament},
|
||||||
navigatorStyle: {tabBarHidden: true}
|
navigatorStyle: {tabBarHidden: true}
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@ export default class TournamentRow extends React.Component {
|
||||||
<Icon name="map-marker" size={16} color={styles.tournamentPromoIconColors.mapMarker} /> {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}</Text>
|
<Icon name="map-marker" size={16} color={styles.tournamentPromoIconColors.mapMarker} /> {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}</Text>
|
||||||
<View style={{flexDirection: 'row'}}>
|
<View style={{flexDirection: 'row'}}>
|
||||||
<Text style={styles.tournamentRowEventsCount}>
|
<Text style={styles.tournamentRowEventsCount}>
|
||||||
<Icon name="trophy-variant" size={16} color={styles.tournamentPromoIconColors.eventsCount} />
|
<Icon name="trophy-variant" size={16} color={styles.tournamentPromoIconColors.eventsCount} /> {this.props.tournament.memeleeEventsCount} Events
|
||||||
{this.props.tournament.memeleeEventsCount} Events
|
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[styles.tournamentRowEventsCount, {marginLeft: 10}]}>
|
<Text style={[styles.tournamentRowEventsCount, {marginLeft: 10}]}>
|
||||||
<Icon name="human-greeting" size={16} color={styles.tournamentPromoIconColors.attendeesCount} /> {this.props.tournament.attendeeCount} Attendees
|
<Icon name="human-greeting" size={16} color={styles.tournamentPromoIconColors.attendeesCount} /> {this.props.tournament.attendeeCount} Attendees
|
||||||
|
|
|
||||||
22
index.js
22
index.js
|
|
@ -13,30 +13,28 @@ import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import Stores from './stores';
|
import Stores from './stores';
|
||||||
|
import Constants from './utils/Constants';
|
||||||
import Provider from './utils/MobxRnnProvider';
|
import Provider from './utils/MobxRnnProvider';
|
||||||
|
|
||||||
import TournamentsListViewController from './controllers/TournamentsListViewController';
|
import TournamentsListViewController from './controllers/TournamentsListViewController';
|
||||||
import TournamentInfoViewController from './controllers/TournamentInfoViewController';
|
import TournamentInfoViewController from './controllers/TournamentInfoViewController';
|
||||||
|
import AttendeesListViewController from './controllers/AttendeesListViewController';
|
||||||
|
import LocationViewController from './controllers/LocationViewController';
|
||||||
|
import ContactViewController from './controllers/ContactViewController';
|
||||||
|
import GenericInfoViewController from './controllers/GenericInfoViewController';
|
||||||
import EventInfoViewController from './controllers/EventInfoViewController';
|
import EventInfoViewController from './controllers/EventInfoViewController';
|
||||||
import BracketViewController from './controllers//BracketViewController';
|
import BracketViewController from './controllers//BracketViewController';
|
||||||
import BookmarksViewController from './controllers/BookmarksViewController';
|
import BookmarksViewController from './controllers/BookmarksViewController';
|
||||||
import SettingsViewController from './controllers/settings';
|
import SettingsViewController from './controllers/settings';
|
||||||
|
|
||||||
const Constants = {
|
|
||||||
Screens: {
|
|
||||||
TournamentsList: 'memelee.tournamentsList',
|
|
||||||
TournamentInfoScreen: 'memelee.tournamentInfoScreen',
|
|
||||||
TournamentEventInfoScreen: 'memelee.tournamentEventInfoScreen',
|
|
||||||
Bracket: 'memelee.tournamentBracket',
|
|
||||||
Bookmarks: 'memelee.bookmarks',
|
|
||||||
Settings: 'memelee.settings'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Navigation.registerComponent(Constants.Screens.TournamentsList, () => TournamentsListViewController, Stores, Provider);
|
Navigation.registerComponent(Constants.Screens.TournamentsList, () => TournamentsListViewController, Stores, Provider);
|
||||||
Navigation.registerComponent(Constants.Screens.TournamentInfoScreen, () => TournamentInfoViewController, Stores, Provider);
|
Navigation.registerComponent(Constants.Screens.TournamentInfoScreen, () => TournamentInfoViewController, Stores, Provider);
|
||||||
Navigation.registerComponent(Constants.Screens.TournamentEventInfoScreen, () => EventInfoViewController, Stores, Provider);
|
Navigation.registerComponent(Constants.Screens.TournamentEventInfoScreen, () => EventInfoViewController, Stores, Provider);
|
||||||
Navigation.registerComponent(Constants.Screens.TournamentEventBracket, () => BracketViewController, Stores, Provider);
|
Navigation.registerComponent(Constants.Screens.Attendees, () => AttendeesListViewController, Stores, Provider);
|
||||||
|
Navigation.registerComponent(Constants.Screens.Location, () => LocationViewController, Stores, Provider);
|
||||||
|
Navigation.registerComponent(Constants.Screens.Contact, () => ContactViewController, Stores, Provider);
|
||||||
|
Navigation.registerComponent(Constants.Screens.Info, () => GenericInfoViewController, Stores, Provider);
|
||||||
|
Navigation.registerComponent(Constants.Screens.Bracket, () => BracketViewController, Stores, Provider);
|
||||||
Navigation.registerComponent(Constants.Screens.Bookmarks, () => BookmarksViewController, Stores, Provider);
|
Navigation.registerComponent(Constants.Screens.Bookmarks, () => BookmarksViewController, Stores, Provider);
|
||||||
Navigation.registerComponent(Constants.Screens.Settings, () => SettingsViewController, Stores, Provider);
|
Navigation.registerComponent(Constants.Screens.Settings, () => SettingsViewController, Stores, Provider);
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -26,15 +26,11 @@
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSExceptionDomains</key>
|
<key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
|
||||||
<dict>
|
<true />
|
||||||
<key>localhost</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<dict>
|
|
||||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>NSLocationWhenInUseUsageDescription</key>
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.0",
|
||||||
"babel-preset-react-native-stage-0": "^1.0.1",
|
"babel-preset-react-native-stage-0": "^1.0.1",
|
||||||
"jsog": "^1.0.7",
|
"jsog": "^1.0.7",
|
||||||
|
"linkify-it": "^2.0.3",
|
||||||
"mobx": "^4.1.1",
|
"mobx": "^4.1.1",
|
||||||
"mobx-persist": "^0.4.1",
|
"mobx-persist": "^0.4.1",
|
||||||
"mobx-react": "^5.0.0",
|
"mobx-react": "^5.0.0",
|
||||||
|
|
@ -29,6 +30,7 @@
|
||||||
"react-controllables": "^0.6.0",
|
"react-controllables": "^0.6.0",
|
||||||
"react-native": "0.52.0",
|
"react-native": "0.52.0",
|
||||||
"react-native-elements": "^0.19.0",
|
"react-native-elements": "^0.19.0",
|
||||||
|
"react-native-hyperlink": "0.0.12",
|
||||||
"react-native-markdown-renderer": "^3.1.0",
|
"react-native-markdown-renderer": "^3.1.0",
|
||||||
"react-native-navigation": "^1.1.426",
|
"react-native-navigation": "^1.1.426",
|
||||||
"react-native-segmented-control-tab": "^3.2.2",
|
"react-native-segmented-control-tab": "^3.2.2",
|
||||||
|
|
|
||||||
|
|
@ -6,95 +6,147 @@
|
||||||
* @copyright Ryan McGrath 2018
|
* @copyright Ryan McGrath 2018
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {v4} from 'uuid';
|
||||||
import {observable, action, runInAction} from 'mobx';
|
import {observable, action, runInAction} from 'mobx';
|
||||||
|
import {parseSlugs} from '../utils';
|
||||||
|
|
||||||
class Store {
|
class Store {
|
||||||
@observable data;
|
@observable.ref phases;
|
||||||
|
@observable.ref bracketData;
|
||||||
@observable fetchingData;
|
@observable fetchingData;
|
||||||
|
|
||||||
|
@observable.ref standings;
|
||||||
|
@observable fetchingStandingData;
|
||||||
|
@observable standingsError;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.data = {};
|
this.phases = [];
|
||||||
|
this.standings = [];
|
||||||
|
this.bracketData = {winners: [], losers: []};
|
||||||
|
this.tournamentSlug = null;
|
||||||
|
this.evtSlug = null;
|
||||||
|
this.fetchingData = false;
|
||||||
|
this.fetchingStandingData = false;
|
||||||
|
this.standingsError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchEventExpanded = async (tournamentSlug, eventSlug, opts) => {
|
parseSlugs = (tournament, evt) => {
|
||||||
const api = 'https://smash.gg/api/-/gg_api./tournament/' + tournamentSlug + '/event/' + eventSlug + ';';
|
const slugs = parseSlugs(tournament, evt);
|
||||||
const args = Object.assign({
|
this.tournamentSlug = slugs.tournament;
|
||||||
|
this.evtSlug = slugs.evt;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadEventData = async(tournament, evt) => {
|
||||||
|
this.phases = [];
|
||||||
|
this.standings = [];
|
||||||
|
this.bracketData = {winners: [], losers: []};
|
||||||
|
this.tournamentSlug = null;
|
||||||
|
this.evtSlug = null;
|
||||||
|
|
||||||
|
this.parseSlugs(tournament, evt);
|
||||||
|
|
||||||
|
if(this.tournamentSlug && this.evtSlug) {
|
||||||
|
this.fetchPhases();
|
||||||
|
this.fetchStandings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fetchPhases
|
||||||
|
*
|
||||||
|
* Given a set of slugs, fetches event phases.
|
||||||
|
*/
|
||||||
|
fetchPhases = () => {
|
||||||
|
const api = 'https://smash.gg/api/-/gg_api./tournament/' + this.tournamentSlug + '/event/' + this.evtSlug + ';';
|
||||||
|
const args = {
|
||||||
expand: JSON.stringify(['phase', 'groups']),
|
expand: JSON.stringify(['phase', 'groups']),
|
||||||
reset: false,
|
reset: false,
|
||||||
slug: tournamentSlug,
|
slug: this.tournamentSlug,
|
||||||
eventSlug: eventSlug
|
eventSlug: this.evtSlug
|
||||||
}, opts || {});
|
};
|
||||||
|
|
||||||
return fetch(
|
fetch(api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true').then(
|
||||||
api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true'
|
response => response.json()
|
||||||
).then(response => response.json()).then(data => {
|
).then(data => {
|
||||||
if(typeof data.success !== 'undefined' && !data.success)
|
if(typeof data.success !== 'undefined' && !data.success)
|
||||||
throw new Error(data.message);
|
throw new Error(data.message);
|
||||||
|
|
||||||
return Promise.resolve(data.entities.phase ? data.entities.phase.map(phase => phase) : []);
|
runInAction('Parse out Phases...', () => {
|
||||||
|
if(data.entities.phase)
|
||||||
|
this.phases = data.entities.phase.map(phase => phase);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fetchStandings
|
* fetchStandings
|
||||||
*
|
*
|
||||||
* Given a set of slugs, fetches event standings.
|
* Given a set of slugs, fetches event standings.
|
||||||
*
|
|
||||||
* @arg tournamentSlug {String} Slug for the tournament (e.g, "the-mango").
|
|
||||||
* @arg eventSlug {String} Slug for the event (e.g, "melee-singles").
|
|
||||||
* @arg opts {Object} Optional object for overriding request properties.
|
|
||||||
* @return Promise
|
|
||||||
*/
|
*/
|
||||||
/*const fetchEventStandings = (tournamentSlug, eventSlug, opts) => {
|
fetchStandings = () => {
|
||||||
const api = 'https://smash.gg/api/-/gg_api./tournament/' + tournamentSlug + '/event/' + eventSlug + '/standings;';
|
const api = 'https://smash.gg/api/-/gg_api./tournament/' + this.tournamentSlug + '/event/' + this.evtSlug + '/standings;';
|
||||||
const args = Object.assign({
|
const args = {
|
||||||
entityId: null,
|
entityId: null,
|
||||||
entityType: 'event',
|
entityType: 'event',
|
||||||
slug: tournamentSlug,
|
slug: this.tournamentSlug,
|
||||||
eventSlug: eventSlug,
|
eventSlug: this.evtSlug,
|
||||||
expand: JSON.stringify(['entrants', 'standingGroup', 'attendee']),
|
expand: JSON.stringify(['entrants', 'standingGroup', 'attendee']),
|
||||||
mutations: JSON.stringify(['playerData', 'standingLosses']),
|
mutations: JSON.stringify(['playerData', 'standingLosses']),
|
||||||
page: 1,
|
page: 1,
|
||||||
per_page: 25
|
per_page: 25
|
||||||
}, opts || {});
|
};
|
||||||
|
|
||||||
return fetch(
|
this.standings = [];
|
||||||
api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true'
|
this.fetchingStandingsData = true;
|
||||||
).then(response => response.json()).then(data => {
|
fetch(api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true').then(
|
||||||
|
response => response.json()
|
||||||
|
).then(data => {
|
||||||
|
runInAction('Parse out Standings...', () => {
|
||||||
var s = data.items.entities.standing,
|
var s = data.items.entities.standing,
|
||||||
l = s.length;
|
l = s.length;
|
||||||
|
|
||||||
return Promise.resolve(data.items.entities.entrants.map(entrants => {
|
this.standingsError = false;
|
||||||
|
this.standings = data.items.entities.entrants.map(entrants => {
|
||||||
if(typeof entrants.losses === 'undefined')
|
if(typeof entrants.losses === 'undefined')
|
||||||
entrants.losses = [];
|
entrants.losses = [];
|
||||||
|
|
||||||
data.items.entities.standing.forEach(standing => {
|
data.items.entities.standing.forEach(standing => {
|
||||||
if(standing.entityId === entrants.id && standing.mutations)
|
if(standing.entityId === entrants.id) {
|
||||||
|
if(standing.mutations)
|
||||||
entrants.losses = entrants.losses.concat(standing.mutations.losses.map(loss => loss.name));
|
entrants.losses = entrants.losses.concat(standing.mutations.losses.map(loss => loss.name));
|
||||||
|
|
||||||
|
entrants.standing = standing.standing;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return entrants;
|
return entrants;
|
||||||
}).sort((a, b) => a.finalPlacement > b.finalPlacement));
|
}).sort((a, b) => a.finalPlacement > b.finalPlacement);
|
||||||
|
this.fetchingStandingsData = false;
|
||||||
});
|
});
|
||||||
};
|
}).catch(error => {
|
||||||
|
runInAction('Event standings data failed', () => {
|
||||||
|
this.standingsError = true;
|
||||||
|
this.fetchingStandingsData = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fetchBracketData
|
* fetchBracketData
|
||||||
*
|
*
|
||||||
* Given a set of slugs/bracket ID, fetches bracket data for rendering. Performs a lot
|
* Given a set of slugs/bracket ID, fetches bracket data for rendering. Performs a lot
|
||||||
* of smaller operations to transpose it into an actually usable format for display.
|
* of smaller operations to transpose it into an actually usable format for display.
|
||||||
*
|
*
|
||||||
* @arg tournamentSlug {String} Slug for the tournament (e.g, "the-mango").
|
|
||||||
* @arg eventSlug {String} Slug for the event (e.g, "melee-singles").
|
|
||||||
* @arg bracketID {String or Number} ID for the bracket - SmashGG calls this a phase. Go fig.
|
* @arg bracketID {String or Number} ID for the bracket - SmashGG calls this a phase. Go fig.
|
||||||
* @arg opts {Object} Optional object for overriding request properties.
|
*/
|
||||||
* @return Promise
|
fetchBracketData = (bracketID) => {
|
||||||
|
this.bracketData = {winners: [], losers: []};
|
||||||
|
this.bracketID = bracketID;
|
||||||
|
|
||||||
const fetchBracketData = (tournamentSlug, eventSlug, bracketID, opts) => {
|
const api = 'https://smash.gg/api/-/gg_api./tournament/' + this.tournamentSlug + '/event/' + this.evtSlug + '/phase_groups;';
|
||||||
const api = 'https://smash.gg/api/-/gg_api./tournament/' + tournamentSlug + '/event/' + eventSlug + '/phase_groups;';
|
|
||||||
const args = {
|
const args = {
|
||||||
slug: tournamentSlug,
|
slug: this.tournamentSlug,
|
||||||
eventSlug: eventSlug,
|
eventSlug: this.evtSlug,
|
||||||
expand: JSON.stringify(['results', 'character']),
|
expand: JSON.stringify(['results', 'character']),
|
||||||
mutations: JSON.stringify(['ffaData', 'playerData']),
|
mutations: JSON.stringify(['ffaData', 'playerData']),
|
||||||
filter: JSON.stringify({phaseId: bracketID}),
|
filter: JSON.stringify({phaseId: bracketID}),
|
||||||
|
|
@ -104,8 +156,10 @@ const fetchBracketData = (tournamentSlug, eventSlug, bracketID, opts) => {
|
||||||
reset: false,
|
reset: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
return fetch(
|
const url = api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true'
|
||||||
api + Object.keys(args).map(key => `${key}=${args[key]}`).join(';') + '?returnMeta=true'
|
console.log(url);
|
||||||
|
fetch(
|
||||||
|
url
|
||||||
).then(response => response.json()).then(data => {
|
).then(response => response.json()).then(data => {
|
||||||
const grands = [];
|
const grands = [];
|
||||||
const brackets = {
|
const brackets = {
|
||||||
|
|
@ -163,9 +217,11 @@ const fetchBracketData = (tournamentSlug, eventSlug, bracketID, opts) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.resolve(brackets);
|
runInAction('Set Bracket Data', () => {
|
||||||
|
this.bracketData = brackets;
|
||||||
});
|
});
|
||||||
};*/
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default new Store();
|
export default new Store();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ const hydrate = create({
|
||||||
|
|
||||||
const stores = {
|
const stores = {
|
||||||
Tournaments: TournamentsListingStore,
|
Tournaments: TournamentsListingStore,
|
||||||
TournamentEventStore: TournamentEventStore,
|
Events: TournamentEventStore,
|
||||||
Bookmarks: BookmarksStore,
|
Bookmarks: BookmarksStore,
|
||||||
Settings: SettingsStore
|
Settings: SettingsStore
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,19 @@ const stylesheet = StyleSheet.create({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: iconColor,
|
backgroundColor: iconColor,
|
||||||
padding: 10,
|
padding: 10,
|
||||||
|
},
|
||||||
|
|
||||||
|
eventsErrorTextHeader: {
|
||||||
|
textAlign: 'center',
|
||||||
|
color: textColor,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
fontSize: 16
|
||||||
|
},
|
||||||
|
|
||||||
|
eventsErrorText: {
|
||||||
|
textAlign: 'center',
|
||||||
|
marginTop: 5,
|
||||||
|
color: textColor
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
24
utils/Constants.js
Normal file
24
utils/Constants.js
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
/**
|
||||||
|
* Constants
|
||||||
|
*
|
||||||
|
* They're constants. CONSTANTS. CONSTANCE TURN THE MUSIC DOWN.
|
||||||
|
*
|
||||||
|
* @copyright Ryan McGrath 2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Screens: {
|
||||||
|
TournamentsList: 'memelee.tournamentsList',
|
||||||
|
TournamentInfoScreen: 'memelee.tournamentInfoScreen',
|
||||||
|
TournamentEventInfoScreen: 'memelee.tournamentEventInfoScreen',
|
||||||
|
|
||||||
|
Attendees: 'memelee.attendeesListViewController',
|
||||||
|
Location: 'memelee.locationViewController',
|
||||||
|
Contact: 'memelee.contactViewController',
|
||||||
|
Info: 'memelee.infoViewController',
|
||||||
|
|
||||||
|
Bracket: 'memelee.tournamentBracket',
|
||||||
|
Bookmarks: 'memelee.bookmarks',
|
||||||
|
Settings: 'memelee.settings'
|
||||||
|
}
|
||||||
|
};
|
||||||
35
utils/index.js
Normal file
35
utils/index.js
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* Utils
|
||||||
|
*
|
||||||
|
* Various utilities used throughout the app. A kitchen junk drawer, if you will.
|
||||||
|
*
|
||||||
|
* @copyright Ryan McGrath 2018
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Linking} from 'react-native';
|
||||||
|
|
||||||
|
export const parseSlugs = (tournament, evt) => {
|
||||||
|
const evtSlugs = evt && evt.slug.split('/');
|
||||||
|
const evtSlug = evt && evtSlugs.length > 0 ? evtSlugs[evtSlugs.length - 1] : null;
|
||||||
|
const tournamentSlug = (
|
||||||
|
tournament.slug ? tournament.slug :
|
||||||
|
tournament.slugs && tournament.slugs.length ? tournament.slugs[0] : ''
|
||||||
|
).replace('tournament/', '');
|
||||||
|
|
||||||
|
const slugs = {tournamentSlug: null, evtSlug: null};
|
||||||
|
|
||||||
|
if(tournamentSlug && tournamentSlug !== '')
|
||||||
|
slugs.tournament = tournamentSlug;
|
||||||
|
|
||||||
|
if(evtSlug && evtSlug !== '')
|
||||||
|
slugs.evt = evtSlug;
|
||||||
|
|
||||||
|
return slugs;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const openURL = (url) => {
|
||||||
|
return Linking.canOpenURL(url).then(supported => {
|
||||||
|
if(supported) Linking.openURL(url);
|
||||||
|
else console.warn('Cannot open URL: ' + url);
|
||||||
|
});
|
||||||
|
};
|
||||||
Reference in a new issue