Players and Teams

Enable a user to organize players into teams.


Environment

Use the environment you are most comfortable with. I recommend using create-react-app to create a local version of the project so that you can inspect the DOM easily from your browser when debugging. Alternatively, you can work from a blank React template in CodeSandbox. Starter code is provided after the problem specification.

Specification

Write a functional component that accepts a list of names as a prop and displays them in a row at the top of the screen. A button should allow the user to toggle between selecting names for team 1 and team 2. When the user clicks on a name in the row, it should be removed from the row and added to the currently selected team. Display two more buttons to randomize the teams and reset the component, respectively. The teams should be displayed under “Team 1” and “Team 2” headings beneath the row and buttons. The finished component after assigning five names to teams is shown below.mf

The finished product
The finished product

Clicking on “Alice”, “Gary”, or “Hector” in the image above would move them from the row at the top to “Team 1”. To instead assign them to Team 2, the user would click the “Now selecting for Team 1” button to select for Team 2 before clicking the names that they would like to move.

Starter Code

Here is some code to get you started:

import React, { useState } from "react";

function App() {
  const PLAYERS = [
    "Alice",
    "Bob",
    "Carol",
    "Daniel",
    "Elaine",
    "Finley",
    "Gary",
    "Hector",
  ];

  return <FormTeams players={PLAYERS} />;
}

const FormTeams = ({ players }) => {
  // YOUR CODE HERE
};

export default App;

Feel free to divide the challenge into multiple subcomponents.

Solution

import React, { useState } from "react";

function App() {
  const PLAYERS = [
    "Alice",
    "Bob",
    "Carol",
    "Daniel",
    "Elaine",
    "Finley",
    "Gary",
    "Hector",
  ];

  return <FormTeams players={PLAYERS} />;
}

const FormTeams = ({ players }) => {
  const [team1, setTeam1] = useState([]);
  const [team2, setTeam2] = useState([]);
  const [remainingPlayers, setRemainingPlayers] = useState(players);
  const [selectedTeam, setSelectedTeam] = useState(1);

  const onClick = (player) => {
    if (selectedTeam == 1) {
      setTeam1([...team1, player]);
    } else setTeam2([...team2, player]);

    setRemainingPlayers(remainingPlayers.filter((person) => person != player));
  };

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        margin: 60,
      }}
    >
      <div style={{ display: "flex", flexDirection: "row", flexWrap: "wrap" }}>
        {remainingPlayers.map((player) => (
          <p1
            onClick={() => onClick(player)}
            style={{ margin: 5, cursor: "pointer" }}
          >
            {player}
          </p1>
        ))}
      </div>
      <div style={{ display: "flex", flexDirection: "row", margin: 30 }}>
        <button onClick={() => setSelectedTeam(selectedTeam == 1 ? 2 : 1)}>
          {"Now selecting for Team " + selectedTeam}
        </button>
        <button
          onClick={() => {
            const shuffledPlayers = [...players];
            shuffledPlayers.sort(() => 0.5 - Math.random());
            setRemainingPlayers([]);
            setTeam1(shuffledPlayers.slice(0, Math.floor(players.length / 2)));
            setTeam2(
              shuffledPlayers.slice(
                Math.floor(players.length / 2),
                players.length
              )
            );
          }}
          style={{ marginRight: 20, marginLeft: 20 }}
        >
          Randomize Teams
        </button>
        <button
          onClick={() => {
            setTeam1([]);
            setTeam2([]);
            setRemainingPlayers(players);
            setSelectedTeam(1);
          }}
        >
          Reset
        </button>
      </div>
      <div
        style={{
          display: "flex",
          flexDirection: "row",
          alignItems: "center",
        }}
      >
        <div style={{ marginRight: 25 }}>
          <h4>Team 1</h4>
          <div style={{ display: "flex", flexDirection: "row" }}>
            {team1.map((player) => (
              <p1 style={{ margin: 5 }}>{player}</p1>
            ))}
          </div>
        </div>
        <div style={{ marginLeft: 25 }}>
          <h4>Team 2</h4>
          <div style={{ display: "flex", flexDirection: "row" }}>
            {team2.map((player) => (
              <p1 style={{ margin: 5 }}>{player}</p1>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default App;

First, we create three state variables to store arrays of names for unselected players, Team 1, and Team 2. We also use a state variable to store the team for which the user is currently selecting players. I separate the logic to move clicked players to the currently selected team into an onClick function. The remaining logic is in in-line functions in the returned elements. The randomize teams button takes advantage of Javascript’s sort() and slice() methods to shuffle the players prop and divide it into two teams. sort() accepts a comparator function, usually of the form

(a,b) => {
    // return positive or negative value 
    // depending on properties of a and b to inform order of array
    }

that enables the user to customize how the function compares elements of the array to determine if one should come before or after another. We use sort() to shuffle the array by passing a comparator function that simply returns a negative or positive value with equal probability.


useState
sort
slice