@umituz/react-native-settings 4.17.16 → 4.17.18
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/package.json +6 -5
- package/src/domains/appearance/index.ts +3 -1
- package/src/domains/appearance/presentation/screens/AppearanceScreen.tsx +2 -1
- package/src/domains/faqs/index.ts +4 -2
- package/src/domains/feedback/index.ts +5 -1
- package/src/domains/legal/__tests__/setup.ts +1 -1
- package/src/domains/rating/domain/entities/Rating.ts +17 -0
- package/src/domains/rating/index.ts +23 -0
- package/src/domains/rating/presentation/components/StarRating.tsx +69 -0
- package/src/index.ts +3 -0
- package/src/presentation/screens/AppearanceScreen.tsx +2 -5
- package/src/presentation/screens/components/SettingsContent.tsx +4 -5
- package/src/presentation/screens/types/FeatureConfig.ts +1 -1
- package/src/domains/feedback/presentation/hooks/useDeleteFeedback.ts +0 -25
- package/src/domains/feedback/presentation/hooks/useSubmitFeedback.ts +0 -55
- package/src/domains/feedback/presentation/hooks/useUserFeedback.ts +0 -29
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.17.
|
|
4
|
-
"description": "Complete settings hub for React Native apps - consolidated package with settings, about, legal, appearance, feedback, and
|
|
3
|
+
"version": "4.17.18",
|
|
4
|
+
"description": "Complete settings hub for React Native apps - consolidated package with settings, about, legal, appearance, feedback, FAQs, and rating",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
7
7
|
"scripts": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"appearance",
|
|
25
25
|
"feedback",
|
|
26
26
|
"faqs",
|
|
27
|
+
"rating",
|
|
27
28
|
"consolidated"
|
|
28
29
|
],
|
|
29
30
|
"author": "Ümit UZ <umit@umituz.com>",
|
|
@@ -42,7 +43,6 @@
|
|
|
42
43
|
"@umituz/react-native-localization": "latest",
|
|
43
44
|
"@umituz/react-native-notifications": "latest",
|
|
44
45
|
"@umituz/react-native-onboarding": "latest",
|
|
45
|
-
"@umituz/react-native-rating": "latest",
|
|
46
46
|
"@umituz/react-native-sentry": "latest",
|
|
47
47
|
"@umituz/react-native-storage": "latest",
|
|
48
48
|
"react": ">=19.0.0",
|
|
@@ -53,6 +53,8 @@
|
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@babel/plugin-transform-runtime": "^7.28.5",
|
|
55
55
|
"@expo/vector-icons": "^15.0.0",
|
|
56
|
+
"@react-navigation/native": "^6.1.18",
|
|
57
|
+
"@react-navigation/stack": "^6.4.1",
|
|
56
58
|
"@types/jest": "^29.5.14",
|
|
57
59
|
"@types/react": "~19.1.10",
|
|
58
60
|
"@umituz/react-native-auth": "latest",
|
|
@@ -61,7 +63,6 @@
|
|
|
61
63
|
"@umituz/react-native-localization": "latest",
|
|
62
64
|
"@umituz/react-native-notifications": "latest",
|
|
63
65
|
"@umituz/react-native-onboarding": "latest",
|
|
64
|
-
"@umituz/react-native-rating": "latest",
|
|
65
66
|
"@umituz/react-native-storage": "latest",
|
|
66
67
|
"react": "19.1.0",
|
|
67
68
|
"react-native": "0.81.5",
|
|
@@ -76,6 +77,6 @@
|
|
|
76
77
|
"LICENSE"
|
|
77
78
|
],
|
|
78
79
|
"dependencies": {
|
|
79
|
-
"@umituz/react-native-design-system": "
|
|
80
|
+
"@umituz/react-native-design-system": "latest"
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
ThemeModeSection,
|
|
15
15
|
CustomColorsSection,
|
|
16
16
|
AppearancePreview,
|
|
17
|
+
type ThemeOptionConfig,
|
|
17
18
|
} from "../components";
|
|
18
19
|
|
|
19
20
|
import type { AppearanceTexts } from "../../types";
|
|
@@ -101,7 +102,7 @@ export const AppearanceScreen: React.FC<AppearanceScreenProps> = ({
|
|
|
101
102
|
|
|
102
103
|
// Construct themes from texts prop
|
|
103
104
|
// This adheres to "Package Driven Design" where content is driven by the consumer (App)
|
|
104
|
-
const themes = [];
|
|
105
|
+
const themes: ThemeOptionConfig[] = [];
|
|
105
106
|
|
|
106
107
|
// We only add the theme option if the corresponding text config is provided
|
|
107
108
|
if (texts?.lightMode) {
|
|
@@ -3,5 +3,7 @@
|
|
|
3
3
|
* Frequently asked questions
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export * from './presentation/screens/
|
|
7
|
-
export * from './presentation/components
|
|
6
|
+
export * from './presentation/screens/FAQScreen';
|
|
7
|
+
export * from './presentation/components';
|
|
8
|
+
export * from './presentation/hooks';
|
|
9
|
+
export * from './domain/entities/FAQEntity';
|
|
@@ -3,4 +3,8 @@
|
|
|
3
3
|
* User feedback, bug reports
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export * from './presentation/
|
|
6
|
+
export * from './presentation/components/FeedbackForm';
|
|
7
|
+
export * from './presentation/components/FeedbackModal';
|
|
8
|
+
export * from './presentation/components/SupportSection';
|
|
9
|
+
export * from './presentation/hooks/useFeedbackForm';
|
|
10
|
+
export * from './domain/entities/FeedbackEntity';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type RatingValue = 0 | 1 | 2 | 3 | 4 | 5;
|
|
2
|
+
|
|
3
|
+
export interface Rating {
|
|
4
|
+
id: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
entityId: string;
|
|
7
|
+
entityType: string;
|
|
8
|
+
value: RatingValue;
|
|
9
|
+
createdAt: string;
|
|
10
|
+
updatedAt: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface RatingStats {
|
|
14
|
+
average: number;
|
|
15
|
+
count: number;
|
|
16
|
+
distribution: Record<RatingValue, number>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rating Domain
|
|
3
|
+
* Star ratings, user reviews, and statistics
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// DOMAIN LAYER - Entities
|
|
8
|
+
// =============================================================================
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
RatingValue,
|
|
12
|
+
Rating,
|
|
13
|
+
RatingStats,
|
|
14
|
+
} from './domain/entities/Rating';
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// PRESENTATION LAYER - Components
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
export { StarRating } from './presentation/components/StarRating';
|
|
21
|
+
export type { StarRatingProps } from './presentation/components/StarRating';
|
|
22
|
+
|
|
23
|
+
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { View, StyleSheet, TouchableOpacity, ViewStyle } from "react-native";
|
|
3
|
+
import { useAppDesignTokens, AtomicIcon } from "@umituz/react-native-design-system";
|
|
4
|
+
|
|
5
|
+
export interface StarRatingProps {
|
|
6
|
+
rating: number;
|
|
7
|
+
maxRating?: number;
|
|
8
|
+
onRatingChange?: (rating: number) => void;
|
|
9
|
+
size?: number;
|
|
10
|
+
activeColor?: string;
|
|
11
|
+
inactiveColor?: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
style?: ViewStyle;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const StarRating: React.FC<StarRatingProps> = ({
|
|
17
|
+
rating,
|
|
18
|
+
maxRating = 5,
|
|
19
|
+
onRatingChange,
|
|
20
|
+
size = 24,
|
|
21
|
+
activeColor,
|
|
22
|
+
inactiveColor,
|
|
23
|
+
disabled = false,
|
|
24
|
+
style,
|
|
25
|
+
}) => {
|
|
26
|
+
const tokens = useAppDesignTokens();
|
|
27
|
+
const [internalRating, setInternalRating] = useState(rating);
|
|
28
|
+
|
|
29
|
+
const filledColor = activeColor || tokens.colors.warning || "#FFD700";
|
|
30
|
+
const emptyColor = inactiveColor || tokens.colors.border || "#E0E0E0";
|
|
31
|
+
|
|
32
|
+
const handlePress = (index: number) => {
|
|
33
|
+
if (disabled) return;
|
|
34
|
+
const newRating = index + 1;
|
|
35
|
+
setInternalRating(newRating);
|
|
36
|
+
onRatingChange?.(newRating);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<View style={[styles.container, style]}>
|
|
41
|
+
{Array.from({ length: maxRating }).map((_, index) => (
|
|
42
|
+
<TouchableOpacity
|
|
43
|
+
key={index}
|
|
44
|
+
onPress={() => handlePress(index)}
|
|
45
|
+
disabled={disabled}
|
|
46
|
+
activeOpacity={0.7}
|
|
47
|
+
style={styles.starContainer}
|
|
48
|
+
>
|
|
49
|
+
<AtomicIcon
|
|
50
|
+
name={index < (onRatingChange ? internalRating : rating) ? "star" : "star-outline"}
|
|
51
|
+
customSize={size}
|
|
52
|
+
customColor={index < (onRatingChange ? internalRating : rating) ? filledColor : emptyColor}
|
|
53
|
+
/>
|
|
54
|
+
</TouchableOpacity>
|
|
55
|
+
))}
|
|
56
|
+
</View>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const styles = StyleSheet.create({
|
|
61
|
+
container: {
|
|
62
|
+
flexDirection: "row",
|
|
63
|
+
alignItems: "center",
|
|
64
|
+
gap: 4,
|
|
65
|
+
},
|
|
66
|
+
starContainer: {
|
|
67
|
+
padding: 4,
|
|
68
|
+
},
|
|
69
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -99,6 +99,9 @@ export * from './domains/feedback';
|
|
|
99
99
|
// FAQs Domain - Frequently asked questions
|
|
100
100
|
export * from './domains/faqs';
|
|
101
101
|
|
|
102
|
+
// Rating Domain - Star ratings, reviews, statistics
|
|
103
|
+
export * from './domains/rating';
|
|
104
|
+
|
|
102
105
|
// =============================================================================
|
|
103
106
|
// PRESENTATION LAYER - Re-exports from Dependencies
|
|
104
107
|
// =============================================================================
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Appearance Settings Screen
|
|
3
3
|
* Advanced appearance settings with theme customization and custom colors
|
|
4
|
-
*
|
|
4
|
+
* Now uses consolidated appearance domain
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
import { AppearanceScreen } from "@umituz/react-native-appearance";
|
|
9
|
-
|
|
10
|
-
export { AppearanceScreen };
|
|
7
|
+
export { AppearanceScreen } from "@domains/appearance/presentation/screens/AppearanceScreen";
|
|
@@ -13,11 +13,11 @@ import { ProfileSection } from "@umituz/react-native-auth";
|
|
|
13
13
|
import { SettingsSection } from "../../components/SettingsSection";
|
|
14
14
|
import { DevSettingsSection, DevSettingsProps } from "../../components/DevSettingsSection";
|
|
15
15
|
import { NotificationsSection } from "@umituz/react-native-notifications";
|
|
16
|
-
import { AboutSection } from "@
|
|
17
|
-
import { LegalSection } from "@
|
|
18
|
-
import { AppearanceSection } from "@
|
|
16
|
+
import { AboutSection } from "@domains/about/presentation/components/AboutSection";
|
|
17
|
+
import { LegalSection } from "@domains/legal/presentation/components/LegalSection";
|
|
18
|
+
import { AppearanceSection } from "@domains/appearance/presentation/components/AppearanceSection";
|
|
19
19
|
import { LanguageSection } from "@umituz/react-native-localization";
|
|
20
|
-
import { SupportSection } from "@
|
|
20
|
+
import { SupportSection } from "@domains/feedback/presentation/components/SupportSection";
|
|
21
21
|
import { SettingItem } from "../../components/SettingItem";
|
|
22
22
|
import type { NormalizedConfig } from "../utils/normalizeConfig";
|
|
23
23
|
import type { CustomSettingsSection } from "../types";
|
|
@@ -190,7 +190,6 @@ export const SettingsContent: React.FC<SettingsContentProps> = ({
|
|
|
190
190
|
normalizedConfig.language.config?.description ||
|
|
191
191
|
t("settings.languageSelection.description"),
|
|
192
192
|
}}
|
|
193
|
-
sectionTitle={t("settings.languageSelection.title")}
|
|
194
193
|
/>
|
|
195
194
|
)}
|
|
196
195
|
|
|
@@ -197,7 +197,7 @@ export interface SubscriptionConfig {
|
|
|
197
197
|
};
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
import type { FeedbackType } from "@
|
|
200
|
+
import type { FeedbackType } from "@domains/feedback/domain/entities/FeedbackEntity";
|
|
201
201
|
|
|
202
202
|
/**
|
|
203
203
|
* Feedback Settings Configuration
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Delete Feedback Hook
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
6
|
-
import type { IFeedbackRepository } from '../../domain/repositories/IFeedbackRepository';
|
|
7
|
-
|
|
8
|
-
export function useDeleteFeedback(repository: IFeedbackRepository) {
|
|
9
|
-
const queryClient = useQueryClient();
|
|
10
|
-
|
|
11
|
-
return useMutation({
|
|
12
|
-
mutationFn: async (feedbackId: string) => {
|
|
13
|
-
const result = await repository.deleteFeedback(feedbackId);
|
|
14
|
-
|
|
15
|
-
if (!result.success) {
|
|
16
|
-
throw new Error(result.error.message);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return result.data;
|
|
20
|
-
},
|
|
21
|
-
onSuccess: () => {
|
|
22
|
-
queryClient.invalidateQueries({ queryKey: ['feedback'] });
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Submit Feedback Hook
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
6
|
-
import type { IFeedbackRepository } from '../../domain/repositories/IFeedbackRepository';
|
|
7
|
-
import {
|
|
8
|
-
createFeedback,
|
|
9
|
-
type FeedbackType,
|
|
10
|
-
} from '../../domain/entities/FeedbackEntity';
|
|
11
|
-
|
|
12
|
-
interface SubmitFeedbackParams {
|
|
13
|
-
userId: string | null;
|
|
14
|
-
userEmail?: string | null;
|
|
15
|
-
type: FeedbackType;
|
|
16
|
-
title: string;
|
|
17
|
-
description: string;
|
|
18
|
-
rating?: 1 | 2 | 3 | 4 | 5;
|
|
19
|
-
deviceInfo?: {
|
|
20
|
-
platform: string;
|
|
21
|
-
osVersion: string;
|
|
22
|
-
appVersion: string;
|
|
23
|
-
};
|
|
24
|
-
metadata?: Record<string, unknown>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function useSubmitFeedback(repository: IFeedbackRepository) {
|
|
28
|
-
const queryClient = useQueryClient();
|
|
29
|
-
|
|
30
|
-
return useMutation({
|
|
31
|
-
mutationFn: async (params: SubmitFeedbackParams) => {
|
|
32
|
-
const feedback = createFeedback(
|
|
33
|
-
params.userId,
|
|
34
|
-
params.type,
|
|
35
|
-
params.title,
|
|
36
|
-
params.description,
|
|
37
|
-
params.userEmail,
|
|
38
|
-
params.rating,
|
|
39
|
-
params.deviceInfo,
|
|
40
|
-
params.metadata
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
const result = await repository.submitFeedback(feedback);
|
|
44
|
-
|
|
45
|
-
if (!result.success) {
|
|
46
|
-
throw new Error(result.error.message);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return result.data;
|
|
50
|
-
},
|
|
51
|
-
onSuccess: () => {
|
|
52
|
-
queryClient.invalidateQueries({ queryKey: ['feedback'] });
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* User Feedback Hook
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { useQuery } from '@tanstack/react-query';
|
|
6
|
-
import type { IFeedbackRepository } from '../../domain/repositories/IFeedbackRepository';
|
|
7
|
-
|
|
8
|
-
export function useUserFeedback(
|
|
9
|
-
repository: IFeedbackRepository,
|
|
10
|
-
userId: string | null
|
|
11
|
-
) {
|
|
12
|
-
return useQuery({
|
|
13
|
-
queryKey: ['feedback', userId],
|
|
14
|
-
queryFn: async () => {
|
|
15
|
-
if (!userId) {
|
|
16
|
-
return [];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const result = await repository.getUserFeedback(userId);
|
|
20
|
-
|
|
21
|
-
if (!result.success) {
|
|
22
|
-
throw new Error(result.error.message);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return result.data;
|
|
26
|
-
},
|
|
27
|
-
enabled: !!userId,
|
|
28
|
-
});
|
|
29
|
-
}
|