@umituz/react-native-settings 4.20.55 → 4.20.57
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 +145 -3
- package/package.json +1 -2
- 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/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 +461 -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,452 @@
|
|
|
1
|
+
# Rating Domain
|
|
2
|
+
|
|
3
|
+
The Rating domain provides a star rating component and rating management utilities for collecting and displaying user ratings in your React Native app.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Interactive Star Rating**: Tap-to-rate functionality with visual feedback
|
|
8
|
+
- **Read-Only Display**: Show existing ratings without interaction
|
|
9
|
+
- **Customizable Appearance**: Configurable colors, sizes, and star count
|
|
10
|
+
- **Rating Statistics**: Track average ratings and distribution
|
|
11
|
+
- **Type-Safe**: Full TypeScript support with rating value types
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This domain is part of `@umituz/react-native-settings`. Install the package to use it:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @umituz/react-native-settings
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Components
|
|
22
|
+
|
|
23
|
+
### StarRating
|
|
24
|
+
|
|
25
|
+
Interactive star rating component with customizable appearance.
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { StarRating } from '@umituz/react-native-settings';
|
|
29
|
+
|
|
30
|
+
function MyRatingComponent() {
|
|
31
|
+
const [rating, setRating] = useState(0);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<StarRating
|
|
35
|
+
rating={rating}
|
|
36
|
+
onRatingChange={setRating}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### Props
|
|
43
|
+
|
|
44
|
+
| Prop | Type | Default | Description |
|
|
45
|
+
|------|------|---------|-------------|
|
|
46
|
+
| `rating` | `number` | **Required** | Current rating value |
|
|
47
|
+
| `maxRating` | `number` | `5` | Maximum rating (number of stars) |
|
|
48
|
+
| `onRatingChange` | `(rating) => void` | `undefined` | Rating change handler |
|
|
49
|
+
| `size` | `number` | `24` | Star icon size |
|
|
50
|
+
| `activeColor` | `string` | `tokens.colors.warning` | Filled star color |
|
|
51
|
+
| `inactiveColor` | `string` | `tokens.colors.border` | Empty star color |
|
|
52
|
+
| `disabled` | `boolean` | `false` | Disable interaction |
|
|
53
|
+
| `style` | `ViewStyle` | `undefined` | Container style |
|
|
54
|
+
|
|
55
|
+
#### Examples
|
|
56
|
+
|
|
57
|
+
**Basic Usage:**
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { StarRating } from '@umituz/react-native-settings';
|
|
61
|
+
|
|
62
|
+
function BasicRating() {
|
|
63
|
+
const [rating, setRating] = useState(3);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<View>
|
|
67
|
+
<Text>Rate this item:</Text>
|
|
68
|
+
<StarRating
|
|
69
|
+
rating={rating}
|
|
70
|
+
onRatingChange={setRating}
|
|
71
|
+
/>
|
|
72
|
+
<Text>Current rating: {rating}/5</Text>
|
|
73
|
+
</View>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Custom Colors:**
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
function CustomColoredRating() {
|
|
82
|
+
return (
|
|
83
|
+
<StarRating
|
|
84
|
+
rating={4}
|
|
85
|
+
activeColor="#FF6B6B"
|
|
86
|
+
inactiveColor="#E0E0E0"
|
|
87
|
+
size={32}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Read-Only Display:**
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
function ReadOnlyRating() {
|
|
97
|
+
return (
|
|
98
|
+
<StarRating
|
|
99
|
+
rating={4.5}
|
|
100
|
+
disabled={true}
|
|
101
|
+
activeColor="#FFD700"
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**10-Star Rating:**
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
function TenStarRating() {
|
|
111
|
+
const [rating, setRating] = useState(7);
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<StarRating
|
|
115
|
+
rating={rating}
|
|
116
|
+
maxRating={10}
|
|
117
|
+
onRatingChange={setRating}
|
|
118
|
+
size={20}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Large Stars:**
|
|
125
|
+
|
|
126
|
+
```tsx
|
|
127
|
+
function LargeStarRating() {
|
|
128
|
+
return (
|
|
129
|
+
<StarRating
|
|
130
|
+
rating={5}
|
|
131
|
+
size={48}
|
|
132
|
+
activeColor="#FFA500"
|
|
133
|
+
/>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**With Custom Style:**
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
function StyledRating() {
|
|
142
|
+
return (
|
|
143
|
+
<StarRating
|
|
144
|
+
rating={4}
|
|
145
|
+
style={{
|
|
146
|
+
backgroundColor: '#F5F5F5',
|
|
147
|
+
padding: 16,
|
|
148
|
+
borderRadius: 8,
|
|
149
|
+
}}
|
|
150
|
+
/>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Types
|
|
156
|
+
|
|
157
|
+
### RatingValue
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
type RatingValue = 0 | 1 | 2 | 3 | 4 | 5;
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Rating
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
interface Rating {
|
|
167
|
+
id: string;
|
|
168
|
+
userId: string;
|
|
169
|
+
entityId: string;
|
|
170
|
+
entityType: string;
|
|
171
|
+
value: RatingValue;
|
|
172
|
+
createdAt: string;
|
|
173
|
+
updatedAt: string;
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### RatingStats
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
interface RatingStats {
|
|
181
|
+
average: number;
|
|
182
|
+
count: number;
|
|
183
|
+
distribution: Record<RatingValue, number>;
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Examples
|
|
188
|
+
|
|
189
|
+
### Product Rating
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
import { StarRating } from '@umituz/react-native-settings';
|
|
193
|
+
|
|
194
|
+
function ProductRating({ product }) {
|
|
195
|
+
const [userRating, setUserRating] = useState(0);
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<View>
|
|
199
|
+
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
200
|
+
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>
|
|
201
|
+
{product.averageRating.toFixed(1)}
|
|
202
|
+
</Text>
|
|
203
|
+
<StarRating
|
|
204
|
+
rating={product.averageRating}
|
|
205
|
+
disabled={true}
|
|
206
|
+
size={20}
|
|
207
|
+
style={{ marginLeft: 8 }}
|
|
208
|
+
/>
|
|
209
|
+
<Text style={{ marginLeft: 8, color: '#666' }}>
|
|
210
|
+
({product.ratingCount} reviews)
|
|
211
|
+
</Text>
|
|
212
|
+
</View>
|
|
213
|
+
|
|
214
|
+
<View style={{ marginTop: 16 }}>
|
|
215
|
+
<Text>Rate this product:</Text>
|
|
216
|
+
<StarRating
|
|
217
|
+
rating={userRating}
|
|
218
|
+
onRatingChange={setUserRating}
|
|
219
|
+
/>
|
|
220
|
+
</View>
|
|
221
|
+
</View>
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Rating Distribution
|
|
227
|
+
|
|
228
|
+
```tsx
|
|
229
|
+
function RatingDistribution({ stats }) {
|
|
230
|
+
return (
|
|
231
|
+
<View>
|
|
232
|
+
<Text style={{ fontSize: 18, fontWeight: 'bold', marginBottom: 16 }}>
|
|
233
|
+
Rating Distribution
|
|
234
|
+
</Text>
|
|
235
|
+
|
|
236
|
+
{[5, 4, 3, 2, 1].map((star) => {
|
|
237
|
+
const count = stats.distribution[star] || 0;
|
|
238
|
+
const percentage = (count / stats.count) * 100;
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<View key={star} style={{ flexDirection: 'row', marginBottom: 8 }}>
|
|
242
|
+
<Text style={{ width: 40 }}>{star} star</Text>
|
|
243
|
+
<View style={{ flex: 1, height: 8, backgroundColor: '#E0E0E0' }}>
|
|
244
|
+
<View
|
|
245
|
+
style={{
|
|
246
|
+
width: `${percentage}%`,
|
|
247
|
+
height: '100%',
|
|
248
|
+
backgroundColor: '#FFD700',
|
|
249
|
+
}}
|
|
250
|
+
/>
|
|
251
|
+
</View>
|
|
252
|
+
<Text style={{ marginLeft: 8, width: 40 }}>{count}</Text>
|
|
253
|
+
</View>
|
|
254
|
+
);
|
|
255
|
+
})}
|
|
256
|
+
</View>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Review with Rating
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
function ReviewCard({ review }) {
|
|
265
|
+
return (
|
|
266
|
+
<View style={{ padding: 16, backgroundColor: '#FFF', marginBottom: 8 }}>
|
|
267
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 8 }}>
|
|
268
|
+
<StarRating
|
|
269
|
+
rating={review.rating}
|
|
270
|
+
disabled={true}
|
|
271
|
+
size={16}
|
|
272
|
+
/>
|
|
273
|
+
<Text style={{ marginLeft: 8, fontWeight: 'bold' }}>
|
|
274
|
+
{review.userName}
|
|
275
|
+
</Text>
|
|
276
|
+
</View>
|
|
277
|
+
|
|
278
|
+
<Text style={{ color: '#666', marginBottom: 8 }}>
|
|
279
|
+
{review.date}
|
|
280
|
+
</Text>
|
|
281
|
+
|
|
282
|
+
<Text>{review.comment}</Text>
|
|
283
|
+
</View>
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Feedback Rating
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
function FeedbackRating() {
|
|
292
|
+
const [rating, setRating] = useState(0);
|
|
293
|
+
const [submitted, setSubmitted] = useState(false);
|
|
294
|
+
|
|
295
|
+
const handleSubmit = async () => {
|
|
296
|
+
await api.submitFeedbackRating(rating);
|
|
297
|
+
setSubmitted(true);
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
if (submitted) {
|
|
301
|
+
return (
|
|
302
|
+
<View style={{ padding: 20, alignItems: 'center' }}>
|
|
303
|
+
<Text>Thanks for your feedback!</Text>
|
|
304
|
+
</View>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return (
|
|
309
|
+
<View style={{ padding: 20 }}>
|
|
310
|
+
<Text style={{ fontSize: 18, marginBottom: 16 }}>
|
|
311
|
+
How would you rate your experience?
|
|
312
|
+
</Text>
|
|
313
|
+
|
|
314
|
+
<StarRating
|
|
315
|
+
rating={rating}
|
|
316
|
+
onRatingChange={setRating}
|
|
317
|
+
size={40}
|
|
318
|
+
/>
|
|
319
|
+
|
|
320
|
+
{rating > 0 && (
|
|
321
|
+
<Button
|
|
322
|
+
title="Submit Rating"
|
|
323
|
+
onPress={handleSubmit}
|
|
324
|
+
style={{ marginTop: 16 }}
|
|
325
|
+
/>
|
|
326
|
+
)}
|
|
327
|
+
</View>
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Animated Rating
|
|
333
|
+
|
|
334
|
+
```tsx
|
|
335
|
+
import { Animated } from 'react-native';
|
|
336
|
+
|
|
337
|
+
function AnimatedStarRating() {
|
|
338
|
+
const [rating, setRating] = useState(0);
|
|
339
|
+
const scaleAnim = useRef(new Animated.Value(1)).current;
|
|
340
|
+
|
|
341
|
+
const handleRatingChange = (newRating) => {
|
|
342
|
+
// Animate scale
|
|
343
|
+
Animated.sequence([
|
|
344
|
+
Animated.timing(scaleAnim, {
|
|
345
|
+
toValue: 1.2,
|
|
346
|
+
duration: 100,
|
|
347
|
+
useNativeDriver: true,
|
|
348
|
+
}),
|
|
349
|
+
Animated.timing(scaleAnim, {
|
|
350
|
+
toValue: 1,
|
|
351
|
+
duration: 100,
|
|
352
|
+
useNativeDriver: true,
|
|
353
|
+
}),
|
|
354
|
+
]).start();
|
|
355
|
+
|
|
356
|
+
setRating(newRating);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
return (
|
|
360
|
+
<Animated.View style={{ transform: [{ scale: scaleAnim }] }}>
|
|
361
|
+
<StarRating
|
|
362
|
+
rating={rating}
|
|
363
|
+
onRatingChange={handleRatingChange}
|
|
364
|
+
size={32}
|
|
365
|
+
/>
|
|
366
|
+
</Animated.View>
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Architecture
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
src/domains/rating/
|
|
375
|
+
├── domain/
|
|
376
|
+
│ └── entities/
|
|
377
|
+
│ └── Rating.ts # Rating types and interfaces
|
|
378
|
+
└── presentation/
|
|
379
|
+
└── components/
|
|
380
|
+
└── StarRating.tsx # Star rating component
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
## Best Practices
|
|
384
|
+
|
|
385
|
+
1. **Clear Purpose**: Always explain what users are rating
|
|
386
|
+
2. **Immediate Feedback**: Show selected rating immediately
|
|
387
|
+
3. **Allow Changes**: Let users change their rating before submitting
|
|
388
|
+
4. **Visual Hierarchy**: Make ratings prominent but not overwhelming
|
|
389
|
+
5. **Accessible**: Use proper accessibility labels for screen readers
|
|
390
|
+
6. **Consistent Sizing**: Use consistent star sizes across your app
|
|
391
|
+
7. **Color Coding**: Use standard colors (gold/yellow for filled stars)
|
|
392
|
+
|
|
393
|
+
## Testing
|
|
394
|
+
|
|
395
|
+
```tsx
|
|
396
|
+
import { render, fireEvent } from '@testing-library/react-native';
|
|
397
|
+
import { StarRating } from '@umituz/react-native-settings';
|
|
398
|
+
|
|
399
|
+
describe('StarRating', () => {
|
|
400
|
+
it('renders correct number of stars', () => {
|
|
401
|
+
const { getAllByTestId } = render(
|
|
402
|
+
<StarRating rating={3} maxRating={5} />
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
expect(getAllByTestId(/star/)).toHaveLength(5);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it('displays filled and empty stars correctly', () => {
|
|
409
|
+
const { getAllByTestId } = render(
|
|
410
|
+
<StarRating rating={3} maxRating={5} />
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
const stars = getAllByTestId(/star/);
|
|
414
|
+
// First 3 should be filled, last 2 empty
|
|
415
|
+
// (implementation-specific assertions)
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
it('calls onRatingChange when star is pressed', () => {
|
|
419
|
+
const mockOnChange = jest.fn();
|
|
420
|
+
const { getAllByTestId } = render(
|
|
421
|
+
<StarRating rating={0} onRatingChange={mockOnChange} maxRating={5} />
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
const stars = getAllByTestId(/star/);
|
|
425
|
+
fireEvent.press(stars[3]);
|
|
426
|
+
|
|
427
|
+
expect(mockOnChange).toHaveBeenCalledWith(4);
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
it('does not respond to presses when disabled', () => {
|
|
431
|
+
const mockOnChange = jest.fn();
|
|
432
|
+
const { getAllByTestId } = render(
|
|
433
|
+
<StarRating rating={3} onRatingChange={mockOnChange} disabled={true} />
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
const stars = getAllByTestId(/star/);
|
|
437
|
+
fireEvent.press(stars[0]);
|
|
438
|
+
|
|
439
|
+
expect(mockOnChange).not.toHaveBeenCalled();
|
|
440
|
+
});
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
## Related
|
|
445
|
+
|
|
446
|
+
- **Feedback**: Feedback forms with ratings
|
|
447
|
+
- **Reviews**: User review management
|
|
448
|
+
- **Settings**: Main settings management
|
|
449
|
+
|
|
450
|
+
## License
|
|
451
|
+
|
|
452
|
+
MIT
|