├── .gitignore
├── README.md
├── deploy.sh
├── package.json
├── public
├── favicon.ico
└── index.html
└── src
├── App.css
├── App.js
├── App.test.js
├── DraftBoard.js
├── Drafted.js
├── Footer.js
├── Header.js
├── PlayerTable.js
├── Undrafted.js
├── UndraftedAll.js
├── UndraftedPositions.js
├── index.css
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This project is a direct port of [Fantasy Football Rankings](https://github.com/jayjzheng/ff_rankings).
2 |
3 | It uses ranking and tiering data [Boris Chen](http://www.borischen.co/) and makes an interactive draftboard to help you during your fantasy football draft.
4 |
5 | it was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
6 |
7 | ## Commands
8 | - Run: `npm start`
9 | - Build: `npm run build`
10 | - Test: `npm test`
11 |
12 | ## TODOs
13 | - Local Storage
14 | - Tests
15 | - Better CSS
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | aws s3 sync ./build s3://jayzheng.com/ff --exclude 'deploy.sh' --exclude '.git/*'
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "draftaid",
3 | "version": "0.1.0",
4 | "private": true,
5 | "homepage": "https://jayzheng.com/ff",
6 | "devDependencies": {
7 | "react-scripts": "0.9.0"
8 | },
9 | "dependencies": {
10 | "bootstrap": "^3.3.7",
11 | "react": "^15.4.2",
12 | "react-dom": "^15.4.2"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test --env=jsdom",
18 | "eject": "react-scripts eject"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jayjzheng/draftaid-react/171ffa06c9130b8d8d88ad612ee7dab0d9bbd72b/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
18 | Draft Aid
19 |
20 |
21 |
22 |
32 |
33 |
34 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .container {padding-left:0;padding-right:5px;}
2 | .row {margin-left:0;margin-right:-5px;}
3 | .row > div {padding-left:0;padding-right:5px;}
4 |
5 | .scrollable {
6 | overflow-y: auto;
7 | }
8 |
9 | .table-condensed > tbody > tr > td {
10 | padding: 2px;
11 | font-size: 12px;
12 | }
13 |
14 | .aid-title {
15 | text-align: center;
16 | font-weight: bold;
17 | background-color: #eee;
18 | padding: 5px;
19 | margin-bottom: 5px;
20 | }
21 |
22 | .position-title {
23 | text-align: center;
24 | font-weight: bold;
25 | margin-bottom: 5px;
26 | }
27 |
28 | html, body {
29 | height: 100%;
30 | }
31 |
32 | #wrap {
33 | min-height: 100%;
34 | }
35 |
36 | #main {
37 | overflow:auto;
38 | padding-bottom:60px; /* this needs to be bigger than footer height*/
39 | }
40 |
41 | .footer {
42 | position: relative;
43 | margin-top: -50px; /* negative value of footer height */
44 | height: 50px;
45 | clear:both;
46 | padding:10px;
47 | }
48 |
49 | .overall-rankings {
50 | height: 250px;
51 | margin-bottom: 10px;
52 | }
53 |
54 | .btn-responsive {
55 | padding: 4px 8px;
56 | font-size: 90%;
57 | }
58 |
59 | .pointer {
60 | cursor: pointer;
61 | }
62 |
63 | @media(min-width: 768px){
64 | .btn-responsive {
65 | font-size: 100%;
66 | padding: 5px 10px;
67 | }
68 |
69 | .overall-rankings {
70 | height: 710px;
71 | margin-bottom: 10px;
72 | }
73 |
74 | .draft-history {
75 | height: 710px;
76 | }
77 |
78 | .table-condensed > tbody > tr > td {
79 | padding: 2px;
80 | font-size: 13px;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import './App.css';
4 |
5 | import Header from './Header'
6 | import Footer from './Footer'
7 | import DraftBoard from './DraftBoard'
8 |
9 | class App extends Component {
10 | render() {
11 | return (
12 |
13 |
14 |
15 |
16 | );
17 | }
18 | }
19 |
20 | export default App;
21 |
--------------------------------------------------------------------------------
/src/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 |
5 | it('renders without crashing', () => {
6 | const div = document.createElement('div');
7 | ReactDOM.render(, div);
8 | });
9 |
--------------------------------------------------------------------------------
/src/DraftBoard.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import UndraftedAll from './UndraftedAll'
4 | import UndraftedPositions from './UndraftedPositions'
5 | import Drafted from './Drafted'
6 |
7 | class DraftBoard extends Component {
8 | constructor() {
9 | super();
10 |
11 | this.state = {
12 | players: [],
13 | filteredPlayers: [],
14 | isLoading: true,
15 | currentDraft: 0,
16 | fetchError: null,
17 | format: 'standard',
18 | query: '',
19 | };
20 | }
21 |
22 | componentDidMount() {
23 | this.fetchPlayers(this.state.format);
24 | }
25 |
26 | fetchPlayers(format) {
27 | // const url = 'https://draftaid-api.herokuapp.com/rankings';
28 | const url = 'https://jayzheng-ff-api.herokuapp.com/rankings';
29 | const self = this;
30 |
31 | fetch(url+'?format='+format, {
32 | method: 'get'
33 | }).then(function(response) {
34 | response.json().then(function(res){
35 | self.setState({
36 | players: res.rankings,
37 | filteredPlayers: res.rankings,
38 | isLoading: false,
39 | format: format,
40 | query: '',
41 | });
42 | });
43 | }).catch(function(err) {
44 | self.setState({
45 | fetchError: err,
46 | isLoading: false,
47 | });
48 | });
49 | }
50 |
51 | searchPlayers(query) {
52 | let players = this.state.players.filter(player =>
53 | player.name.toUpperCase().includes(query.toUpperCase())
54 | );
55 |
56 | this.setState({
57 | filteredPlayers: players,
58 | query: query,
59 | });
60 | }
61 |
62 | draft(player) {
63 | const players = this.state.players.slice();
64 | const index = players.indexOf(player);
65 | if (~index) {
66 | players[index].drafted = this.state.currentDraft + 1;
67 | }
68 |
69 | this.setState({
70 | currentDraft: this.state.currentDraft + 1,
71 | players: players,
72 | filteredPlayers: players,
73 | query: '',
74 | });
75 | }
76 |
77 | undo(currentDraft) {
78 | if(currentDraft === 0) {
79 | return
80 | }
81 |
82 | const players = this.state.players.slice();
83 | const index = players.findIndex(p => p.drafted === currentDraft);
84 | if (~index) {
85 | players[index].drafted = null;
86 | }
87 |
88 | this.setState({
89 | currentDraft: this.state.currentDraft - 1,
90 | players: players,
91 | });
92 | }
93 |
94 | reset() {
95 | const players = this.state.players.slice();
96 | players.map((player, i) => {
97 | return player.drafted = null;
98 | });
99 |
100 | this.setState({
101 | currentDraft: 0,
102 | players: players,
103 | });
104 | }
105 |
106 | render() {
107 | if (this.state.isLoading) {
108 | return (Loading...
)
109 | }
110 |
111 | if (this.state.fetchError) {
112 | return (error fetching rankings...
)
113 | }
114 |
115 | return (
116 |
117 | this.draft(p) }
120 | fetch={ (e) => this.fetchPlayers(e.target.value) }
121 | search={ (e) => this.searchPlayers(e.target.value) }
122 | format={ this.state.format }
123 | query={ this.state.query }
124 | />
125 |
126 | this.draft(p)}
129 | />
130 |
131 | this.undo(c) }
135 | reset={ () => this.reset() }
136 | />
137 |
138 | );
139 | }
140 | }
141 |
142 | export default DraftBoard;
143 |
--------------------------------------------------------------------------------
/src/Drafted.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import PlayerTable from './PlayerTable'
4 |
5 | function Drafted(props) {
6 | let players = props.players.slice().filter(p => p.drafted);
7 | players = players.sort((a, b) => b.drafted - a.drafted);
8 |
9 | return (
10 |
11 |
12 | Draft History
13 |
14 |
15 |
16 |
17 |
22 |
23 |
28 |
29 |
30 |
31 |
36 |
37 | );
38 | }
39 |
40 | Drafted.propTypes = {
41 | currentDraft: React.PropTypes.number.isRequired,
42 | reset: React.PropTypes.func.isRequired,
43 | undo: React.PropTypes.func.isRequired,
44 | players: React.PropTypes.array.isRequired,
45 | };
46 |
47 | export default Drafted
48 |
--------------------------------------------------------------------------------
/src/Footer.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function Footer() {
4 | return (
5 |
6 | footer
7 |
8 | );
9 | }
10 |
11 | export default Footer
--------------------------------------------------------------------------------
/src/Header.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | function Header() {
4 | return (
5 |
11 | );
12 | }
13 |
14 | export default Header
--------------------------------------------------------------------------------
/src/PlayerTable.js:
--------------------------------------------------------------------------------
1 | import React, { PureComponent } from 'react';
2 |
3 | class PlayerTable extends PureComponent {
4 | rows() {
5 | let players = this.props.players.slice();
6 |
7 | if (this.props.size) {
8 | players = players.slice(0, this.props.size);
9 | }
10 |
11 | return players.map((player, i) => {
12 | return (
13 | this.onClick(player)}>
16 | {this.columns(player)}
17 |
18 | )
19 | });
20 | }
21 |
22 | onClick(player) {
23 | if (this.props.onClick) {
24 | return this.props.onClick(player);
25 | }
26 | }
27 |
28 | trClassName(tier, disable) {
29 | if (disable) {
30 | return 'pointer'
31 | }
32 | if (tier % 4 === 0) {
33 | return 'active pointer'
34 | }
35 | if (tier % 4 === 1) {
36 | return 'success pointer'
37 | }
38 | if (tier % 4 === 2) {
39 | return 'warning pointer'
40 | }
41 | if (tier % 4 === 3) {
42 | return 'info pointer'
43 | }
44 | return 'danger pointer'
45 | }
46 |
47 | columns(player) {
48 | return this.props.fields.map((f, i) => {
49 | if (f === 'tier') {
50 | return Tier {player[f]} |
51 | } else {
52 | return {player[f]} |
53 | }
54 | });
55 | }
56 |
57 | render() {
58 | return (
59 |
62 | );
63 | }
64 | }
65 |
66 | PlayerTable.propTypes = {
67 | players: React.PropTypes.array.isRequired,
68 | fields: React.PropTypes.array.isRequired,
69 |
70 | onClick: React.PropTypes.func,
71 | size: React.PropTypes.number,
72 | disableColor: React.PropTypes.bool,
73 | };
74 |
75 | export default PlayerTable
76 |
--------------------------------------------------------------------------------
/src/Undrafted.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import PlayerTable from './PlayerTable'
4 |
5 | function Undrafted(props) {
6 | let players = props.players.slice().filter(p => !p.drafted);
7 |
8 | if (props.position) {
9 | players = players.filter(p => p.position.includes(props.position));
10 | }
11 |
12 | players = players.sort((a, b) => a.rank - b.rank);
13 |
14 | return (
15 | props.draft(p)}
20 | />
21 | );
22 | }
23 |
24 |
25 | Undrafted.propTypes = {
26 | draft: React.PropTypes.func.isRequired,
27 | players: React.PropTypes.array.isRequired,
28 | fields: React.PropTypes.array.isRequired,
29 |
30 | size: React.PropTypes.number,
31 | position: React.PropTypes.string,
32 | };
33 |
34 | export default Undrafted
35 |
--------------------------------------------------------------------------------
/src/UndraftedAll.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Undrafted from './Undrafted'
4 |
5 | function UndraftedAll(props) {
6 | return (
7 |
8 |
9 | Overall Rankings
10 |
11 |
12 |
13 |
14 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 | props.draft(p)}
37 | />
38 |
39 |
40 | )
41 | }
42 |
43 | UndraftedAll.propTypes = {
44 | players: React.PropTypes.array.isRequired,
45 | format: React.PropTypes.string.isRequired,
46 | query: React.PropTypes.string.isRequired,
47 | search: React.PropTypes.func.isRequired,
48 | fetch: React.PropTypes.func.isRequired,
49 | };
50 |
51 | export default UndraftedAll
52 |
--------------------------------------------------------------------------------
/src/UndraftedPositions.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Undrafted from './Undrafted'
4 |
5 | function UndraftedPositions(props) {
6 | const fields = ['tier', 'name', 'team'];
7 |
8 | return (
9 |
10 |
11 | Top Picks By Position
12 |
13 |
14 |
15 | Runningbacks
16 | props.draft(p)}
20 | size={15}
21 | position='RB'
22 | />
23 |
24 |
25 |
26 | Wide Receivers
27 | props.draft(p)}
31 | size={15}
32 | position='WR'
33 | />
34 |
35 |
36 |
37 | Quarterbacks
38 | props.draft(p)}
42 | size={15}
43 | position='QB'
44 | />
45 |
46 |
47 |
48 | Tightends
49 | props.draft(p)}
53 | size={15}
54 | position='TE'
55 | />
56 |
57 |
58 | )
59 | }
60 |
61 | UndraftedPositions.propTypes = {
62 | draft: React.PropTypes.func.isRequired,
63 | players: React.PropTypes.array.isRequired,
64 | };
65 |
66 | export default UndraftedPositions
67 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: sans-serif;
5 | }
6 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import 'bootstrap/dist/css/bootstrap.css';
5 | import App from './App';
6 |
7 | import './index.css';
8 |
9 | ReactDOM.render(
10 | ,
11 | document.getElementById('root')
12 | );
13 |
--------------------------------------------------------------------------------