Source: pages/Dashboard.js

import React, { useState } from 'react';
import { DIFFICULTY_COLORS, STATUS_CONFIG } from '../constants';

/**
 * @fileoverview Dashboard component for the AutoSuggestion Quiz application.
 * @module Dashboard
 */

/**
 * @typedef {Object} Problem
 * @property {string} id - Unique identifier for the problem.
 * @property {string} title - Display title of the problem.
 * @property {'easy'|'medium'|'hard'} difficulty - Difficulty level, used to look up a color from {@link DIFFICULTY_COLORS}.
 * @property {'not-started'|'in-progress'|'completed'} status - Current completion status.
 * @property {string[]} tags - List of topic tags (e.g. `['arrays', 'sorting']`). Used in search matching.
 * @property {number} [grade] - Optional numeric grade (0–100) shown as a badge when present.
 */

/**
 * A dashboard page that displays all available problems in a filterable,
 * searchable grid. Also shows aggregate progress statistics at the top.
 *
 * Search matches against both problem titles and tags (case-insensitive).
 * Status filters and search can be applied simultaneously.
 *
 * @component
 * @param {Object} props
 * @param {Problem[]} props.problems - Full list of problems to display and derive stats from.
 * @param {function(Problem): void} props.onOpenProblem - Callback invoked with the selected
 *   problem when the user clicks a problem card.
 * @returns {React.ReactElement} The rendered dashboard page.
 *
 * @example
 * <Dashboard problems={allProblems} onOpenProblem={(p) => setActiveProblem(p)} />
 */
function Dashboard({ problems, onOpenProblem }) {
  /**
   * @type {['all'|'not-started'|'in-progress'|'completed', function(string): void]}
   * The currently active status filter. `'all'` shows every problem regardless of status.
   */
  const [filter, setFilter] = useState('all');

  /** @type {[string, function(string): void]} The current search query string. */
  const [searchQuery, setSearchQuery] = useState('');

  /** @type {number} Number of problems with status `'completed'`. */
  const completedCount = problems.filter((p) => p.status === 'completed').length;

  /** @type {number} Number of problems with status `'in-progress'`. */
  const inProgressCount = problems.filter((p) => p.status === 'in-progress').length;

  /** @type {number} Total number of problems, regardless of status. */
  const totalCount = problems.length;

  /**
   * The subset of problems that match both the active status filter and the search query.
   * Search is performed case-insensitively against `problem.title` and each entry in `problem.tags`.
   *
   * @type {Problem[]}
   */
  const filtered = problems.filter((p) => {
    const matchesFilter = filter === 'all' || p.status === filter;
    const matchesSearch =
      searchQuery === '' ||
      p.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
      p.tags.some((t) => t.toLowerCase().includes(searchQuery.toLowerCase()));
    return matchesFilter && matchesSearch;
  });

  return (
    <div className="app">
      <header className="app-header">
        <div className="header-left">
          <h1 className="logo">AutoSuggestion Quiz</h1>
        </div>
        <div className="header-right">
          <span className="dashboard-greeting">Welcome back, Student</span>
        </div>
      </header>

      <div className="dashboard">
        <div className="stats-bar">
          <div className="stat-card">
            <span className="stat-value">{totalCount}</span>
            <span className="stat-label">Total Problems</span>
          </div>
          <div className="stat-card">
            <span className="stat-value" style={{ color: '#16825d' }}>{completedCount}</span>
            <span className="stat-label">Completed</span>
          </div>
          <div className="stat-card">
            <span className="stat-value" style={{ color: '#569cd6' }}>{inProgressCount}</span>
            <span className="stat-label">In Progress</span>
          </div>
          <div className="stat-card">
            <span className="stat-value" style={{ color: '#888' }}>{totalCount - completedCount - inProgressCount}</span>
            <span className="stat-label">Not Started</span>
          </div>
          <div className="stat-card">
            <div className="progress-bar-container">
              <div
                className="progress-bar-fill"
                style={{ width: `${(completedCount / totalCount) * 100}%` }}
              />
            </div>
            <span className="stat-label">{Math.round((completedCount / totalCount) * 100)}% Complete</span>
          </div>
        </div>

        <div className="dashboard-toolbar">
          <div className="search-box">
            <span className="search-icon">⌕</span>
            <input
              type="text"
              className="search-input"
              placeholder="Search problems or tags..."
              value={searchQuery}
              onChange={(e) => setSearchQuery(e.target.value)}
            />
          </div>
          <div className="filter-group">
            {['all', 'not-started', 'in-progress', 'completed'].map((f) => (
              <button
                key={f}
                className={`filter-btn ${filter === f ? 'active' : ''}`}
                onClick={() => setFilter(f)}
              >
                {f === 'all' ? 'All' : STATUS_CONFIG[f]?.label || f}
              </button>
            ))}
          </div>
        </div>

        <div className="problem-grid">
          {filtered.map((problem) => {
            const status = STATUS_CONFIG[problem.status];
            return (
              /**
               * Individual problem card. Rendered as a `<button>` so the entire
               * card surface area is keyboard-accessible and natively focusable.
               */
              <button
                key={problem.id}
                className="problem-card"
                onClick={() => onOpenProblem(problem)}
              >
                <div className="card-top">
                  <span
                    className="difficulty-badge"
                    style={{ color: DIFFICULTY_COLORS[problem.difficulty] }}
                  >
                    {problem.difficulty}
                  </span>
                  <span className="status-indicator" style={{ color: status.color }}>
                    {status.icon}
                  </span>
                </div>

                <h3 className="card-title">{problem.title}</h3>

                <div className="card-tags">
                  {problem.tags.map((tag) => (
                    <span key={tag} className="tag">{tag}</span>
                  ))}
                </div>

                <div className="card-bottom">
                  <span className="status-label" style={{ color: status.color }}>
                    {status.label}
                  </span>
                  {problem.grade && (
                    <span className="grade-badge">{problem.grade}%</span>
                  )}
                </div>
              </button>
            );
          })}
        </div>

        {filtered.length === 0 && (
          <div className="empty-state">
            <p>No problems match your search.</p>
          </div>
        )}
      </div>
    </div>
  );
}

export default Dashboard;