hexlet-codebattle/codebattle

View on GitHub
services/app/apps/codebattle/assets/js/widgets/pages/profile/UserProfile.jsx

Summary

Maintainability
C
1 day
Test Coverage
import React, { useState, useEffect } from 'react';

import axios from 'axios';
import cn from 'classnames';
import { camelizeKeys } from 'humps';
import sum from 'lodash/sum';
import { useDispatch } from 'react-redux';

import Loading from '../../components/Loading';
import langIconNames from '../../config/langIconNames';
import { actions } from '../../slices';
import CompletedGames from '../lobby/CompletedGames';

import Achievement from './Achievement';
import Heatmap from './Heatmap';
import UserStatCharts from './UserStatCharts';

function UserProfile() {
  const [userData, setUserData] = useState(null);
  const dispatch = useDispatch();

  useEffect(() => {
    const userId = window.location.pathname.split('/').pop();

    axios
      .get(`/api/v1/user/${userId}/stats`)
      .then(response => {
        setUserData(camelizeKeys(response.data));
      })
      .catch(error => {
        dispatch(actions.setError(error));
      });
  }, [dispatch]);

  if (!userData) {
    return <Loading />;
  }

  const { stats, user } = userData;
  const userInsertedAt = new Date(user.insertedAt).toLocaleString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });
  const gamesCount = sum(Object.values(stats.games));

  return (
    <div className="row">
      <div className="col-12 col-md-3 my-4">
        <div className="pl-md-2 text-center">
          <div className="mb-2 mb-sm-4">
            <img
              className="cb-profile-avatar rounded"
              src={user.avatarUrl}
              alt="User avatar"
            />
          </div>
          <div>
            <h1 className="cb-heading text-break font-weight-bold">{user.name}</h1>
            <hr />
            <h3 className="cb-heading">
              <span>Lang:</span>
              <img
                src={`/assets/images/achievements/${langIconNames[user.lang]}.png`}
                alt={user.lang}
                title={user.lang}
                width="30"
                height="30"
              />
            </h3>
            <hr />
            <p className="mb-2 small text-monospace text-muted">{`joined at ${userInsertedAt}`}</p>
            {user.githubName && (
              <h3 className="h1">
                <a
                  title="Github account"
                  className="text-muted"
                  href={`https://github.com/${user.githubName}`}
                >
                  <span className="fab fa-github" />
                </a>
              </h3>
            )}
            {user.achievements.length > 0 && (
              <>
                <hr className="mt-2" />
                <h3 className="text-break cb-heading">Achievements</h3>
                <div className="d-flex flex-wrap justify-content-start mt-3">
                  {user.achievements.map(item => <Achievement key={item} achievement={item} />)}
                </div>
              </>
            )}
          </div>
        </div>
      </div>
      <div className="col-12 col-md-9 my-4">
        <div className="pr-md-2 min-h-100 d-flex flex-column">
          <nav>
            <div
              id="nav-tab"
              role="tablist"
              className="nav nav-tabs justify-content-around border-bottom"
            >
              <a
                className="nav-item nav-link active text-uppercase border-0 text-center font-weight-bold rounded-0 w-50 p-3"
                id="statistics-tab"
                data-toggle="tab"
                href="#statistics"
                role="tab"
                aria-controls="statistics"
                aria-selected="true"
              >
                Statistics
              </a>
              <a
                className="nav-item nav-link text-uppercase border-0 text-center font-weight-bold rounded-0 w-50 p-3"
                id="completedGames-tab"
                data-toggle="tab"
                href="#completedGames"
                role="tab"
                aria-controls="completedGames"
                aria-selected="false"
              >
                Completed games
              </a>
            </div>
          </nav>
          <div className="tab-content border border-top-0 rounded-bottom flex-grow-1 basis-0" id="nav-tabContent">
            <div
              className="tab-pane fade show active"
              id="statistics"
              role="tabpanel"
              aria-labelledby="statistics-tab"
            >
              <div className="row mt-5 px-3 justify-content-center">
                {!user.isBot && (
                  <div className="col col-md-3 text-center">
                    <div className="h1 cb-stats-number">{user.rank}</div>
                    <p className="lead">rank</p>
                  </div>
                )}
                <div className="col col-md-3 text-center">
                  <div className="h1 cb-stats-number">{user.rating}</div>
                  <p className="lead">elo_rating</p>
                </div>
                <div className="col col-md-3 text-center">
                  <div className="h1 cb-stats-number">{gamesCount}</div>
                  <p className="lead">games_played</p>
                </div>
              </div>
              {gamesCount > 0 && <UserStatCharts stats={stats} />}
              <div className={cn('row mt-5 mb-md-3 mb-lg-4', { 'mt-lg-0': gamesCount > 0 })}>
                <div className="col-md-11 col-lg-10 mx-auto">
                  <Heatmap />
                </div>
              </div>
            </div>
            <div
              className="tab-pane fade min-h-100"
              id="completedGames"
              role="tabpanel"
              aria-labelledby="completedGames-tab"
            >
              <div className="h-100 d-flex flex-column justify-content-center">
                <CompletedGames className="h-100" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

export default UserProfile;