Initial commit.
This commit is contained in:
commit
1f90ca2575
63 changed files with 4059 additions and 0 deletions
24
controllers/BookmarksViewController.js
Normal file
24
controllers/BookmarksViewController.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* BookmarksViewController
|
||||
*
|
||||
* Yeah, I do it iOS style. Handles bookmarked tournaments.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import {FlatList, Image, Text, View, TouchableOpacity} from 'react-native';
|
||||
|
||||
import MemeleeViewController from './MemeleeViewController';
|
||||
|
||||
export default class BookmarksViewController extends MemeleeViewController {
|
||||
state = {data: []};
|
||||
keyExtractor = (item, index) => item.id;
|
||||
|
||||
render() {
|
||||
return <FlatList data={this.state.data} keyExtractor={this.keyExtractor} renderItem={({item}) => {
|
||||
return <View />;
|
||||
}} />
|
||||
}
|
||||
}
|
||||
61
controllers/BracketViewController.js
Normal file
61
controllers/BracketViewController.js
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* BracketViewController
|
||||
*
|
||||
* Yeah, I do it iOS style. Handles displaying tournament bracket data.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import {ScrollView, Text, View} from 'react-native';
|
||||
import {v4} from 'uuid';
|
||||
|
||||
//import SmashGG from '../store';
|
||||
import MemeleeViewController from './MemeleeViewController';
|
||||
|
||||
const Match = ({set, ...rest}) => (
|
||||
<View style={{backgroundColor: '#3b3b48', borderColor: '#0e0e12', borderWidth: 0.5, borderRadius: 4, marginBottom: 20}}>
|
||||
<Text style={{padding: 5, color: '#dbdbde'}}>{set.entrant1.name ? set.entrant1.name : ''} <Text>{set.entrant1Score}</Text></Text>
|
||||
<View style={{borderTopWidth: 0.5, borderTopColor: '#2a2a33'}} />
|
||||
<Text style={{padding: 5, color: '#dbdbde'}}>{set.entrant2.name ? set.entrant2.name : ''} <Text>{set.entrant2Score}</Text></Text>
|
||||
</View>
|
||||
);
|
||||
|
||||
export default class BracketViewController extends MemeleeViewController {
|
||||
state = {
|
||||
brackets: {
|
||||
winners: [],
|
||||
losers: [],
|
||||
grandFinals: []
|
||||
}
|
||||
};
|
||||
|
||||
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/', '');
|
||||
|
||||
SmashGG.fetchBracketData(tournamentSlug, evtSlug, this.props.bracket.id).then(this.updateBracketsData).catch(console.error);
|
||||
}
|
||||
|
||||
updateBracketsData = (brackets) => {
|
||||
this.setState({brackets: brackets});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<ScrollView style={{flex: 1, backgroundColor: '#21212d'}} contentContainerStyle={{width: 10001}}>
|
||||
{['winners', 'losers'].map(key => (
|
||||
<View key={key} style={{backgroundColor: '#21212d', flexDirection: 'row', paddingTop: 20, paddingBottom: 20, paddingLeft: 20}}>
|
||||
{this.state.brackets[key].map(bracket => (
|
||||
<View key={bracket.key} style={{backgroundColor: '#21212d', marginRight: 20, width: 200, flexDirection: 'column'}}>
|
||||
<Text>{bracket.title}</Text>
|
||||
{bracket.sets.map(set => <Match key={set.id} set={set} />)}
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>);
|
||||
}
|
||||
}
|
||||
|
||||
81
controllers/EventInfoViewController.js
Normal file
81
controllers/EventInfoViewController.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/**
|
||||
* EventInfoViewController
|
||||
*
|
||||
* Yeah, I do it iOS style. Handles displaying tournament event data.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import {ScrollView, Image, Text, View, TouchableOpacity} from 'react-native';
|
||||
import Markdown from 'react-native-simple-markdown'
|
||||
//import SmashGG from '../store';
|
||||
|
||||
import MemeleeViewController from './MemeleeViewController';
|
||||
|
||||
export default class EventInfoViewController extends MemeleeViewController {
|
||||
state = {
|
||||
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) => {
|
||||
this.props.navigator.push({
|
||||
screen: 'memelee.bracket',
|
||||
title: bracket.name,
|
||||
backButtonTitle: 'Back',
|
||||
passProps: {
|
||||
tournament: this.props.tournament,
|
||||
evt: this.props.evt,
|
||||
bracket: bracket
|
||||
},
|
||||
navigatorStyle: {tabBarHidden: true}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (<ScrollView>
|
||||
<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>
|
||||
<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>
|
||||
{this.state.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.finalPlacement}
|
||||
</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>);
|
||||
}
|
||||
}
|
||||
15
controllers/MemeleeViewController.js
Normal file
15
controllers/MemeleeViewController.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* MemeleeViewController.js
|
||||
*
|
||||
* Yes yes iOS style etc etc. Handles ensuring that all view controllers have default styling
|
||||
* and such applied.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import styles from '../styles';
|
||||
|
||||
export default class MemeleeController extends React.Component {
|
||||
static navigatorStyle = styles.navigatorStyles;
|
||||
};
|
||||
73
controllers/TournamentInfoViewController.js
Normal file
73
controllers/TournamentInfoViewController.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* TournamentInfoViewController
|
||||
*
|
||||
* Yeah, I do it iOS style. Handles fetching and displaying tournament data.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import moment from 'moment';
|
||||
import React from 'react';
|
||||
import {ScrollView, StyleSheet, Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
|
||||
//import Markdown from 'react-native-simple-markdown'
|
||||
import Markdown from 'react-native-markdown-renderer';
|
||||
import SegmentedControlTab from 'react-native-segmented-control-tab';
|
||||
import SettingsList, {Header, Item} from 'react-native-settings-list';
|
||||
|
||||
import styles from '../styles';
|
||||
import MemeleeViewController from './MemeleeViewController';
|
||||
|
||||
const w = Dimensions.get('screen').width;
|
||||
/* <View style={styles.tournamentInfoButtonsRow}>
|
||||
<TouchableOpacity style={styles.tournamentRegistrationButton} onPress={this.registerForTournament}>
|
||||
<Text style={styles.tournamentRegistrationButtonText}>Register</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.tournamentBookmarkButton} onPress={this.registerForTournament}>
|
||||
<Text style={styles.tournamentRegistrationButtonText}>Bookmark</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
*/
|
||||
|
||||
|
||||
export default class TournamentInfoViewController extends MemeleeViewController {
|
||||
state = {
|
||||
selectedIndex: 0
|
||||
};
|
||||
|
||||
onEventTapped = (evt) => {
|
||||
this.props.navigator.push({
|
||||
screen: 'memelee.tournamentEventInfoScreen',
|
||||
title: evt.name,
|
||||
passProps: {tournament: this.props.tournament, evt: evt},
|
||||
navigatorStyle: {tabBarHidden: true}
|
||||
});
|
||||
}
|
||||
|
||||
swapIndex = (index) => {
|
||||
this.setState({
|
||||
selectedIndex: index
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
|
||||
|
||||
return (<ScrollView>
|
||||
<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} />
|
||||
|
||||
{this.state.selectedIndex === 0 ? (<View style={styles.tournamentDetailsTextWrapper}>
|
||||
<Markdown style={styles.tournamentDetailsText}>
|
||||
{this.props.tournament.details && this.props.tournament.details !== '' ? this.props.tournament.details : ''}
|
||||
</Markdown>
|
||||
</View>) : null}
|
||||
|
||||
{this.state.selectedIndex === 1 ? (<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
|
||||
{this.props.tournament.memeleeEvents.map(evt => (
|
||||
<Item key={evt.id} itemWidth={50} title={evt.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} />
|
||||
))}
|
||||
</SettingsList>) : null}
|
||||
</ScrollView>);
|
||||
}
|
||||
}
|
||||
63
controllers/TournamentsListViewController.js
Normal file
63
controllers/TournamentsListViewController.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* UpcomingTournamentsViewController
|
||||
*
|
||||
* 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 MemeleeViewController from './MemeleeViewController';
|
||||
import TournamentRow from './components/TournamentRow';
|
||||
|
||||
const keyExtractor = (item, index) => item.id;
|
||||
|
||||
@inject('Tournaments') @observer
|
||||
export default class UpcomingTournamentsViewController extends MemeleeViewController {
|
||||
componentWillMount() {
|
||||
this.props.Tournaments.fetchFeatured();
|
||||
}
|
||||
|
||||
onTap = (tournament) => {
|
||||
this.props.navigator.push({
|
||||
screen: 'memelee.tournamentInfoScreen',
|
||||
title: tournament.name,
|
||||
passProps: {tournament: tournament},
|
||||
navigatorStyle: {tabBarHidden: true}
|
||||
});
|
||||
}
|
||||
|
||||
renderHeader = () => (
|
||||
<SearchBar lightTheme round placeholder={""} onChangeText={this.props.Tournaments.search} containerStyle={styles.searchContainerStyle} />
|
||||
)
|
||||
|
||||
renderFooter = () => (
|
||||
this.props.Tournaments.fetchingData ? (<View style={{paddingTop: 200}}>
|
||||
<ActivityIndicator animating size="large" />
|
||||
</View>) : null
|
||||
)
|
||||
|
||||
renderItem = ({item}) => (<TournamentRow tournament={item} onTap={this.onTap} />)
|
||||
|
||||
render() {
|
||||
const props = {
|
||||
data: this.props.Tournaments.fetchingData ? [] :
|
||||
this.props.Tournaments.mode === 'search' ? this.props.Tournaments.searchResults :
|
||||
this.props.Tournaments.tournamentsList,
|
||||
|
||||
keyExtractor: keyExtractor,
|
||||
contentContainerStyle: styles.tournamentsListView,
|
||||
ListHeaderComponent: this.renderHeader,
|
||||
ListFooterComponent: this.renderFooter,
|
||||
renderItem: this.renderItem
|
||||
};
|
||||
|
||||
return <FlatList {...props} renderItem={this.renderItem} />
|
||||
}
|
||||
}
|
||||
51
controllers/components/TournamentRow.js
Normal file
51
controllers/components/TournamentRow.js
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* TournamentRow.js
|
||||
*
|
||||
* That row that displays tournament info.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
|
||||
import styles from '../../styles';
|
||||
|
||||
const width = Dimensions.get('window').width;
|
||||
|
||||
export default class TournamentRow extends React.Component {
|
||||
onPress = () => {
|
||||
this.props.onTap(this.props.tournament);
|
||||
}
|
||||
|
||||
render() {
|
||||
const x = width - 32;
|
||||
const w = {width: x, height: 130}; //x * this.props.tournament.memeleePromoImage.ratio};
|
||||
|
||||
return (<View style={styles.tournamentRowWrapper}>
|
||||
<TouchableOpacity onPress={this.onPress} style={styles.tournamentRow}>
|
||||
<Image style={[styles.tournamentRowPromoImage, w]} source={this.props.tournament.memeleePromoImage.msrc} />
|
||||
<View style={styles.tournamentRowTextWrapper}>
|
||||
<Text style={styles.tournamentRowName}>{this.props.tournament.name}</Text>
|
||||
|
||||
<Text style={styles.tournamentRowDateRange}>
|
||||
<Icon name="calendar-text" size={16} color={styles.tournamentPromoIconColors.calendar} /> {this.props.tournament.memeleeTournamentRange}
|
||||
</Text>
|
||||
|
||||
<Text style={styles.tournamentRowLocation}>
|
||||
<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'}}>
|
||||
<Text style={styles.tournamentRowEventsCount}>
|
||||
<Icon name="trophy-variant" size={16} color={styles.tournamentPromoIconColors.eventsCount} />
|
||||
{this.props.tournament.memeleeEventsCount} Events
|
||||
</Text>
|
||||
<Text style={[styles.tournamentRowEventsCount, {marginLeft: 10}]}>
|
||||
<Icon name="human-greeting" size={16} color={styles.tournamentPromoIconColors.attendeesCount} /> {this.props.tournament.attendeeCount} Attendees
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>);
|
||||
}
|
||||
}
|
||||
27
controllers/settings/index.js
Normal file
27
controllers/settings/index.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* SettingsViewController
|
||||
*
|
||||
* Yeah, I do it iOS style. Handles settings.
|
||||
*
|
||||
* @copyright Ryan McGrath 2018.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {ScrollView} from 'react-native';
|
||||
import SettingsList, {Header, Item} from 'react-native-settings-list';
|
||||
|
||||
import styles from '../../styles';
|
||||
import MemeleeViewController from '../MemeleeViewController';
|
||||
|
||||
export default class SettingsViewController extends MemeleeViewController {
|
||||
pressed = () => {}
|
||||
|
||||
render() {
|
||||
return (<ScrollView>
|
||||
<SettingsList>
|
||||
<Header headerText='First Grouping' headerStyle={{color:'white'}}/>
|
||||
<Item itemWidth={50} title='Icon Example' onPress={this.pressed} />
|
||||
</SettingsList>
|
||||
</ScrollView>);
|
||||
}
|
||||
}
|
||||
Reference in a new issue