# Frontend Architecture Redesign

## Overview

This document outlines a production-ready frontend architecture for the ProfytAI Compliance Management Platform, addressing scalability, maintainability, and developer experience.

## Design Principles

1. **Feature-Based Organization**: Group related code by feature/domain
2. **Separation of Concerns**: Clear boundaries between layers
3. **Type Safety**: Full TypeScript coverage
4. **Reusability**: Shared components and utilities
5. **Testability**: Easy to test components and logic
6. **Performance**: Code splitting, lazy loading, optimization
7. **Developer Experience**: Clear structure, good DX

---

## New Directory Structure

```
fe0/
├── src/
│   ├── app/                          # App-level configuration
│   │   ├── providers/                # Global providers
│   │   │   ├── QueryProvider.tsx
│   │   │   ├── AuthProvider.tsx
│   │   │   ├── ThemeProvider.tsx
│   │   │   └── ErrorBoundary.tsx
│   │   ├── router/                   # Routing configuration
│   │   │   ├── index.tsx
│   │   │   ├── routes.tsx
│   │   │   └── guards.tsx
│   │   └── store/                    # Global state (if needed)
│   │       └── index.ts
│   │
│   ├── features/                      # Feature-based modules
│   │   ├── auth/
│   │   │   ├── components/
│   │   │   │   ├── LoginForm.tsx
│   │   │   │   └── SignUpForm.tsx
│   │   │   ├── hooks/
│   │   │   │   ├── useAuth.ts
│   │   │   │   └── useLogin.ts
│   │   │   ├── services/
│   │   │   │   └── authService.ts
│   │   │   ├── types/
│   │   │   │   └── auth.types.ts
│   │   │   └── index.ts
│   │   │
│   │   ├── workflows/
│   │   │   ├── components/
│   │   │   │   ├── WorkflowList.tsx
│   │   │   │   ├── WorkflowCard.tsx
│   │   │   │   ├── WorkflowForm.tsx
│   │   │   │   └── WorkflowItem.tsx
│   │   │   ├── hooks/
│   │   │   │   ├── useWorkflows.ts
│   │   │   │   ├── useWorkflow.ts
│   │   │   │   └── useCreateWorkflow.ts
│   │   │   ├── services/
│   │   │   │   └── workflowService.ts
│   │   │   ├── types/
│   │   │   │   └── workflow.types.ts
│   │   │   └── index.ts
│   │   │
│   │   ├── documents/
│   │   │   ├── components/
│   │   │   ├── hooks/
│   │   │   ├── services/
│   │   │   └── types/
│   │   │
│   │   ├── compliance/
│   │   │   ├── components/
│   │   │   ├── hooks/
│   │   │   ├── services/
│   │   │   └── types/
│   │   │
│   │   └── dashboard/
│   │       ├── components/
│   │       ├── hooks/
│   │       └── types/
│   │
│   ├── shared/                       # Shared code
│   │   ├── api/                      # API client
│   │   │   ├── client.ts             # Axios/Fetch client
│   │   │   ├── interceptors.ts       # Request/Response interceptors
│   │   │   ├── endpoints.ts          # API endpoint constants
│   │   │   └── types.ts               # API response types
│   │   │
│   │   ├── components/               # Shared UI components
│   │   │   ├── ui/                    # shadcn components (existing)
│   │   │   ├── layout/
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── Sidebar.tsx
│   │   │   │   └── Footer.tsx
│   │   │   ├── feedback/
│   │   │   │   ├── LoadingSpinner.tsx
│   │   │   │   ├── ErrorMessage.tsx
│   │   │   │   └── EmptyState.tsx
│   │   │   └── forms/
│   │   │       └── FormField.tsx
│   │   │
│   │   ├── hooks/                     # Shared hooks
│   │   │   ├── useApi.ts
│   │   │   ├── useDebounce.ts
│   │   │   ├── useLocalStorage.ts
│   │   │   └── useMediaQuery.ts
│   │   │
│   │   ├── utils/                     # Utility functions
│   │   │   ├── format.ts
│   │   │   ├── validation.ts
│   │   │   ├── date.ts
│   │   │   └── constants.ts
│   │   │
│   │   ├── types/                     # Shared TypeScript types
│   │   │   ├── api.types.ts
│   │   │   ├── common.types.ts
│   │   │   └── index.ts
│   │   │
│   │   └── config/                    # Configuration
│   │       ├── env.ts                 # Environment variables
│   │       ├── constants.ts           # App constants
│   │       └── routes.ts              # Route constants
│   │
│   ├── pages/                         # Page components
│   │   ├── public/
│   │   │   ├── HomePage.tsx
│   │   │   ├── LoginPage.tsx
│   │   │   └── NotFoundPage.tsx
│   │   └── protected/
│   │       ├── DashboardPage.tsx
│   │       └── WorkflowsPage.tsx
│   │
│   ├── layouts/                       # Layout components
│   │   ├── PublicLayout.tsx
│   │   ├── DashboardLayout.tsx
│   │   └── AuthLayout.tsx
│   │
│   ├── assets/                        # Static assets
│   │   ├── images/
│   │   ├── icons/
│   │   └── fonts/
│   │
│   ├── styles/                        # Global styles
│   │   ├── globals.css
│   │   └── themes.css
│   │
│   ├── App.tsx                        # Root component
│   └── main.tsx                       # Entry point
│
├── public/                             # Public assets
├── tests/                             # Test files
│   ├── unit/
│   ├── integration/
│   ├── e2e/
│   └── setup.ts
│
├── .env.example
├── .env.development
├── .env.production
├── vite.config.ts
├── tsconfig.json
└── package.json
```

---

## Key Architectural Components

### 1. API Client Layer

**Purpose**: Centralized HTTP client with interceptors, error handling, and type safety.

**Features**:
- Request/Response interceptors
- Automatic token refresh
- Error handling
- Type-safe endpoints
- Request cancellation
- Retry logic

### 2. Service Layer

**Purpose**: Business logic and API communication abstraction.

**Features**:
- Type-safe API calls
- Data transformation
- Error handling
- Caching strategies

### 3. Feature Modules

**Purpose**: Self-contained feature modules with all related code.

**Structure**:
- Components (UI)
- Hooks (React hooks)
- Services (API calls)
- Types (TypeScript types)
- Utils (Feature-specific utilities)

### 4. Shared Layer

**Purpose**: Reusable code across features.

**Includes**:
- UI components
- Utilities
- Hooks
- Types
- Configuration

### 5. Routing

**Purpose**: Centralized route configuration with guards.

**Features**:
- Route guards (auth, permissions)
- Lazy loading
- Code splitting
- Route constants

---

## Implementation Examples

### Example 1: API Client

```typescript
// shared/api/client.ts
import axios, { AxiosInstance, AxiosError, InternalAxiosRequestConfig } from 'axios';
import { env } from '@/shared/config/env';
import { getAccessToken, clearAccessToken, setAccessToken } from '@/shared/utils/token';

class ApiClient {
  private client: AxiosInstance;

  constructor() {
    this.client = axios.create({
      baseURL: env.API_URL,
      timeout: 30000,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    this.setupInterceptors();
  }

  private setupInterceptors(): void {
    // Request interceptor
    this.client.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        const token = getAccessToken();
        if (token && config.headers) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => Promise.reject(error)
    );

    // Response interceptor
    this.client.interceptors.response.use(
      (response) => response,
      async (error: AxiosError) => {
        const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };

        // Handle 401 - Unauthorized
        if (error.response?.status === 401 && !originalRequest._retry) {
          originalRequest._retry = true;

          try {
            const newToken = await this.refreshToken();
            if (newToken && originalRequest.headers) {
              originalRequest.headers.Authorization = `Bearer ${newToken}`;
              return this.client(originalRequest);
            }
          } catch (refreshError) {
            clearAccessToken();
            window.location.href = '/login';
            return Promise.reject(refreshError);
          }
        }

        // Handle other errors
        return Promise.reject(this.handleError(error));
      }
    );
  }

  private async refreshToken(): Promise<string | null> {
    try {
      const response = await axios.post(`${env.API_URL}/auth/refresh`, {}, {
        withCredentials: true,
      });
      const { accessToken } = response.data;
      setAccessToken(accessToken);
      return accessToken;
    } catch (error) {
      return null;
    }
  }

  private handleError(error: AxiosError): ApiError {
    if (error.response) {
      // Server responded with error
      return {
        message: error.response.data?.message || 'An error occurred',
        status: error.response.status,
        data: error.response.data,
      };
    } else if (error.request) {
      // Request made but no response
      return {
        message: 'Network error. Please check your connection.',
        status: 0,
      };
    } else {
      // Error setting up request
      return {
        message: error.message || 'An unexpected error occurred',
        status: 0,
      };
    }
  }

  public get<T = any>(url: string, config?: any): Promise<T> {
    return this.client.get<T>(url, config).then((res) => res.data);
  }

  public post<T = any>(url: string, data?: any, config?: any): Promise<T> {
    return this.client.post<T>(url, data, config).then((res) => res.data);
  }

  public put<T = any>(url: string, data?: any, config?: any): Promise<T> {
    return this.client.put<T>(url, data, config).then((res) => res.data);
  }

  public delete<T = any>(url: string, config?: any): Promise<T> {
    return this.client.delete<T>(url, config).then((res) => res.data);
  }

  public patch<T = any>(url: string, data?: any, config?: any): Promise<T> {
    return this.client.patch<T>(url, data, config).then((res) => res.data);
  }
}

export const apiClient = new ApiClient();
export type ApiError = {
  message: string;
  status: number;
  data?: any;
};
```

### Example 2: Service Layer

```typescript
// features/workflows/services/workflowService.ts
import { apiClient } from '@/shared/api/client';
import { Workflow, CreateWorkflowDto, UpdateWorkflowItemDto } from '../types/workflow.types';
import { ApiResponse, PaginatedResponse } from '@/shared/types/api.types';

export const workflowService = {
  async getAll(params?: {
    skip?: number;
    limit?: number;
    projectName?: string;
  }): Promise<PaginatedResponse<Workflow>> {
    return apiClient.get<PaginatedResponse<Workflow>>('/api/v1/workflows', { params });
  },

  async getById(id: string): Promise<Workflow> {
    return apiClient.get<Workflow>(`/api/v1/workflows/${id}`);
  },

  async create(data: CreateWorkflowDto): Promise<Workflow> {
    return apiClient.post<Workflow>('/api/v1/workflows', data);
  },

  async updateItem(
    workflowId: string,
    data: UpdateWorkflowItemDto
  ): Promise<Workflow> {
    return apiClient.put<Workflow>(
      `/api/v1/workflows/${workflowId}/items`,
      data
    );
  },

  async advancePhase(workflowId: string): Promise<Workflow> {
    return apiClient.post<Workflow>(
      `/api/v1/workflows/${workflowId}/advance`
    );
  },

  async delete(id: string): Promise<void> {
    return apiClient.delete(`/api/v1/workflows/${id}`);
  },
};
```

### Example 3: Custom Hooks

```typescript
// features/workflows/hooks/useWorkflows.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { workflowService } from '../services/workflowService';
import { CreateWorkflowDto, UpdateWorkflowItemDto } from '../types/workflow.types';
import { toast } from 'sonner';

export const useWorkflows = (params?: {
  skip?: number;
  limit?: number;
  projectName?: string;
}) => {
  return useQuery({
    queryKey: ['workflows', params],
    queryFn: () => workflowService.getAll(params),
  });
};

export const useWorkflow = (id: string) => {
  return useQuery({
    queryKey: ['workflow', id],
    queryFn: () => workflowService.getById(id),
    enabled: !!id,
  });
};

export const useCreateWorkflow = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: (data: CreateWorkflowDto) => workflowService.create(data),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['workflows'] });
      toast.success('Workflow created successfully');
    },
    onError: (error: any) => {
      toast.error(error.message || 'Failed to create workflow');
    },
  });
};

export const useUpdateWorkflowItem = () => {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: ({ workflowId, data }: { workflowId: string; data: UpdateWorkflowItemDto }) =>
      workflowService.updateItem(workflowId, data),
    onSuccess: (_, variables) => {
      queryClient.invalidateQueries({ queryKey: ['workflow', variables.workflowId] });
      queryClient.invalidateQueries({ queryKey: ['workflows'] });
      toast.success('Workflow item updated');
    },
    onError: (error: any) => {
      toast.error(error.message || 'Failed to update workflow item');
    },
  });
};
```

### Example 4: Environment Configuration

```typescript
// shared/config/env.ts
interface EnvConfig {
  API_URL: string;
  WS_URL?: string;
  ENVIRONMENT: 'development' | 'staging' | 'production';
  ENABLE_DEV_TOOLS: boolean;
}

const getEnvVar = (key: string, defaultValue?: string): string => {
  const value = import.meta.env[key];
  if (!value && !defaultValue) {
    throw new Error(`Missing required environment variable: ${key}`);
  }
  return value || defaultValue || '';
};

export const env: EnvConfig = {
  API_URL: getEnvVar('VITE_API_URL', 'http://localhost:4402'),
  WS_URL: getEnvVar('VITE_WS_URL'),
  ENVIRONMENT: (getEnvVar('VITE_ENV', 'development') as EnvConfig['ENVIRONMENT']),
  ENABLE_DEV_TOOLS: getEnvVar('VITE_ENABLE_DEV_TOOLS', 'false') === 'true',
};

export const isDevelopment = env.ENVIRONMENT === 'development';
export const isProduction = env.ENVIRONMENT === 'production';
```

### Example 5: Route Configuration

```typescript
// app/router/routes.tsx
import { lazy } from 'react';
import { RouteObject } from 'react-router-dom';
import { PublicLayout } from '@/layouts/PublicLayout';
import { DashboardLayout } from '@/layouts/DashboardLayout';
import { ProtectedRoute } from '@/app/router/guards';

// Lazy load pages for code splitting
const HomePage = lazy(() => import('@/pages/public/HomePage'));
const LoginPage = lazy(() => import('@/pages/public/LoginPage'));
const DashboardPage = lazy(() => import('@/pages/protected/DashboardPage'));
const WorkflowsPage = lazy(() => import('@/pages/protected/WorkflowsPage'));
const NotFoundPage = lazy(() => import('@/pages/public/NotFoundPage'));

export const routes: RouteObject[] = [
  {
    path: '/',
    element: <PublicLayout />,
    children: [
      { index: true, element: <HomePage /> },
      { path: 'login', element: <LoginPage /> },
      { path: 'about', element: <div>About</div> },
    ],
  },
  {
    path: '/dashboard',
    element: (
      <ProtectedRoute requiredPermission="dashboard.access">
        <DashboardLayout />
      </ProtectedRoute>
    ),
    children: [
      { index: true, element: <DashboardPage /> },
      {
        path: 'workflows',
        element: (
          <ProtectedRoute requiredPermission="workflows.view">
            <WorkflowsPage />
          </ProtectedRoute>
        ),
      },
    ],
  },
  { path: '*', element: <NotFoundPage /> },
];
```

### Example 6: Error Boundary

```typescript
// app/providers/ErrorBoundary.tsx
import React, { Component, ErrorInfo, ReactNode } from 'react';
import { Button } from '@/shared/components/ui/button';
import { AlertTriangle } from 'lucide-react';

interface Props {
  children: ReactNode;
  fallback?: ReactNode;
}

interface State {
  hasError: boolean;
  error: Error | null;
}

export class ErrorBoundary extends Component<Props, State> {
  public state: State = {
    hasError: false,
    error: null,
  };

  public static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error };
  }

  public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.error('Uncaught error:', error, errorInfo);
    // Log to error reporting service
  }

  private handleReset = () => {
    this.setState({ hasError: false, error: null });
  };

  public render() {
    if (this.state.hasError) {
      if (this.props.fallback) {
        return this.props.fallback;
      }

      return (
        <div className="flex min-h-screen items-center justify-center p-4">
          <div className="text-center">
            <AlertTriangle className="mx-auto h-12 w-12 text-destructive" />
            <h1 className="mt-4 text-2xl font-bold">Something went wrong</h1>
            <p className="mt-2 text-muted-foreground">
              {this.state.error?.message || 'An unexpected error occurred'}
            </p>
            <Button onClick={this.handleReset} className="mt-4">
              Try again
            </Button>
          </div>
        </div>
      );
    }

    return this.props.children;
  }
}
```

---

## Benefits

1. **Scalability**: Easy to add new features
2. **Maintainability**: Clear structure, easy to find code
3. **Type Safety**: Full TypeScript coverage
4. **Testability**: Easy to test components and logic
5. **Performance**: Code splitting, lazy loading
6. **Developer Experience**: Clear patterns, good DX
7. **Reusability**: Shared components and utilities

---

## Migration Strategy

### Phase 1: Foundation (Week 1)
1. Set up new directory structure
2. Create API client
3. Set up environment configuration
4. Create shared utilities

### Phase 2: Features (Week 2-3)
1. Migrate auth feature
2. Migrate workflows feature
3. Migrate documents feature
4. Migrate compliance feature

### Phase 3: Refinement (Week 4)
1. Add error boundaries
2. Improve error handling
3. Add loading states
4. Optimize performance

### Phase 4: Testing & Polish (Week 5)
1. Write tests
2. Add documentation
3. Performance optimization
4. Final review

---

## Next Steps

1. Review and approve architecture
2. Create detailed implementation plan
3. Set up project structure
4. Begin Phase 1 implementation
