Implemented comprehensive JWT-based authentication with token refresh mechanism, user state management, and protected routes. Changes: - Upgraded API client from fetch to Axios with automatic token refresh interceptors - Created API configuration with centralized endpoint definitions - Implemented Zustand auth store for user state management with persistence - Created React Query hooks for login, register, logout, and current user - Built login and registration pages with form validation (Zod + React Hook Form) - Implemented AuthGuard component for route protection - Enhanced Header with user dropdown menu and logout functionality - Updated Sidebar with user information display at bottom - Added Team navigation item to sidebar - Configured environment variables for API base URL Technical Details: - JWT token storage in localStorage with secure key names - Automatic token refresh on 401 responses - Request queueing during token refresh to prevent race conditions - TypeScript strict typing throughout - ESLint compliant code (fixed type safety issues) - Proper error handling with user-friendly messages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
46 lines
1.0 KiB
TypeScript
46 lines
1.0 KiB
TypeScript
import { create } from 'zustand';
|
|
import { persist } from 'zustand/middleware';
|
|
|
|
export interface User {
|
|
id: string;
|
|
email: string;
|
|
fullName: string;
|
|
tenantId: string;
|
|
tenantName: string;
|
|
role: 'TenantOwner' | 'TenantAdmin' | 'TenantMember' | 'TenantGuest';
|
|
isEmailVerified: boolean;
|
|
}
|
|
|
|
interface AuthState {
|
|
user: User | null;
|
|
isAuthenticated: boolean;
|
|
isLoading: boolean;
|
|
|
|
setUser: (user: User) => void;
|
|
clearUser: () => void;
|
|
setLoading: (loading: boolean) => void;
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>()(
|
|
persist(
|
|
(set) => ({
|
|
user: null,
|
|
isAuthenticated: false,
|
|
isLoading: true,
|
|
|
|
setUser: (user) =>
|
|
set({ user, isAuthenticated: true, isLoading: false }),
|
|
clearUser: () =>
|
|
set({ user: null, isAuthenticated: false, isLoading: false }),
|
|
setLoading: (loading) => set({ isLoading: loading }),
|
|
}),
|
|
{
|
|
name: 'colaflow-auth',
|
|
partialize: (state) => ({
|
|
user: state.user,
|
|
isAuthenticated: state.isAuthenticated,
|
|
}),
|
|
}
|
|
)
|
|
);
|