# React Frontend Implementation Plan for Sim-Search

## Overview

This document outlines the plan for implementing a React frontend for the sim-search project, replacing the current Gradio interface with a modern, responsive, and feature-rich user interface. The frontend will communicate with the new FastAPI backend to provide a seamless user experience.

## Architecture

### Core Components

1. **Next.js Framework**
   - Server-side rendering for improved SEO
   - API routes for backend proxying if needed
   - Static site generation for performance

2. **Component Library**
   - Modular React components
   - Reusable UI elements
   - Styling with Tailwind CSS

3. **State Management**
   - React Query for server state
   - Context API for application state
   - Form state management

4. **Authentication**
   - JWT token management
   - Protected routes
   - User profile management

## Directory Structure

```
sim-search-ui/
├── src/
│   ├── components/
│   │   ├── layout/
│   │   │   ├── Header.jsx          # Application header
│   │   │   ├── Sidebar.jsx         # Sidebar menu
│   │   │   └── Layout.jsx          # Main layout wrapper
│   │   ├── search/
│   │   │   ├── SearchForm.jsx      # Search input form
│   │   │   ├── SearchResults.jsx   # Results display
│   │   │   ├── ResultItem.jsx      # Individual result
│   │   │   └── EngineSelector.jsx  # Search engine selector
│   │   ├── report/
│   │   │   ├── ReportGenerator.jsx # Report generation form
│   │   │   ├── ReportViewer.jsx    # Report display
│   │   │   ├── ReportsList.jsx     # Reports list/management
│   │   │   └── ReportOptions.jsx   # Report generation options
│   │   ├── common/
│   │   │   ├── Button.jsx          # Reusable button component
│   │   │   ├── Card.jsx            # Card container component
│   │   │   ├── Loading.jsx         # Loading indicator
│   │   │   └── Modal.jsx           # Modal dialog
│   │   └── auth/
│   │       ├── LoginForm.jsx       # User login form
│   │       └── RegisterForm.jsx    # User registration form
│   ├── hooks/
│   │   ├── useAuth.js              # Authentication hook
│   │   ├── useSearch.js            # Search execution hook
│   │   └── useReport.js            # Report management hook
│   ├── context/
│   │   ├── AuthContext.jsx         # Authentication context
│   │   └── SearchContext.jsx       # Search state context
│   ├── services/
│   │   ├── api.js                  # API client service
│   │   ├── auth.js                 # Authentication service
│   │   ├── search.js               # Search service
│   │   └── report.js               # Report service
│   ├── utils/
│   │   ├── formatting.js           # Text/data formatting utilities
│   │   └── validation.js           # Form validation utilities
│   ├── styles/
│   │   ├── globals.css             # Global styles
│   │   └── theme.js                # Theme configuration
│   └── pages/
│       ├── _app.jsx                # App component
│       ├── index.jsx               # Home page
│       ├── search.jsx              # Search page
│       ├── reports/
│       │   ├── index.jsx           # Reports list page
│       │   ├── [id].jsx            # Individual report page
│       │   └── new.jsx             # New report page
│       └── auth/
│           ├── login.jsx           # Login page
│           └── register.jsx        # Registration page
├── public/
│   ├── logo.svg                    # Application logo
│   └── favicon.ico                 # Favicon
├── tailwind.config.js              # Tailwind configuration
├── next.config.js                  # Next.js configuration
└── package.json                    # Dependencies
```

## Key Pages and Features

### Home Page
- Overview of the system
- Quick access to search and reports
- Feature highlights and documentation

### Search Page
- Comprehensive search form
- Multiple search engine selection
- Advanced search options
- Results display with filtering and sorting
- Options to generate reports from results

### Report Generation Page
- Detail level selection
- Query type selection
- Model selection
- Advanced options
- Progress tracking

### Reports Management Page
- List of generated reports
- Filtering and sorting options
- Download in different formats
- Delete and manage reports

### Authentication Pages
- Login page
- Registration page
- User profile management

## Component Design

### Search Components

#### SearchForm Component
```jsx
const SearchForm = ({ onSearchComplete }) => {
  const [query, setQuery] = useState('');
  const [selectedEngines, setSelectedEngines] = useState([]);
  const [numResults, setNumResults] = useState(10);
  const [useReranker, setUseReranker] = useState(true);
  const { engines, loading, error, loadEngines, search } = useSearch();

  // Load available search engines on component mount
  useEffect(() => {
    loadEngines();
  }, []);

  // Handle search submission
  const handleSubmit = async (e) => {
    e.preventDefault();
    
    const searchParams = {
      query: query.trim(),
      search_engines: selectedEngines.length > 0 ? selectedEngines : undefined,
      num_results: numResults,
      use_reranker: useReranker,
    };
    
    const results = await search(searchParams);
    
    if (results && onSearchComplete) {
      onSearchComplete(results);
    }
  };

  return (
    // Form UI with input fields, engine selection, and options
  );
};
```

#### SearchResults Component
```jsx
const SearchResults = ({ results, query, onGenerateReport }) => {
  const [selectedResults, setSelectedResults] = useState([]);
  const [sortBy, setSortBy] = useState('relevance');

  // Toggle a result's selection
  const toggleResultSelection = (resultId) => {
    setSelectedResults(prev => (
      prev.includes(resultId)
        ? prev.filter(id => id !== resultId)
        : [...prev, resultId]
    ));
  };

  // Handle generate report button click
  const handleGenerateReport = () => {
    // Filter results to only include selected ones if any are selected
    const resultsToUse = selectedResults.length > 0
      ? results.filter((result, index) => selectedResults.includes(index))
      : results;
    
    if (onGenerateReport) {
      onGenerateReport(resultsToUse, query);
    }
  };

  return (
    // Results UI with sorting, filtering, and item selection
  );
};
```

### Report Components

#### ReportGenerator Component
```jsx
const ReportGenerator = ({ query, searchResults, searchId }) => {
  const [detailLevel, setDetailLevel] = useState('standard');
  const [queryType, setQueryType] = useState('auto-detect');
  const [customModel, setCustomModel] = useState('');
  const [initialResults, setInitialResults] = useState(10);
  const [finalResults, setFinalResults] = useState(7);
  const { loading, error, createReport } = useReport();

  // Generate the report
  const handleGenerateReport = async () => {
    const reportParams = {
      query,
      search_id: searchId,
      search_results: !searchId ? searchResults : undefined,
      detail_level: detailLevel,
      query_type: queryType,
      custom_model: customModel || undefined,
      initial_results: initialResults,
      final_results: finalResults
    };
    
    await createReport(reportParams);
  };

  return (
    // Report generation form with options
  );
};
```

#### ReportViewer Component
```jsx
const ReportViewer = ({ report, onDownload }) => {
  const [selectedFormat, setSelectedFormat] = useState('markdown');
  const { download, loading } = useReport();

  const handleDownload = async () => {
    if (onDownload) {
      onDownload(report.id, selectedFormat);
    } else {
      await download(report.id, selectedFormat);
    }
  };

  return (
    // Report content display with markdown rendering and download options
  );
};
```

## API Integration Services

### API Client Service
```javascript
import axios from 'axios';

// Create an axios instance with default config
const api = axios.create({
  baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
  headers: {
    'Content-Type': 'application/json',
  },
});

// Add a request interceptor to include auth token in requests
api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Add a response interceptor to handle common errors
api.interceptors.response.use(
  (response) => response,
  (error) => {
    // Handle 401 Unauthorized - redirect to login
    if (error.response && error.response.status === 401) {
      localStorage.removeItem('token');
      window.location.href = '/auth/login';
    }
    return Promise.reject(error);
  }
);

export default api;
```

### Search Service
```javascript
import api from './api';

export const executeSearch = async (searchParams) => {
  try {
    const response = await api.post('/api/search/execute', searchParams);
    return { success: true, data: response.data };
  } catch (error) {
    return { 
      success: false, 
      error: error.response?.data?.detail || 'Failed to execute search' 
    };
  }
};

export const getAvailableEngines = async () => {
  try {
    const response = await api.get('/api/search/engines');
    return { success: true, data: response.data };
  } catch (error) {
    return { 
      success: false, 
      error: error.response?.data?.detail || 'Failed to get search engines' 
    };
  }
};
```

### Report Service
```javascript
import api from './api';

export const generateReport = async (reportParams) => {
  try {
    const response = await api.post('/api/report/generate', reportParams);
    return { success: true, data: response.data };
  } catch (error) {
    return { 
      success: false, 
      error: error.response?.data?.detail || 'Failed to generate report' 
    };
  }
};

export const getReportsList = async (skip = 0, limit = 100) => {
  try {
    const response = await api.get(`/api/report/list?skip=${skip}&limit=${limit}`);
    return { success: true, data: response.data };
  } catch (error) {
    return { 
      success: false, 
      error: error.response?.data?.detail || 'Failed to get reports list' 
    };
  }
};
```

## Custom Hooks

### Authentication Hook
```javascript
import { useState, useEffect, useContext, createContext } from 'react';
import { getCurrentUser, isAuthenticated } from '../services/auth';

// Create auth context
const AuthContext = createContext(null);

// Auth provider component
export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    // Check if user is authenticated and fetch user data
    const fetchUser = async () => {
      if (isAuthenticated()) {
        try {
          setLoading(true);
          const result = await getCurrentUser();
          if (result.success) {
            setUser(result.data);
          } else {
            setError(result.error);
          }
        } catch (err) {
          setError('Failed to fetch user data');
        } finally {
          setLoading(false);
        }
      } else {
        setLoading(false);
      }
    };

    fetchUser();
  }, []);

  // Return provider with auth context
  return (
    <AuthContext.Provider value={{ user, loading, error, setUser }}>
      {children}
    </AuthContext.Provider>
  );
};

// Custom hook to use auth context
export const useAuth = () => {
  const context = useContext(AuthContext);
  if (context === null) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};
```

### Search Hook
```javascript
import { useState } from 'react';
import { executeSearch, getAvailableEngines } from '../services/search';

export const useSearch = () => {
  const [results, setResults] = useState([]);
  const [engines, setEngines] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  // Load available search engines
  const loadEngines = async () => {
    try {
      setLoading(true);
      const result = await getAvailableEngines();
      if (result.success) {
        setEngines(result.data);
      } else {
        setError(result.error);
      }
    } catch (err) {
      setError('Failed to load search engines');
    } finally {
      setLoading(false);
    }
  };

  // Execute a search
  const search = async (searchParams) => {
    try {
      setLoading(true);
      setError(null);
      const result = await executeSearch(searchParams);
      if (result.success) {
        setResults(result.data.results);
        return result.data;
      } else {
        setError(result.error);
        return null;
      }
    } catch (err) {
      setError('Failed to execute search');
      return null;
    } finally {
      setLoading(false);
    }
  };

  return {
    results,
    engines,
    loading,
    error,
    search,
    loadEngines,
  };
};
```

## Implementation Phases

### Phase 1: Project Setup & Core Components (Week 1)
- Set up Next.js project
- Configure Tailwind CSS
- Implement common UI components
- Create layout components

### Phase 2: Authentication & API Integration (Week 1-2)
- Implement authentication components
- Create API service layer
- Implement custom hooks
- Set up protected routes

### Phase 3: Search Functionality (Week 2)
- Implement search form
- Create search results display
- Add filtering and sorting
- Implement search engine selection

### Phase 4: Report Generation & Management (Week 2-3)
- Implement report generation form
- Create report viewer with markdown rendering
- Add report management interface
- Implement download functionality

### Phase 5: Testing & Refinement (Week 3)
- Write component tests
- Perform cross-browser testing
- Add responsive design improvements
- Optimize performance

### Phase 6: Deployment & Documentation (Week 3-4)
- Set up deployment configuration
- Create user documentation
- Add inline help and tooltips
- Perform final testing

## Dependencies

```json
{
  "dependencies": {
    "next": "^13.5.4",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "axios": "^1.5.1",
    "react-markdown": "^9.0.0",
    "react-query": "^3.39.3",
    "tailwindcss": "^3.3.3",
    "postcss": "^8.4.31",
    "autoprefixer": "^10.4.16",
    "jose": "^4.14.6"
  },
  "devDependencies": {
    "eslint": "^8.51.0",
    "eslint-config-next": "^13.5.4",
    "typescript": "^5.2.2",
    "@types/react": "^18.2.28",
    "@types/node": "^20.8.6",
    "jest": "^29.7.0",
    "@testing-library/react": "^14.0.0",
    "@testing-library/jest-dom": "^6.1.4"
  }
}
```

## Accessibility Considerations

The React frontend will be built with accessibility in mind:

1. **Semantic HTML**: Use proper HTML elements for their intended purpose
2. **ARIA Attributes**: Add ARIA attributes where necessary
3. **Keyboard Navigation**: Ensure all interactive elements are keyboard accessible
4. **Focus Management**: Properly manage focus, especially in modals and dialogs
5. **Color Contrast**: Ensure sufficient color contrast for text and UI elements
6. **Screen Reader Support**: Test with screen readers to ensure compatibility

## Performance Optimization

To ensure optimal performance:

1. **Code Splitting**: Use Next.js code splitting to reduce initial bundle size
2. **Lazy Loading**: Implement lazy loading for components not needed immediately
3. **Memoization**: Use React.memo and useMemo to prevent unnecessary re-renders
4. **Image Optimization**: Use Next.js image optimization for faster loading
5. **API Response Caching**: Cache API responses with React Query
6. **Bundle Analysis**: Regularly analyze bundle size to identify improvements

## Conclusion

This implementation plan provides a structured approach to creating a modern React frontend for the sim-search project. By following this plan, we will create a user-friendly, accessible, and feature-rich interface that leverages the power of the new FastAPI backend.

The component-based architecture ensures reusability and maintainability, while the use of modern React patterns and hooks simplifies state management and side effects. The integration with the FastAPI backend is handled through a clean service layer, making it easy to adapt to changes in the API.

With this implementation, users will have a much improved experience compared to the current Gradio interface, with better search capabilities, more advanced report generation options, and a more intuitive interface for managing their research.
