@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 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 };