playball 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.eslintrc.json +1 -1
  2. package/README.md +62 -0
  3. package/bin/playball.js +1 -1
  4. package/package.json +10 -6
  5. package/src/cli.js +46 -0
  6. package/src/components/AllPlays.jsx +14 -13
  7. package/src/components/App.jsx +6 -6
  8. package/src/components/AtBat.jsx +1 -1
  9. package/src/components/Bases.jsx +3 -2
  10. package/src/components/Count.jsx +5 -4
  11. package/src/components/FinishedGame.jsx +2 -2
  12. package/src/components/Game.jsx +5 -5
  13. package/src/components/GameList.jsx +8 -5
  14. package/src/components/Grid.jsx +1 -1
  15. package/src/components/HelpBar.jsx +1 -1
  16. package/src/components/InningDisplay.jsx +1 -1
  17. package/src/components/LineScore.jsx +1 -1
  18. package/src/components/LiveGame.jsx +7 -7
  19. package/src/components/LoadingSpinner.jsx +2 -2
  20. package/src/components/Matchup.jsx +1 -1
  21. package/src/components/PreviewGame.jsx +1 -1
  22. package/src/components/Standings.jsx +6 -3
  23. package/src/config.js +167 -0
  24. package/src/features/games.js +2 -1
  25. package/src/features/keys.js +5 -4
  26. package/src/features/schedule.js +2 -1
  27. package/src/features/standings.js +2 -1
  28. package/src/hooks/useKey.js +1 -1
  29. package/src/logger.js +4 -1
  30. package/src/main.js +19 -15
  31. package/src/package.js +7 -0
  32. package/src/screen.js +18 -10
  33. package/src/store/index.js +6 -5
  34. package/src/utils.js +10 -0
  35. package/dist/components/AllPlays.js +0 -133
  36. package/dist/components/App.js +0 -68
  37. package/dist/components/AtBat.js +0 -67
  38. package/dist/components/Bases.js +0 -38
  39. package/dist/components/Count.js +0 -36
  40. package/dist/components/FinishedGame.js +0 -124
  41. package/dist/components/Game.js +0 -82
  42. package/dist/components/GameList.js +0 -222
  43. package/dist/components/Grid.js +0 -115
  44. package/dist/components/HelpBar.js +0 -30
  45. package/dist/components/InningDisplay.js +0 -26
  46. package/dist/components/LineScore.js +0 -60
  47. package/dist/components/LiveGame.js +0 -70
  48. package/dist/components/LoadingSpinner.js +0 -55
  49. package/dist/components/Matchup.js +0 -58
  50. package/dist/components/PreviewGame.js +0 -76
  51. package/dist/components/Standings.js +0 -91
  52. package/dist/features/games.js +0 -135
  53. package/dist/features/keys.js +0 -63
  54. package/dist/features/schedule.js +0 -58
  55. package/dist/features/standings.js +0 -57
  56. package/dist/hooks/useKey.js +0 -23
  57. package/dist/logger.js +0 -22
  58. package/dist/main.js +0 -28
  59. package/dist/screen.js +0 -22
  60. package/dist/store/index.js +0 -32
  61. package/dist/style/index.js +0 -22
package/.eslintrc.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "ecmaFeatures": {
12
12
  "jsx": true
13
13
  },
14
- "ecmaVersion": 2020,
14
+ "ecmaVersion": 2022,
15
15
  "sourceType": "module"
16
16
  },
17
17
  "plugins": [
package/README.md CHANGED
@@ -46,6 +46,68 @@ key | action
46
46
  ----|--------
47
47
  <kbd>&darr;</kbd>/<kbd>j</kbd>, <kbd>&uarr;</kbd>/<kbd>k</kbd> | scroll list of all plays
48
48
 
49
+ ### Configuration
50
+
51
+ Playball can be configured using the `config` subcommand. To list the current configuration values run the subcommand with no additional arguments:
52
+
53
+ ```shell
54
+ playball config
55
+ ```
56
+
57
+ You should see output similar to:
58
+
59
+ ```
60
+ color.ball = green
61
+ color.favorite-star = yellow
62
+ color.in-play-no-out = blue
63
+ color.in-play-out = white
64
+ color.in-play-runs-bg = white
65
+ color.in-play-runs-fg = black
66
+ color.on-base = yellow
67
+ color.other-event = white
68
+ color.out = red
69
+ color.strike = red
70
+ color.strike-out = red
71
+ color.walk = green
72
+ favorites =
73
+ ```
74
+
75
+ To get the value of a single setting pass the key as an additional argument:
76
+
77
+ ```shell
78
+ playball config color.strike
79
+ ```
80
+
81
+ To change a setting pass the key and value as arguments:
82
+
83
+ ```shell
84
+ playball config color.strike blue
85
+ ```
86
+
87
+ To revert a setting to its default value provide the key and the `--unset` flag:
88
+
89
+ ```shell
90
+ playball config color.strike --unset
91
+ ```
92
+
93
+ This table summarizes the available settings:
94
+
95
+ key | description | default | allowed values
96
+ ----|-------------|---------|---------------
97
+ `color.ball` | Color of dots representing balls in top row of game view | green | One of the following: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `grey`. Any of those colors may be prefixed by `bright-` or `light-` (for example `bright-green`). The exact color used will depend on your terminal settings. The value `default` may be used to specify the default text color for your terminal. Finally hex colors (e.g `#FFA500`) can be specified. If your terminal does not support true color, the closest supported color may be used.
98
+ `color.favorite-star` | Color of star indiciating favorite team in schedule and standing views | yellow | _See above_
99
+ `color.in-play-no-out` | Color of result where ball was put in play and no out was made (single, double, etc) in list of plays in game view | blue | _See above_
100
+ `color.in-play-out` | Color of result where ball was put in play and an out was made (flyout, fielder's choice, etc) in list of plays in game view | white | _See above_
101
+ `color.in-play-runs-bg` | Background color for score update in list of plays in game view | white | _See above_
102
+ `color.in-play-runs-fg` | Foreground color for score update in list of plays in game view | black | _See above_
103
+ `color.on-base` | Color of diamonds representing runners on base in top row of game view | yellow | _See above_
104
+ `color.other-event` | Color of other events (mound visit, injury delay, etc) in list of plays in game view | white | _See above_
105
+ `color.out` | Color of dots representing outs in top row of game view | red | _See above_
106
+ `color.strike` | Color of dots representing strikes in top row of game view | red | _See above_
107
+ `color.strike-out` | Color of result where play ends on a strike (strike out) in list of plays in game view | red | _See above_
108
+ `color.walk` | Color of result where play ends on a ball (walk, hit by pitch) in list of plays in game view | green | _See above_
109
+ `favorites` | Teams to highlight in schedule and standings views | | Any one of the following: `ATL`, `AZ`, `BAL`, `BOS`, `CHC`, `CIN`, `CLE`, `COL`, `CWS`, `DET`, `HOU`, `KC`, `LAA`, `LAD`, `MIA`, `MIL`, `MIN`, `NYM`, `NYY`, `OAK`, `PHI`, `PIT`, `SD`, `SEA`, `SF`, `STL`, `TB`, `TEX`, `TOR`, `WSH`. Or a comma-separated list of multiple (e.g. `SEA,MIL`)
110
+
49
111
  ### Development
50
112
  ```
51
113
  git clone https://github.com/paaatrick/playball.git
package/bin/playball.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- require('..');
2
+ import '../dist/cli.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playball",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "Watch MLB games from the comfort of your terminal",
5
5
  "keywords": [
6
6
  "MLB",
@@ -14,11 +14,10 @@
14
14
  "clean": "rimraf ./dist",
15
15
  "compile": "babel src --out-dir dist",
16
16
  "lint": "eslint --ext .jsx,.js src",
17
- "start": "babel-node ./src/main.js",
17
+ "start": "babel src --out-dir dist --watch",
18
18
  "prepublishOnly": "npm run build",
19
19
  "react-devtools": "react-devtools"
20
20
  },
21
- "main": "dist/main.js",
22
21
  "bin": {
23
22
  "playball": "./bin/playball.js"
24
23
  },
@@ -37,6 +36,8 @@
37
36
  "@reduxjs/toolkit": "^1.8.0",
38
37
  "axios": "^0.26.1",
39
38
  "blessed": "^0.1.81",
39
+ "commander": "^11.0.0",
40
+ "conf": "^11.0.1",
40
41
  "date-fns": "^2.28.0",
41
42
  "json-patch": "^0.7.0",
42
43
  "prop-types": "^15.8.1",
@@ -46,6 +47,7 @@
46
47
  "react-devtools-core": "^4.24.7",
47
48
  "react-redux": "^7.2.6",
48
49
  "redux": "^4.1.2",
50
+ "update-notifier": "^6.0.2",
49
51
  "winston": "^3.7.2"
50
52
  },
51
53
  "devDependencies": {
@@ -61,14 +63,16 @@
61
63
  "rimraf": "^2.6.3",
62
64
  "ws": "^8.5.0"
63
65
  },
66
+ "type": "module",
64
67
  "babel": {
65
68
  "presets": [
66
69
  [
67
70
  "@babel/preset-env",
68
71
  {
69
72
  "targets": {
70
- "node": "10"
71
- }
73
+ "node": "14"
74
+ },
75
+ "modules": false
72
76
  }
73
77
  ],
74
78
  "@babel/preset-react"
@@ -78,7 +82,7 @@
78
82
  "module-resolver",
79
83
  {
80
84
  "alias": {
81
- "react-redux": "react-redux/lib/alternate-renderers"
85
+ "react-redux": "react-redux/lib/alternate-renderers.js"
82
86
  }
83
87
  }
84
88
  ]
package/src/cli.js ADDED
@@ -0,0 +1,46 @@
1
+ /* eslint no-console: 0 */
2
+ import { Command } from 'commander';
3
+ import updateNotifier from 'update-notifier';
4
+
5
+ import * as config from './config.js';
6
+ import main from './main.js';
7
+ import pkg from './package.js';
8
+
9
+ const program = new Command();
10
+ const notifier = updateNotifier({
11
+ pkg,
12
+ updateCheckInterval: 1000 * 60 * 60 * 24 * 7 // 1 week
13
+ });
14
+
15
+ program
16
+ .name(pkg.name)
17
+ .description(pkg.description)
18
+ .version(pkg.version)
19
+ .action(main)
20
+ .hook('postAction', () => notifier.notify({
21
+ isGlobal: true,
22
+ }));
23
+
24
+ program.command('config')
25
+ .description('Set or get configration values')
26
+ .argument('[key]')
27
+ .argument('[value]')
28
+ .option('--unset', 'Unset configuration value')
29
+ .action((key, value, options) => {
30
+ if (options.unset) {
31
+ config.unset(key);
32
+ return;
33
+ }
34
+ if (!key) {
35
+ for (const [key, value] of Object.entries(config.getAll())) {
36
+ console.log(`${key} = ${value}`);
37
+ }
38
+ } else if (!value) {
39
+ console.log(config.get(key));
40
+ } else {
41
+ config.set(key, value);
42
+ }
43
+ });
44
+
45
+
46
+ program.parse();
@@ -1,27 +1,28 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { selectAllPlays, selectTeams } from '../features/games';
3
+ import { selectAllPlays, selectTeams } from '../features/games.js';
4
4
 
5
- import style from '../style';
5
+ import { get } from '../config.js';
6
+ import style from '../style/index.js';
6
7
 
7
8
 
8
9
  function getPlayResultColor(play) {
9
10
  const lastPlay = play.playEvents[play.playEvents.length - 1]?.details;
10
11
  if (!lastPlay) {
11
- return 'white';
12
+ return get('color.other-event');
12
13
  } else if (lastPlay.isBall) {
13
- return 'green';
14
+ return get('color.walk');
14
15
  } else if (lastPlay.isStrike) {
15
- return 'red';
16
+ return get('color.strike-out');
16
17
  } else if (lastPlay.isInPlay && !play.about.hasOut) {
17
- return 'blue';
18
+ return get('color.in-play-no-out');
18
19
  } else {
19
- return 'white';
20
+ return get('color.in-play-out');
20
21
  }
21
22
  }
22
23
 
23
24
  function formatOut(out) {
24
- return ` {bold}${out} out{/bold}`;
25
+ return ` {bold}${out} out{/}`;
25
26
  }
26
27
 
27
28
 
@@ -30,10 +31,10 @@ function AllPlays() {
30
31
  const teams = useSelector(selectTeams);
31
32
 
32
33
  const formatScoreDetail = (scoreObj) => (
33
- ' {bold}{white-bg}{black-fg} ' +
34
+ ` {bold}{${get('color.in-play-runs-bg')}-bg}{${get('color.in-play-runs-fg')}-fg} ` +
34
35
  `${teams.away.abbreviation} ${scoreObj.awayScore} - ` +
35
36
  `${teams.home.abbreviation} ${scoreObj.homeScore}` +
36
- ' {/black-fg}{/white-bg}{/bold}'
37
+ ' {/}'
37
38
  );
38
39
 
39
40
  let inning = '';
@@ -49,12 +50,12 @@ function AllPlays() {
49
50
  if (lines.length > 0) {
50
51
  lines.push('');
51
52
  }
52
- lines.push(`{bold}[${inning.toUpperCase()}]{/bold}`);
53
+ lines.push(`{bold}[${inning.toUpperCase()}]{/}`);
53
54
  }
54
55
 
55
56
  if (play.about.isComplete) {
56
57
  const color = getPlayResultColor(play);
57
- let line = `{${color}-fg}[${play.result.event}]{/${color}-fg} ${play.result.description}`;
58
+ let line = `{${color}-fg}[${play.result.event}]{/} ${play.result.description}`;
58
59
  if (play.about.hasOut) {
59
60
  const lastOut = play.playEvents[play.playEvents.length - 1].count.outs;
60
61
  if (lastOut !== play.count.outs) {
@@ -71,7 +72,7 @@ function AllPlays() {
71
72
  if (event.type === 'action') {
72
73
  let line = '';
73
74
  if (event.details.event) {
74
- line += `[${event.details.event}] `;
75
+ line += `{${get('color.other-event')}-fg}[${event.details.event}]{/} `;
75
76
  }
76
77
  line += event.details.description;
77
78
  if (event.isScoringPlay || event.details.isScoringPlay) {
@@ -1,11 +1,11 @@
1
1
  import React, { useState } from 'react';
2
2
  import { useDispatch } from 'react-redux';
3
- import GameList from './GameList';
4
- import HelpBar from './HelpBar';
5
- import { setSelectedId } from '../features/games';
6
- import Game from './Game';
7
- import useKey from '../hooks/useKey';
8
- import Standings from './Standings';
3
+ import GameList from './GameList.js';
4
+ import HelpBar from './HelpBar.js';
5
+ import { setSelectedId } from '../features/games.js';
6
+ import Game from './Game.js';
7
+ import useKey from '../hooks/useKey.js';
8
+ import Standings from './Standings.js';
9
9
 
10
10
  const SCHEDULE = 'schedule';
11
11
  const STANDINGS = 'standings';
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { selectCurrentPlay } from '../features/games';
3
+ import { selectCurrentPlay } from '../features/games.js';
4
4
 
5
5
  function AtBat() {
6
6
  const currentPlay = useSelector(selectCurrentPlay);
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
3
  import PropTypes from 'prop-types';
4
- import { selectLineScore } from '../features/games';
4
+ import { get } from '../config.js';
5
+ import { selectLineScore } from '../features/games.js';
5
6
 
6
- const formatBase = (offense, base) => (base in offense) ? '{yellow-fg}◆{/yellow-fg}' : '◇';
7
+ const formatBase = (offense, base) => (base in offense) ? `{${get('color.on-base')}-fg}◆{/}` : '◇';
7
8
 
8
9
  function Bases({align}) {
9
10
  const { offense } = useSelector(selectLineScore);
@@ -2,16 +2,17 @@ import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
3
  import PropTypes from 'prop-types';
4
4
 
5
- import { selectLineScore } from '../features/games';
5
+ import { get } from '../config.js';
6
+ import { selectLineScore } from '../features/games.js';
6
7
 
7
8
  const formatCount = (count, total) => '● '.repeat(count) + '○ '.repeat(total - count);
8
9
 
9
10
  function Count({align}) {
10
11
  const linescore = useSelector(selectLineScore);
11
12
  const content =
12
- `B: {green-fg}${formatCount(linescore.balls, 4)}{/green-fg}\n` +
13
- `S: {red-fg}${formatCount(linescore.strikes, 3)}{/red-fg}\n` +
14
- `O: {red-fg}${formatCount(linescore.outs, 3)}{/red-fg}`;
13
+ `B: {${get('color.ball')}-fg}${formatCount(linescore.balls, 4)}{/}\n` +
14
+ `S: {${get('color.strike')}-fg}${formatCount(linescore.strikes, 3)}{/}\n` +
15
+ `O: {${get('color.out')}-fg}${formatCount(linescore.outs, 3)}{/}`;
15
16
  return (
16
17
  <box align={align} content={content} tags />
17
18
  );
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { selectLineScore, selectTeams, selectDecisions, selectBoxscore, selectGameStatus } from '../features/games';
4
- import LineScore from './LineScore';
3
+ import { selectLineScore, selectTeams, selectDecisions, selectBoxscore, selectGameStatus } from '../features/games.js';
4
+ import LineScore from './LineScore.js';
5
5
 
6
6
  const getPlayer = (id, boxscore) => {
7
7
  const homePlayer = boxscore.home?.players?.['ID' + id];
@@ -1,13 +1,13 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
 
4
- import { fetchGame, selectGame, selectSelectedId, selectFullUpdateRequired } from '../features/games';
4
+ import { fetchGame, selectGame, selectSelectedId, selectFullUpdateRequired } from '../features/games.js';
5
5
 
6
- import PreviewGame from './PreviewGame';
7
- import LiveGame from './LiveGame';
8
- import FinishedGame from './FinishedGame';
6
+ import PreviewGame from './PreviewGame.js';
7
+ import LiveGame from './LiveGame.js';
8
+ import FinishedGame from './FinishedGame.js';
9
9
 
10
- import log from '../logger';
10
+ import log from '../logger.js';
11
11
 
12
12
  function Game() {
13
13
  const dispatch = useDispatch();
@@ -2,17 +2,20 @@ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import PropTypes from 'prop-types';
4
4
  import { add, format } from 'date-fns';
5
- import { fetchSchedule, selectData, selectLoading } from '../features/schedule';
6
-
7
- import Grid from './Grid';
8
- import useKey from '../hooks/useKey';
5
+ import { fetchSchedule, selectData, selectLoading } from '../features/schedule.js';
6
+ import { teamFavoriteStar } from '../utils.js';
7
+ import Grid from './Grid.js';
8
+ import useKey from '../hooks/useKey.js';
9
9
 
10
10
  const formatGame = game => {
11
11
  const startTime = format(new Date(game.gameDate), 'p');
12
12
  const start = (game.doubleHeader === 'Y' && game.gameNumber > 1) ?
13
13
  'Game ' + game.gameNumber :
14
14
  startTime;
15
- const teamName = (team) => `${team.team.teamName} (${team.leagueRecord.wins}-${team.leagueRecord.losses})`.padEnd(20);
15
+ const teamName = (team) => {
16
+ const star = teamFavoriteStar(team.team);
17
+ return star + `${team.team.teamName} (${team.leagueRecord.wins}-${team.leagueRecord.losses})`.padEnd(star ? 18 : 20);
18
+ };
16
19
  let content = [start, teamName(game.teams.away), teamName(game.teams.home)];
17
20
  const gameState = game.status.abstractGameCode;
18
21
  const detailedState = game.status.detailedState;
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import useKey from '../hooks/useKey';
3
+ import useKey from '../hooks/useKey.js';
4
4
 
5
5
  function Grid({ items, itemHeight, itemMinWidth, onSelect }) {
6
6
  const containerRef = useRef();
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import LoadingSpinner from './LoadingSpinner';
3
+ import LoadingSpinner from './LoadingSpinner.js';
4
4
 
5
5
  const HelpBar = () => {
6
6
  const keys = useSelector(state => state.keys);
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
3
 
4
- import { selectLineScore } from '../features/games';
4
+ import { selectLineScore } from '../features/games.js';
5
5
 
6
6
  function InningDisplay() {
7
7
  const linescore = useSelector(selectLineScore);
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useSelector } from 'react-redux';
4
- import { selectLineScore, selectTeams } from '../features/games';
4
+ import { selectLineScore, selectTeams } from '../features/games.js';
5
5
 
6
6
  const getRuns = (inning, homeAway, isFinal) => {
7
7
  const runs = inning[homeAway].runs;
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
2
 
3
- import Count from './Count';
4
- import Bases from './Bases';
5
- import LineScore from './LineScore';
6
- import Matchup from './Matchup';
7
- import AtBat from './AtBat';
8
- import AllPlays from './AllPlays';
9
- import InningDisplay from './InningDisplay';
3
+ import Count from './Count.js';
4
+ import Bases from './Bases.js';
5
+ import LineScore from './LineScore.js';
6
+ import Matchup from './Matchup.js';
7
+ import AtBat from './AtBat.js';
8
+ import AllPlays from './AllPlays.js';
9
+ import InningDisplay from './InningDisplay.js';
10
10
 
11
11
  function LiveGame() {
12
12
  return (
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { selectLoading as selectScheduleLoading } from '../features/schedule';
4
- import { selectLoading as gamesLoading } from '../features/games';
3
+ import { selectLoading as selectScheduleLoading } from '../features/schedule.js';
4
+ import { selectLoading as gamesLoading } from '../features/games.js';
5
5
 
6
6
  const frames = [
7
7
  '⠋',
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { selectCurrentPlay, selectBoxscore, selectTeams } from '../features/games';
3
+ import { selectCurrentPlay, selectBoxscore, selectTeams } from '../features/games.js';
4
4
 
5
5
  const getPlayerStats = (boxscore, teams, id) => {
6
6
  const key = 'ID' + id;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
3
  import { format } from 'date-fns';
4
- import { selectTeams, selectVenue, selectStartTime, selectBoxscore, selectProbablePitchers, selectGameStatus } from '../features/games';
4
+ import { selectTeams, selectVenue, selectStartTime, selectBoxscore, selectProbablePitchers, selectGameStatus } from '../features/games.js';
5
5
 
6
6
  const formatPitcherName = (pitcher) => {
7
7
  let display = pitcher.person.fullName;
@@ -1,7 +1,8 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useDispatch, useSelector } from 'react-redux';
4
- import { fetchStandings, selectData } from '../features/standings';
4
+ import { fetchStandings, selectData } from '../features/standings.js';
5
+ import { teamFavoriteStar } from '../utils.js';
5
6
 
6
7
  function formatHeaderRow(record) {
7
8
  return record.division.nameShort.padEnd(15) +
@@ -16,7 +17,9 @@ function formatHeaderRow(record) {
16
17
 
17
18
  function formatTeamRow(record) {
18
19
  const lastTen = record.records.splitRecords.find(o => o.type === 'lastTen');
19
- return record.team.teamName.padEnd(15) +
20
+ const star = teamFavoriteStar(record.team);
21
+ return star +
22
+ record.team.teamName.padEnd(star ? 13 : 15) +
20
23
  record.wins.toString().padStart(5) +
21
24
  record.losses.toString().padStart(5) +
22
25
  record.winningPercentage.padStart(7) +
@@ -30,7 +33,7 @@ function Division({record, top, left, width}) {
30
33
  return (
31
34
  <box top={top} left={left} height={6} width={width}>
32
35
  <box top={0} left={0} height={1} fg='black' bg='white' content={formatHeaderRow(record)} wrap={false} />
33
- <box top={1} left={0} height={5} content={record.teamRecords.map(formatTeamRow).join('\n')} wrap={false} />
36
+ <box top={1} left={0} height={5} content={record.teamRecords.map(formatTeamRow).join('\n')} wrap={false} tags />
34
37
  </box>
35
38
  );
36
39
  }