@foxpixel/react 0.1.0
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/README.md +216 -0
- package/dist/index.d.mts +408 -0
- package/dist/index.d.ts +408 -0
- package/dist/index.js +495 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +448 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +39 -0
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# @foxpixel/react
|
|
2
|
+
|
|
3
|
+
React SDK for FoxPixel API - Headless integration for custom sites and portals.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @foxpixel/react
|
|
9
|
+
# or
|
|
10
|
+
yarn add @foxpixel/react
|
|
11
|
+
# or
|
|
12
|
+
pnpm add @foxpixel/react
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### 1. Wrap your app with FoxPixelProvider
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
// app.tsx or _app.tsx
|
|
21
|
+
import { FoxPixelProvider } from '@foxpixel/react';
|
|
22
|
+
|
|
23
|
+
function App() {
|
|
24
|
+
return (
|
|
25
|
+
<FoxPixelProvider>
|
|
26
|
+
<YourApp />
|
|
27
|
+
</FoxPixelProvider>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 2. Use hooks in your components
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import { useServices } from '@foxpixel/react';
|
|
36
|
+
|
|
37
|
+
function ServicesPage() {
|
|
38
|
+
const { services, isLoading, error } = useServices({ active: true });
|
|
39
|
+
|
|
40
|
+
if (isLoading) return <div>Loading...</div>;
|
|
41
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
{services?.map(service => (
|
|
46
|
+
<div key={service.id}>
|
|
47
|
+
<h3>{service.name}</h3>
|
|
48
|
+
<p>{service.description}</p>
|
|
49
|
+
</div>
|
|
50
|
+
))}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
### Environment Variables
|
|
59
|
+
|
|
60
|
+
```env
|
|
61
|
+
# Client-side (public)
|
|
62
|
+
NEXT_PUBLIC_FOXPIXEL_API_URL=https://api.foxpixel.com
|
|
63
|
+
|
|
64
|
+
# Server-side only (NEVER expose in client)
|
|
65
|
+
FOXPIXEL_API_KEY=sk_live_your_key_here
|
|
66
|
+
FOXPIXEL_TENANT_ID=your_tenant_id_here
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Provider Configuration
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
<FoxPixelProvider
|
|
73
|
+
config={{
|
|
74
|
+
apiUrl: 'https://api.foxpixel.com',
|
|
75
|
+
// apiKey: Only use server-side (via proxy)
|
|
76
|
+
// tenantId: Optional, can be set per request
|
|
77
|
+
}}
|
|
78
|
+
>
|
|
79
|
+
<App />
|
|
80
|
+
</FoxPixelProvider>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Security: Server-Side Proxy
|
|
84
|
+
|
|
85
|
+
**IMPORTANT:** API Keys should NEVER be exposed in client-side code.
|
|
86
|
+
|
|
87
|
+
Use Next.js API routes to proxy requests:
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
// pages/api/foxpixel/[...path].ts
|
|
91
|
+
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
92
|
+
|
|
93
|
+
export default async function handler(
|
|
94
|
+
req: NextApiRequest,
|
|
95
|
+
res: NextApiResponse
|
|
96
|
+
) {
|
|
97
|
+
const apiKey = process.env.FOXPIXEL_API_KEY;
|
|
98
|
+
const apiUrl = process.env.NEXT_PUBLIC_FOXPIXEL_API_URL;
|
|
99
|
+
|
|
100
|
+
// Proxy request with API Key
|
|
101
|
+
const response = await fetch(`${apiUrl}${req.url}`, {
|
|
102
|
+
method: req.method,
|
|
103
|
+
headers: {
|
|
104
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
105
|
+
'Content-Type': 'application/json',
|
|
106
|
+
},
|
|
107
|
+
body: req.method !== 'GET' ? JSON.stringify(req.body) : undefined,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const data = await response.json();
|
|
111
|
+
res.status(response.status).json(data);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Then configure SDK to use proxy:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
<FoxPixelProvider
|
|
119
|
+
config={{
|
|
120
|
+
apiUrl: '/api/foxpixel', // Use proxy instead of direct API
|
|
121
|
+
}}
|
|
122
|
+
>
|
|
123
|
+
<App />
|
|
124
|
+
</FoxPixelProvider>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Hooks
|
|
128
|
+
|
|
129
|
+
### `useServices(options?)`
|
|
130
|
+
|
|
131
|
+
Fetch services from Projects module.
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
const { services, isLoading, error, refetch } = useServices({
|
|
135
|
+
category: 'pools',
|
|
136
|
+
active: true,
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `useLeadCapture()`
|
|
141
|
+
|
|
142
|
+
Capture leads (create lead in CRM).
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
const { captureLead, isLoading, error } = useLeadCapture();
|
|
146
|
+
|
|
147
|
+
await captureLead({
|
|
148
|
+
fullName: 'John Doe',
|
|
149
|
+
email: 'john@example.com',
|
|
150
|
+
phone: '+1234567890',
|
|
151
|
+
source: 'website',
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### `useAuth()`
|
|
156
|
+
|
|
157
|
+
Authenticate End Users (clients of your tenant).
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
const { user, isAuthenticated, login, logout, isLoading } = useAuth();
|
|
161
|
+
|
|
162
|
+
// Login
|
|
163
|
+
await login({
|
|
164
|
+
email: 'user@example.com',
|
|
165
|
+
password: 'password123',
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Logout
|
|
169
|
+
await logout();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## End User Authentication
|
|
173
|
+
|
|
174
|
+
End Users are authenticated via httpOnly cookies (secure, XSS-resistant).
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
function LoginPage() {
|
|
178
|
+
const { login, isLoading, error } = useAuth();
|
|
179
|
+
|
|
180
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
181
|
+
e.preventDefault();
|
|
182
|
+
try {
|
|
183
|
+
await login({
|
|
184
|
+
email: e.target.email.value,
|
|
185
|
+
password: e.target.password.value,
|
|
186
|
+
});
|
|
187
|
+
router.push('/dashboard');
|
|
188
|
+
} catch (err) {
|
|
189
|
+
console.error('Login failed:', err);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
return (
|
|
194
|
+
<form onSubmit={handleSubmit}>
|
|
195
|
+
<input name="email" type="email" required />
|
|
196
|
+
<input name="password" type="password" required />
|
|
197
|
+
<button type="submit" disabled={isLoading}>
|
|
198
|
+
{isLoading ? 'Logging in...' : 'Login'}
|
|
199
|
+
</button>
|
|
200
|
+
{error && <div>{error.message}</div>}
|
|
201
|
+
</form>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## TypeScript
|
|
207
|
+
|
|
208
|
+
Full TypeScript support with exported types:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
import type { Service, Lead, EndUser } from '@foxpixel/react';
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## License
|
|
215
|
+
|
|
216
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode, ComponentType } from 'react';
|
|
3
|
+
import { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Core types for FoxPixel React SDK
|
|
7
|
+
*/
|
|
8
|
+
interface FoxPixelConfig {
|
|
9
|
+
/**
|
|
10
|
+
* Base URL of the FoxPixel API
|
|
11
|
+
* Default: process.env.NEXT_PUBLIC_FOXPIXEL_API_URL
|
|
12
|
+
*/
|
|
13
|
+
apiUrl?: string;
|
|
14
|
+
/**
|
|
15
|
+
* API Key for authentication (server-side only)
|
|
16
|
+
* NEVER expose this in client-side code
|
|
17
|
+
* Default: process.env.FOXPIXEL_API_KEY
|
|
18
|
+
*/
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Tenant ID (optional, can be set per request)
|
|
22
|
+
*/
|
|
23
|
+
tenantId?: string;
|
|
24
|
+
}
|
|
25
|
+
interface Service {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
category?: string;
|
|
30
|
+
price?: number;
|
|
31
|
+
active: boolean;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
}
|
|
35
|
+
interface ServiceCatalogResponse {
|
|
36
|
+
id: string;
|
|
37
|
+
tenantId: string;
|
|
38
|
+
name: string;
|
|
39
|
+
description?: string;
|
|
40
|
+
unitPrice: number;
|
|
41
|
+
unitType: string;
|
|
42
|
+
currency: string;
|
|
43
|
+
category?: string;
|
|
44
|
+
isActive: boolean;
|
|
45
|
+
version: number;
|
|
46
|
+
createdAt: string;
|
|
47
|
+
updatedAt: string;
|
|
48
|
+
}
|
|
49
|
+
interface Lead {
|
|
50
|
+
id: string;
|
|
51
|
+
fullName: string;
|
|
52
|
+
email: string;
|
|
53
|
+
phone?: string;
|
|
54
|
+
source?: string;
|
|
55
|
+
status: string;
|
|
56
|
+
createdAt: string;
|
|
57
|
+
}
|
|
58
|
+
interface CreateLeadRequest {
|
|
59
|
+
fullName: string;
|
|
60
|
+
email?: string;
|
|
61
|
+
phone?: string;
|
|
62
|
+
source?: string;
|
|
63
|
+
notes?: string;
|
|
64
|
+
}
|
|
65
|
+
interface EndUser {
|
|
66
|
+
id: string;
|
|
67
|
+
email: string;
|
|
68
|
+
fullName?: string;
|
|
69
|
+
phone?: string;
|
|
70
|
+
tenantId: string;
|
|
71
|
+
subscriptionStatus: 'trial' | 'active' | 'inactive' | 'cancelled';
|
|
72
|
+
trialEndsAt?: string;
|
|
73
|
+
hasAccess: boolean;
|
|
74
|
+
[key: string]: any;
|
|
75
|
+
}
|
|
76
|
+
interface EndUserLoginRequest {
|
|
77
|
+
email: string;
|
|
78
|
+
password: string;
|
|
79
|
+
}
|
|
80
|
+
interface ApiError$1 {
|
|
81
|
+
message: string;
|
|
82
|
+
code?: string;
|
|
83
|
+
status?: number;
|
|
84
|
+
expected?: boolean;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* HTTP client for FoxPixel API
|
|
89
|
+
* Handles authentication and request/response transformation
|
|
90
|
+
*/
|
|
91
|
+
|
|
92
|
+
declare class FoxPixelHttpClient {
|
|
93
|
+
private client;
|
|
94
|
+
private apiKey?;
|
|
95
|
+
private tenantId?;
|
|
96
|
+
private endUserToken?;
|
|
97
|
+
constructor(config: FoxPixelConfig);
|
|
98
|
+
/**
|
|
99
|
+
* Set API Key (server-side only)
|
|
100
|
+
*/
|
|
101
|
+
setApiKey(apiKey: string): void;
|
|
102
|
+
/**
|
|
103
|
+
* Set tenant ID
|
|
104
|
+
*/
|
|
105
|
+
setTenantId(tenantId: string): void;
|
|
106
|
+
/**
|
|
107
|
+
* Set end user token (for client-side auth)
|
|
108
|
+
* Note: In practice, end user auth uses httpOnly cookies
|
|
109
|
+
*/
|
|
110
|
+
setEndUserToken(token: string): void;
|
|
111
|
+
/**
|
|
112
|
+
* Clear end user token (logout)
|
|
113
|
+
*/
|
|
114
|
+
clearEndUserToken(): void;
|
|
115
|
+
/**
|
|
116
|
+
* Get underlying axios instance
|
|
117
|
+
*/
|
|
118
|
+
getInstance(): AxiosInstance;
|
|
119
|
+
/**
|
|
120
|
+
* Make GET request
|
|
121
|
+
*/
|
|
122
|
+
get<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
|
|
123
|
+
/**
|
|
124
|
+
* Make POST request
|
|
125
|
+
*/
|
|
126
|
+
post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
|
|
127
|
+
/**
|
|
128
|
+
* Make PUT request
|
|
129
|
+
*/
|
|
130
|
+
put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
|
|
131
|
+
/**
|
|
132
|
+
* Make DELETE request
|
|
133
|
+
*/
|
|
134
|
+
delete<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface FoxPixelContextValue {
|
|
138
|
+
client: FoxPixelHttpClient;
|
|
139
|
+
config: FoxPixelConfig;
|
|
140
|
+
}
|
|
141
|
+
interface FoxPixelProviderProps {
|
|
142
|
+
children: ReactNode;
|
|
143
|
+
config?: FoxPixelConfig;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* FoxPixelProvider - Wraps your app and provides SDK functionality
|
|
147
|
+
*
|
|
148
|
+
* IMPORTANT: API Key should NEVER be passed from client-side.
|
|
149
|
+
* Use server-side proxy (Next.js API routes) for API Key authentication.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```tsx
|
|
153
|
+
* // Client-side (no API Key)
|
|
154
|
+
* <FoxPixelProvider>
|
|
155
|
+
* <App />
|
|
156
|
+
* </FoxPixelProvider>
|
|
157
|
+
*
|
|
158
|
+
* // Server-side proxy (Next.js API route)
|
|
159
|
+
* // pages/api/foxpixel/[...path].ts
|
|
160
|
+
* export default async function handler(req, res) {
|
|
161
|
+
* const apiKey = process.env.FOXPIXEL_API_KEY;
|
|
162
|
+
* // Proxy request with API Key
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
declare function FoxPixelProvider({ children, config }: FoxPixelProviderProps): react_jsx_runtime.JSX.Element;
|
|
167
|
+
/**
|
|
168
|
+
* Hook to access FoxPixel context
|
|
169
|
+
* @throws Error if used outside FoxPixelProvider
|
|
170
|
+
*/
|
|
171
|
+
declare function useFoxPixelContext(): FoxPixelContextValue;
|
|
172
|
+
|
|
173
|
+
interface AuthContextValue {
|
|
174
|
+
user: EndUser | null;
|
|
175
|
+
isLoading: boolean;
|
|
176
|
+
isAuthenticated: boolean;
|
|
177
|
+
error: ApiError$1 | null;
|
|
178
|
+
login: (credentials: EndUserLoginRequest) => Promise<void>;
|
|
179
|
+
logout: () => Promise<void>;
|
|
180
|
+
register: (data: {
|
|
181
|
+
email: string;
|
|
182
|
+
password: string;
|
|
183
|
+
fullName: string;
|
|
184
|
+
phone?: string;
|
|
185
|
+
}) => Promise<void>;
|
|
186
|
+
updateProfile: (data: {
|
|
187
|
+
fullName?: string;
|
|
188
|
+
phone?: string;
|
|
189
|
+
}) => Promise<void>;
|
|
190
|
+
refetch: () => Promise<void>;
|
|
191
|
+
}
|
|
192
|
+
interface AuthProviderProps {
|
|
193
|
+
children: ReactNode;
|
|
194
|
+
/**
|
|
195
|
+
* Redirect path when user is not authenticated
|
|
196
|
+
* Default: '/login'
|
|
197
|
+
*/
|
|
198
|
+
loginPath?: string;
|
|
199
|
+
/**
|
|
200
|
+
* Redirect path after successful login
|
|
201
|
+
* Default: '/account'
|
|
202
|
+
*/
|
|
203
|
+
accountPath?: string;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* AuthProvider - Manages authentication state globally
|
|
207
|
+
*
|
|
208
|
+
* Automatically:
|
|
209
|
+
* - Restores session on mount (checks httpOnly cookie)
|
|
210
|
+
* - Manages user state across the app
|
|
211
|
+
* - Handles login/logout transparently
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```tsx
|
|
215
|
+
* // In _app.tsx
|
|
216
|
+
* <FoxPixelProvider>
|
|
217
|
+
* <AuthProvider>
|
|
218
|
+
* <Component {...pageProps} />
|
|
219
|
+
* </AuthProvider>
|
|
220
|
+
* </FoxPixelProvider>
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
declare function AuthProvider({ children, loginPath, accountPath }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
224
|
+
/**
|
|
225
|
+
* Hook to access authentication context
|
|
226
|
+
* @throws Error if used outside AuthProvider
|
|
227
|
+
*/
|
|
228
|
+
declare function useAuth(): AuthContextValue;
|
|
229
|
+
|
|
230
|
+
interface ProtectedRouteProps {
|
|
231
|
+
children: ReactNode;
|
|
232
|
+
/**
|
|
233
|
+
* Redirect path when not authenticated
|
|
234
|
+
* Default: '/login'
|
|
235
|
+
*/
|
|
236
|
+
loginPath?: string;
|
|
237
|
+
/**
|
|
238
|
+
* Show loading spinner while checking auth
|
|
239
|
+
*/
|
|
240
|
+
loadingComponent?: ReactNode;
|
|
241
|
+
}
|
|
242
|
+
declare function ProtectedRoute({ children, loginPath, loadingComponent, }: ProtectedRouteProps): string | number | true | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null;
|
|
243
|
+
|
|
244
|
+
interface GuestOnlyRouteProps {
|
|
245
|
+
children: ReactNode;
|
|
246
|
+
/**
|
|
247
|
+
* Where to redirect when already authenticated.
|
|
248
|
+
* Default: '/account'
|
|
249
|
+
*/
|
|
250
|
+
redirectTo?: string;
|
|
251
|
+
/**
|
|
252
|
+
* Show this while checking auth or redirecting.
|
|
253
|
+
*/
|
|
254
|
+
loadingComponent?: ReactNode;
|
|
255
|
+
}
|
|
256
|
+
declare function GuestOnlyRoute({ children, redirectTo, loadingComponent, }: GuestOnlyRouteProps): string | number | true | Iterable<ReactNode> | react_jsx_runtime.JSX.Element;
|
|
257
|
+
|
|
258
|
+
interface WithAuthOptions {
|
|
259
|
+
loginPath?: string;
|
|
260
|
+
loadingComponent?: ReactNode;
|
|
261
|
+
}
|
|
262
|
+
declare function withAuth<P extends object>(Component: ComponentType<P>, options?: WithAuthOptions): (props: P) => string | number | true | Iterable<ReactNode> | react_jsx_runtime.JSX.Element | null;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Hook to fetch and manage services (Projects module)
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
interface UseServicesOptions {
|
|
269
|
+
category?: string;
|
|
270
|
+
active?: boolean;
|
|
271
|
+
}
|
|
272
|
+
interface UseServicesReturn {
|
|
273
|
+
services: ServiceCatalogResponse[] | null;
|
|
274
|
+
isLoading: boolean;
|
|
275
|
+
error: ApiError$1 | null;
|
|
276
|
+
refetch: () => Promise<void>;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Fetch services from Projects module
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```tsx
|
|
283
|
+
* function ServicesPage() {
|
|
284
|
+
* const { services, isLoading, error } = useServices({ active: true });
|
|
285
|
+
*
|
|
286
|
+
* if (isLoading) return <div>Loading...</div>;
|
|
287
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
288
|
+
*
|
|
289
|
+
* return (
|
|
290
|
+
* <div>
|
|
291
|
+
* {services?.map(service => (
|
|
292
|
+
* <ServiceCard key={service.id} service={service} />
|
|
293
|
+
* ))}
|
|
294
|
+
* </div>
|
|
295
|
+
* );
|
|
296
|
+
* }
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
declare function useServices(options?: UseServicesOptions): UseServicesReturn;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Hook to capture leads (CRM module)
|
|
303
|
+
*/
|
|
304
|
+
|
|
305
|
+
interface UseLeadCaptureReturn {
|
|
306
|
+
captureLead: (data: CreateLeadRequest) => Promise<Lead>;
|
|
307
|
+
isLoading: boolean;
|
|
308
|
+
error: ApiError$1 | null;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Capture a lead (create lead in CRM)
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```tsx
|
|
315
|
+
* function ContactForm() {
|
|
316
|
+
* const { captureLead, isLoading, error } = useLeadCapture();
|
|
317
|
+
*
|
|
318
|
+
* const handleSubmit = async (e) => {
|
|
319
|
+
* e.preventDefault();
|
|
320
|
+
* try {
|
|
321
|
+
* const lead = await captureLead({
|
|
322
|
+
* fullName: 'John Doe',
|
|
323
|
+
* email: 'john@example.com',
|
|
324
|
+
* phone: '+1234567890',
|
|
325
|
+
* source: 'website',
|
|
326
|
+
* });
|
|
327
|
+
* alert('Lead created!');
|
|
328
|
+
* } catch (err) {
|
|
329
|
+
* console.error('Error:', err);
|
|
330
|
+
* }
|
|
331
|
+
* };
|
|
332
|
+
*
|
|
333
|
+
* return <form onSubmit={handleSubmit}>...</form>;
|
|
334
|
+
* }
|
|
335
|
+
* ```
|
|
336
|
+
*/
|
|
337
|
+
declare function useLeadCapture(): UseLeadCaptureReturn;
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Hook to capture contacts (CRM module)
|
|
341
|
+
*/
|
|
342
|
+
interface Contact {
|
|
343
|
+
id: string;
|
|
344
|
+
fullName: string;
|
|
345
|
+
email?: string;
|
|
346
|
+
phone?: string;
|
|
347
|
+
company?: string;
|
|
348
|
+
notes?: string;
|
|
349
|
+
postalCode?: string;
|
|
350
|
+
address?: string;
|
|
351
|
+
city?: string;
|
|
352
|
+
createdAt: string;
|
|
353
|
+
}
|
|
354
|
+
interface CreateContactRequest {
|
|
355
|
+
fullName: string;
|
|
356
|
+
email?: string;
|
|
357
|
+
phone?: string;
|
|
358
|
+
company?: string;
|
|
359
|
+
notes?: string;
|
|
360
|
+
nif?: string;
|
|
361
|
+
address?: string;
|
|
362
|
+
postalCode?: string;
|
|
363
|
+
city?: string;
|
|
364
|
+
}
|
|
365
|
+
interface ApiError {
|
|
366
|
+
message: string;
|
|
367
|
+
status?: number;
|
|
368
|
+
code?: string;
|
|
369
|
+
}
|
|
370
|
+
interface UseContactCaptureReturn {
|
|
371
|
+
captureContact: (data: CreateContactRequest) => Promise<Contact>;
|
|
372
|
+
isLoading: boolean;
|
|
373
|
+
error: ApiError | null;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Capture a contact (create contact in CRM)
|
|
377
|
+
*
|
|
378
|
+
* The frontend/SDK decides which fields to fill.
|
|
379
|
+
* This hook accepts any fields from CreateContactRequest.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```tsx
|
|
383
|
+
* function ContactForm() {
|
|
384
|
+
* const { captureContact, isLoading, error } = useContactCapture();
|
|
385
|
+
*
|
|
386
|
+
* const handleSubmit = async (e) => {
|
|
387
|
+
* e.preventDefault();
|
|
388
|
+
* try {
|
|
389
|
+
* const contact = await captureContact({
|
|
390
|
+
* fullName: 'John Doe',
|
|
391
|
+
* email: 'john@example.com',
|
|
392
|
+
* phone: '+1234567890',
|
|
393
|
+
* postalCode: '75001',
|
|
394
|
+
* notes: 'Interested in garden maintenance',
|
|
395
|
+
* });
|
|
396
|
+
* alert('Contact created!');
|
|
397
|
+
* } catch (err) {
|
|
398
|
+
* console.error('Error:', err);
|
|
399
|
+
* }
|
|
400
|
+
* };
|
|
401
|
+
*
|
|
402
|
+
* return <form onSubmit={handleSubmit}>...</form>;
|
|
403
|
+
* }
|
|
404
|
+
* ```
|
|
405
|
+
*/
|
|
406
|
+
declare function useContactCapture(): UseContactCaptureReturn;
|
|
407
|
+
|
|
408
|
+
export { type ApiError$1 as ApiError, AuthProvider, type CreateLeadRequest, type EndUser, type EndUserLoginRequest, type FoxPixelConfig, FoxPixelHttpClient, FoxPixelProvider, GuestOnlyRoute, type Lead, ProtectedRoute, type Service, type ServiceCatalogResponse, useAuth, useContactCapture, useFoxPixelContext, useLeadCapture, useServices, withAuth };
|