@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,565 @@
|
|
|
1
|
+
# Feedback Domain
|
|
2
|
+
|
|
3
|
+
The Feedback domain provides components and utilities for collecting user feedback in your React Native app, including feedback forms, modals, and support sections.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Feedback Form**: Comprehensive form with type selection, rating, and description
|
|
8
|
+
- **Feedback Modal**: Modal-based feedback submission
|
|
9
|
+
- **Support Section**: Display support resources and contact information
|
|
10
|
+
- **Type Categorization**: Categorize feedback by type (bug, feature, general, etc.)
|
|
11
|
+
- **Star Rating**: Interactive 1-5 star rating system
|
|
12
|
+
- **Form Validation**: Built-in validation and error handling
|
|
13
|
+
- **Customizable Texts**: Full localization support
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
This domain is part of `@umituz/react-native-settings`. Install the package to use it:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @umituz/react-native-settings
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Components
|
|
24
|
+
|
|
25
|
+
### FeedbackForm
|
|
26
|
+
|
|
27
|
+
A comprehensive feedback form with type selection, star rating, and text input.
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { FeedbackForm } from '@umituz/react-native-settings';
|
|
31
|
+
|
|
32
|
+
function MyFeedbackForm() {
|
|
33
|
+
const handleSubmit = async (data) => {
|
|
34
|
+
// Send feedback to your backend
|
|
35
|
+
await api.submitFeedback(data);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const texts = {
|
|
39
|
+
ratingLabel: 'How would you rate this feature?',
|
|
40
|
+
descriptionPlaceholder: 'Tell us more about your experience...',
|
|
41
|
+
submitButton: 'Submit Feedback',
|
|
42
|
+
submittingButton: 'Submitting...',
|
|
43
|
+
feedbackTypes: [
|
|
44
|
+
{ type: 'bug', label: 'Report Bug' },
|
|
45
|
+
{ type: 'feature', label: 'Feature Request' },
|
|
46
|
+
{ type: 'general', label: 'General Feedback' },
|
|
47
|
+
],
|
|
48
|
+
defaultTitle: (type) => `User ${type} submission`,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return <FeedbackForm onSubmit={handleSubmit} texts={texts} />;
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
#### Props
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Default | Description |
|
|
58
|
+
|------|------|---------|-------------|
|
|
59
|
+
| `onSubmit` | `(data) => Promise<void>` | **Required** | Submit handler |
|
|
60
|
+
| `texts` | `FeedbackFormTexts` | **Required** | Text configuration |
|
|
61
|
+
| `initialType` | `FeedbackType` | `undefined` | Initial feedback type |
|
|
62
|
+
| `isSubmitting` | `boolean` | `false` | Loading state |
|
|
63
|
+
|
|
64
|
+
### FeedbackModal
|
|
65
|
+
|
|
66
|
+
A modal wrapper for the feedback form.
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
import { FeedbackModal } from '@umituz/react-native-settings';
|
|
70
|
+
|
|
71
|
+
function MyFeedbackModal() {
|
|
72
|
+
const [visible, setVisible] = useState(false);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<FeedbackModal
|
|
76
|
+
visible={visible}
|
|
77
|
+
onClose={() => setVisible(false)}
|
|
78
|
+
onSubmit={async (data) => {
|
|
79
|
+
await submitFeedback(data);
|
|
80
|
+
setVisible(false);
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Props
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Default | Description |
|
|
90
|
+
|------|------|---------|-------------|
|
|
91
|
+
| `visible` | `boolean` | **Required** | Modal visibility |
|
|
92
|
+
| `onClose` | `() => void` | **Required** | Close handler |
|
|
93
|
+
| `onSubmit` | `(data) => Promise<void>` | **Required** | Submit handler |
|
|
94
|
+
| `texts` | `FeedbackFormTexts` | `undefined` | Text configuration |
|
|
95
|
+
|
|
96
|
+
### SupportSection
|
|
97
|
+
|
|
98
|
+
Display support resources and contact information.
|
|
99
|
+
|
|
100
|
+
```tsx
|
|
101
|
+
import { SupportSection } from '@umituz/react-native-settings';
|
|
102
|
+
|
|
103
|
+
function MySupportSection() {
|
|
104
|
+
const supportItems = [
|
|
105
|
+
{
|
|
106
|
+
title: 'Help Center',
|
|
107
|
+
description: 'Browse our help articles',
|
|
108
|
+
onPress: () => navigation.navigate('HelpCenter'),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
title: 'Contact Us',
|
|
112
|
+
description: 'Get in touch with our team',
|
|
113
|
+
onPress: () => Linking.openURL('mailto:support@example.com'),
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
title: 'Community',
|
|
117
|
+
description: 'Join our community forum',
|
|
118
|
+
onPress: () => Linking.openURL('https://community.example.com'),
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<SupportSection
|
|
124
|
+
title="Need Help?"
|
|
125
|
+
description="We're here to assist you"
|
|
126
|
+
items={supportItems}
|
|
127
|
+
/>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Props
|
|
133
|
+
|
|
134
|
+
| Prop | Type | Default | Description |
|
|
135
|
+
|------|------|---------|-------------|
|
|
136
|
+
| `title` | `string` | `undefined` | Section title |
|
|
137
|
+
| `description` | `string` | `undefined` | Section description |
|
|
138
|
+
| `items` | `SupportItem[]` | `[]` | Support items array |
|
|
139
|
+
|
|
140
|
+
## Hooks
|
|
141
|
+
|
|
142
|
+
### useFeedbackForm
|
|
143
|
+
|
|
144
|
+
Hook for managing feedback form state.
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import { useFeedbackForm } from '@umituz/react-native-settings';
|
|
148
|
+
|
|
149
|
+
function FeedbackManager() {
|
|
150
|
+
const {
|
|
151
|
+
formState,
|
|
152
|
+
setType,
|
|
153
|
+
setTitle,
|
|
154
|
+
setDescription,
|
|
155
|
+
setRating,
|
|
156
|
+
reset,
|
|
157
|
+
isValid,
|
|
158
|
+
} = useFeedbackForm({
|
|
159
|
+
type: 'general',
|
|
160
|
+
title: 'Default Title',
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<View>
|
|
165
|
+
<TextInput
|
|
166
|
+
value={formState.title}
|
|
167
|
+
onChangeText={setTitle}
|
|
168
|
+
placeholder="Title"
|
|
169
|
+
/>
|
|
170
|
+
<TextInput
|
|
171
|
+
value={formState.description}
|
|
172
|
+
onChangeText={setDescription}
|
|
173
|
+
placeholder="Description"
|
|
174
|
+
/>
|
|
175
|
+
<Button title="Submit" onPress={handleSubmit} disabled={!isValid} />
|
|
176
|
+
</View>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Return Value
|
|
182
|
+
|
|
183
|
+
| Property | Type | Description |
|
|
184
|
+
|----------|------|-------------|
|
|
185
|
+
| `formState` | `FeedbackFormState` | Current form state |
|
|
186
|
+
| `setType` | `(type) => void` | Set feedback type |
|
|
187
|
+
| `setTitle` | `(title) => void` | Set title |
|
|
188
|
+
| `setDescription` | `(desc) => void` | Set description |
|
|
189
|
+
| `setRating` | `(rating) => void` | Set rating (1-5) |
|
|
190
|
+
| `reset` | `() => void` | Reset form to initial state |
|
|
191
|
+
| `isValid` | `boolean` | Form validation status |
|
|
192
|
+
|
|
193
|
+
## Types
|
|
194
|
+
|
|
195
|
+
### FeedbackType
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
type FeedbackType = 'bug' | 'feature' | 'general' | 'ui' | 'performance';
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### FeedbackRating
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
type FeedbackRating = 1 | 2 | 3 | 4 | 5;
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### FeedbackFormState
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
interface FeedbackFormState {
|
|
211
|
+
type: FeedbackType;
|
|
212
|
+
title: string;
|
|
213
|
+
description: string;
|
|
214
|
+
rating?: FeedbackRating;
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### FeedbackFormTexts
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
interface FeedbackFormTexts {
|
|
222
|
+
ratingLabel: string;
|
|
223
|
+
descriptionPlaceholder: string;
|
|
224
|
+
submitButton: string;
|
|
225
|
+
submittingButton: string;
|
|
226
|
+
feedbackTypes: Array<{
|
|
227
|
+
type: FeedbackType;
|
|
228
|
+
label: string;
|
|
229
|
+
}>;
|
|
230
|
+
defaultTitle: (type: FeedbackType) => string;
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Examples
|
|
235
|
+
|
|
236
|
+
### Basic Feedback Form
|
|
237
|
+
|
|
238
|
+
```tsx
|
|
239
|
+
import { FeedbackForm } from '@umituz/react-native-settings';
|
|
240
|
+
|
|
241
|
+
function BasicFeedback() {
|
|
242
|
+
const handleSubmit = async (data) => {
|
|
243
|
+
console.log('Feedback submitted:', data);
|
|
244
|
+
// Send to backend
|
|
245
|
+
await fetch('/api/feedback', {
|
|
246
|
+
method: 'POST',
|
|
247
|
+
body: JSON.stringify(data),
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const texts = {
|
|
252
|
+
ratingLabel: 'Rate your experience',
|
|
253
|
+
descriptionPlaceholder: 'What did you like or dislike?',
|
|
254
|
+
submitButton: 'Send Feedback',
|
|
255
|
+
submittingButton: 'Sending...',
|
|
256
|
+
feedbackTypes: [
|
|
257
|
+
{ type: 'general', label: 'General' },
|
|
258
|
+
{ type: 'bug', label: 'Bug Report' },
|
|
259
|
+
{ type: 'feature', label: 'Feature Request' },
|
|
260
|
+
],
|
|
261
|
+
defaultTitle: (type) => `${type} feedback`,
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<View style={{ padding: 20 }}>
|
|
266
|
+
<FeedbackForm onSubmit={handleSubmit} texts={texts} />
|
|
267
|
+
</View>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Feedback Modal in Settings
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
import { FeedbackModal } from '@umituz/react-native-settings';
|
|
276
|
+
|
|
277
|
+
function SettingsScreen() {
|
|
278
|
+
const [showFeedback, setShowFeedback] = useState(false);
|
|
279
|
+
|
|
280
|
+
return (
|
|
281
|
+
<ScreenLayout>
|
|
282
|
+
<Button
|
|
283
|
+
title="Send Feedback"
|
|
284
|
+
onPress={() => setShowFeedback(true)}
|
|
285
|
+
/>
|
|
286
|
+
|
|
287
|
+
<FeedbackModal
|
|
288
|
+
visible={showFeedback}
|
|
289
|
+
onClose={() => setShowFeedback(false)}
|
|
290
|
+
onSubmit={async (data) => {
|
|
291
|
+
await submitFeedback(data);
|
|
292
|
+
Alert.alert('Success', 'Thank you for your feedback!');
|
|
293
|
+
setShowFeedback(false);
|
|
294
|
+
}}
|
|
295
|
+
/>
|
|
296
|
+
</ScreenLayout>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Using the Hook
|
|
302
|
+
|
|
303
|
+
```tsx
|
|
304
|
+
import { useFeedbackForm } from '@umituz/react-native-settings';
|
|
305
|
+
|
|
306
|
+
function CustomFeedbackForm() {
|
|
307
|
+
const {
|
|
308
|
+
formState,
|
|
309
|
+
setType,
|
|
310
|
+
setTitle,
|
|
311
|
+
setDescription,
|
|
312
|
+
setRating,
|
|
313
|
+
reset,
|
|
314
|
+
isValid,
|
|
315
|
+
} = useFeedbackForm();
|
|
316
|
+
|
|
317
|
+
const handleSubmit = async () => {
|
|
318
|
+
if (!isValid) {
|
|
319
|
+
Alert.alert('Error', 'Please fill in all required fields');
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
await api.submitFeedback(formState);
|
|
324
|
+
reset();
|
|
325
|
+
Alert.alert('Success', 'Feedback submitted!');
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
return (
|
|
329
|
+
<View>
|
|
330
|
+
<Picker
|
|
331
|
+
selectedValue={formState.type}
|
|
332
|
+
onValueChange={setType}
|
|
333
|
+
>
|
|
334
|
+
<Picker.Item label="Bug" value="bug" />
|
|
335
|
+
<Picker.Item label="Feature" value="feature" />
|
|
336
|
+
<Picker.Item label="General" value="general" />
|
|
337
|
+
</Picker>
|
|
338
|
+
|
|
339
|
+
<StarRating
|
|
340
|
+
rating={formState.rating}
|
|
341
|
+
onRatingChange={setRating}
|
|
342
|
+
/>
|
|
343
|
+
|
|
344
|
+
<TextInput
|
|
345
|
+
value={formState.title}
|
|
346
|
+
onChangeText={setTitle}
|
|
347
|
+
placeholder="Title"
|
|
348
|
+
/>
|
|
349
|
+
|
|
350
|
+
<TextInput
|
|
351
|
+
value={formState.description}
|
|
352
|
+
onChangeText={setDescription}
|
|
353
|
+
placeholder="Description"
|
|
354
|
+
multiline
|
|
355
|
+
/>
|
|
356
|
+
|
|
357
|
+
<Button
|
|
358
|
+
title="Submit"
|
|
359
|
+
onPress={handleSubmit}
|
|
360
|
+
disabled={!isValid}
|
|
361
|
+
/>
|
|
362
|
+
</View>
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Support Section
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
import { SupportSection } from '@umituz/react-native-settings';
|
|
371
|
+
|
|
372
|
+
function HelpScreen() {
|
|
373
|
+
const supportItems = [
|
|
374
|
+
{
|
|
375
|
+
title: 'FAQ',
|
|
376
|
+
description: 'Frequently asked questions',
|
|
377
|
+
onPress: () => navigation.navigate('FAQ'),
|
|
378
|
+
iconName: 'help-circle',
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
title: 'Email Support',
|
|
382
|
+
description: 'support@example.com',
|
|
383
|
+
onPress: () => Linking.openURL('mailto:support@example.com'),
|
|
384
|
+
iconName: 'mail',
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
title: 'Live Chat',
|
|
388
|
+
description: 'Chat with our team',
|
|
389
|
+
onPress: () => openChat(),
|
|
390
|
+
iconName: 'message-circle',
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
title: 'Report Issue',
|
|
394
|
+
description: 'Report a bug or problem',
|
|
395
|
+
onPress: () => navigation.navigate('ReportIssue'),
|
|
396
|
+
iconName: 'alert-triangle',
|
|
397
|
+
},
|
|
398
|
+
];
|
|
399
|
+
|
|
400
|
+
return (
|
|
401
|
+
<ScrollView>
|
|
402
|
+
<SupportSection
|
|
403
|
+
title="Support Options"
|
|
404
|
+
items={supportItems}
|
|
405
|
+
/>
|
|
406
|
+
</ScrollView>
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Complete Feedback Flow
|
|
412
|
+
|
|
413
|
+
```tsx
|
|
414
|
+
import { FeedbackForm, SupportSection } from '@umituz/react-native-settings';
|
|
415
|
+
|
|
416
|
+
function FeedbackScreen() {
|
|
417
|
+
const [submitted, setSubmitted] = useState(false);
|
|
418
|
+
|
|
419
|
+
if (submitted) {
|
|
420
|
+
return (
|
|
421
|
+
<View style={{ padding: 20, alignItems: 'center' }}>
|
|
422
|
+
<Icon name="check-circle" size={64} color="#10B981" />
|
|
423
|
+
<Text style={{ fontSize: 20, fontWeight: 'bold', marginTop: 16 }}>
|
|
424
|
+
Thank You!
|
|
425
|
+
</Text>
|
|
426
|
+
<Text style={{ marginTop: 8, textAlign: 'center' }}>
|
|
427
|
+
Your feedback helps us improve the app.
|
|
428
|
+
</Text>
|
|
429
|
+
|
|
430
|
+
<SupportSection
|
|
431
|
+
title="Need More Help?"
|
|
432
|
+
items={[
|
|
433
|
+
{
|
|
434
|
+
title: 'Contact Support',
|
|
435
|
+
description: 'Get direct assistance',
|
|
436
|
+
onPress: () => Linking.openURL('mailto:support@example.com'),
|
|
437
|
+
},
|
|
438
|
+
]}
|
|
439
|
+
/>
|
|
440
|
+
</View>
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return (
|
|
445
|
+
<FeedbackForm
|
|
446
|
+
onSubmit={async (data) => {
|
|
447
|
+
await submitFeedback(data);
|
|
448
|
+
setSubmitted(true);
|
|
449
|
+
}}
|
|
450
|
+
texts={{
|
|
451
|
+
ratingLabel: 'How would you rate this app?',
|
|
452
|
+
descriptionPlaceholder: 'Tell us what you think...',
|
|
453
|
+
submitButton: 'Submit Feedback',
|
|
454
|
+
submittingButton: 'Sending...',
|
|
455
|
+
feedbackTypes: [
|
|
456
|
+
{ type: 'bug', label: 'Bug Report' },
|
|
457
|
+
{ type: 'feature', label: 'Feature Request' },
|
|
458
|
+
{ type: 'general', label: 'General' },
|
|
459
|
+
],
|
|
460
|
+
defaultTitle: (type) => `User ${type}`,
|
|
461
|
+
}}
|
|
462
|
+
/>
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Architecture
|
|
468
|
+
|
|
469
|
+
```
|
|
470
|
+
src/domains/feedback/
|
|
471
|
+
├── domain/
|
|
472
|
+
│ ├── entities/ # FeedbackEntity
|
|
473
|
+
│ └── repositories/ # IFeedbackRepository interface
|
|
474
|
+
├── presentation/
|
|
475
|
+
│ ├── components/
|
|
476
|
+
│ │ ├── FeedbackForm.tsx
|
|
477
|
+
│ │ ├── FeedbackModal.tsx
|
|
478
|
+
│ │ └── SupportSection.tsx
|
|
479
|
+
│ └── hooks/
|
|
480
|
+
│ └── useFeedbackForm.ts
|
|
481
|
+
└── index.ts # Public API exports
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## Best Practices
|
|
485
|
+
|
|
486
|
+
1. **Categorize Feedback**: Use clear categories to help route feedback
|
|
487
|
+
2. **Keep it Simple**: Don't ask for too much information upfront
|
|
488
|
+
3. **Provide Context**: Explain why you're collecting feedback
|
|
489
|
+
4. **Follow Up**: Consider providing a way to track feedback status
|
|
490
|
+
5. **Validate Input**: Ensure required fields are filled before submission
|
|
491
|
+
6. **Handle Errors**: Show clear error messages for submission failures
|
|
492
|
+
7. **Confirmation**: Always show confirmation after successful submission
|
|
493
|
+
|
|
494
|
+
## Testing
|
|
495
|
+
|
|
496
|
+
```tsx
|
|
497
|
+
import { render, fireEvent, waitFor } from '@testing-library/react-native';
|
|
498
|
+
import { FeedbackForm } from '@umituz/react-native-settings';
|
|
499
|
+
|
|
500
|
+
describe('FeedbackForm', () => {
|
|
501
|
+
it('renders feedback type selector', () => {
|
|
502
|
+
const onSubmit = jest.fn();
|
|
503
|
+
const texts = {
|
|
504
|
+
ratingLabel: 'Rate',
|
|
505
|
+
descriptionPlaceholder: 'Describe',
|
|
506
|
+
submitButton: 'Submit',
|
|
507
|
+
submittingButton: 'Submitting',
|
|
508
|
+
feedbackTypes: [
|
|
509
|
+
{ type: 'bug', label: 'Bug' },
|
|
510
|
+
{ type: 'feature', label: 'Feature' },
|
|
511
|
+
],
|
|
512
|
+
defaultTitle: (t) => t,
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const { getByText } = render(
|
|
516
|
+
<FeedbackForm onSubmit={onSubmit} texts={texts} />
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
expect(getByText('Bug')).toBeTruthy();
|
|
520
|
+
expect(getByText('Feature')).toBeTruthy();
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
it('submits form with correct data', async () => {
|
|
524
|
+
const onSubmit = jest.fn().mockResolvedValue(undefined);
|
|
525
|
+
const texts = {
|
|
526
|
+
ratingLabel: 'Rate',
|
|
527
|
+
descriptionPlaceholder: 'Describe',
|
|
528
|
+
submitButton: 'Submit',
|
|
529
|
+
submittingButton: 'Submitting',
|
|
530
|
+
feedbackTypes: [{ type: 'general', label: 'General' }],
|
|
531
|
+
defaultTitle: (t) => t,
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
const { getByText, getByPlaceholderText } = render(
|
|
535
|
+
<FeedbackForm onSubmit={onSubmit} texts={texts} />
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
const input = getByPlaceholderText('Describe');
|
|
539
|
+
fireEvent.changeText(input, 'Great app!');
|
|
540
|
+
|
|
541
|
+
const submitButton = getByText('Submit');
|
|
542
|
+
fireEvent.press(submitButton);
|
|
543
|
+
|
|
544
|
+
await waitFor(() => {
|
|
545
|
+
expect(onSubmit).toHaveBeenCalledWith(
|
|
546
|
+
expect.objectContaining({
|
|
547
|
+
description: 'Great app!',
|
|
548
|
+
type: 'general',
|
|
549
|
+
rating: 5,
|
|
550
|
+
})
|
|
551
|
+
);
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
## Related
|
|
558
|
+
|
|
559
|
+
- **Settings**: Main settings management
|
|
560
|
+
- **Rating**: Star rating component
|
|
561
|
+
- **FAQs**: Frequently asked questions
|
|
562
|
+
|
|
563
|
+
## License
|
|
564
|
+
|
|
565
|
+
MIT
|