@umituz/react-native-settings 5.3.42 → 5.3.44
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/dist/account.d.ts +1 -2
- package/dist/domains/feedback/domain/entities/FeatureRequestEntity.d.ts +0 -10
- package/dist/domains/feedback/domain/entities/FeedbackEntity.d.ts +0 -20
- package/dist/domains/feedback/index.d.ts +0 -1
- package/dist/presentation/utils/index.d.ts +0 -1
- package/package.json +1 -1
- package/src/account.ts +1 -4
- package/src/domains/feedback/README.md +2 -4
- package/src/domains/feedback/domain/entities/FeatureRequestEntity.ts +0 -12
- package/src/domains/feedback/domain/entities/FeedbackEntity.ts +0 -47
- package/src/domains/feedback/index.ts +0 -1
- package/src/domains/feedback/infrastructure/useFeatureRequests.ts +43 -12
- package/src/domains/feedback/presentation/screens/FeatureRequestScreen.tsx +7 -17
- package/src/presentation/hooks/useSettingsScreenConfig.ts +1 -7
- package/src/presentation/utils/index.ts +0 -1
- package/src/domains/feedback/domain/repositories/IFeedbackRepository.ts +0 -28
- package/src/presentation/utils/faqTranslator.ts +0 -9
package/dist/account.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* import {
|
|
9
|
-
*
|
|
9
|
+
* useSettingsScreenConfig,
|
|
10
10
|
* AccountScreen,
|
|
11
11
|
* ProfileSection,
|
|
12
12
|
* } from '@umituz/react-native-settings/account';
|
|
@@ -22,6 +22,5 @@ export { AccountScreen, ProfileSection } from "@umituz/react-native-auth";
|
|
|
22
22
|
export { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
|
|
23
23
|
export type { AccountScreenConfig } from "@umituz/react-native-auth";
|
|
24
24
|
export { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
|
|
25
|
-
export { useSettingsScreenConfig as useSettingsScreenConfigWithAuth } from './presentation/hooks/useSettingsScreenConfig';
|
|
26
25
|
export type { UseSettingsScreenConfigParams, SettingsScreenConfigResult, SettingsFeatures, } from './presentation/hooks/useSettingsScreenConfig';
|
|
27
26
|
export type { AccountConfig } from './presentation/navigation/types';
|
|
@@ -18,13 +18,3 @@ export interface FeatureRequestItem {
|
|
|
18
18
|
createdAt: string;
|
|
19
19
|
updatedAt: string;
|
|
20
20
|
}
|
|
21
|
-
export interface FeatureRequestVote {
|
|
22
|
-
type: VoteType;
|
|
23
|
-
votedAt: string;
|
|
24
|
-
}
|
|
25
|
-
export interface FeatureRequestSubmitData {
|
|
26
|
-
title: string;
|
|
27
|
-
description: string;
|
|
28
|
-
type: string;
|
|
29
|
-
rating?: number;
|
|
30
|
-
}
|
|
@@ -2,24 +2,4 @@
|
|
|
2
2
|
* Feedback Entity
|
|
3
3
|
*/
|
|
4
4
|
export type FeedbackType = 'general' | 'bug_report' | 'feature_request' | 'improvement' | 'other';
|
|
5
|
-
export type FeedbackStatus = 'pending' | 'reviewed' | 'resolved' | 'closed';
|
|
6
5
|
export type FeedbackRating = 1 | 2 | 3 | 4 | 5;
|
|
7
|
-
export interface FeedbackEntity {
|
|
8
|
-
id: string;
|
|
9
|
-
userId: string | null;
|
|
10
|
-
userEmail?: string | null;
|
|
11
|
-
type: FeedbackType;
|
|
12
|
-
title: string;
|
|
13
|
-
description: string;
|
|
14
|
-
rating?: FeedbackRating;
|
|
15
|
-
status: FeedbackStatus;
|
|
16
|
-
deviceInfo?: {
|
|
17
|
-
platform: string;
|
|
18
|
-
osVersion: string;
|
|
19
|
-
appVersion: string;
|
|
20
|
-
};
|
|
21
|
-
metadata?: Record<string, unknown>;
|
|
22
|
-
createdAt: string;
|
|
23
|
-
updatedAt: string;
|
|
24
|
-
}
|
|
25
|
-
export declare function createFeedback(userId: string | null, type: FeedbackType, title: string, description: string, userEmail?: string | null, rating?: FeedbackRating, deviceInfo?: FeedbackEntity['deviceInfo'], metadata?: Record<string, unknown>): Omit<FeedbackEntity, 'id'>;
|
|
@@ -8,4 +8,3 @@ export * from './presentation/components/SupportSection';
|
|
|
8
8
|
export * from './presentation/hooks/useFeedbackForm';
|
|
9
9
|
export * from './domain/entities/FeedbackEntity';
|
|
10
10
|
export * from './domain/entities/FeatureRequestEntity';
|
|
11
|
-
export * from './domain/repositories/IFeedbackRepository';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.44",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
package/src/account.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
8
|
* import {
|
|
9
|
-
*
|
|
9
|
+
* useSettingsScreenConfig,
|
|
10
10
|
* AccountScreen,
|
|
11
11
|
* ProfileSection,
|
|
12
12
|
* } from '@umituz/react-native-settings/account';
|
|
@@ -31,9 +31,6 @@ export type { AccountScreenConfig } from "@umituz/react-native-auth";
|
|
|
31
31
|
// Base hook (already handles auth internally via useAuth/useUserProfile/useAuthHandlers)
|
|
32
32
|
export { useSettingsScreenConfig } from './presentation/hooks/useSettingsScreenConfig';
|
|
33
33
|
|
|
34
|
-
// Alias for clarity - useSettingsScreenConfig already includes auth
|
|
35
|
-
export { useSettingsScreenConfig as useSettingsScreenConfigWithAuth } from './presentation/hooks/useSettingsScreenConfig';
|
|
36
|
-
|
|
37
34
|
// Re-export types
|
|
38
35
|
export type {
|
|
39
36
|
UseSettingsScreenConfigParams,
|
|
@@ -16,7 +16,7 @@ Provides components and utilities for collecting user feedback including feedbac
|
|
|
16
16
|
|
|
17
17
|
**Domain:**
|
|
18
18
|
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/feedback/domain/entities/FeedbackEntity.ts`
|
|
19
|
-
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/feedback/domain/
|
|
19
|
+
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/feedback/domain/entities/FeatureRequestEntity.ts`
|
|
20
20
|
|
|
21
21
|
**Index:**
|
|
22
22
|
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-settings/src/domains/feedback/index.ts`
|
|
@@ -26,14 +26,12 @@ Provides components and utilities for collecting user feedback including feedbac
|
|
|
26
26
|
1. **Form State Management**: Use useFeedbackForm hook for centralized form state and validation
|
|
27
27
|
2. **Type Categorization**: Categorize feedback by type (bug, feature, general, etc.) for better routing
|
|
28
28
|
3. **Star Rating Integration**: Integrate with Rating domain for 1-5 star ratings
|
|
29
|
-
4. **
|
|
30
|
-
5. **Validation First**: Always validate form state before submission to prevent invalid data
|
|
29
|
+
4. **Validation First**: Always validate form state before submission to prevent invalid data
|
|
31
30
|
|
|
32
31
|
## Restrictions (Forbidden)
|
|
33
32
|
|
|
34
33
|
### DO NOT
|
|
35
34
|
- ❌ DO NOT submit feedback without validating required fields (type, title)
|
|
36
|
-
- ❌ DO NOT bypass the repository pattern when submitting feedback
|
|
37
35
|
- ❌ DO NOT use FeedbackForm without providing texts configuration
|
|
38
36
|
- ❌ DO NOT handle feedback submission manually when the hook provides everything needed
|
|
39
37
|
|
|
@@ -21,15 +21,3 @@ export interface FeatureRequestItem {
|
|
|
21
21
|
createdAt: string;
|
|
22
22
|
updatedAt: string;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
export interface FeatureRequestVote {
|
|
26
|
-
type: VoteType;
|
|
27
|
-
votedAt: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface FeatureRequestSubmitData {
|
|
31
|
-
title: string;
|
|
32
|
-
description: string;
|
|
33
|
-
type: string;
|
|
34
|
-
rating?: number;
|
|
35
|
-
}
|
|
@@ -9,51 +9,4 @@ export type FeedbackType =
|
|
|
9
9
|
| 'improvement'
|
|
10
10
|
| 'other';
|
|
11
11
|
|
|
12
|
-
export type FeedbackStatus = 'pending' | 'reviewed' | 'resolved' | 'closed';
|
|
13
|
-
|
|
14
12
|
export type FeedbackRating = 1 | 2 | 3 | 4 | 5;
|
|
15
|
-
|
|
16
|
-
export interface FeedbackEntity {
|
|
17
|
-
id: string;
|
|
18
|
-
userId: string | null;
|
|
19
|
-
userEmail?: string | null;
|
|
20
|
-
type: FeedbackType;
|
|
21
|
-
title: string;
|
|
22
|
-
description: string;
|
|
23
|
-
rating?: FeedbackRating;
|
|
24
|
-
status: FeedbackStatus;
|
|
25
|
-
deviceInfo?: {
|
|
26
|
-
platform: string;
|
|
27
|
-
osVersion: string;
|
|
28
|
-
appVersion: string;
|
|
29
|
-
};
|
|
30
|
-
metadata?: Record<string, unknown>;
|
|
31
|
-
createdAt: string;
|
|
32
|
-
updatedAt: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function createFeedback(
|
|
36
|
-
userId: string | null,
|
|
37
|
-
type: FeedbackType,
|
|
38
|
-
title: string,
|
|
39
|
-
description: string,
|
|
40
|
-
userEmail?: string | null,
|
|
41
|
-
rating?: FeedbackRating,
|
|
42
|
-
deviceInfo?: FeedbackEntity['deviceInfo'],
|
|
43
|
-
metadata?: Record<string, unknown>
|
|
44
|
-
): Omit<FeedbackEntity, 'id'> {
|
|
45
|
-
const now = new Date().toISOString();
|
|
46
|
-
return {
|
|
47
|
-
userId,
|
|
48
|
-
userEmail,
|
|
49
|
-
type,
|
|
50
|
-
title,
|
|
51
|
-
description,
|
|
52
|
-
rating,
|
|
53
|
-
status: 'pending',
|
|
54
|
-
deviceInfo,
|
|
55
|
-
metadata,
|
|
56
|
-
createdAt: now,
|
|
57
|
-
updatedAt: now,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
@@ -9,4 +9,3 @@ export * from './presentation/components/SupportSection';
|
|
|
9
9
|
export * from './presentation/hooks/useFeedbackForm';
|
|
10
10
|
export * from './domain/entities/FeedbackEntity';
|
|
11
11
|
export * from './domain/entities/FeatureRequestEntity';
|
|
12
|
-
export * from './domain/repositories/IFeedbackRepository';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Works with both authenticated and anonymous users
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { useState, useEffect, useCallback } from "react";
|
|
7
|
+
import { useState, useEffect, useCallback, useRef } from "react";
|
|
8
8
|
import { Platform } from "react-native";
|
|
9
9
|
import { useAuth } from "@umituz/react-native-auth";
|
|
10
10
|
import {
|
|
@@ -48,6 +48,13 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
48
48
|
const [userVotes, setUserVotes] = useState<Record<string, VoteType>>({});
|
|
49
49
|
const [isLoading, setIsLoading] = useState(true);
|
|
50
50
|
|
|
51
|
+
// Ref to avoid stale closure in vote()
|
|
52
|
+
const userVotesRef = useRef(userVotes);
|
|
53
|
+
userVotesRef.current = userVotes;
|
|
54
|
+
|
|
55
|
+
// Guard against rapid double-tap on the same request
|
|
56
|
+
const votingInProgress = useRef(new Set<string>());
|
|
57
|
+
|
|
51
58
|
const fetchAll = useCallback(async () => {
|
|
52
59
|
const db = getFirestore();
|
|
53
60
|
if (!db) {
|
|
@@ -58,7 +65,6 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
58
65
|
try {
|
|
59
66
|
setIsLoading(true);
|
|
60
67
|
|
|
61
|
-
// Fetch requests
|
|
62
68
|
const q = query(collection(db, COLLECTION), orderBy("votes", "desc"));
|
|
63
69
|
const snapshot = await getDocs(q);
|
|
64
70
|
|
|
@@ -82,17 +88,25 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
82
88
|
|
|
83
89
|
setRequests(items);
|
|
84
90
|
|
|
85
|
-
// Fetch user votes
|
|
86
|
-
if (userId) {
|
|
87
|
-
const
|
|
88
|
-
for (const reqDoc of snapshot.docs) {
|
|
91
|
+
// Fetch user votes in parallel (not N+1 sequential)
|
|
92
|
+
if (userId && snapshot.docs.length > 0) {
|
|
93
|
+
const votePromises = snapshot.docs.map(async (reqDoc) => {
|
|
89
94
|
const voteRef = doc(db, COLLECTION, reqDoc.id, "votes", userId);
|
|
90
95
|
const voteSnap = await getDoc(voteRef);
|
|
91
96
|
if (voteSnap.exists()) {
|
|
92
|
-
|
|
97
|
+
return [reqDoc.id, voteSnap.data().type as VoteType] as const;
|
|
93
98
|
}
|
|
99
|
+
return null;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const results = await Promise.all(votePromises);
|
|
103
|
+
const votes: Record<string, VoteType> = {};
|
|
104
|
+
for (const result of results) {
|
|
105
|
+
if (result) votes[result[0]] = result[1];
|
|
94
106
|
}
|
|
95
107
|
setUserVotes(votes);
|
|
108
|
+
} else {
|
|
109
|
+
setUserVotes({});
|
|
96
110
|
}
|
|
97
111
|
} catch (error) {
|
|
98
112
|
if (__DEV__) console.warn("[useFeatureRequests] Load failed:", error);
|
|
@@ -108,10 +122,18 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
108
122
|
const vote = useCallback(async (requestId: string, type: VoteType) => {
|
|
109
123
|
if (!userId) return;
|
|
110
124
|
|
|
125
|
+
// Prevent rapid double-tap on the same request
|
|
126
|
+
if (votingInProgress.current.has(requestId)) return;
|
|
127
|
+
votingInProgress.current.add(requestId);
|
|
128
|
+
|
|
111
129
|
const db = getFirestore();
|
|
112
|
-
if (!db)
|
|
130
|
+
if (!db) {
|
|
131
|
+
votingInProgress.current.delete(requestId);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
113
134
|
|
|
114
|
-
|
|
135
|
+
// Read latest vote from ref (not stale closure)
|
|
136
|
+
const previousVote = userVotesRef.current[requestId] as VoteType | undefined;
|
|
115
137
|
const isUndo = previousVote === type;
|
|
116
138
|
|
|
117
139
|
// Optimistic UI
|
|
@@ -150,23 +172,26 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
150
172
|
await updateDoc(requestRef, { votes: increment(type === "up" ? 1 : -1) });
|
|
151
173
|
}
|
|
152
174
|
} catch (error) {
|
|
153
|
-
// Rollback
|
|
154
175
|
if (__DEV__) console.warn("[useFeatureRequests] Vote failed:", error);
|
|
176
|
+
// Rollback using previous known state
|
|
155
177
|
setUserVotes((prev) => {
|
|
156
178
|
const next = { ...prev };
|
|
157
179
|
if (previousVote) next[requestId] = previousVote; else delete next[requestId];
|
|
158
180
|
return next;
|
|
159
181
|
});
|
|
160
182
|
fetchAll();
|
|
183
|
+
} finally {
|
|
184
|
+
votingInProgress.current.delete(requestId);
|
|
161
185
|
}
|
|
162
|
-
}, [userId,
|
|
186
|
+
}, [userId, fetchAll]);
|
|
163
187
|
|
|
164
188
|
const submitRequest = useCallback(async (data: { title: string; description: string; type: string; rating?: number }) => {
|
|
165
189
|
const db = getFirestore();
|
|
166
190
|
if (!db) throw new Error("Firestore not available");
|
|
167
191
|
if (!userId) throw new Error("User not authenticated");
|
|
168
192
|
|
|
169
|
-
|
|
193
|
+
// Create the feature request
|
|
194
|
+
const docRef = await addDoc(collection(db, COLLECTION), {
|
|
170
195
|
title: data.title,
|
|
171
196
|
description: data.description,
|
|
172
197
|
type: data.type || "feature_request",
|
|
@@ -181,6 +206,12 @@ export function useFeatureRequests(): UseFeatureRequestsResult {
|
|
|
181
206
|
updatedAt: serverTimestamp(),
|
|
182
207
|
});
|
|
183
208
|
|
|
209
|
+
// Create the creator's upvote doc so votes count matches reality
|
|
210
|
+
await setDoc(doc(db, COLLECTION, docRef.id, "votes", userId), {
|
|
211
|
+
type: "up" as VoteType,
|
|
212
|
+
votedAt: serverTimestamp(),
|
|
213
|
+
});
|
|
214
|
+
|
|
184
215
|
await fetchAll();
|
|
185
216
|
}, [userId, user?.isAnonymous, fetchAll]);
|
|
186
217
|
|
|
@@ -4,13 +4,11 @@ import {
|
|
|
4
4
|
StyleSheet,
|
|
5
5
|
TouchableOpacity,
|
|
6
6
|
ScrollView,
|
|
7
|
-
FlatList,
|
|
8
7
|
ActivityIndicator,
|
|
9
8
|
} from "react-native";
|
|
10
9
|
import {
|
|
11
10
|
AtomicText,
|
|
12
11
|
AtomicIcon,
|
|
13
|
-
AtomicButton,
|
|
14
12
|
} from "@umituz/react-native-design-system/atoms";
|
|
15
13
|
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
16
14
|
import { ScreenLayout } from "@umituz/react-native-design-system/layouts";
|
|
@@ -47,10 +45,6 @@ export const FeatureRequestScreen: React.FC<any> = ({ config, texts }) => {
|
|
|
47
45
|
dismissed: t.status?.dismissed || "Dismissed",
|
|
48
46
|
};
|
|
49
47
|
|
|
50
|
-
const handleVote = useCallback(async (id: string, type: VoteType) => {
|
|
51
|
-
await vote(id, type);
|
|
52
|
-
}, [vote]);
|
|
53
|
-
|
|
54
48
|
const handleSubmit = useCallback(async (data: any) => {
|
|
55
49
|
setIsSubmitting(true);
|
|
56
50
|
try {
|
|
@@ -90,19 +84,19 @@ export const FeatureRequestScreen: React.FC<any> = ({ config, texts }) => {
|
|
|
90
84
|
}
|
|
91
85
|
})();
|
|
92
86
|
|
|
93
|
-
const
|
|
87
|
+
const renderRequestCard = (item: FeatureRequestItem) => {
|
|
94
88
|
const voted = userVotes[item.id] || null;
|
|
95
89
|
|
|
96
90
|
return (
|
|
97
|
-
<View style={[styles.card, { backgroundColor: tokens.colors.surfaceSecondary, borderColor: tokens.colors.borderLight }]}>
|
|
91
|
+
<View key={item.id} style={[styles.card, { backgroundColor: tokens.colors.surfaceSecondary, borderColor: tokens.colors.borderLight }]}>
|
|
98
92
|
<View style={styles.voteColumn}>
|
|
99
|
-
<TouchableOpacity onPress={() =>
|
|
93
|
+
<TouchableOpacity onPress={() => vote(item.id, 'up')}>
|
|
100
94
|
<AtomicIcon name="chevron-up" size="md" color={voted === 'up' ? "primary" : "textSecondary" as any} />
|
|
101
95
|
</TouchableOpacity>
|
|
102
96
|
<AtomicText style={[styles.voteCount, { color: voted === 'up' ? tokens.colors.primary : tokens.colors.textPrimary }]}>
|
|
103
97
|
{item.votes}
|
|
104
98
|
</AtomicText>
|
|
105
|
-
<TouchableOpacity onPress={() =>
|
|
99
|
+
<TouchableOpacity onPress={() => vote(item.id, 'down')}>
|
|
106
100
|
<AtomicIcon name="chevron-down" size="md" color={voted === 'down' ? "primary" : "textSecondary" as any} />
|
|
107
101
|
</TouchableOpacity>
|
|
108
102
|
</View>
|
|
@@ -196,13 +190,9 @@ export const FeatureRequestScreen: React.FC<any> = ({ config, texts }) => {
|
|
|
196
190
|
</AtomicText>
|
|
197
191
|
</View>
|
|
198
192
|
) : (
|
|
199
|
-
<
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
keyExtractor={item => item.id}
|
|
203
|
-
scrollEnabled={false}
|
|
204
|
-
contentContainerStyle={styles.listContent}
|
|
205
|
-
/>
|
|
193
|
+
<View style={styles.listContent}>
|
|
194
|
+
{filteredRequests.map(renderRequestCard)}
|
|
195
|
+
</View>
|
|
206
196
|
)}
|
|
207
197
|
</ScrollView>
|
|
208
198
|
|
|
@@ -10,7 +10,6 @@ import { useMemo } from "react";
|
|
|
10
10
|
import { useAuth, useUserProfile, useAuthHandlers } from "@umituz/react-native-auth";
|
|
11
11
|
import { createUserProfileDisplay } from "../utils/userProfileUtils";
|
|
12
12
|
import { createAccountConfig } from "../utils/accountConfigUtils";
|
|
13
|
-
import { translateFAQData } from "../utils/faqTranslator";
|
|
14
13
|
import { useSettingsConfigFactory } from "../utils/settingsConfigFactory";
|
|
15
14
|
import type { SettingsConfig, SettingsTranslations } from "../screens/types";
|
|
16
15
|
import type { FeedbackFormData } from "../utils/config-creators";
|
|
@@ -151,16 +150,11 @@ export const useSettingsScreenConfig = (
|
|
|
151
150
|
translations: translations?.account as any,
|
|
152
151
|
}), [user, userProfileData, handleSignIn, handleSignOut, handleDeleteAccount, translations]);
|
|
153
152
|
|
|
154
|
-
const translatedFaqData = useMemo(() =>
|
|
155
|
-
translateFAQData(faqData, appInfo),
|
|
156
|
-
[faqData, appInfo]
|
|
157
|
-
);
|
|
158
|
-
|
|
159
153
|
return {
|
|
160
154
|
settingsConfig,
|
|
161
155
|
userProfile,
|
|
162
156
|
accountConfig,
|
|
163
|
-
translatedFaqData,
|
|
157
|
+
translatedFaqData: faqData,
|
|
164
158
|
isLoading: loading,
|
|
165
159
|
isAuthReady,
|
|
166
160
|
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Feedback Repository Interface
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import type { FeedbackEntity } from '../entities/FeedbackEntity';
|
|
6
|
-
|
|
7
|
-
export interface FeedbackError {
|
|
8
|
-
message: string;
|
|
9
|
-
code?: 'SUBMIT_FAILED' | 'FETCH_FAILED' | 'DELETE_FAILED' | 'VALIDATION_ERROR';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type FeedbackResult<T> =
|
|
13
|
-
| {
|
|
14
|
-
success: true;
|
|
15
|
-
data: T;
|
|
16
|
-
}
|
|
17
|
-
| {
|
|
18
|
-
success: false;
|
|
19
|
-
error: FeedbackError;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export interface IFeedbackRepository {
|
|
23
|
-
submitFeedback(
|
|
24
|
-
feedback: FeedbackEntity | Omit<FeedbackEntity, 'id'>
|
|
25
|
-
): Promise<FeedbackResult<FeedbackEntity>>;
|
|
26
|
-
getUserFeedback(userId: string): Promise<FeedbackResult<FeedbackEntity[]>>;
|
|
27
|
-
deleteFeedback(feedbackId: string): Promise<FeedbackResult<boolean>>;
|
|
28
|
-
}
|