JSFiddle - React, Tailwind, and code Playground

[ASSIGNMENT] Close Frontend Application Quiz

by Facundo Flores

HTML

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>

CSS

.Header {
  font-size: 10px;
  margin: 16px;
}

.Chip {
  display: inline-block;
  border: 1px solid pink;
  border-radius: 3px;
  min-height: 12px;
  padding: 5px;
  margin: 5px;
}

.List {
  margin: 16px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  grid-auto-rows: 60px;
  grid-gap: 16px;
}

.List__item {
  line-height: 60px;
  text-align: center;
  color: white;
  text-shadow: 1px 1px rgba(0, 0, 0, 0.5);
  box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.05);
}

.List__item--highlighted {
  text-shadow: 1.5px 1.5px pink;
}


/* Taken from https://clrs.cc/ */

.List__item--navy {
  background-color: #001f3f;
}

.List__item--blue {
  background-color: #0074d9;
}

.List__item--aqua {
  background-color: #7fdbff;
}

.List__item--teal {
  background-color: #39cccc;
}

.List__item--olive {
  background-color: #3d9970;
}

.List__item--green {
  background-color: #2ecc40;
}

.List__item--lime {
  background-color: #01ff70;
}

.List__item--yellow {
  background-color: #ffdc00;
}

.List__item--orange {
  background-color: #ff851b;
}

.List__item--red {
  background-color: #ff4136;
}

.List__item--maroon {
  background-color: #85144b;
}

.List__item--fuchsia {
  background-color: #f012be;
}

.List__item--purple {
  background-color: #b10dc9;
}

.List__item--black {
  background-color: #111111;
}

.List__item--gray {
  background-color: #aaaaaa;
}

.List__item--silver {
  background-color: #dddddd;
}

React

const { Component, Fragment } = React;

// Implement a feature to allow item selection with the following requirements:
// 1. Clicking an item selects/unselects it.
// 2. Multiple items can be selected at a time.
// 3. Currently selected items should be visually highlighted.
// 4. Currently selected items' names should be shown at the top of the page.
// 5. Make sure to avoid unnecessary re-renders.

const shouldHighlight = (items, key) => items.find(({ name }) => name === key);

const Chip = ({ label }) => (
  <div className="Chip">
    <span>{label}</span>
  </div>
);

const Header = ({ items }) => (
  <div className="Header">
    {items.length ? (
      items.map(({ name }) => <Chip key={name} label={name} />)
    ) : (
      <h1>No items were selected.</h1>
    )}
  </div>
);

const ListTable = ({ onSelect, selectedItems, items }) => (
  <ul className="List">
    {items.map(item => (
      <li
        onClick={() => onSelect(item)}
        key={item.name}
        className={`List__item List__item--${item.color} ${shouldHighlight(
          selectedItems,
          item.name
        ) && "List__item--highlighted"}`}
      >
        {item.name}
      </li>
    ))}
  </ul>
);

class List extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedItems: []
    };
  }

  handleSelect = item => {
    const { selectedItems } = this.state;

    const filteredItems = selectedItems.filter(
      ({ name }) => name !== item.name
    );

    if (filteredItems.length < selectedItems.length) {
      this.setState({
        selectedItems: filteredItems
      });

      return;
    }

    this.setState({
      selectedItems: [...selectedItems, item]
    });
  };

  render() {
    const { items } = this.props;
    const { selectedItems } = this.state;

    return (
      <Fragment>
        <Header items={selectedItems} />
        <ListTable
          onSelect={this.handleSelect}
          selectedItems={selectedItems}
         ...