396 lines
10 KiB
Markdown
Raw Normal View History

# Design Document
## Overview
This design document outlines a comprehensive refactoring strategy to transform the current customer portal codebase into a modern, maintainable, and scalable architecture. The refactoring will eliminate redundancies, establish consistent patterns, and improve developer experience while maintaining existing functionality.
## Architecture
### High-Level Structure
The refactored architecture will follow a feature-driven, layered approach:
```
apps/portal/src/
├── app/ # Next.js App Router pages
├── components/ # Shared UI components (Design System)
│ ├── ui/ # Base UI components (atoms)
│ ├── layout/ # Layout components (organisms)
│ └── common/ # Shared business components (molecules)
├── features/ # Feature-specific modules
│ ├── auth/ # Authentication feature
│ ├── dashboard/ # Dashboard feature
│ ├── billing/ # Billing feature
│ ├── subscriptions/ # Subscriptions feature
│ ├── catalog/ # Product catalog feature
│ └── support/ # Support feature
├── lib/ # Core utilities and services
│ ├── api/ # API client and services
│ ├── auth/ # Authentication logic
│ ├── hooks/ # Shared React hooks
│ ├── stores/ # State management
│ ├── types/ # Shared TypeScript types
│ └── utils/ # Utility functions
├── providers/ # React context providers
└── styles/ # Global styles and design tokens
```
### Design Principles
1. **Feature-First Organization**: Group related functionality together
2. **Atomic Design**: Build UI components in a hierarchical manner
3. **Separation of Concerns**: Separate business logic from presentation
4. **Single Responsibility**: Each module has one clear purpose
5. **Dependency Inversion**: Depend on abstractions, not concretions
## Components and Interfaces
### Design System Architecture
#### Atomic Design Structure
```typescript
// Base UI Components (Atoms)
components/ui/
├── Button/
│ ├── Button.tsx
│ ├── Button.stories.tsx
│ ├── Button.test.tsx
│ └── index.ts
├── Input/
├── Badge/
└── ...
// Composite Components (Molecules)
components/common/
├── DataTable/
├── SearchBar/
├── StatusIndicator/
└── ...
// Layout Components (Organisms)
components/layout/
├── DashboardLayout/
├── AuthLayout/
├── PageLayout/
└── ...
```
#### Component Interface Standards
```typescript
// Base component props interface
interface BaseComponentProps {
className?: string;
children?: React.ReactNode;
testId?: string;
}
// Variant-based component pattern
interface ButtonProps extends BaseComponentProps {
variant?: 'primary' | 'secondary' | 'outline' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
loading?: boolean;
onClick?: () => void;
}
```
### Feature Module Structure
Each feature will follow a consistent internal structure:
```typescript
features/[feature-name]/
├── components/ # Feature-specific components
│ ├── [Component]/
│ │ ├── Component.tsx
│ │ ├── Component.test.tsx
│ │ └── index.ts
│ └── index.ts
├── hooks/ # Feature-specific hooks
│ ├── use[Feature].ts
│ └── index.ts
├── services/ # Feature business logic
│ ├── [feature].service.ts
│ └── index.ts
├── types/ # Feature-specific types
│ ├── [feature].types.ts
│ └── index.ts
├── utils/ # Feature utilities
└── index.ts # Feature public API
```
### API Service Layer
```typescript
// Centralized API service structure
lib/api/
├── client.ts # Base API client
├── types.ts # API response types
├── services/
│ ├── auth.service.ts
│ ├── billing.service.ts
│ ├── subscriptions.service.ts
│ └── index.ts
└── index.ts
// Service interface pattern
interface ApiService<T> {
getAll(params?: QueryParams): Promise<T[]>;
getById(id: string): Promise<T>;
create(data: CreateT): Promise<T>;
update(id: string, data: UpdateT): Promise<T>;
delete(id: string): Promise<void>;
}
```
## Data Models
### Centralized Type Definitions
```typescript
// lib/types/index.ts - Centralized type exports
export * from './api.types';
export * from './auth.types';
export * from './billing.types';
export * from './subscription.types';
export * from './common.types';
// Common base types
interface BaseEntity {
id: string;
createdAt: string;
updatedAt: string;
}
interface PaginatedResponse<T> {
data: T[];
pagination: {
page: number;
limit: number;
total: number;
totalPages: number;
};
}
// Feature-specific type extensions
interface Subscription extends BaseEntity {
userId: string;
planId: string;
status: SubscriptionStatus;
// ... other properties
}
```
### State Management Pattern
```typescript
// Zustand store pattern for each feature
interface FeatureStore {
// State
data: FeatureData[];
loading: boolean;
error: string | null;
// Actions
fetchData: () => Promise<void>;
updateItem: (id: string, data: Partial<FeatureData>) => Promise<void>;
reset: () => void;
}
// React Query integration for server state
const useFeatureQuery = (params?: QueryParams) => {
return useQuery({
queryKey: ['feature', params],
queryFn: () => featureService.getAll(params),
staleTime: 5 * 60 * 1000, // 5 minutes
});
};
```
## Error Handling
### Centralized Error Management
```typescript
// lib/errors/index.ts
export class AppError extends Error {
constructor(
message: string,
public code: string,
public statusCode?: number
) {
super(message);
this.name = 'AppError';
}
}
// Error boundary component
export function ErrorBoundary({ children }: { children: React.ReactNode }) {
// Implementation with error logging and user-friendly fallbacks
}
// API error handling
export function handleApiError(error: unknown): AppError {
if (error instanceof ApiError) {
return new AppError(error.message, error.code, error.status);
}
return new AppError('An unexpected error occurred', 'UNKNOWN_ERROR');
}
```
### Error Display Strategy
```typescript
// Consistent error display components
interface ErrorStateProps {
error: AppError;
onRetry?: () => void;
variant?: 'page' | 'inline' | 'toast';
}
export function ErrorState({ error, onRetry, variant = 'page' }: ErrorStateProps) {
// Render appropriate error UI based on variant
}
```
## Testing Strategy
### Testing Architecture
```typescript
// Test utilities and setup
__tests__/
├── setup.ts # Test environment setup
├── utils/
│ ├── render.tsx # Custom render with providers
│ ├── mocks/ # API and service mocks
│ └── factories/ # Test data factories
└── fixtures/ # Test data fixtures
// Component testing pattern
describe('Button Component', () => {
it('renders with correct variant styles', () => {
render(<Button variant="primary">Click me</Button>);
expect(screen.getByRole('button')).toHaveClass('bg-blue-600');
});
it('handles click events', async () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
await user.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
```
### Integration Testing
```typescript
// Feature integration tests
describe('Dashboard Feature', () => {
beforeEach(() => {
// Setup mocks and test data
mockApiService.dashboard.getSummary.mockResolvedValue(mockDashboardData);
});
it('displays user dashboard with correct data', async () => {
render(<DashboardPage />);
await waitFor(() => {
expect(screen.getByText('Active Subscriptions')).toBeInTheDocument();
expect(screen.getByText('3')).toBeInTheDocument();
});
});
});
```
## Performance Optimization
### Code Splitting Strategy
```typescript
// Feature-based code splitting
const DashboardPage = lazy(() => import('@/features/dashboard/pages/DashboardPage'));
const BillingPage = lazy(() => import('@/features/billing/pages/BillingPage'));
// Component-level splitting for heavy components
const DataVisualization = lazy(() => import('@/components/common/DataVisualization'));
```
### Bundle Optimization
```typescript
// Tree-shakeable exports
// Instead of: export * from './components';
// Use specific exports:
export { Button } from './Button';
export { Input } from './Input';
export type { ButtonProps, InputProps } from './types';
// Dynamic imports for heavy dependencies
const heavyLibrary = await import('heavy-library');
```
### Caching Strategy
```typescript
// React Query configuration
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 60 * 1000, // 5 minutes
gcTime: 10 * 60 * 1000, // 10 minutes
retry: (failureCount, error) => {
if (error.status === 404) return false;
return failureCount < 3;
},
},
},
});
```
## Migration Strategy
### Phase 1: Foundation (Weeks 1-2)
- Set up new folder structure
- Create base UI components (Button, Input, etc.)
- Establish design tokens and styling system
- Set up centralized API client
### Phase 2: Core Features (Weeks 3-4)
- Refactor authentication module
- Migrate dashboard feature
- Consolidate layout components
- Implement error handling system
### Phase 3: Business Features (Weeks 5-6)
- Migrate billing feature
- Refactor subscriptions feature
- Consolidate catalog functionality
- Implement testing framework
### Phase 4: Optimization (Weeks 7-8)
- Performance optimization
- Bundle analysis and splitting
- Documentation and cleanup
- Final testing and validation
## Risk Mitigation
### Backward Compatibility
- Maintain existing API contracts during migration
- Use feature flags for gradual rollout
- Keep old components until migration is complete
### Testing Coverage
- Maintain existing functionality through comprehensive testing
- Implement visual regression testing
- Set up automated testing pipeline
### Performance Monitoring
- Implement bundle size monitoring
- Set up performance metrics tracking
- Monitor Core Web Vitals during migration