feat(phase-4): implement modern Chakra UI frontend with comprehensive tracking interface
🎨 Modern React Frontend: - Complete Chakra UI integration with custom theme and dark/light mode - Responsive design with mobile-first navigation and layout - Beautiful component library with cards, forms, and data visualization - Professional typography and color system with brand consistency 🚀 Advanced URL Tracking Interface: - Comprehensive tracking form with real-time validation using React Hook Form + Zod - Advanced options panel with configurable parameters (max hops, timeout, headers) - SSL, SEO, and security analysis toggles with user-friendly controls - Smart URL normalization and method selection interface 📊 Rich Results Visualization: - Interactive tracking results with hop-by-hop analysis tables - Performance metrics with latency visualization and progress bars - Status badges with color-coded redirect types and HTTP status codes - Comprehensive error handling and user feedback system 🧭 Navigation & Layout: - Responsive navigation bar with user authentication state - Mobile-friendly drawer navigation with touch-optimized interactions - Professional footer with feature highlights and API documentation links - Breadcrumb navigation and page structure for optimal UX 🔐 Authentication Integration: - Complete authentication context with JWT token management - User registration and login flow preparation (backend ready) - Protected routes and role-based access control framework - Session management with automatic token refresh and error handling 🌟 User Experience Features: - Toast notifications for all user actions and API responses - Loading states and skeleton screens for smooth interactions - Copy-to-clipboard functionality for tracking IDs and results - Tooltips and help text for advanced features and configuration 📱 Responsive Design: - Mobile-first design approach with breakpoint-aware components - Touch-friendly interfaces with appropriate sizing and spacing - Optimized layouts for desktop, tablet, and mobile viewports - Accessible design with proper ARIA labels and keyboard navigation 🔧 Developer Experience: - TypeScript throughout with comprehensive type safety - React Query for efficient API state management and caching - Custom hooks for authentication and API interactions - Modular component architecture with clear separation of concerns 🎯 API Integration: - Complete integration with all v2 API endpoints - Real-time health monitoring and status display - Backward compatibility with legacy API endpoints - Comprehensive error handling with user-friendly messages Ready for enhanced dashboard and analysis features in future phases!
This commit is contained in:
152
apps/web/src/contexts/AuthContext.tsx
Normal file
152
apps/web/src/contexts/AuthContext.tsx
Normal file
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* Authentication Context for Redirect Intelligence v2
|
||||
*
|
||||
* Manages user authentication state and API interactions
|
||||
*/
|
||||
|
||||
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { authApi, AuthUser, LoginRequest, RegisterRequest } from '../services/api';
|
||||
|
||||
interface AuthContextType {
|
||||
user: AuthUser | null;
|
||||
isLoading: boolean;
|
||||
isAuthenticated: boolean;
|
||||
login: (credentials: LoginRequest) => Promise<void>;
|
||||
register: (userData: RegisterRequest) => Promise<void>;
|
||||
logout: () => void;
|
||||
refreshUser: () => Promise<void>;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
|
||||
interface AuthProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function AuthProvider({ children }: AuthProviderProps) {
|
||||
const [user, setUser] = useState<AuthUser | null>(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const toast = useToast();
|
||||
|
||||
const isAuthenticated = !!user;
|
||||
|
||||
// Check for existing session on mount
|
||||
useEffect(() => {
|
||||
checkExistingSession();
|
||||
}, []);
|
||||
|
||||
const checkExistingSession = async () => {
|
||||
try {
|
||||
const userData = await authApi.getCurrentUser();
|
||||
setUser(userData);
|
||||
} catch (error) {
|
||||
// No existing session or session expired
|
||||
console.log('No existing session');
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const login = async (credentials: LoginRequest) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await authApi.login(credentials);
|
||||
setUser(response.user);
|
||||
|
||||
toast({
|
||||
title: 'Login successful',
|
||||
description: `Welcome back, ${response.user.name}!`,
|
||||
status: 'success',
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
} catch (error: any) {
|
||||
const message = error.response?.data?.message || 'Login failed';
|
||||
toast({
|
||||
title: 'Login failed',
|
||||
description: message,
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
throw error;
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const register = async (userData: RegisterRequest) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await authApi.register(userData);
|
||||
|
||||
toast({
|
||||
title: 'Registration successful',
|
||||
description: `Welcome, ${response.user.name}! Please log in to continue.`,
|
||||
status: 'success',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
} catch (error: any) {
|
||||
const message = error.response?.data?.message || 'Registration failed';
|
||||
toast({
|
||||
title: 'Registration failed',
|
||||
description: message,
|
||||
status: 'error',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
});
|
||||
throw error;
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
authApi.logout();
|
||||
setUser(null);
|
||||
|
||||
toast({
|
||||
title: 'Logged out',
|
||||
description: 'You have been successfully logged out.',
|
||||
status: 'info',
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
|
||||
const refreshUser = async () => {
|
||||
try {
|
||||
const userData = await authApi.getCurrentUser();
|
||||
setUser(userData);
|
||||
} catch (error) {
|
||||
// Session expired or invalid
|
||||
setUser(null);
|
||||
}
|
||||
};
|
||||
|
||||
const value: AuthContextType = {
|
||||
user,
|
||||
isLoading,
|
||||
isAuthenticated,
|
||||
login,
|
||||
register,
|
||||
logout,
|
||||
refreshUser,
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={value}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useAuth() {
|
||||
const context = useContext(AuthContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useAuth must be used within an AuthProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in New Issue
Block a user