@umituz/react-native-settings 4.20.56 → 4.20.58
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 +146 -4
- package/package.json +1 -2
- package/src/__tests__/setup.ts +1 -4
- package/src/application/README.md +322 -0
- package/src/domains/about/README.md +452 -0
- package/src/domains/about/presentation/hooks/README.md +350 -0
- package/src/domains/appearance/README.md +596 -0
- package/src/domains/appearance/hooks/README.md +366 -0
- package/src/domains/appearance/infrastructure/services/README.md +455 -0
- package/src/domains/appearance/presentation/components/README.md +493 -0
- package/src/domains/cloud-sync/README.md +451 -0
- package/src/domains/cloud-sync/presentation/components/README.md +493 -0
- package/src/domains/dev/README.md +477 -0
- package/src/domains/disclaimer/README.md +421 -0
- package/src/domains/disclaimer/presentation/components/README.md +394 -0
- package/src/domains/faqs/README.md +586 -0
- package/src/domains/feedback/README.md +565 -0
- package/src/domains/feedback/presentation/hooks/README.md +428 -0
- package/src/domains/legal/README.md +549 -0
- package/src/domains/rating/README.md +452 -0
- package/src/domains/rating/presentation/components/README.md +475 -0
- package/src/domains/video-tutorials/README.md +482 -0
- package/src/domains/video-tutorials/presentation/components/README.md +433 -0
- package/src/infrastructure/README.md +509 -0
- package/src/infrastructure/repositories/README.md +475 -0
- package/src/infrastructure/services/README.md +510 -0
- package/src/presentation/components/README.md +482 -0
- package/src/presentation/components/SettingsErrorBoundary/README.md +455 -0
- package/src/presentation/components/SettingsFooter/README.md +446 -0
- package/src/presentation/components/SettingsItemCard/README.md +457 -0
- package/src/presentation/components/SettingsSection/README.md +421 -0
- package/src/presentation/hooks/README.md +413 -0
- package/src/presentation/hooks/mutations/README.md +430 -0
- package/src/presentation/hooks/queries/README.md +441 -0
- package/src/presentation/navigation/README.md +532 -0
- package/src/presentation/navigation/components/README.md +330 -0
- package/src/presentation/navigation/hooks/README.md +399 -0
- package/src/presentation/navigation/utils/README.md +442 -0
- package/src/presentation/screens/README.md +525 -0
- package/src/presentation/screens/components/SettingsContent/README.md +404 -0
- package/src/presentation/screens/components/SettingsHeader/README.md +322 -0
- package/src/presentation/screens/components/sections/CustomSettingsList/README.md +388 -0
- package/src/presentation/screens/components/sections/FeatureSettingsSection/README.md +232 -0
- package/src/presentation/screens/components/sections/IdentitySettingsSection/README.md +325 -0
- package/src/presentation/screens/components/sections/ProfileSectionLoader/README.md +480 -0
- package/src/presentation/screens/components/sections/SupportSettingsSection/README.md +391 -0
- package/src/presentation/screens/hooks/README.md +383 -0
- package/src/presentation/screens/types/README.md +439 -0
- package/src/presentation/screens/utils/README.md +288 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
# useFeedbackForm Hook
|
|
2
|
+
|
|
3
|
+
Custom hook for managing feedback form state, validation, and submission.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Form State**: Manages feedback type, rating, and message
|
|
8
|
+
- **Validation**: Validates form before submission
|
|
9
|
+
- **Submission**: Handles feedback submission with callbacks
|
|
10
|
+
- **Reset**: Resets form after successful submission
|
|
11
|
+
- **Rating Management**: Handles star rating state
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This hook is part of `@umituz/react-native-settings`.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Basic Usage
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { useFeedbackForm } from '@umituz/react-native-settings';
|
|
23
|
+
|
|
24
|
+
function FeedbackScreen() {
|
|
25
|
+
const {
|
|
26
|
+
feedbackType,
|
|
27
|
+
rating,
|
|
28
|
+
message,
|
|
29
|
+
setFeedbackType,
|
|
30
|
+
setRating,
|
|
31
|
+
setMessage,
|
|
32
|
+
submitFeedback,
|
|
33
|
+
canSubmit,
|
|
34
|
+
isSubmitting,
|
|
35
|
+
} = useFeedbackForm();
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<View>
|
|
39
|
+
<FeedbackTypeSelector
|
|
40
|
+
selected={feedbackType}
|
|
41
|
+
onSelect={setFeedbackType}
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<StarRating
|
|
45
|
+
rating={rating}
|
|
46
|
+
onRatingChange={setRating}
|
|
47
|
+
/>
|
|
48
|
+
|
|
49
|
+
<TextInput
|
|
50
|
+
value={message}
|
|
51
|
+
onChangeText={setMessage}
|
|
52
|
+
placeholder="Describe your feedback..."
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<Button
|
|
56
|
+
onPress={submitFeedback}
|
|
57
|
+
disabled={!canSubmit || isSubmitting}
|
|
58
|
+
title={isSubmitting ? 'Submitting...' : 'Submit Feedback'}
|
|
59
|
+
/>
|
|
60
|
+
</View>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Return Value
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
interface UseFeedbackFormResult {
|
|
69
|
+
// Form state
|
|
70
|
+
feedbackType: FeedbackType | null;
|
|
71
|
+
rating: number;
|
|
72
|
+
message: string;
|
|
73
|
+
|
|
74
|
+
// Setters
|
|
75
|
+
setFeedbackType: (type: FeedbackType) => void;
|
|
76
|
+
setRating: (rating: number) => void;
|
|
77
|
+
setMessage: (message: string) => void;
|
|
78
|
+
|
|
79
|
+
// Actions
|
|
80
|
+
submitFeedback: () => Promise<void>;
|
|
81
|
+
resetForm: () => void;
|
|
82
|
+
|
|
83
|
+
// State
|
|
84
|
+
canSubmit: boolean;
|
|
85
|
+
isSubmitting: boolean;
|
|
86
|
+
error?: string;
|
|
87
|
+
|
|
88
|
+
// Validation
|
|
89
|
+
errors: {
|
|
90
|
+
feedbackType?: string;
|
|
91
|
+
rating?: string;
|
|
92
|
+
message?: string;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Examples
|
|
98
|
+
|
|
99
|
+
### With Callbacks
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
function FeedbackForm() {
|
|
103
|
+
const feedbackForm = useFeedbackForm({
|
|
104
|
+
onSubmit: async (data) => {
|
|
105
|
+
await api.submitFeedback(data);
|
|
106
|
+
Alert.alert('Success', 'Thank you for your feedback!');
|
|
107
|
+
},
|
|
108
|
+
onError: (error) => {
|
|
109
|
+
Alert.alert('Error', 'Failed to submit feedback');
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<View>
|
|
115
|
+
<FeedbackTypeSelector
|
|
116
|
+
selected={feedbackForm.feedbackType}
|
|
117
|
+
onSelect={feedbackForm.setFeedbackType}
|
|
118
|
+
/>
|
|
119
|
+
<StarRating
|
|
120
|
+
rating={feedbackForm.rating}
|
|
121
|
+
onRatingChange={feedbackForm.setRating}
|
|
122
|
+
/>
|
|
123
|
+
<TextInput
|
|
124
|
+
value={feedbackForm.message}
|
|
125
|
+
onChangeText={feedbackForm.setMessage}
|
|
126
|
+
/>
|
|
127
|
+
<Button
|
|
128
|
+
onPress={feedbackForm.submitFeedback}
|
|
129
|
+
disabled={!feedbackForm.canSubmit}
|
|
130
|
+
title="Submit"
|
|
131
|
+
/>
|
|
132
|
+
</View>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### With Custom Validation
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
function ValidatedFeedbackForm() {
|
|
141
|
+
const { feedbackType, rating, message, submitFeedback, canSubmit } = useFeedbackForm({
|
|
142
|
+
validate: (data) => {
|
|
143
|
+
const errors = {};
|
|
144
|
+
|
|
145
|
+
if (!data.feedbackType) {
|
|
146
|
+
errors.feedbackType = 'Please select a feedback type';
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (data.rating === 0) {
|
|
150
|
+
errors.rating = 'Please provide a rating';
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (data.message.length < 10) {
|
|
154
|
+
errors.message = 'Message must be at least 10 characters';
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return errors;
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<View>
|
|
163
|
+
{/* Form fields */}
|
|
164
|
+
</View>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### With Auto-Reset
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
function AutoResetFeedbackForm() {
|
|
173
|
+
const { submitFeedback, resetForm } = useFeedbackForm({
|
|
174
|
+
autoReset: true,
|
|
175
|
+
resetDelay: 2000, // Reset after 2 seconds
|
|
176
|
+
onSubmitSuccess: () => {
|
|
177
|
+
Alert.alert('Success', 'Feedback submitted!');
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
return (
|
|
182
|
+
<View>
|
|
183
|
+
<Button onPress={submitFeedback} title="Submit" />
|
|
184
|
+
</View>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### With Character Limit
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
function LimitedFeedbackForm() {
|
|
193
|
+
const { message, setMessage, submitFeedback, canSubmit } = useFeedbackForm({
|
|
194
|
+
maxLength: 500,
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
const remainingChars = 500 - message.length;
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<View>
|
|
201
|
+
<TextInput
|
|
202
|
+
value={message}
|
|
203
|
+
onChangeText={setMessage}
|
|
204
|
+
placeholder="Your feedback..."
|
|
205
|
+
maxLength={500}
|
|
206
|
+
multiline
|
|
207
|
+
/>
|
|
208
|
+
|
|
209
|
+
<Text>
|
|
210
|
+
{remainingChars} characters remaining
|
|
211
|
+
</Text>
|
|
212
|
+
|
|
213
|
+
<Button
|
|
214
|
+
onPress={submitFeedback}
|
|
215
|
+
disabled={!canSubmit}
|
|
216
|
+
title="Submit"
|
|
217
|
+
/>
|
|
218
|
+
</View>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### With Categories
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
function CategorizedFeedbackForm() {
|
|
227
|
+
const categories = [
|
|
228
|
+
{ id: 'bug', label: 'Bug Report', icon: 'bug-outline' },
|
|
229
|
+
{ id: 'feature', label: 'Feature Request', icon: 'lightbulb-outline' },
|
|
230
|
+
{ id: 'general', label: 'General Feedback', icon: 'chatbubble-outline' },
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
const { feedbackType, setFeedbackType, submitFeedback } = useFeedbackForm();
|
|
234
|
+
|
|
235
|
+
return (
|
|
236
|
+
<View>
|
|
237
|
+
<Text style={styles.label}>Feedback Type</Text>
|
|
238
|
+
|
|
239
|
+
{categories.map((category) => (
|
|
240
|
+
<TouchableOpacity
|
|
241
|
+
key={category.id}
|
|
242
|
+
onPress={() => setFeedbackType(category.id as FeedbackType)}
|
|
243
|
+
style={[
|
|
244
|
+
styles.category,
|
|
245
|
+
feedbackType === category.id && styles.selectedCategory,
|
|
246
|
+
]}
|
|
247
|
+
>
|
|
248
|
+
<Ionicons
|
|
249
|
+
name={category.icon}
|
|
250
|
+
size={24}
|
|
251
|
+
color={feedbackType === category.id ? 'white' : 'black'}
|
|
252
|
+
/>
|
|
253
|
+
<Text>{category.label}</Text>
|
|
254
|
+
</TouchableOpacity>
|
|
255
|
+
))}
|
|
256
|
+
|
|
257
|
+
<Button onPress={submitFeedback} title="Submit" />
|
|
258
|
+
</View>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Form Options
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
interface FeedbackFormOptions {
|
|
267
|
+
onSubmit?: (data: FeedbackData) => Promise<void>;
|
|
268
|
+
onSubmitSuccess?: () => void;
|
|
269
|
+
onError?: (error: Error) => void;
|
|
270
|
+
validate?: (data: FeedbackData) => ValidationErrors;
|
|
271
|
+
autoReset?: boolean;
|
|
272
|
+
resetDelay?: number;
|
|
273
|
+
maxLength?: number;
|
|
274
|
+
minRating?: number;
|
|
275
|
+
requireMessage?: boolean;
|
|
276
|
+
minMessageLength?: number;
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Feedback Types
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
type FeedbackType =
|
|
284
|
+
| 'bug' // Bug report
|
|
285
|
+
| 'feature' // Feature request
|
|
286
|
+
| 'improvement' // Improvement suggestion
|
|
287
|
+
| 'compliment' // Positive feedback
|
|
288
|
+
| 'complaint' // Complaint
|
|
289
|
+
| 'general'; // General feedback
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Validation
|
|
293
|
+
|
|
294
|
+
### Default Validation
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const defaultValidation = {
|
|
298
|
+
// Feedback type is required
|
|
299
|
+
feedbackType: (value) => !value ? 'Required' : undefined,
|
|
300
|
+
|
|
301
|
+
// Rating must be at least 1
|
|
302
|
+
rating: (value) => value === 0 ? 'Required' : undefined,
|
|
303
|
+
|
|
304
|
+
// Message must be at least 10 characters
|
|
305
|
+
message: (value) => value.length < 10 ? 'Too short' : undefined,
|
|
306
|
+
};
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Custom Validation Rules
|
|
310
|
+
|
|
311
|
+
```tsx
|
|
312
|
+
function CustomValidatedForm() {
|
|
313
|
+
const { message, setMessage, canSubmit } = useFeedbackForm({
|
|
314
|
+
validate: (data) => {
|
|
315
|
+
const errors = {};
|
|
316
|
+
|
|
317
|
+
// Custom feedback type validation
|
|
318
|
+
if (!data.feedbackType) {
|
|
319
|
+
errors.feedbackType = 'Please select a type';
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Custom rating validation
|
|
323
|
+
if (data.rating < 3 && data.message.length < 50) {
|
|
324
|
+
errors.message = 'Low ratings require detailed explanation';
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Custom message validation
|
|
328
|
+
if (data.message.includes('spam')) {
|
|
329
|
+
errors.message = 'Inappropriate content detected';
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return errors;
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
return (
|
|
337
|
+
<View>
|
|
338
|
+
<TextInput
|
|
339
|
+
value={message}
|
|
340
|
+
onChangeText={setMessage}
|
|
341
|
+
placeholder="Your feedback..."
|
|
342
|
+
/>
|
|
343
|
+
<Button disabled={!canSubmit} title="Submit" />
|
|
344
|
+
</View>
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Error Handling
|
|
350
|
+
|
|
351
|
+
### Display Errors
|
|
352
|
+
|
|
353
|
+
```tsx
|
|
354
|
+
function FeedbackFormWithErrorDisplay() {
|
|
355
|
+
const { errors, submitFeedback, feedbackType } = useFeedbackForm();
|
|
356
|
+
|
|
357
|
+
return (
|
|
358
|
+
<View>
|
|
359
|
+
<FeedbackTypeSelector
|
|
360
|
+
selected={feedbackType}
|
|
361
|
+
onSelect={setFeedbackType}
|
|
362
|
+
/>
|
|
363
|
+
|
|
364
|
+
{errors.feedbackType && (
|
|
365
|
+
<Text style={styles.error}>{errors.feedbackType}</Text>
|
|
366
|
+
)}
|
|
367
|
+
|
|
368
|
+
{errors.rating && (
|
|
369
|
+
<Text style={styles.error}>{errors.rating}</Text>
|
|
370
|
+
)}
|
|
371
|
+
|
|
372
|
+
{errors.message && (
|
|
373
|
+
<Text style={styles.error}>{errors.message}</Text>
|
|
374
|
+
)}
|
|
375
|
+
|
|
376
|
+
<Button onPress={submitFeedback} title="Submit" />
|
|
377
|
+
</View>
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Submission Errors
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
function FeedbackFormWithErrorHandling() {
|
|
386
|
+
const { submitFeedback, error, isSubmitting } = useFeedbackForm({
|
|
387
|
+
onError: (error) => {
|
|
388
|
+
console.error('Submission error:', error);
|
|
389
|
+
Alert.alert(
|
|
390
|
+
'Submission Failed',
|
|
391
|
+
'Please check your connection and try again'
|
|
392
|
+
);
|
|
393
|
+
},
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<View>
|
|
398
|
+
{error && <Text style={styles.error}>{error}</Text>}
|
|
399
|
+
|
|
400
|
+
<Button
|
|
401
|
+
onPress={submitFeedback}
|
|
402
|
+
disabled={isSubmitting}
|
|
403
|
+
title={isSubmitting ? 'Submitting...' : 'Submit'}
|
|
404
|
+
/>
|
|
405
|
+
</View>
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## Best Practices
|
|
411
|
+
|
|
412
|
+
1. **Validation**: Always validate form before submission
|
|
413
|
+
2. **Feedback**: Provide immediate feedback on errors
|
|
414
|
+
3. **Loading States**: Show loading indicator during submission
|
|
415
|
+
4. **Reset**: Reset form after successful submission
|
|
416
|
+
5. **Character Limits**: Enforce reasonable message length limits
|
|
417
|
+
6. **Clear Errors**: Display clear, actionable error messages
|
|
418
|
+
7. **Accessibility**: Ensure form is accessible to all users
|
|
419
|
+
|
|
420
|
+
## Related
|
|
421
|
+
|
|
422
|
+
- **FeedbackForm**: Feedback form component
|
|
423
|
+
- **FeedbackModal**: Feedback modal component
|
|
424
|
+
- **StarRating**: Star rating component
|
|
425
|
+
|
|
426
|
+
## License
|
|
427
|
+
|
|
428
|
+
MIT
|