# Streamlined Error & Load State Handling - Quick Reference

## 🎯 Goal
Standardize error and loading state handling across all GridPilot website pages using user-friendly, accessible, and consistent shared components.

## 📁 File Structure

```
apps/website/components/shared/
├── state/
│   ├── LoadingWrapper.tsx          # Loading states
│   ├── ErrorDisplay.tsx            # Error states
│   ├── EmptyState.tsx              # Empty states
│   └── StateContainer.tsx          # Combined wrapper
├── hooks/
│   └── useDataFetching.ts          # Unified data fetching
└── types/
    └── state.types.ts              # TypeScript interfaces
```

## 🚀 Quick Start Examples

### 1. Basic Page Implementation

```typescript
import { useDataFetching } from '@/components/shared/hooks/useDataFetching';
import { LoadingWrapper } from '@/ui/LoadingWrapper';
import { ErrorDisplay } from '@/ui/ErrorDisplay';
import { EmptyState } from '@/ui/EmptyState';

function MyPage() {
  const { data, isLoading, error, retry } = useDataFetching({
    queryKey: ['myData'],
    queryFn: () => myService.getData(),
  });

  if (isLoading) return <LoadingWrapper variant="full-screen" />;
  if (error) return <ErrorDisplay error={error} onRetry={retry} variant="full-screen" />;
  if (!data) return <EmptyState icon={Calendar} title="No data" />;

  return <MyContent data={data} />;
}
```

### 2. Using StateContainer (Recommended)

```typescript
import { StateContainer } from '@/ui/StateContainer';

function MyPage() {
  const { data, isLoading, error, retry } = useDataFetching({
    queryKey: ['myData'],
    queryFn: () => myService.getData(),
  });

  return (
    <StateContainer
      data={data}
      isLoading={isLoading}
      error={error}
      retry={retry}
      config={{
        loading: { variant: 'skeleton', message: 'Loading...' },
        error: { variant: 'full-screen' },
        empty: {
          icon: Trophy,
          title: 'No data found',
          description: 'Try refreshing the page',
          action: { label: 'Refresh', onClick: retry }
        }
      }}
    >
      {(content) => <MyContent data={content} />}
    </StateContainer>
  );
}
```

## 🎨 Component Variants

### LoadingWrapper
- `spinner` - Traditional spinner (default)
- `skeleton` - Skeleton screens
- `full-screen` - Centered in viewport
- `inline` - Compact inline
- `card` - Card placeholders

### ErrorDisplay
- `full-screen` - Full page error
- `inline` - Inline error message
- `card` - Error card
- `toast` - Toast notification

### EmptyState
- `default` - Standard empty state
- `minimal` - Simple version
- `full-page` - Full page empty state

## 🔧 useDataFetching Hook

```typescript
const {
  data,           // The fetched data
  isLoading,      // Initial load
  isFetching,     // Any fetch (including refetch)
  error,          // ApiError or null
  retry,          // Retry failed request
  refetch,        // Manual refetch
  lastUpdated,    // Timestamp
  isStale         // Cache status
} = useDataFetching({
  queryKey: ['uniqueKey', id],
  queryFn: () => apiService.getData(id),
  enabled: true,           // Enable/disable query
  retryOnMount: true,      // Auto-retry on mount
  cacheTime: 5 * 60 * 1000, // 5 minutes
  staleTime: 1 * 60 * 1000, // 1 minute
  maxRetries: 3,
  retryDelay: 1000,
  onSuccess: (data) => { /* ... */ },
  onError: (error) => { /* ... */ },
});
```

## 📋 Migration Checklist

### Phase 1: Foundation
- [ ] Create `components/shared/state/` directory
- [ ] Implement `LoadingWrapper.tsx`
- [ ] Implement `ErrorDisplay.tsx`
- [ ] Implement `EmptyState.tsx`
- [ ] Implement `StateContainer.tsx`
- [ ] Implement `useDataFetching.ts` hook
- [ ] Create TypeScript interfaces
- [ ] Add comprehensive tests

### Phase 2: Core Pages (High Priority)
- [ ] `app/dashboard/page.tsx`
- [ ] `app/leagues/[id]/LeagueDetailInteractive.tsx`
- [ ] `app/races/[id]/RaceDetailInteractive.tsx`

### Phase 3: Additional Pages
- [ ] `app/teams/[id]/TeamDetailInteractive.tsx`
- [ ] `app/leagues/[id]/schedule/page.tsx`
- [ ] `app/races/[id]/results/RaceResultsInteractive.tsx`
- [ ] `app/races/[id]/stewarding/RaceStewardingInteractive.tsx`
- [ ] Sponsor pages
- [ ] Profile pages

### Phase 4: Cleanup
- [ ] Remove old loading components
- [ ] Remove old error components
- [ ] Update documentation
- [ ] Team training

## 🔄 Before & After

### Before (Inconsistent)
```typescript
function DashboardPage() {
  const { data, isLoading, error } = useDashboardOverview();

  if (isLoading) {
    return (
      <main className="min-h-screen bg-deep-graphite flex items-center justify-center">
        <div className="text-white">Loading dashboard...</div>
      </main>
    );
  }

  if (error || !dashboardData) {
    return (
      <main className="min-h-screen bg-deep-graphite flex items-center justify-center">
        <div className="text-red-400">Failed to load dashboard</div>
      </main>
    );
  }

  return <DashboardContent data={dashboardData} />;
}
```

### After (Standardized)
```typescript
function DashboardPage() {
  const { data, isLoading, error, retry } = useDataFetching({
    queryKey: ['dashboardOverview'],
    queryFn: () => dashboardService.getDashboardOverview(),
  });

  return (
    <StateContainer
      data={data}
      isLoading={isLoading}
      error={error}
      retry={retry}
      config={{
        loading: { variant: 'full-screen', message: 'Loading dashboard...' },
        error: { variant: 'full-screen' },
        empty: {
          icon: Activity,
          title: 'No dashboard data',
          description: 'Try refreshing the page',
          action: { label: 'Refresh', onClick: retry }
        }
      }}
    >
      {(content) => <DashboardContent data={content} />}
    </StateContainer>
  );
}
```

## 🎯 Key Benefits

1. **Consistency**: Same patterns across all pages
2. **User-Friendly**: Clear messages and helpful actions
3. **Accessible**: ARIA labels, keyboard navigation
4. **Developer-Friendly**: Simple API, less boilerplate
5. **Maintainable**: Single source of truth
6. **Flexible**: Multiple variants for different needs
7. **Type-Safe**: Full TypeScript support

## 📊 Success Metrics

- ✅ 100% page coverage
- ✅ 60% less error handling code
- ✅ Consistent UX across app
- ✅ Better error recovery
- ✅ Faster development

## 🔗 Related Files

- Design Document: `STREAMLINED_STATE_HANDLING_DESIGN.md`
- TypeScript Interfaces: `components/shared/state/types.ts`
- Component Tests: `components/shared/state/*.test.tsx`
- Hook Tests: `components/shared/hooks/useDataFetching.test.ts`

## 💡 Tips

1. **Always use `useDataFetching`** instead of manual state management
2. **Prefer `StateContainer`** for complex pages
3. **Use `skeleton` variant** for better perceived performance
4. **Enable `retryOnMount`** for recoverable errors
5. **Customize config** per page needs
6. **Test all states**: loading, error, empty, success

## 🆘 Troubleshooting

**Q: Error not showing?**
A: Check if error is instance of `ApiError`

**Q: Loading not visible?**
A: Verify `isLoading` is true and component is rendered

**Q: Retry not working?**
A: Ensure `onRetry` prop is passed to ErrorDisplay

**Q: Empty state not showing?**
A: Check if data is null/undefined and `showEmpty` is true

---

For detailed implementation guide, see: `STREAMLINED_STATE_HANDLING_DESIGN.md`