@fluxbase/sdk-react 0.0.1-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/README-ADMIN.md +1076 -0
- package/README.md +178 -0
- package/dist/index.d.mts +606 -0
- package/dist/index.d.ts +606 -0
- package/dist/index.js +992 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +926 -0
- package/dist/index.mjs.map +1 -0
- package/examples/AdminDashboard.tsx +513 -0
- package/examples/README.md +163 -0
- package/package.json +52 -0
- package/src/context.tsx +33 -0
- package/src/index.ts +113 -0
- package/src/use-admin-auth.ts +168 -0
- package/src/use-admin-hooks.ts +309 -0
- package/src/use-api-keys.ts +174 -0
- package/src/use-auth.ts +146 -0
- package/src/use-query.ts +165 -0
- package/src/use-realtime.ts +161 -0
- package/src/use-rpc.ts +109 -0
- package/src/use-storage.ts +257 -0
- package/src/use-users.ts +191 -0
- package/tsconfig.json +24 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/tsup.config.ts +11 -0
- package/typedoc.json +35 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# React Admin Hooks Examples
|
|
2
|
+
|
|
3
|
+
This directory contains complete, production-ready examples demonstrating the Fluxbase React admin hooks.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### AdminDashboard.tsx
|
|
8
|
+
|
|
9
|
+
A complete admin dashboard application demonstrating all admin hooks in action.
|
|
10
|
+
|
|
11
|
+
**Features:**
|
|
12
|
+
- Admin authentication with protected routes
|
|
13
|
+
- User management with pagination and search
|
|
14
|
+
- Real-time statistics dashboard
|
|
15
|
+
- Modern UI with Tailwind CSS
|
|
16
|
+
- Full TypeScript support
|
|
17
|
+
|
|
18
|
+
**Hooks demonstrated:**
|
|
19
|
+
- `useAdminAuth()` - Authentication state management
|
|
20
|
+
- `useUsers()` - User CRUD operations with pagination
|
|
21
|
+
- `useAPIKeys()` - API key management
|
|
22
|
+
- `useWebhooks()` - Webhook configuration
|
|
23
|
+
- `useAppSettings()` - Application settings
|
|
24
|
+
- `useSystemSettings()` - System settings
|
|
25
|
+
|
|
26
|
+
**Run the example:**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
# Install dependencies
|
|
30
|
+
npm install @fluxbase/sdk @fluxbase/sdk-react @tanstack/react-query
|
|
31
|
+
|
|
32
|
+
# Copy AdminDashboard.tsx to your project
|
|
33
|
+
# Add Tailwind CSS to your project (optional, for styling)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Basic usage:**
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { createClient } from '@fluxbase/sdk'
|
|
40
|
+
import { FluxbaseProvider } from '@fluxbase/sdk-react'
|
|
41
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
42
|
+
import AdminDashboard from './AdminDashboard'
|
|
43
|
+
|
|
44
|
+
const client = createClient({ url: 'http://localhost:8080' })
|
|
45
|
+
const queryClient = new QueryClient()
|
|
46
|
+
|
|
47
|
+
function App() {
|
|
48
|
+
return (
|
|
49
|
+
<QueryClientProvider client={queryClient}>
|
|
50
|
+
<FluxbaseProvider client={client}>
|
|
51
|
+
<AdminDashboard />
|
|
52
|
+
</FluxbaseProvider>
|
|
53
|
+
</QueryClientProvider>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Key Patterns
|
|
59
|
+
|
|
60
|
+
### 1. Authentication Flow
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
const { isAuthenticated, isLoading, login, logout } = useAdminAuth({
|
|
64
|
+
autoCheck: true // Automatically check auth status on mount
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
if (isLoading) return <LoadingSpinner />
|
|
68
|
+
if (!isAuthenticated) return <LoginPage />
|
|
69
|
+
return <Dashboard />
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 2. Data Fetching with Pagination
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
const [page, setPage] = useState(0)
|
|
76
|
+
const limit = 20
|
|
77
|
+
|
|
78
|
+
const { users, total, isLoading } = useUsers({
|
|
79
|
+
autoFetch: true,
|
|
80
|
+
limit,
|
|
81
|
+
offset: page * limit
|
|
82
|
+
})
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Search and Filters
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
const [searchEmail, setSearchEmail] = useState('')
|
|
89
|
+
const [roleFilter, setRoleFilter] = useState<'admin' | 'user' | ''>('')
|
|
90
|
+
|
|
91
|
+
const { users, refetch } = useUsers({
|
|
92
|
+
autoFetch: true,
|
|
93
|
+
email: searchEmail || undefined,
|
|
94
|
+
role: roleFilter || undefined
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
// Refetch when filters change
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
refetch()
|
|
100
|
+
}, [searchEmail, roleFilter, refetch])
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4. Optimistic Updates
|
|
104
|
+
|
|
105
|
+
All mutation functions automatically refetch data:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
const { users, inviteUser, deleteUser } = useUsers({ autoFetch: true })
|
|
109
|
+
|
|
110
|
+
// These automatically refetch the user list after success
|
|
111
|
+
await inviteUser('new@example.com', 'user')
|
|
112
|
+
await deleteUser(userId)
|
|
113
|
+
// users state is now updated
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 5. Error Handling
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
const { data, error, isLoading, refetch } = useUsers({ autoFetch: true })
|
|
120
|
+
|
|
121
|
+
if (isLoading) return <LoadingSpinner />
|
|
122
|
+
if (error) return <ErrorMessage error={error} onRetry={refetch} />
|
|
123
|
+
return <DataDisplay data={data} />
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Styling
|
|
127
|
+
|
|
128
|
+
The example uses Tailwind CSS utility classes, but you can easily adapt it to your preferred styling solution:
|
|
129
|
+
|
|
130
|
+
- **CSS Modules**: Replace `className` with module imports
|
|
131
|
+
- **Styled Components**: Replace elements with styled components
|
|
132
|
+
- **Material-UI**: Use MUI components instead of native HTML
|
|
133
|
+
- **Chakra UI**: Use Chakra components for rapid development
|
|
134
|
+
|
|
135
|
+
## TypeScript
|
|
136
|
+
|
|
137
|
+
All examples are fully typed. The hooks provide complete type safety:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import type { EnrichedUser, APIKey, Webhook } from '@fluxbase/sdk-react'
|
|
141
|
+
|
|
142
|
+
const { users }: { users: EnrichedUser[] } = useUsers({ autoFetch: true })
|
|
143
|
+
const { keys }: { keys: APIKey[] } = useAPIKeys({ autoFetch: true })
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Next Steps
|
|
147
|
+
|
|
148
|
+
1. **Customize the UI** - Adapt the styling to match your design system
|
|
149
|
+
2. **Add more features** - Implement API keys, webhooks, and settings tabs
|
|
150
|
+
3. **Add validation** - Add form validation for user inputs
|
|
151
|
+
4. **Add loading states** - Improve loading and error states
|
|
152
|
+
5. **Add notifications** - Show success/error toasts for mutations
|
|
153
|
+
6. **Add search** - Enhance search with debouncing and advanced filters
|
|
154
|
+
|
|
155
|
+
## Documentation
|
|
156
|
+
|
|
157
|
+
- [Complete Admin Hooks Guide](../README-ADMIN.md) - Full API reference and examples
|
|
158
|
+
- [React Hooks Documentation](../../docs/docs/sdks/react-hooks.md) - Core hooks documentation
|
|
159
|
+
- [Admin API Documentation](../../docs/docs/sdk/admin.md) - Admin operations reference
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fluxbase/sdk-react",
|
|
3
|
+
"version": "0.0.1-rc.2",
|
|
4
|
+
"description": "React hooks for Fluxbase SDK",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"dev": "tsup --watch",
|
|
18
|
+
"docs": "typedoc",
|
|
19
|
+
"docs:watch": "typedoc --watch",
|
|
20
|
+
"type-check": "tsc --noEmit",
|
|
21
|
+
"format": "prettier --write src",
|
|
22
|
+
"format:check": "prettier --check src"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"fluxbase",
|
|
26
|
+
"react",
|
|
27
|
+
"hooks",
|
|
28
|
+
"database",
|
|
29
|
+
"realtime"
|
|
30
|
+
],
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/wayli-app/fluxbase"
|
|
34
|
+
},
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@fluxbase/sdk": "^0.1.0",
|
|
40
|
+
"@tanstack/react-query": "^5.0.0",
|
|
41
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@fluxbase/sdk": "file:../sdk",
|
|
45
|
+
"@tanstack/react-query": "^5.62.14",
|
|
46
|
+
"@types/react": "^19.0.0",
|
|
47
|
+
"prettier": "^3.4.2",
|
|
48
|
+
"tsup": "^8.3.5",
|
|
49
|
+
"typedoc": "^0.28.14",
|
|
50
|
+
"typescript": "^5.7.3"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/context.tsx
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React context for Fluxbase client
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createContext, useContext, type ReactNode } from 'react'
|
|
6
|
+
import type { FluxbaseClient } from '@fluxbase/sdk'
|
|
7
|
+
|
|
8
|
+
const FluxbaseContext = createContext<FluxbaseClient | null>(null)
|
|
9
|
+
|
|
10
|
+
export interface FluxbaseProviderProps {
|
|
11
|
+
client: FluxbaseClient
|
|
12
|
+
children: ReactNode
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Provider component to make Fluxbase client available throughout the app
|
|
17
|
+
*/
|
|
18
|
+
export function FluxbaseProvider({ client, children }: FluxbaseProviderProps) {
|
|
19
|
+
return <FluxbaseContext.Provider value={client}>{children}</FluxbaseContext.Provider>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Hook to access the Fluxbase client from context
|
|
24
|
+
*/
|
|
25
|
+
export function useFluxbaseClient(): FluxbaseClient {
|
|
26
|
+
const client = useContext(FluxbaseContext)
|
|
27
|
+
|
|
28
|
+
if (!client) {
|
|
29
|
+
throw new Error('useFluxbaseClient must be used within a FluxbaseProvider')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return client
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fluxbase React Hooks
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```tsx
|
|
6
|
+
* import { createClient } from '@fluxbase/sdk'
|
|
7
|
+
* import { FluxbaseProvider, useAuth, useTable } from '@fluxbase/sdk-react'
|
|
8
|
+
* import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
9
|
+
*
|
|
10
|
+
* const client = createClient({ url: 'http://localhost:8080' })
|
|
11
|
+
* const queryClient = new QueryClient()
|
|
12
|
+
*
|
|
13
|
+
* function App() {
|
|
14
|
+
* return (
|
|
15
|
+
* <QueryClientProvider client={queryClient}>
|
|
16
|
+
* <FluxbaseProvider client={client}>
|
|
17
|
+
* <MyComponent />
|
|
18
|
+
* </FluxbaseProvider>
|
|
19
|
+
* </QueryClientProvider>
|
|
20
|
+
* )
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* function MyComponent() {
|
|
24
|
+
* const { user, signIn, signOut } = useAuth()
|
|
25
|
+
* const { data: products } = useTable('products', (q) => q.select('*').eq('active', true))
|
|
26
|
+
*
|
|
27
|
+
* return <div>...</div>
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
// Context and provider
|
|
33
|
+
export { FluxbaseProvider, useFluxbaseClient } from './context'
|
|
34
|
+
|
|
35
|
+
// Auth hooks
|
|
36
|
+
export {
|
|
37
|
+
useAuth,
|
|
38
|
+
useUser,
|
|
39
|
+
useSession,
|
|
40
|
+
useSignIn,
|
|
41
|
+
useSignUp,
|
|
42
|
+
useSignOut,
|
|
43
|
+
useUpdateUser,
|
|
44
|
+
} from './use-auth'
|
|
45
|
+
|
|
46
|
+
// Database query hooks
|
|
47
|
+
export {
|
|
48
|
+
useFluxbaseQuery,
|
|
49
|
+
useTable,
|
|
50
|
+
useInsert,
|
|
51
|
+
useUpdate,
|
|
52
|
+
useUpsert,
|
|
53
|
+
useDelete,
|
|
54
|
+
} from './use-query'
|
|
55
|
+
|
|
56
|
+
// Realtime hooks
|
|
57
|
+
export {
|
|
58
|
+
useRealtime,
|
|
59
|
+
useTableSubscription,
|
|
60
|
+
useTableInserts,
|
|
61
|
+
useTableUpdates,
|
|
62
|
+
useTableDeletes,
|
|
63
|
+
} from './use-realtime'
|
|
64
|
+
|
|
65
|
+
// Storage hooks
|
|
66
|
+
export {
|
|
67
|
+
useStorageList,
|
|
68
|
+
useStorageUpload,
|
|
69
|
+
useStorageDownload,
|
|
70
|
+
useStorageDelete,
|
|
71
|
+
useStoragePublicUrl,
|
|
72
|
+
useStorageSignedUrl,
|
|
73
|
+
useStorageMove,
|
|
74
|
+
useStorageCopy,
|
|
75
|
+
useStorageBuckets,
|
|
76
|
+
useCreateBucket,
|
|
77
|
+
useDeleteBucket,
|
|
78
|
+
} from './use-storage'
|
|
79
|
+
|
|
80
|
+
// RPC hooks
|
|
81
|
+
export {
|
|
82
|
+
useRPC,
|
|
83
|
+
useRPCMutation,
|
|
84
|
+
useRPCBatch,
|
|
85
|
+
} from './use-rpc'
|
|
86
|
+
|
|
87
|
+
// Admin hooks
|
|
88
|
+
export { useAdminAuth } from './use-admin-auth'
|
|
89
|
+
export { useUsers } from './use-users'
|
|
90
|
+
export { useAPIKeys } from './use-api-keys'
|
|
91
|
+
export {
|
|
92
|
+
useWebhooks,
|
|
93
|
+
useAppSettings,
|
|
94
|
+
useSystemSettings,
|
|
95
|
+
} from './use-admin-hooks'
|
|
96
|
+
|
|
97
|
+
// Re-export types from SDK
|
|
98
|
+
export type {
|
|
99
|
+
FluxbaseClient,
|
|
100
|
+
AuthSession,
|
|
101
|
+
User,
|
|
102
|
+
SignInCredentials,
|
|
103
|
+
SignUpCredentials,
|
|
104
|
+
PostgrestResponse,
|
|
105
|
+
RealtimeChangePayload,
|
|
106
|
+
StorageObject,
|
|
107
|
+
AdminUser,
|
|
108
|
+
EnrichedUser,
|
|
109
|
+
APIKey,
|
|
110
|
+
Webhook,
|
|
111
|
+
AppSettings,
|
|
112
|
+
SystemSetting,
|
|
113
|
+
} from '@fluxbase/sdk'
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react'
|
|
2
|
+
import { useFluxbaseClient } from './context'
|
|
3
|
+
import type { AdminAuthResponse } from '@fluxbase/sdk'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Simplified admin user type returned by authentication
|
|
7
|
+
*/
|
|
8
|
+
export interface AdminUser {
|
|
9
|
+
id: string
|
|
10
|
+
email: string
|
|
11
|
+
role: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface UseAdminAuthOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Automatically check authentication status on mount
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
19
|
+
autoCheck?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UseAdminAuthReturn {
|
|
23
|
+
/**
|
|
24
|
+
* Current admin user if authenticated
|
|
25
|
+
*/
|
|
26
|
+
user: AdminUser | null
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Whether the admin is authenticated
|
|
30
|
+
*/
|
|
31
|
+
isAuthenticated: boolean
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Whether the authentication check is in progress
|
|
35
|
+
*/
|
|
36
|
+
isLoading: boolean
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Any error that occurred during authentication
|
|
40
|
+
*/
|
|
41
|
+
error: Error | null
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Login as admin
|
|
45
|
+
*/
|
|
46
|
+
login: (email: string, password: string) => Promise<AdminAuthResponse>
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Logout admin
|
|
50
|
+
*/
|
|
51
|
+
logout: () => Promise<void>
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Refresh admin user info
|
|
55
|
+
*/
|
|
56
|
+
refresh: () => Promise<void>
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Hook for admin authentication
|
|
61
|
+
*
|
|
62
|
+
* Manages admin login state, authentication checks, and user info.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```tsx
|
|
66
|
+
* function AdminLogin() {
|
|
67
|
+
* const { user, isAuthenticated, isLoading, login, logout } = useAdminAuth()
|
|
68
|
+
*
|
|
69
|
+
* const handleLogin = async (e: React.FormEvent) => {
|
|
70
|
+
* e.preventDefault()
|
|
71
|
+
* await login(email, password)
|
|
72
|
+
* }
|
|
73
|
+
*
|
|
74
|
+
* if (isLoading) return <div>Loading...</div>
|
|
75
|
+
* if (isAuthenticated) return <div>Welcome {user?.email}</div>
|
|
76
|
+
*
|
|
77
|
+
* return <form onSubmit={handleLogin}>...</form>
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function useAdminAuth(options: UseAdminAuthOptions = {}): UseAdminAuthReturn {
|
|
82
|
+
const { autoCheck = true } = options
|
|
83
|
+
const client = useFluxbaseClient()
|
|
84
|
+
|
|
85
|
+
const [user, setUser] = useState<AdminUser | null>(null)
|
|
86
|
+
const [isLoading, setIsLoading] = useState(autoCheck)
|
|
87
|
+
const [error, setError] = useState<Error | null>(null)
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Check current authentication status
|
|
91
|
+
*/
|
|
92
|
+
const checkAuth = useCallback(async () => {
|
|
93
|
+
try {
|
|
94
|
+
setIsLoading(true)
|
|
95
|
+
setError(null)
|
|
96
|
+
const { user } = await client.admin.me()
|
|
97
|
+
setUser(user)
|
|
98
|
+
} catch (err) {
|
|
99
|
+
setUser(null)
|
|
100
|
+
setError(err as Error)
|
|
101
|
+
} finally {
|
|
102
|
+
setIsLoading(false)
|
|
103
|
+
}
|
|
104
|
+
}, [client])
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Login as admin
|
|
108
|
+
*/
|
|
109
|
+
const login = useCallback(
|
|
110
|
+
async (email: string, password: string): Promise<AdminAuthResponse> => {
|
|
111
|
+
try {
|
|
112
|
+
setIsLoading(true)
|
|
113
|
+
setError(null)
|
|
114
|
+
const response = await client.admin.login({ email, password })
|
|
115
|
+
setUser(response.user)
|
|
116
|
+
return response
|
|
117
|
+
} catch (err) {
|
|
118
|
+
setError(err as Error)
|
|
119
|
+
throw err
|
|
120
|
+
} finally {
|
|
121
|
+
setIsLoading(false)
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
[client]
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Logout admin
|
|
129
|
+
*/
|
|
130
|
+
const logout = useCallback(async (): Promise<void> => {
|
|
131
|
+
try {
|
|
132
|
+
setIsLoading(true)
|
|
133
|
+
setError(null)
|
|
134
|
+
// Clear user state
|
|
135
|
+
setUser(null)
|
|
136
|
+
// Note: Add logout endpoint call here when available
|
|
137
|
+
} catch (err) {
|
|
138
|
+
setError(err as Error)
|
|
139
|
+
throw err
|
|
140
|
+
} finally {
|
|
141
|
+
setIsLoading(false)
|
|
142
|
+
}
|
|
143
|
+
}, [])
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Refresh admin user info
|
|
147
|
+
*/
|
|
148
|
+
const refresh = useCallback(async (): Promise<void> => {
|
|
149
|
+
await checkAuth()
|
|
150
|
+
}, [checkAuth])
|
|
151
|
+
|
|
152
|
+
// Auto-check authentication on mount
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
if (autoCheck) {
|
|
155
|
+
checkAuth()
|
|
156
|
+
}
|
|
157
|
+
}, [autoCheck, checkAuth])
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
user,
|
|
161
|
+
isAuthenticated: user !== null,
|
|
162
|
+
isLoading,
|
|
163
|
+
error,
|
|
164
|
+
login,
|
|
165
|
+
logout,
|
|
166
|
+
refresh
|
|
167
|
+
}
|
|
168
|
+
}
|