DEV Community

Armaan Khan
Armaan Khan

Posted on

Table design

import React, { useState, useMemo, useCallback, useEffect } from 'react';
import { 
  Search, 
  ChevronUp, 
  ChevronDown, 
  Filter, 
  Eye, 
  Edit, 
  Trash2, 
  User, 
  Mail, 
  Phone, 
  Settings,
  Download,
  Plus,
  X,
  Check,
  Star,
  ArrowUpDown,
  MoreHorizontal,
  Calendar,
  Building,
  Shield,
  Activity,
  TrendingUp,
  Zap
} from 'lucide-react';

const PremiumTable = () => {
  // Enhanced sample data with more fields
  const [data] = useState([
    { 
      id: 1, 
      name: 'Alexandra Chen', 
      email: 'alex.chen@company.com', 
      role: 'Senior Engineer', 
      status: 'Active', 
      age: 28, 
      department: 'Engineering',
      salary: 125000,
      joinDate: '2023-01-15',
      performance: 95,
      projects: 12,
      avatar: 'AC',
      phone: '+1 (555) 123-4567',
      location: 'San Francisco, CA'
    },
    { 
      id: 2, 
      name: 'Marcus Rodriguez', 
      email: 'marcus.r@company.com', 
      role: 'Product Manager', 
      status: 'Active', 
      age: 32, 
      department: 'Product',
      salary: 135000,
      joinDate: '2022-08-20',
      performance: 88,
      projects: 8,
      avatar: 'MR',
      phone: '+1 (555) 987-6543',
      location: 'New York, NY'
    },
    { 
      id: 3, 
      name: 'Sarah Kim', 
      email: 'sarah.kim@company.com', 
      role: 'Design Lead', 
      status: 'Active', 
      age: 29, 
      department: 'Design',
      salary: 118000,
      joinDate: '2023-03-10',
      performance: 92,
      projects: 15,
      avatar: 'SK',
      phone: '+1 (555) 456-7890',
      location: 'Austin, TX'
    },
    { 
      id: 4, 
      name: 'David Thompson', 
      email: 'david.t@company.com', 
      role: 'Data Scientist', 
      status: 'Inactive', 
      age: 35, 
      department: 'Analytics',
      salary: 140000,
      joinDate: '2021-11-05',
      performance: 78,
      projects: 6,
      avatar: 'DT',
      phone: '+1 (555) 321-0987',
      location: 'Seattle, WA'
    },
    { 
      id: 5, 
      name: 'Emily Watson', 
      email: 'emily.watson@company.com', 
      role: 'Marketing Director', 
      status: 'Active', 
      age: 38, 
      department: 'Marketing',
      salary: 145000,
      joinDate: '2020-06-12',
      performance: 91,
      projects: 20,
      avatar: 'EW',
      phone: '+1 (555) 654-3210',
      location: 'Los Angeles, CA'
    },
    { 
      id: 6, 
      name: 'James Wilson', 
      email: 'james.wilson@company.com', 
      role: 'DevOps Engineer', 
      status: 'Active', 
      age: 31, 
      department: 'Engineering',
      salary: 128000,
      joinDate: '2022-12-01',
      performance: 89,
      projects: 9,
      avatar: 'JW',
      phone: '+1 (555) 789-0123',
      location: 'Denver, CO'
    }
  ]);

  const [searchTerm, setSearchTerm] = useState('');
  const [sortConfig, setSortConfig] = useState({ key: 'performance', direction: 'desc' });
  const [selectedRows, setSelectedRows] = useState(new Set());
  const [viewMode, setViewMode] = useState('table'); // table, grid, compact
  const [showAdvancedFilters, setShowAdvancedFilters] = useState(false);
  const [animateRows, setAnimateRows] = useState(false);

  const [filters, setFilters] = useState({
    role: '',
    status: '',
    department: '',
    salaryMin: '',
    salaryMax: '',
    performanceMin: 0,
    joinDateFrom: '',
    joinDateTo: ''
  });

  useEffect(() => {
    setAnimateRows(true);
    const timer = setTimeout(() => setAnimateRows(false), 300);
    return () => clearTimeout(timer);
  }, [sortConfig, filters, searchTerm]);

  // Enhanced column configuration
  const columns = [
    {
      key: 'select',
      header: '',
      width: '60px',
      render: (item) => (
        <div className="flex items-center justify-center">
          <input
            type="checkbox"
            checked={selectedRows.has(item.id)}
            onChange={(e) => handleRowSelect(item.id, e.target.checked)}
            className="w-4 h-4 text-indigo-600 bg-gray-100 border-2 border-gray-300 rounded-md focus:ring-indigo-500 focus:ring-2 transition-all duration-200"
          />
        </div>
      ),
      sortable: false
    },
    {
      key: 'name',
      header: 'Employee',
      sortable: true,
      render: (item) => (
        <div className="flex items-center space-x-4 group cursor-pointer">
          <div className="relative">
            <div className="w-12 h-12 bg-gradient-to-br from-indigo-400 to-purple-600 rounded-xl flex items-center justify-center text-white font-bold text-sm shadow-lg group-hover:shadow-xl transition-all duration-300 group-hover:scale-105">
              {item.avatar}
            </div>
            <div className={`absolute -bottom-1 -right-1 w-4 h-4 rounded-full border-2 border-white ${
              item.status === 'Active' ? 'bg-emerald-400' : 'bg-gray-400'
            }`}></div>
          </div>
          <div className="flex-1">
            <div className="font-semibold text-gray-900 group-hover:text-indigo-600 transition-colors duration-200">
              {item.name}
            </div>
            <div className="text-sm text-gray-500 flex items-center space-x-2">
              <span>{item.location}</span>
              <span>โ€ข</span>
              <span>ID: {item.id}</span>
            </div>
          </div>
        </div>
      ),
      onClick: (item) => handleEmployeeClick(item)
    },
    {
      key: 'role',
      header: 'Role & Department',
      sortable: true,
      render: (item) => (
        <div className="space-y-1">
          <div className="font-medium text-gray-900">{item.role}</div>
          <div className="flex items-center space-x-1">
            <Building className="w-3 h-3 text-gray-400" />
            <span className="text-sm text-gray-600">{item.department}</span>
          </div>
        </div>
      )
    },
    {
      key: 'performance',
      header: 'Performance',
      sortable: true,
      render: (item) => (
        <div className="space-y-2">
          <div className="flex items-center justify-between">
            <span className="text-sm font-medium text-gray-900">{item.performance}%</span>
            <div className="flex items-center space-x-1">
              {item.performance >= 90 ? (
                <Star className="w-4 h-4 text-yellow-500 fill-current" />
              ) : item.performance >= 80 ? (
                <TrendingUp className="w-4 h-4 text-green-500" />
              ) : (
                <Activity className="w-4 h-4 text-orange-500" />
              )}
            </div>
          </div>
          <div className="w-full bg-gray-200 rounded-full h-2 overflow-hidden">
            <div 
              className={`h-2 rounded-full transition-all duration-500 ${
                item.performance >= 90 ? 'bg-gradient-to-r from-green-400 to-emerald-500' :
                item.performance >= 80 ? 'bg-gradient-to-r from-blue-400 to-indigo-500' :
                item.performance >= 70 ? 'bg-gradient-to-r from-yellow-400 to-orange-500' :
                'bg-gradient-to-r from-red-400 to-pink-500'
              }`}
              style={{ width: `${item.performance}%` }}
            ></div>
          </div>
        </div>
      )
    },
    {
      key: 'salary',
      header: 'Compensation',
      sortable: true,
      render: (item) => (
        <div className="space-y-1">
          <div className="font-bold text-gray-900">
            ${item.salary.toLocaleString()}
          </div>
          <div className="text-xs text-gray-500">Annual</div>
          <div className="text-xs text-gray-400">{item.projects} projects</div>
        </div>
      )
    },
    {
      key: 'contact',
      header: 'Contact',
      sortable: false,
      render: (item) => (
        <div className="space-y-2">
          <div 
            className="flex items-center space-x-2 cursor-pointer text-indigo-600 hover:text-indigo-800 transition-colors"
            onClick={(e) => {e.stopPropagation(); handleEmailClick(item);}}
          >
            <Mail className="w-4 h-4" />
            <span className="text-sm truncate max-w-32">{item.email}</span>
          </div>
          <div 
            className="flex items-center space-x-2 cursor-pointer text-gray-600 hover:text-gray-800 transition-colors"
            onClick={(e) => {e.stopPropagation(); handlePhoneClick(item);}}
          >
            <Phone className="w-4 h-4" />
            <span className="text-sm">{item.phone}</span>
          </div>
        </div>
      )
    },
    {
      key: 'joinDate',
      header: 'Join Date',
      sortable: true,
      render: (item) => (
        <div className="space-y-1">
          <div className="flex items-center space-x-2">
            <Calendar className="w-4 h-4 text-gray-400" />
            <span className="text-sm text-gray-900">
              {new Date(item.joinDate).toLocaleDateString()}
            </span>
          </div>
          <div className="text-xs text-gray-500">
            {Math.floor((new Date() - new Date(item.joinDate)) / (1000 * 60 * 60 * 24 * 365))} years
          </div>
        </div>
      )
    },
    {
      key: 'status',
      header: 'Status',
      sortable: true,
      render: (item) => (
        <div className="flex flex-col items-center space-y-2">
          <span className={`px-3 py-1 text-xs font-bold rounded-full shadow-sm ${
            item.status === 'Active' 
              ? 'bg-emerald-100 text-emerald-800 border border-emerald-200' 
              : 'bg-gray-100 text-gray-800 border border-gray-200'
          }`}>
            {item.status}
          </span>
          {item.status === 'Active' && (
            <Zap className="w-4 h-4 text-emerald-500 animate-pulse" />
          )}
        </div>
      )
    },
    {
      key: 'actions',
      header: 'Actions',
      width: '140px',
      render: (item) => (
        <div className="flex items-center space-x-1">
          <button
            onClick={(e) => {e.stopPropagation(); handleView(item);}}
            className="p-2 text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-lg transition-all duration-200 group"
            title="View Details"
          >
            <Eye className="w-4 h-4 group-hover:scale-110 transition-transform" />
          </button>
          <button
            onClick={(e) => {e.stopPropagation(); handleEdit(item);}}
            className="p-2 text-emerald-600 hover:text-emerald-800 hover:bg-emerald-50 rounded-lg transition-all duration-200 group"
            title="Edit Employee"
          >
            <Edit className="w-4 h-4 group-hover:scale-110 transition-transform" />
          </button>
          <button
            onClick={(e) => {e.stopPropagation(); handleDelete(item);}}
            className="p-2 text-red-600 hover:text-red-800 hover:bg-red-50 rounded-lg transition-all duration-200 group"
            title="Delete Employee"
          >
            <Trash2 className="w-4 h-4 group-hover:scale-110 transition-transform" />
          </button>
          <div className="relative group">
            <button className="p-2 text-gray-600 hover:text-gray-800 hover:bg-gray-50 rounded-lg transition-all duration-200">
              <MoreHorizontal className="w-4 h-4" />
            </button>
          </div>
        </div>
      ),
      sortable: false
    }
  ];

  // Enhanced click handlers
  const handleEmployeeClick = (item) => {
    alert(`๐Ÿ‘ค Employee Profile: ${item.name}\n๐Ÿ“ง ${item.email}\n๐Ÿข ${item.role} at ${item.department}\n๐Ÿ“Š Performance: ${item.performance}%`);
  };

  const handleEmailClick = (item) => {
    window.open(`mailto:${item.email}?subject=Hello ${item.name}`, '_blank');
  };

  const handlePhoneClick = (item) => {
    navigator.clipboard.writeText(item.phone);
    alert(`๐Ÿ“‹ Phone number copied: ${item.phone}`);
  };

  const handleView = (item) => {
    alert(`๐Ÿ‘๏ธ Viewing detailed profile for ${item.name}`);
  };

  const handleEdit = (item) => {
    alert(`โœ๏ธ Opening edit form for ${item.name}`);
  };

  const handleDelete = (item) => {
    if (window.confirm(`๐Ÿ—‘๏ธ Are you sure you want to delete ${item.name}?`)) {
      alert(`โŒ ${item.name} has been deleted`);
    }
  };

  // Enhanced selection handlers
  const handleRowSelect = (id, checked) => {
    const newSelected = new Set(selectedRows);
    if (checked) {
      newSelected.add(id);
    } else {
      newSelected.delete(id);
    }
    setSelectedRows(newSelected);
  };

  const handleSelectAll = (checked) => {
    if (checked) {
      setSelectedRows(new Set(filteredAndSortedData.map(item => item.id)));
    } else {
      setSelectedRows(new Set());
    }
  };

  // Enhanced sorting with animation
  const handleSort = useCallback((key) => {
    setSortConfig(prevConfig => ({
      key,
      direction: prevConfig.key === key && prevConfig.direction === 'asc' ? 'desc' : 'asc'
    }));
  }, []);

  // Advanced filtering and sorting
  const filteredAndSortedData = useMemo(() => {
    let result = [...data];

    // Global search
    if (searchTerm) {
      result = result.filter(item =>
        Object.values(item).some(value =>
          value.toString().toLowerCase().includes(searchTerm.toLowerCase())
        )
      );
    }

    // Advanced filters
    if (filters.role) {
      result = result.filter(item => 
        item.role.toLowerCase().includes(filters.role.toLowerCase())
      );
    }

    if (filters.status) {
      result = result.filter(item => item.status === filters.status);
    }

    if (filters.department) {
      result = result.filter(item => item.department === filters.department);
    }

    if (filters.salaryMin) {
      result = result.filter(item => item.salary >= parseInt(filters.salaryMin));
    }

    if (filters.salaryMax) {
      result = result.filter(item => item.salary <= parseInt(filters.salaryMax));
    }

    if (filters.performanceMin > 0) {
      result = result.filter(item => item.performance >= filters.performanceMin);
    }

    if (filters.joinDateFrom) {
      result = result.filter(item => new Date(item.joinDate) >= new Date(filters.joinDateFrom));
    }

    if (filters.joinDateTo) {
      result = result.filter(item => new Date(item.joinDate) <= new Date(filters.joinDateTo));
    }

    // Enhanced sorting
    if (sortConfig.key) {
      result.sort((a, b) => {
        let aValue = a[sortConfig.key];
        let bValue = b[sortConfig.key];

        if (sortConfig.key === 'joinDate') {
          aValue = new Date(aValue);
          bValue = new Date(bValue);
        }

        if (aValue < bValue) return sortConfig.direction === 'asc' ? -1 : 1;
        if (aValue > bValue) return sortConfig.direction === 'asc' ? 1 : -1;
        return 0;
      });
    }

    return result;
  }, [data, searchTerm, filters, sortConfig]);

  const getUniqueValues = (key) => {
    return [...new Set(data.map(item => item[key]))].sort();
  };

  const clearFilters = () => {
    setFilters({
      role: '',
      status: '',
      department: '',
      salaryMin: '',
      salaryMax: '',
      performanceMin: 0,
      joinDateFrom: '',
      joinDateTo: ''
    });
    setSearchTerm('');
  };

  return (
    <div className="min-h-screen bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-50 p-6">
      <div className="max-w-7xl mx-auto">
        {/* Premium Header */}
        <div className="bg-white rounded-2xl shadow-xl border border-gray-100 mb-6 overflow-hidden">
          <div className="bg-gradient-to-r from-indigo-600 via-purple-600 to-indigo-800 px-8 py-6">
            <div className="flex items-center justify-between">
              <div>
                <h1 className="text-3xl font-bold text-white mb-2">Employee Directory</h1>
                <p className="text-indigo-200">
                  {filteredAndSortedData.length} of {data.length} employees
                  {selectedRows.size > 0 && (
                    <span className="ml-2 px-3 py-1 bg-white/20 rounded-full text-sm">
                      {selectedRows.size} selected
                    </span>
                  )}
                </p>
              </div>
              <div className="flex items-center space-x-4">
                <button className="px-6 py-3 bg-white/20 hover:bg-white/30 text-white rounded-xl font-semibold transition-all duration-200 flex items-center space-x-2">
                  <Plus className="w-5 h-5" />
                  <span>Add Employee</span>
                </button>
                <button className="p-3 bg-white/20 hover:bg-white/30 text-white rounded-xl transition-all duration-200">
                  <Settings className="w-5 h-5" />
                </button>
              </div>
            </div>
          </div>

          {/* Enhanced Controls */}
          <div className="p-6 bg-gradient-to-r from-gray-50 to-white">
            <div className="flex flex-wrap gap-4 items-center justify-between mb-4">
              {/* Search with enhanced styling */}
              <div className="relative flex-1 max-w-md">
                <Search className="absolute left-4 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
                <input
                  type="text"
                  placeholder="Search employees, roles, departments..."
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  className="w-full pl-12 pr-4 py-3 bg-white border-2 border-gray-200 rounded-xl focus:ring-4 focus:ring-indigo-100 focus:border-indigo-500 transition-all duration-200 shadow-sm"
                />
              </div>

              {/* Filter Controls */}
              <div className="flex items-center space-x-3">
                <button
                  onClick={() => setShowAdvancedFilters(!showAdvancedFilters)}
                  className={`px-4 py-2 rounded-lg font-medium transition-all duration-200 flex items-center space-x-2 ${
                    showAdvancedFilters 
                      ? 'bg-indigo-100 text-indigo-700 border-2 border-indigo-200' 
                      : 'bg-gray-100 text-gray-700 border-2 border-gray-200 hover:bg-gray-200'
                  }`}
                >
                  <Filter className="w-4 h-4" />
                  <span>Advanced Filters</span>
                </button>

                {selectedRows.size > 0 && (
                  <div className="flex space-x-2 animate-in slide-in-from-right duration-300">
                    <button className="px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white rounded-lg font-medium transition-all duration-200 flex items-center space-x-2">
                      <Download className="w-4 h-4" />
                      <span>Export</span>
                    </button>
                    <button className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg font-medium transition-all duration-200">
                      <Trash2 className="w-4 h-4" />
                    </button>
                  </div>
                )}
              </div>
            </div>

            {/* Advanced Filters Panel */}
            {showAdvancedFilters && (
              <div className="bg-white rounded-xl border-2 border-gray-100 p-6 animate-in slide-in-from-top duration-300">
                <div className="flex items-center justify-between mb-4">
                  <h3 className="text-lg font-semibold text-gray-900">Advanced Filters</h3>
                  <button
                    onClick={clearFilters}
                    className="text-sm text-indigo-600 hover:text-indigo-800 font-medium"
                  >
                    Clear All
                  </button>
                </div>

                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Role</label>
                    <select
                      value={filters.role}
                      onChange={(e) => setFilters(prev => ({ ...prev, role: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    >
                      <option value="">All Roles</option>
                      {getUniqueValues('role').map(role => (
                        <option key={role} value={role}>{role}</option>
                      ))}
                    </select>
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Department</label>
                    <select
                      value={filters.department}
                      onChange={(e) => setFilters(prev => ({ ...prev, department: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    >
                      <option value="">All Departments</option>
                      {getUniqueValues('department').map(dept => (
                        <option key={dept} value={dept}>{dept}</option>
                      ))}
                    </select>
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Status</label>
                    <select
                      value={filters.status}
                      onChange={(e) => setFilters(prev => ({ ...prev, status: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    >
                      <option value="">All Status</option>
                      {getUniqueValues('status').map(status => (
                        <option key={status} value={status}>{status}</option>
                      ))}
                    </select>
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Min Performance</label>
                    <input
                      type="range"
                      min="0"
                      max="100"
                      value={filters.performanceMin}
                      onChange={(e) => setFilters(prev => ({ ...prev, performanceMin: parseInt(e.target.value) }))}
                      className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"
                    />
                    <div className="text-sm text-gray-600 mt-1">{filters.performanceMin}%+</div>
                  </div>
                </div>

                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mt-4">
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Min Salary</label>
                    <input
                      type="number"
                      placeholder="50000"
                      value={filters.salaryMin}
                      onChange={(e) => setFilters(prev => ({ ...prev, salaryMin: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Max Salary</label>
                    <input
                      type="number"
                      placeholder="200000"
                      value={filters.salaryMax}
                      onChange={(e) => setFilters(prev => ({ ...prev, salaryMax: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Join Date From</label>
                    <input
                      type="date"
                      value={filters.joinDateFrom}
                      onChange={(e) => setFilters(prev => ({ ...prev, joinDateFrom: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    />
                  </div>

                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-2">Join Date To</label>
                    <input
                      type="date"
                      value={filters.joinDateTo}
                      onChange={(e) => setFilters(prev => ({ ...prev, joinDateTo: e.target.value }))}
                      className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500"
                    />
                  </div>
                </div>
              </div>
            )}
          </div>
        </div>

        {/* Premium Table */}
        <div className="bg-white rounded-2xl shadow-xl border border-gray-100 overflow-hidden">
          <div className="overflow-x-auto">
            <table className="w-full">
              <thead>
                <tr className="bg-gradient-to-r from-gray-50 to-gray-100 border-b border-gray-200">
                  <th className="px-6 py-4">
                    <input
                      type="checkbox"
                      checked={selectedRows.size === filteredAndSortedData.length && filteredAndSortedData.length > 0}
                      onChange={(e) => handleSelectAll(e.target.checked)}
                      className="w-4 h-4 text-indigo-600 bg-gray-100 border-2 border-gray-300 rounded-md focus:ring-indigo-500 focus:ring-2"
                    />
                  </th>
                  {columns.slice(1).map((column) => (
                    <th
                      key={column.key}
                      className={`px-6 py-4 text-left text-sm font-bold text-gray-700 uppercase tracking-wider ${
                        column.sortable ? 'cursor-pointer hover:bg-gray-200 transition-colors duration-200 select-none' : ''
                      }`}
                      style={{ width: column.width }}
                      onClick={() => column.sortable && handleSort(column.key)}
                    >
                      <div className="flex items-center space-x-2 group">
                        <span className="group-hover:text-indigo-600 transition-colors">{column.header}</span>
                        {column.sortable && (
                          <div className="flex flex-col opacity-50 group-hover:opacity-100 transition-opacity">
                            {sortConfig.key === column.key ? (
                              sortConfig.direction === 'asc' ? (
                                <ChevronUp className="w-4 h-4 text-indigo-600" />
                              ) : (
                                <ChevronDown className="w-4 h-4 text-indigo-600" />
                              )
                            ) : (
                              <ArrowUpDown className="w-4 h-4 text-gray-400 group-hover:text-indigo-500" />
                            )}
                          </div>
                        )}
                      </div>
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-100">
                {filteredAndSortedData.map((item, index) => (
                  <tr 
                    key={item.id} 
                    className={`
                      hover:bg-gradient-to-r hover:from-indigo-50 hover:to-purple-50 
                      transition-all duration-300 cursor-pointer group
                      ${selectedRows.has(item.id) ? 'bg-indigo-50 border-l-4 border-indigo-500' : ''}
                      ${animateRows ? 'animate-pulse' : ''}
                    `}
                    style={{
                      animationDelay: animateRows ? `${index * 50}ms` : '0ms'
                    }}
                  >
                    {columns.map((column) => (
                      <td
                        key={column.key}
                        className={`px-6 py-6 whitespace-nowrap transition-all duration-200 ${
                          column.onClick ? 'cursor-pointer' : ''
                        }`}
                        onClick={() => column.onClick && column.onClick(item)}
                      >
                        {column.render ? column.render(item) : item[column.key]}
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>

            {/* Empty State */}
            {filteredAndSortedData.length === 0 && (
              <div className="text-center py-16">
                <div className="w-24 h-24 mx-auto mb-4 bg-gradient-to-br from-gray-100 to-gray-200 rounded-full flex items-center justify-center">
                  <Search className="w-12 h-12 text-gray-400" />
                </div>
                <h3 className="text-xl font-semibold text-gray-900 mb-2">No employees found</h3>
                <p className="text-gray-500 mb-6">Try adjusting your search criteria or filters</p>
                <button
                  onClick={clearFilters}
                  className="px-6 py-3 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl font-semibold transition-all duration-200"
                >
                  Clear all filters
                </button>
              </div>
            )}
          </div>

          {/* Premium Footer with Analytics */}
          <div className="bg-gradient-to-r from-gray-50 to-white border-t border-gray-200 px-8 py-6">
            <div className="flex flex-wrap items-center justify-between gap-4">
              <div className="flex items-center space-x-8">
                <div className="text-sm text-gray-600">
                  <span className="font-semibold text-gray-900">
                    {filteredAndSortedData.length}
                  </span> of <span className="font-semibold">{data.length}</span> employees
                </div>

                <div className="flex items-center space-x-6 text-sm text-gray-600">
                  <div className="flex items-center space-x-2">
                    <div className="w-3 h-3 bg-emerald-400 rounded-full"></div>
                    <span>Active: {data.filter(item => item.status === 'Active').length}</span>
                  </div>
                  <div className="flex items-center space-x-2">
                    <div className="w-3 h-3 bg-gray-400 rounded-full"></div>
                    <span>Inactive: {data.filter(item => item.status === 'Inactive').length}</span>
                  </div>
                </div>
              </div>

              <div className="flex items-center space-x-6">
                <div className="text-sm text-gray-600">
                  <span className="font-semibold">Avg Performance:</span> 
                  <span className="ml-1 text-indigo-600 font-bold">
                    {Math.round(data.reduce((sum, item) => sum + item.performance, 0) / data.length)}%
                  </span>
                </div>

                <div className="text-sm text-gray-600">
                  <span className="font-semibold">Total Projects:</span> 
                  <span className="ml-1 text-purple-600 font-bold">
                    {data.reduce((sum, item) => sum + item.projects, 0)}
                  </span>
                </div>

                <div className="text-xs text-gray-500 bg-gray-100 px-3 py-2 rounded-full">
                  Built with React & Premium UI
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Floating Action Button */}
        <div className="fixed bottom-8 right-8">
          <button className="w-16 h-16 bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-700 hover:to-purple-700 text-white rounded-full shadow-2xl hover:shadow-3xl transition-all duration-300 flex items-center justify-center group hover:scale-110">
            <Plus className="w-8 h-8 group-hover:rotate-90 transition-transform duration-300" />
          </button>
        </div>

        {/* Selection Info Toast */}
        {selectedRows.size > 0 && (
          <div className="fixed bottom-8 left-8 bg-white rounded-2xl shadow-2xl border border-gray-200 p-6 animate-in slide-in-from-left duration-300">
            <div className="flex items-center space-x-4">
              <div className="w-12 h-12 bg-indigo-100 rounded-xl flex items-center justify-center">
                <Check className="w-6 h-6 text-indigo-600" />
              </div>
              <div>
                <div className="font-semibold text-gray-900">
                  {selectedRows.size} employee{selectedRows.size > 1 ? 's' : ''} selected
                </div>
                <div className="text-sm text-gray-500">
                  Ready for bulk actions
                </div>
              </div>
              <button
                onClick={() => setSelectedRows(new Set())}
                className="p-2 text-gray-400 hover:text-gray-600 transition-colors"
              >
                <X className="w-5 h-5" />
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default PremiumTable;
Enter fullscreen mode Exit fullscreen mode

Top comments (0)