# Frontend Components

## 6.1 Component Architecture

### React Component Structure
The frontend is built with React 19 and TypeScript, following modern React patterns and best practices.

```
resources/js/
├── components/           # Reusable components
│   ├── ui/              # UI components (buttons, inputs, etc.)
│   ├── forms/           # Form components
│   ├── layout/          # Layout components
│   └── frontend/        # Frontend-specific components
├── pages/               # Page components
│   ├── Admin/           # Admin pages
│   ├── TeamManager/     # Team manager pages
│   ├── Player/          # Player pages
│   └── Frontend/        # Public pages
├── layouts/             # Layout components
├── hooks/               # Custom React hooks
├── contexts/            # React contexts
├── lib/                 # Utility functions
└── types/               # TypeScript type definitions
```

### Component Design Principles
- **Atomic Design**: Components organized by complexity (atoms, molecules, organisms)
- **Composition**: Component composition over inheritance
- **Props Interface**: TypeScript interfaces for all props
- **State Management**: React hooks and context for state
- **Error Boundaries**: Error handling for component failures

## 6.2 Layout Components

### Main Layout
```typescript
interface MainLayoutProps {
  children: React.ReactNode;
  title?: string;
  description?: string;
}

const MainLayout: React.FC<MainLayoutProps> = ({ 
  children, 
  title = "Tournament Management System",
  description 
}) => {
  return (
    <div className="min-h-screen bg-gray-50">
      <Head>
        <title>{title}</title>
        {description && <meta name="description" content={description} />}
      </Head>
      
      <Header />
      <main className="container mx-auto px-4 py-8">
        {children}
      </main>
      <Footer />
    </div>
  );
};
```

### Admin Layout
```typescript
interface AdminLayoutProps {
  children: React.ReactNode;
  title?: string;
  breadcrumbs?: BreadcrumbItem[];
}

const AdminLayout: React.FC<AdminLayoutProps> = ({ 
  children, 
  title,
  breadcrumbs 
}) => {
  const [sidebarOpen, setSidebarOpen] = useState(false);

  return (
    <div className="min-h-screen bg-gray-100">
      <AdminSidebar open={sidebarOpen} onClose={() => setSidebarOpen(false)} />
      
      <div className="lg:pl-64">
        <AdminHeader onMenuClick={() => setSidebarOpen(true)} />
        
        <main className="py-6">
          <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
            {breadcrumbs && <Breadcrumbs items={breadcrumbs} />}
            {title && <h1 className="text-2xl font-bold text-gray-900">{title}</h1>}
            {children}
          </div>
        </main>
      </div>
    </div>
  );
};
```

### Team Manager Layout
```typescript
interface TeamManagerLayoutProps {
  children: React.ReactNode;
  team: Team;
}

const TeamManagerLayout: React.FC<TeamManagerLayoutProps> = ({ 
  children, 
  team 
}) => {
  return (
    <div className="min-h-screen bg-gray-50">
      <TeamManagerHeader team={team} />
      
      <div className="flex">
        <TeamManagerSidebar team={team} />
        
        <main className="flex-1 p-6">
          {children}
        </main>
      </div>
    </div>
  );
};
```

## 6.3 Form Components

### Form Input Components
```typescript
interface InputProps {
  label: string;
  name: string;
  type?: string;
  placeholder?: string;
  required?: boolean;
  error?: string;
  value: string;
  onChange: (value: string) => void;
}

const Input: React.FC<InputProps> = ({
  label,
  name,
  type = "text",
  placeholder,
  required = false,
  error,
  value,
  onChange
}) => {
  return (
    <div className="space-y-2">
      <label htmlFor={name} className="block text-sm font-medium text-gray-700">
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </label>
      
      <input
        id={name}
        name={name}
        type={type}
        placeholder={placeholder}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className={`block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 ${
          error ? 'border-red-300' : ''
        }`}
      />
      
      {error && (
        <p className="text-sm text-red-600">{error}</p>
      )}
    </div>
  );
};
```

### Form Select Component
```typescript
interface SelectProps {
  label: string;
  name: string;
  options: { value: string; label: string }[];
  value: string;
  onChange: (value: string) => void;
  error?: string;
  required?: boolean;
}

const Select: React.FC<SelectProps> = ({
  label,
  name,
  options,
  value,
  onChange,
  error,
  required = false
}) => {
  return (
    <div className="space-y-2">
      <label htmlFor={name} className="block text-sm font-medium text-gray-700">
        {label}
        {required && <span className="text-red-500 ml-1">*</span>}
      </label>
      
      <select
        id={name}
        name={name}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        className={`block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 ${
          error ? 'border-red-300' : ''
        }`}
      >
        <option value="">Select {label}</option>
        {options.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
      
      {error && (
        <p className="text-sm text-red-600">{error}</p>
      )}
    </div>
  );
};
```

### Form Validation
```typescript
interface FormValidation {
  [key: string]: string | undefined;
}

const useFormValidation = (initialValues: Record<string, any>) => {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState<FormValidation>({});
  const [touched, setTouched] = useState<Record<string, boolean>>({});

  const validate = (field: string, value: any): string | undefined => {
    // Validation rules
    if (field === 'email' && value && !/\S+@\S+\.\S+/.test(value)) {
      return 'Email is invalid';
    }
    
    if (field === 'phone' && value && !/^\+?[\d\s-()]+$/.test(value)) {
      return 'Phone number is invalid';
    }
    
    if (field === 'password' && value && value.length < 8) {
      return 'Password must be at least 8 characters';
    }
    
    return undefined;
  };

  const handleChange = (field: string, value: any) => {
    setValues(prev => ({ ...prev, [field]: value }));
    
    if (touched[field]) {
      const error = validate(field, value);
      setErrors(prev => ({ ...prev, [field]: error }));
    }
  };

  const handleBlur = (field: string) => {
    setTouched(prev => ({ ...prev, [field]: true }));
    const error = validate(field, values[field]);
    setErrors(prev => ({ ...prev, [field]: error }));
  };

  return {
    values,
    errors,
    touched,
    handleChange,
    handleBlur,
    isValid: Object.values(errors).every(error => !error)
  };
};
```

## 6.4 Data Display Components

### Data Table Component
```typescript
interface Column<T> {
  key: keyof T;
  label: string;
  sortable?: boolean;
  render?: (value: any, item: T) => React.ReactNode;
}

interface DataTableProps<T> {
  data: T[];
  columns: Column<T>[];
  loading?: boolean;
  onSort?: (key: keyof T, direction: 'asc' | 'desc') => void;
  onRowClick?: (item: T) => void;
}

const DataTable = <T extends Record<string, any>>({
  data,
  columns,
  loading = false,
  onSort,
  onRowClick
}: DataTableProps<T>) => {
  const [sortKey, setSortKey] = useState<keyof T | null>(null);
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');

  const handleSort = (key: keyof T) => {
    const direction = sortKey === key && sortDirection === 'asc' ? 'desc' : 'asc';
    setSortKey(key);
    setSortDirection(direction);
    onSort?.(key, direction);
  };

  if (loading) {
    return <TableSkeleton />;
  }

  return (
    <div className="overflow-x-auto">
      <table className="min-w-full divide-y divide-gray-200">
        <thead className="bg-gray-50">
          <tr>
            {columns.map((column) => (
              <th
                key={String(column.key)}
                className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
              >
                {column.sortable ? (
                  <button
                    onClick={() => handleSort(column.key)}
                    className="flex items-center space-x-1 hover:text-gray-700"
                  >
                    <span>{column.label}</span>
                    {sortKey === column.key && (
                      <span>{sortDirection === 'asc' ? '↑' : '↓'}</span>
                    )}
                  </button>
                ) : (
                  column.label
                )}
              </th>
            ))}
          </tr>
        </thead>
        <tbody className="bg-white divide-y divide-gray-200">
          {data.map((item, index) => (
            <tr
              key={index}
              onClick={() => onRowClick?.(item)}
              className="hover:bg-gray-50 cursor-pointer"
            >
              {columns.map((column) => (
                <td key={String(column.key)} className="px-6 py-4 whitespace-nowrap">
                  {column.render
                    ? column.render(item[column.key], item)
                    : String(item[column.key] || '')
                  }
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};
```

### Card Component
```typescript
interface CardProps {
  title?: string;
  children: React.ReactNode;
  actions?: React.ReactNode;
  className?: string;
}

const Card: React.FC<CardProps> = ({ 
  title, 
  children, 
  actions, 
  className = '' 
}) => {
  return (
    <div className={`bg-white shadow rounded-lg ${className}`}>
      {(title || actions) && (
        <div className="px-6 py-4 border-b border-gray-200 flex items-center justify-between">
          {title && <h3 className="text-lg font-medium text-gray-900">{title}</h3>}
          {actions && <div className="flex space-x-2">{actions}</div>}
        </div>
      )}
      <div className="px-6 py-4">
        {children}
      </div>
    </div>
  );
};
```

### Statistics Cards
```typescript
interface StatCardProps {
  title: string;
  value: string | number;
  change?: {
    value: number;
    type: 'increase' | 'decrease';
  };
  icon?: React.ReactNode;
}

const StatCard: React.FC<StatCardProps> = ({ 
  title, 
  value, 
  change, 
  icon 
}) => {
  return (
    <div className="bg-white overflow-hidden shadow rounded-lg">
      <div className="p-5">
        <div className="flex items-center">
          <div className="flex-shrink-0">
            {icon}
          </div>
          <div className="ml-5 w-0 flex-1">
            <dl>
              <dt className="text-sm font-medium text-gray-500 truncate">
                {title}
              </dt>
              <dd className="flex items-baseline">
                <div className="text-2xl font-semibold text-gray-900">
                  {value}
                </div>
                {change && (
                  <div className={`ml-2 flex items-baseline text-sm font-semibold ${
                    change.type === 'increase' ? 'text-green-600' : 'text-red-600'
                  }`}>
                    <span>{change.type === 'increase' ? '+' : '-'}{change.value}%</span>
                  </div>
                )}
              </dd>
            </dl>
          </div>
        </div>
      </div>
    </div>
  );
};
```

## 6.5 Navigation Components

### Navigation Menu
```typescript
interface NavItem {
  name: string;
  href: string;
  icon?: React.ReactNode;
  children?: NavItem[];
  permission?: string;
}

interface NavigationProps {
  items: NavItem[];
  currentPath: string;
  userPermissions: string[];
}

const Navigation: React.FC<NavigationProps> = ({ 
  items, 
  currentPath, 
  userPermissions 
}) => {
  const filteredItems = items.filter(item => 
    !item.permission || userPermissions.includes(item.permission)
  );

  return (
    <nav className="space-y-1">
      {filteredItems.map((item) => (
        <NavItemComponent
          key={item.name}
          item={item}
          currentPath={currentPath}
          userPermissions={userPermissions}
        />
      ))}
    </nav>
  );
};
```

### Breadcrumbs
```typescript
interface BreadcrumbItem {
  name: string;
  href?: string;
  current?: boolean;
}

interface BreadcrumbsProps {
  items: BreadcrumbItem[];
}

const Breadcrumbs: React.FC<BreadcrumbsProps> = ({ items }) => {
  return (
    <nav className="flex" aria-label="Breadcrumb">
      <ol className="flex items-center space-x-4">
        {items.map((item, index) => (
          <li key={item.name} className="flex">
            <div className="flex items-center">
              {index > 0 && (
                <svg
                  className="flex-shrink-0 h-5 w-5 text-gray-300"
                  fill="currentColor"
                  viewBox="0 0 20 20"
                >
                  <path
                    fillRule="evenodd"
                    d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
                    clipRule="evenodd"
                  />
                </svg>
              )}
              {item.current ? (
                <span className="ml-4 text-sm font-medium text-gray-500">
                  {item.name}
                </span>
              ) : (
                <a
                  href={item.href}
                  className="ml-4 text-sm font-medium text-gray-500 hover:text-gray-700"
                >
                  {item.name}
                </a>
              )}
            </div>
          </li>
        ))}
      </ol>
    </nav>
  );
};
```

## 6.6 Utility Components

### Loading Spinner
```typescript
interface SpinnerProps {
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

const Spinner: React.FC<SpinnerProps> = ({ 
  size = 'md', 
  className = '' 
}) => {
  const sizeClasses = {
    sm: 'h-4 w-4',
    md: 'h-8 w-8',
    lg: 'h-12 w-12'
  };

  return (
    <div className={`animate-spin rounded-full border-2 border-gray-300 border-t-indigo-600 ${sizeClasses[size]} ${className}`} />
  );
};
```

### Modal Component
```typescript
interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  title?: string;
  children: React.ReactNode;
  size?: 'sm' | 'md' | 'lg' | 'xl';
}

const Modal: React.FC<ModalProps> = ({ 
  isOpen, 
  onClose, 
  title, 
  children, 
  size = 'md' 
}) => {
  const sizeClasses = {
    sm: 'max-w-md',
    md: 'max-w-lg',
    lg: 'max-w-2xl',
    xl: 'max-w-4xl'
  };

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 z-50 overflow-y-auto">
      <div className="flex items-center justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
        <div className="fixed inset-0 transition-opacity" onClick={onClose}>
          <div className="absolute inset-0 bg-gray-500 opacity-75" />
        </div>

        <div className={`inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle ${sizeClasses[size]} sm:w-full`}>
          {title && (
            <div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
              <h3 className="text-lg leading-6 font-medium text-gray-900">
                {title}
              </h3>
            </div>
          )}
          <div className="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
            {children}
          </div>
        </div>
      </div>
    </div>
  );
};
```

### Toast Notifications
```typescript
interface ToastProps {
  message: string;
  type: 'success' | 'error' | 'warning' | 'info';
  onClose: () => void;
  duration?: number;
}

const Toast: React.FC<ToastProps> = ({ 
  message, 
  type, 
  onClose, 
  duration = 5000 
}) => {
  useEffect(() => {
    const timer = setTimeout(onClose, duration);
    return () => clearTimeout(timer);
  }, [onClose, duration]);

  const typeClasses = {
    success: 'bg-green-50 border-green-200 text-green-800',
    error: 'bg-red-50 border-red-200 text-red-800',
    warning: 'bg-yellow-50 border-yellow-200 text-yellow-800',
    info: 'bg-blue-50 border-blue-200 text-blue-800'
  };

  return (
    <div className={`fixed top-4 right-4 z-50 max-w-sm w-full bg-white shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden ${typeClasses[type]}`}>
      <div className="p-4">
        <div className="flex items-start">
          <div className="flex-shrink-0">
            {/* Icon based on type */}
          </div>
          <div className="ml-3 w-0 flex-1">
            <p className="text-sm font-medium">{message}</p>
          </div>
          <div className="ml-4 flex-shrink-0 flex">
            <button
              onClick={onClose}
              className="bg-white rounded-md inline-flex text-gray-400 hover:text-gray-500 focus:outline-none"
            >
              <span className="sr-only">Close</span>
              <svg className="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
                <path fillRule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clipRule="evenodd" />
              </svg>
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};
```

---

## Component Usage Examples

### Tournament List Page
```typescript
const TournamentList: React.FC = () => {
  const [tournaments, setTournaments] = useState<Tournament[]>([]);
  const [loading, setLoading] = useState(true);

  const columns: Column<Tournament>[] = [
    { key: 'name', label: 'Name', sortable: true },
    { key: 'status', label: 'Status', sortable: true },
    { key: 'start_date', label: 'Start Date', sortable: true },
    { key: 'participants', label: 'Participants' }
  ];

  return (
    <AdminLayout title="Tournaments">
      <Card title="Tournaments" actions={<CreateTournamentButton />}>
        <DataTable
          data={tournaments}
          columns={columns}
          loading={loading}
          onRowClick={(tournament) => router.push(`/admin/tournaments/${tournament.id}`)}
        />
      </Card>
    </AdminLayout>
  );
};
```

### Team Registration Form
```typescript
const TeamRegistrationForm: React.FC = () => {
  const { values, errors, handleChange, handleBlur, isValid } = useFormValidation({
    name: '',
    description: '',
    founded_year: '',
    location: ''
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!isValid) return;
    
    // Submit form
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-6">
      <Input
        label="Team Name"
        name="name"
        value={values.name}
        onChange={(value) => handleChange('name', value)}
        onBlur={() => handleBlur('name')}
        error={errors.name}
        required
      />
      
      <Input
        label="Description"
        name="description"
        value={values.description}
        onChange={(value) => handleChange('description', value)}
        onBlur={() => handleBlur('description')}
        error={errors.description}
      />
      
      <button
        type="submit"
        disabled={!isValid}
        className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
      >
        Register Team
      </button>
    </form>
  );
};
```

---

## Next Steps

- [User Interface](07_User_Interface.md) - UI design and user experience
- [Core Features](08_Core_Features.md) - Core system functionality
- [API Documentation](05_API_Documentation.md) - API usage and endpoints
- [Developer Guide](18_Developer_Guide.md) - Development and customization
