morethanadiagnosis-hub/web/lib/hooks/useApi.ts
Claude 9232ebe294
feat(web): complete Phase 1 - foundation components, layouts, and hooks
Implemented complete design system and foundational infrastructure:

**Design System Components:**
- Button (all variants: primary, secondary, ghost, danger)
- Input & Textarea (with validation and error states)
- Card (elevated, outlined, flat variants)
- Modal/Dialog (with focus trap and accessibility)
- Avatar (with fallback initials)
- Badge (all color variants)
- Form helpers (FormField, Checkbox, Select)
- Link component with Next.js integration
- Navigation (Header, Footer with responsive design)

**Layouts:**
- MainLayout (with Header/Footer for public pages)
- AuthLayout (minimal layout for auth flows)
- DashboardLayout (with sidebar navigation)

**Hooks & Utilities:**
- useAuth() - authentication state management
- useApi() - API calls with loading/error states
- useLocalStorage() - persistent state management
- apiClient - Axios instance with token refresh
- authStore - Zustand store for auth state

**Configuration:**
- Tailwind config with design tokens
- Dark mode support via CSS variables
- Global styles with accessibility focus
- WCAG 2.2 AA+ compliant focus indicators

All components follow accessibility best practices with proper ARIA labels,
keyboard navigation, and screen reader support.

Job ID: MTAD-IMPL-2025-11-18-CL
2025-11-18 01:02:05 +00:00

73 lines
1.6 KiB
TypeScript

'use client'
import { useState, useCallback } from 'react'
import { AxiosError, AxiosRequestConfig } from 'axios'
import { apiClient } from '../api'
export interface UseApiOptions {
onSuccess?: (data: any) => void
onError?: (error: Error) => void
}
export interface UseApiReturn<T> {
data: T | null
error: Error | null
isLoading: boolean
execute: (config: AxiosRequestConfig) => Promise<T | null>
reset: () => void
}
export function useApi<T = any>(options?: UseApiOptions): UseApiReturn<T> {
const [data, setData] = useState<T | null>(null)
const [error, setError] = useState<Error | null>(null)
const [isLoading, setIsLoading] = useState(false)
const execute = useCallback(
async (config: AxiosRequestConfig): Promise<T | null> => {
setIsLoading(true)
setError(null)
try {
const response = await apiClient.request<T>(config)
setData(response.data)
if (options?.onSuccess) {
options.onSuccess(response.data)
}
return response.data
} catch (err) {
const error = err as AxiosError
const errorMessage = error.response?.data
? JSON.stringify(error.response.data)
: error.message
const finalError = new Error(errorMessage)
setError(finalError)
if (options?.onError) {
options.onError(finalError)
}
return null
} finally {
setIsLoading(false)
}
},
[options]
)
const reset = useCallback(() => {
setData(null)
setError(null)
setIsLoading(false)
}, [])
return {
data,
error,
isLoading,
execute,
reset,
}
}