@businessflow/reviews 1.0.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 +97 -0
- package/dist/client/index.d.mts +245 -0
- package/dist/client/index.d.ts +245 -0
- package/dist/client/index.js +400 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +368 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index.d.mts +239 -0
- package/dist/index.d.ts +239 -0
- package/dist/index.js +1381 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1349 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react/index.d.mts +311 -0
- package/dist/react/index.d.ts +311 -0
- package/dist/react/index.js +1390 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +1355 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/server/index.d.mts +189 -0
- package/dist/server/index.d.ts +189 -0
- package/dist/server/index.js +402 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/index.mjs +369 -0
- package/dist/server/index.mjs.map +1 -0
- package/dist/types/index.d.mts +141 -0
- package/dist/types/index.d.ts +141 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/index.mjs +1 -0
- package/dist/types/index.mjs.map +1 -0
- package/package.json +104 -0
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# @businessflow/reviews
|
|
2
|
+
|
|
3
|
+
Generic review and testimonial management utilities for React and NextJS applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ⭐ **Star Ratings**: Customizable star rating components
|
|
8
|
+
- 📝 **Review Forms**: Pre-built review submission forms
|
|
9
|
+
- 🎨 **Display Components**: Beautiful testimonial display layouts
|
|
10
|
+
- 🔒 **Secure**: Server-side API handling with reCAPTCHA
|
|
11
|
+
- 📱 **Responsive**: Mobile-friendly components
|
|
12
|
+
- 🎨 **Customizable**: Flexible styling and configuration
|
|
13
|
+
- 📝 **TypeScript**: Full type safety and IntelliSense support
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @businessflow/reviews
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Create API Routes (NextJS App Router)
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// app/api/reviews/featured/route.ts
|
|
27
|
+
import { createReviewHandler } from '@businessflow/reviews/server';
|
|
28
|
+
|
|
29
|
+
export const GET = createReviewHandler({
|
|
30
|
+
onFetch: async (params) => {
|
|
31
|
+
// Fetch from your database/API
|
|
32
|
+
const reviews = await fetchReviewsFromDB({
|
|
33
|
+
limit: params?.limit || 10,
|
|
34
|
+
featured: true
|
|
35
|
+
});
|
|
36
|
+
return reviews;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// app/api/reviews/submit/route.ts
|
|
41
|
+
export const POST = createReviewHandler({
|
|
42
|
+
onSubmit: async (data) => {
|
|
43
|
+
// Save to your database/API
|
|
44
|
+
const result = await saveReviewToDB(data);
|
|
45
|
+
return {
|
|
46
|
+
success: !!result.id,
|
|
47
|
+
reviewId: result.id,
|
|
48
|
+
message: 'Review submitted successfully'
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
recaptcha: {
|
|
52
|
+
secretKey: process.env.RECAPTCHA_SECRET_KEY!
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 2. Display Testimonials
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { TestimonialsSection } from '@businessflow/reviews/react';
|
|
61
|
+
|
|
62
|
+
export default function HomePage() {
|
|
63
|
+
return (
|
|
64
|
+
<TestimonialsSection
|
|
65
|
+
limit={6}
|
|
66
|
+
layout="grid"
|
|
67
|
+
showRating={true}
|
|
68
|
+
autoRefresh={true}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 3. Review Submission Form
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { ReviewForm } from '@businessflow/reviews/react';
|
|
78
|
+
|
|
79
|
+
export default function ReviewPage() {
|
|
80
|
+
return (
|
|
81
|
+
<ReviewForm
|
|
82
|
+
recaptcha={{ siteKey: process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY! }}
|
|
83
|
+
onSuccess={(response) => console.log('Review submitted!', response)}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Documentation
|
|
90
|
+
|
|
91
|
+
- [API Reference](./docs/api.md)
|
|
92
|
+
- [Examples](./examples/)
|
|
93
|
+
- [Component Gallery](./docs/components.md)
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
MIT
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
interface Review {
|
|
2
|
+
id: string | number;
|
|
3
|
+
reviewerName: string;
|
|
4
|
+
reviewerEmail?: string;
|
|
5
|
+
reviewerTitle?: string;
|
|
6
|
+
reviewerCompany?: string;
|
|
7
|
+
reviewerAvatar?: string;
|
|
8
|
+
rating: number;
|
|
9
|
+
content?: string;
|
|
10
|
+
createdAt: string | Date;
|
|
11
|
+
updatedAt?: string | Date;
|
|
12
|
+
featured?: boolean;
|
|
13
|
+
approved?: boolean;
|
|
14
|
+
metadata?: Record<string, any>;
|
|
15
|
+
}
|
|
16
|
+
interface ReviewFormData {
|
|
17
|
+
reviewerName: string;
|
|
18
|
+
reviewerEmail: string;
|
|
19
|
+
reviewerTitle?: string;
|
|
20
|
+
reviewerCompany?: string;
|
|
21
|
+
rating: number;
|
|
22
|
+
content?: string;
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}
|
|
25
|
+
interface ReviewApiResponse {
|
|
26
|
+
success: boolean;
|
|
27
|
+
message?: string;
|
|
28
|
+
reviewId?: string | number;
|
|
29
|
+
status?: 'pending' | 'approved' | 'rejected';
|
|
30
|
+
data?: any;
|
|
31
|
+
}
|
|
32
|
+
interface ReviewSubmissionConfig {
|
|
33
|
+
endpoint: string;
|
|
34
|
+
method?: 'POST' | 'PUT';
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
maxRetries?: number;
|
|
37
|
+
timeout?: number;
|
|
38
|
+
transformRequest?: (data: ReviewFormData) => any;
|
|
39
|
+
transformResponse?: (response: any) => ReviewApiResponse;
|
|
40
|
+
onSuccess?: (response: ReviewApiResponse) => void;
|
|
41
|
+
onError?: (error: Error) => void;
|
|
42
|
+
}
|
|
43
|
+
interface ReviewFetchConfig {
|
|
44
|
+
endpoint: string;
|
|
45
|
+
method?: 'GET';
|
|
46
|
+
headers?: Record<string, string>;
|
|
47
|
+
maxRetries?: number;
|
|
48
|
+
timeout?: number;
|
|
49
|
+
params?: {
|
|
50
|
+
limit?: number;
|
|
51
|
+
offset?: number;
|
|
52
|
+
featured?: boolean;
|
|
53
|
+
minRating?: number;
|
|
54
|
+
sortBy?: 'date' | 'rating' | 'name';
|
|
55
|
+
sortOrder?: 'asc' | 'desc';
|
|
56
|
+
};
|
|
57
|
+
transformResponse?: (response: any) => Review[];
|
|
58
|
+
onError?: (error: Error) => void;
|
|
59
|
+
}
|
|
60
|
+
interface ReviewFieldConfig {
|
|
61
|
+
show?: boolean;
|
|
62
|
+
required?: boolean;
|
|
63
|
+
label?: string;
|
|
64
|
+
type?: string;
|
|
65
|
+
placeholder?: string;
|
|
66
|
+
validation?: ValidationRule[];
|
|
67
|
+
}
|
|
68
|
+
interface ReviewFormConfig {
|
|
69
|
+
fields?: {
|
|
70
|
+
reviewerName?: ReviewFieldConfig;
|
|
71
|
+
reviewerEmail?: ReviewFieldConfig;
|
|
72
|
+
reviewerTitle?: ReviewFieldConfig;
|
|
73
|
+
reviewerCompany?: ReviewFieldConfig;
|
|
74
|
+
rating?: ReviewFieldConfig;
|
|
75
|
+
content?: ReviewFieldConfig;
|
|
76
|
+
[key: string]: ReviewFieldConfig | undefined;
|
|
77
|
+
};
|
|
78
|
+
recaptcha?: {
|
|
79
|
+
siteKey: string;
|
|
80
|
+
action?: string;
|
|
81
|
+
};
|
|
82
|
+
styling?: {
|
|
83
|
+
className?: string;
|
|
84
|
+
fieldClassName?: string;
|
|
85
|
+
buttonClassName?: string;
|
|
86
|
+
errorClassName?: string;
|
|
87
|
+
starClassName?: string;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
interface TestimonialDisplayConfig {
|
|
91
|
+
limit?: number;
|
|
92
|
+
showRating?: boolean;
|
|
93
|
+
showDate?: boolean;
|
|
94
|
+
showAvatar?: boolean;
|
|
95
|
+
showCompany?: boolean;
|
|
96
|
+
showTitle?: boolean;
|
|
97
|
+
layout?: 'grid' | 'list' | 'slider';
|
|
98
|
+
columns?: number;
|
|
99
|
+
autoRefresh?: boolean;
|
|
100
|
+
refreshInterval?: number;
|
|
101
|
+
styling?: {
|
|
102
|
+
containerClassName?: string;
|
|
103
|
+
cardClassName?: string;
|
|
104
|
+
headerClassName?: string;
|
|
105
|
+
contentClassName?: string;
|
|
106
|
+
ratingClassName?: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
interface ValidationRule {
|
|
110
|
+
type: 'required' | 'email' | 'minLength' | 'maxLength' | 'pattern' | 'custom' | 'rating';
|
|
111
|
+
value?: string | number;
|
|
112
|
+
message?: string;
|
|
113
|
+
validator?: (value: any) => boolean | string;
|
|
114
|
+
}
|
|
115
|
+
interface ValidationErrors {
|
|
116
|
+
[field: string]: string;
|
|
117
|
+
}
|
|
118
|
+
interface ReviewHandlerConfig {
|
|
119
|
+
onFetch?: (params?: any) => Promise<Review[]>;
|
|
120
|
+
onSubmit?: (data: ReviewFormData) => Promise<ReviewApiResponse>;
|
|
121
|
+
recaptcha?: {
|
|
122
|
+
secretKey: string;
|
|
123
|
+
minimumScore?: number;
|
|
124
|
+
};
|
|
125
|
+
validation?: {
|
|
126
|
+
[field: string]: ValidationRule[];
|
|
127
|
+
};
|
|
128
|
+
onSuccess?: (data: ReviewFormData, response: ReviewApiResponse) => Promise<void>;
|
|
129
|
+
onError?: (data: ReviewFormData, error: Error) => Promise<void>;
|
|
130
|
+
rateLimiter?: (request: Request) => Promise<boolean>;
|
|
131
|
+
}
|
|
132
|
+
interface StarRatingProps {
|
|
133
|
+
rating: number;
|
|
134
|
+
maxRating?: number;
|
|
135
|
+
editable?: boolean;
|
|
136
|
+
onChange?: (rating: number) => void;
|
|
137
|
+
size?: 'small' | 'medium' | 'large';
|
|
138
|
+
className?: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Generic review client for fetching and submitting reviews
|
|
143
|
+
*/
|
|
144
|
+
declare class ReviewClient {
|
|
145
|
+
private fetchConfig?;
|
|
146
|
+
private submitConfig?;
|
|
147
|
+
private maxRetries;
|
|
148
|
+
private timeout;
|
|
149
|
+
constructor(config: {
|
|
150
|
+
fetchConfig?: ReviewFetchConfig;
|
|
151
|
+
submitConfig?: ReviewSubmissionConfig;
|
|
152
|
+
maxRetries?: number;
|
|
153
|
+
timeout?: number;
|
|
154
|
+
});
|
|
155
|
+
/**
|
|
156
|
+
* Fetch reviews with retry logic
|
|
157
|
+
*/
|
|
158
|
+
fetchReviews(params?: {
|
|
159
|
+
limit?: number;
|
|
160
|
+
offset?: number;
|
|
161
|
+
featured?: boolean;
|
|
162
|
+
minRating?: number;
|
|
163
|
+
}, retryCount?: number): Promise<Review[]>;
|
|
164
|
+
/**
|
|
165
|
+
* Submit a review with retry logic
|
|
166
|
+
*/
|
|
167
|
+
submitReview(reviewData: ReviewFormData, retryCount?: number): Promise<ReviewApiResponse>;
|
|
168
|
+
/**
|
|
169
|
+
* Update configuration
|
|
170
|
+
*/
|
|
171
|
+
updateConfig(config: {
|
|
172
|
+
fetchConfig?: Partial<ReviewFetchConfig>;
|
|
173
|
+
submitConfig?: Partial<ReviewSubmissionConfig>;
|
|
174
|
+
}): void;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Default validation rules for review forms
|
|
179
|
+
*/
|
|
180
|
+
declare const DEFAULT_REVIEW_VALIDATION_RULES: {
|
|
181
|
+
reviewerName: ({
|
|
182
|
+
type: "required";
|
|
183
|
+
message: string;
|
|
184
|
+
value?: undefined;
|
|
185
|
+
} | {
|
|
186
|
+
type: "minLength";
|
|
187
|
+
value: number;
|
|
188
|
+
message: string;
|
|
189
|
+
} | {
|
|
190
|
+
type: "maxLength";
|
|
191
|
+
value: number;
|
|
192
|
+
message: string;
|
|
193
|
+
})[];
|
|
194
|
+
reviewerEmail: ({
|
|
195
|
+
type: "required";
|
|
196
|
+
message: string;
|
|
197
|
+
} | {
|
|
198
|
+
type: "email";
|
|
199
|
+
message: string;
|
|
200
|
+
})[];
|
|
201
|
+
rating: ({
|
|
202
|
+
type: "required";
|
|
203
|
+
message: string;
|
|
204
|
+
} | {
|
|
205
|
+
type: "rating";
|
|
206
|
+
message: string;
|
|
207
|
+
})[];
|
|
208
|
+
content: {
|
|
209
|
+
type: "maxLength";
|
|
210
|
+
value: number;
|
|
211
|
+
message: string;
|
|
212
|
+
}[];
|
|
213
|
+
reviewerTitle: {
|
|
214
|
+
type: "maxLength";
|
|
215
|
+
value: number;
|
|
216
|
+
message: string;
|
|
217
|
+
}[];
|
|
218
|
+
reviewerCompany: {
|
|
219
|
+
type: "maxLength";
|
|
220
|
+
value: number;
|
|
221
|
+
message: string;
|
|
222
|
+
}[];
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Validate review form data
|
|
226
|
+
*/
|
|
227
|
+
declare function validateReviewData(data: ReviewFormData, customRules?: {
|
|
228
|
+
[field: string]: ValidationRule[];
|
|
229
|
+
}): ValidationErrors | null;
|
|
230
|
+
/**
|
|
231
|
+
* Validate a single field - useful for real-time validation
|
|
232
|
+
*/
|
|
233
|
+
declare function validateSingleReviewField(field: string, value: any, customRules?: {
|
|
234
|
+
[field: string]: ValidationRule[];
|
|
235
|
+
}): string | null;
|
|
236
|
+
/**
|
|
237
|
+
* Check if rating is valid (1-5 stars)
|
|
238
|
+
*/
|
|
239
|
+
declare function isValidRating(rating: number): boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Sanitize review form data - trim strings and remove empty optional fields
|
|
242
|
+
*/
|
|
243
|
+
declare function sanitizeReviewData(data: ReviewFormData): ReviewFormData;
|
|
244
|
+
|
|
245
|
+
export { DEFAULT_REVIEW_VALIDATION_RULES, type Review, type ReviewApiResponse, ReviewClient, type ReviewFetchConfig, type ReviewFieldConfig, type ReviewFormConfig, type ReviewFormData, type ReviewHandlerConfig, type ReviewSubmissionConfig, type StarRatingProps, type TestimonialDisplayConfig, type ValidationErrors, type ValidationRule, isValidRating, sanitizeReviewData, validateReviewData, validateSingleReviewField };
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
interface Review {
|
|
2
|
+
id: string | number;
|
|
3
|
+
reviewerName: string;
|
|
4
|
+
reviewerEmail?: string;
|
|
5
|
+
reviewerTitle?: string;
|
|
6
|
+
reviewerCompany?: string;
|
|
7
|
+
reviewerAvatar?: string;
|
|
8
|
+
rating: number;
|
|
9
|
+
content?: string;
|
|
10
|
+
createdAt: string | Date;
|
|
11
|
+
updatedAt?: string | Date;
|
|
12
|
+
featured?: boolean;
|
|
13
|
+
approved?: boolean;
|
|
14
|
+
metadata?: Record<string, any>;
|
|
15
|
+
}
|
|
16
|
+
interface ReviewFormData {
|
|
17
|
+
reviewerName: string;
|
|
18
|
+
reviewerEmail: string;
|
|
19
|
+
reviewerTitle?: string;
|
|
20
|
+
reviewerCompany?: string;
|
|
21
|
+
rating: number;
|
|
22
|
+
content?: string;
|
|
23
|
+
[key: string]: any;
|
|
24
|
+
}
|
|
25
|
+
interface ReviewApiResponse {
|
|
26
|
+
success: boolean;
|
|
27
|
+
message?: string;
|
|
28
|
+
reviewId?: string | number;
|
|
29
|
+
status?: 'pending' | 'approved' | 'rejected';
|
|
30
|
+
data?: any;
|
|
31
|
+
}
|
|
32
|
+
interface ReviewSubmissionConfig {
|
|
33
|
+
endpoint: string;
|
|
34
|
+
method?: 'POST' | 'PUT';
|
|
35
|
+
headers?: Record<string, string>;
|
|
36
|
+
maxRetries?: number;
|
|
37
|
+
timeout?: number;
|
|
38
|
+
transformRequest?: (data: ReviewFormData) => any;
|
|
39
|
+
transformResponse?: (response: any) => ReviewApiResponse;
|
|
40
|
+
onSuccess?: (response: ReviewApiResponse) => void;
|
|
41
|
+
onError?: (error: Error) => void;
|
|
42
|
+
}
|
|
43
|
+
interface ReviewFetchConfig {
|
|
44
|
+
endpoint: string;
|
|
45
|
+
method?: 'GET';
|
|
46
|
+
headers?: Record<string, string>;
|
|
47
|
+
maxRetries?: number;
|
|
48
|
+
timeout?: number;
|
|
49
|
+
params?: {
|
|
50
|
+
limit?: number;
|
|
51
|
+
offset?: number;
|
|
52
|
+
featured?: boolean;
|
|
53
|
+
minRating?: number;
|
|
54
|
+
sortBy?: 'date' | 'rating' | 'name';
|
|
55
|
+
sortOrder?: 'asc' | 'desc';
|
|
56
|
+
};
|
|
57
|
+
transformResponse?: (response: any) => Review[];
|
|
58
|
+
onError?: (error: Error) => void;
|
|
59
|
+
}
|
|
60
|
+
interface ReviewFieldConfig {
|
|
61
|
+
show?: boolean;
|
|
62
|
+
required?: boolean;
|
|
63
|
+
label?: string;
|
|
64
|
+
type?: string;
|
|
65
|
+
placeholder?: string;
|
|
66
|
+
validation?: ValidationRule[];
|
|
67
|
+
}
|
|
68
|
+
interface ReviewFormConfig {
|
|
69
|
+
fields?: {
|
|
70
|
+
reviewerName?: ReviewFieldConfig;
|
|
71
|
+
reviewerEmail?: ReviewFieldConfig;
|
|
72
|
+
reviewerTitle?: ReviewFieldConfig;
|
|
73
|
+
reviewerCompany?: ReviewFieldConfig;
|
|
74
|
+
rating?: ReviewFieldConfig;
|
|
75
|
+
content?: ReviewFieldConfig;
|
|
76
|
+
[key: string]: ReviewFieldConfig | undefined;
|
|
77
|
+
};
|
|
78
|
+
recaptcha?: {
|
|
79
|
+
siteKey: string;
|
|
80
|
+
action?: string;
|
|
81
|
+
};
|
|
82
|
+
styling?: {
|
|
83
|
+
className?: string;
|
|
84
|
+
fieldClassName?: string;
|
|
85
|
+
buttonClassName?: string;
|
|
86
|
+
errorClassName?: string;
|
|
87
|
+
starClassName?: string;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
interface TestimonialDisplayConfig {
|
|
91
|
+
limit?: number;
|
|
92
|
+
showRating?: boolean;
|
|
93
|
+
showDate?: boolean;
|
|
94
|
+
showAvatar?: boolean;
|
|
95
|
+
showCompany?: boolean;
|
|
96
|
+
showTitle?: boolean;
|
|
97
|
+
layout?: 'grid' | 'list' | 'slider';
|
|
98
|
+
columns?: number;
|
|
99
|
+
autoRefresh?: boolean;
|
|
100
|
+
refreshInterval?: number;
|
|
101
|
+
styling?: {
|
|
102
|
+
containerClassName?: string;
|
|
103
|
+
cardClassName?: string;
|
|
104
|
+
headerClassName?: string;
|
|
105
|
+
contentClassName?: string;
|
|
106
|
+
ratingClassName?: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
interface ValidationRule {
|
|
110
|
+
type: 'required' | 'email' | 'minLength' | 'maxLength' | 'pattern' | 'custom' | 'rating';
|
|
111
|
+
value?: string | number;
|
|
112
|
+
message?: string;
|
|
113
|
+
validator?: (value: any) => boolean | string;
|
|
114
|
+
}
|
|
115
|
+
interface ValidationErrors {
|
|
116
|
+
[field: string]: string;
|
|
117
|
+
}
|
|
118
|
+
interface ReviewHandlerConfig {
|
|
119
|
+
onFetch?: (params?: any) => Promise<Review[]>;
|
|
120
|
+
onSubmit?: (data: ReviewFormData) => Promise<ReviewApiResponse>;
|
|
121
|
+
recaptcha?: {
|
|
122
|
+
secretKey: string;
|
|
123
|
+
minimumScore?: number;
|
|
124
|
+
};
|
|
125
|
+
validation?: {
|
|
126
|
+
[field: string]: ValidationRule[];
|
|
127
|
+
};
|
|
128
|
+
onSuccess?: (data: ReviewFormData, response: ReviewApiResponse) => Promise<void>;
|
|
129
|
+
onError?: (data: ReviewFormData, error: Error) => Promise<void>;
|
|
130
|
+
rateLimiter?: (request: Request) => Promise<boolean>;
|
|
131
|
+
}
|
|
132
|
+
interface StarRatingProps {
|
|
133
|
+
rating: number;
|
|
134
|
+
maxRating?: number;
|
|
135
|
+
editable?: boolean;
|
|
136
|
+
onChange?: (rating: number) => void;
|
|
137
|
+
size?: 'small' | 'medium' | 'large';
|
|
138
|
+
className?: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Generic review client for fetching and submitting reviews
|
|
143
|
+
*/
|
|
144
|
+
declare class ReviewClient {
|
|
145
|
+
private fetchConfig?;
|
|
146
|
+
private submitConfig?;
|
|
147
|
+
private maxRetries;
|
|
148
|
+
private timeout;
|
|
149
|
+
constructor(config: {
|
|
150
|
+
fetchConfig?: ReviewFetchConfig;
|
|
151
|
+
submitConfig?: ReviewSubmissionConfig;
|
|
152
|
+
maxRetries?: number;
|
|
153
|
+
timeout?: number;
|
|
154
|
+
});
|
|
155
|
+
/**
|
|
156
|
+
* Fetch reviews with retry logic
|
|
157
|
+
*/
|
|
158
|
+
fetchReviews(params?: {
|
|
159
|
+
limit?: number;
|
|
160
|
+
offset?: number;
|
|
161
|
+
featured?: boolean;
|
|
162
|
+
minRating?: number;
|
|
163
|
+
}, retryCount?: number): Promise<Review[]>;
|
|
164
|
+
/**
|
|
165
|
+
* Submit a review with retry logic
|
|
166
|
+
*/
|
|
167
|
+
submitReview(reviewData: ReviewFormData, retryCount?: number): Promise<ReviewApiResponse>;
|
|
168
|
+
/**
|
|
169
|
+
* Update configuration
|
|
170
|
+
*/
|
|
171
|
+
updateConfig(config: {
|
|
172
|
+
fetchConfig?: Partial<ReviewFetchConfig>;
|
|
173
|
+
submitConfig?: Partial<ReviewSubmissionConfig>;
|
|
174
|
+
}): void;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Default validation rules for review forms
|
|
179
|
+
*/
|
|
180
|
+
declare const DEFAULT_REVIEW_VALIDATION_RULES: {
|
|
181
|
+
reviewerName: ({
|
|
182
|
+
type: "required";
|
|
183
|
+
message: string;
|
|
184
|
+
value?: undefined;
|
|
185
|
+
} | {
|
|
186
|
+
type: "minLength";
|
|
187
|
+
value: number;
|
|
188
|
+
message: string;
|
|
189
|
+
} | {
|
|
190
|
+
type: "maxLength";
|
|
191
|
+
value: number;
|
|
192
|
+
message: string;
|
|
193
|
+
})[];
|
|
194
|
+
reviewerEmail: ({
|
|
195
|
+
type: "required";
|
|
196
|
+
message: string;
|
|
197
|
+
} | {
|
|
198
|
+
type: "email";
|
|
199
|
+
message: string;
|
|
200
|
+
})[];
|
|
201
|
+
rating: ({
|
|
202
|
+
type: "required";
|
|
203
|
+
message: string;
|
|
204
|
+
} | {
|
|
205
|
+
type: "rating";
|
|
206
|
+
message: string;
|
|
207
|
+
})[];
|
|
208
|
+
content: {
|
|
209
|
+
type: "maxLength";
|
|
210
|
+
value: number;
|
|
211
|
+
message: string;
|
|
212
|
+
}[];
|
|
213
|
+
reviewerTitle: {
|
|
214
|
+
type: "maxLength";
|
|
215
|
+
value: number;
|
|
216
|
+
message: string;
|
|
217
|
+
}[];
|
|
218
|
+
reviewerCompany: {
|
|
219
|
+
type: "maxLength";
|
|
220
|
+
value: number;
|
|
221
|
+
message: string;
|
|
222
|
+
}[];
|
|
223
|
+
};
|
|
224
|
+
/**
|
|
225
|
+
* Validate review form data
|
|
226
|
+
*/
|
|
227
|
+
declare function validateReviewData(data: ReviewFormData, customRules?: {
|
|
228
|
+
[field: string]: ValidationRule[];
|
|
229
|
+
}): ValidationErrors | null;
|
|
230
|
+
/**
|
|
231
|
+
* Validate a single field - useful for real-time validation
|
|
232
|
+
*/
|
|
233
|
+
declare function validateSingleReviewField(field: string, value: any, customRules?: {
|
|
234
|
+
[field: string]: ValidationRule[];
|
|
235
|
+
}): string | null;
|
|
236
|
+
/**
|
|
237
|
+
* Check if rating is valid (1-5 stars)
|
|
238
|
+
*/
|
|
239
|
+
declare function isValidRating(rating: number): boolean;
|
|
240
|
+
/**
|
|
241
|
+
* Sanitize review form data - trim strings and remove empty optional fields
|
|
242
|
+
*/
|
|
243
|
+
declare function sanitizeReviewData(data: ReviewFormData): ReviewFormData;
|
|
244
|
+
|
|
245
|
+
export { DEFAULT_REVIEW_VALIDATION_RULES, type Review, type ReviewApiResponse, ReviewClient, type ReviewFetchConfig, type ReviewFieldConfig, type ReviewFormConfig, type ReviewFormData, type ReviewHandlerConfig, type ReviewSubmissionConfig, type StarRatingProps, type TestimonialDisplayConfig, type ValidationErrors, type ValidationRule, isValidRating, sanitizeReviewData, validateReviewData, validateSingleReviewField };
|