@umituz/react-native-ai-generation-content 1.17.0 → 1.17.1
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 +13 -14
- package/src/domains/creations/domain/entities/Creation.ts +33 -2
- package/src/domains/creations/domain/entities/index.ts +1 -1
- package/src/domains/creations/domain/types/creation-categories.ts +133 -0
- package/src/domains/creations/domain/types/creation-filter.ts +131 -0
- package/src/domains/creations/domain/types/creation-types.ts +63 -0
- package/src/domains/creations/domain/types/index.ts +44 -0
- package/src/domains/creations/domain/utils/creation-helpers.ts +134 -0
- package/src/domains/creations/domain/utils/index.ts +8 -0
- package/src/domains/creations/domain/utils/preview-helpers.ts +84 -0
- package/src/domains/creations/domain/utils/status-helpers.ts +90 -0
- package/src/domains/creations/index.ts +95 -21
- package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +14 -1
- package/src/domains/creations/presentation/components/CreationActions.tsx +120 -0
- package/src/domains/creations/presentation/components/CreationBadges.tsx +111 -0
- package/src/domains/creations/presentation/components/CreationCard.tsx +201 -102
- package/src/domains/creations/presentation/components/CreationPreview.tsx +117 -0
- package/src/domains/creations/presentation/components/CreationsFilterBar.tsx +254 -0
- package/src/domains/creations/presentation/components/CreationsGrid.tsx +121 -68
- package/src/domains/creations/presentation/components/index.ts +23 -3
- package/src/domains/creations/presentation/hooks/index.ts +1 -0
- package/src/domains/creations/presentation/hooks/useAdvancedFilter.ts +262 -0
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +5 -6
- package/src/features/ai-hug/domain/index.ts +5 -0
- package/src/features/ai-hug/domain/types/ai-hug.types.ts +72 -0
- package/src/features/ai-hug/domain/types/index.ts +14 -0
- package/src/features/ai-hug/index.ts +27 -0
- package/src/features/ai-hug/infrastructure/index.ts +5 -0
- package/src/features/ai-hug/infrastructure/services/ai-hug-executor.ts +96 -0
- package/src/features/ai-hug/infrastructure/services/index.ts +6 -0
- package/src/features/ai-hug/presentation/hooks/index.ts +9 -0
- package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +157 -0
- package/src/features/ai-hug/presentation/index.ts +5 -0
- package/src/features/ai-kiss/domain/index.ts +5 -0
- package/src/features/ai-kiss/domain/types/ai-kiss.types.ts +72 -0
- package/src/features/ai-kiss/domain/types/index.ts +14 -0
- package/src/features/ai-kiss/index.ts +27 -0
- package/src/features/ai-kiss/infrastructure/index.ts +5 -0
- package/src/features/ai-kiss/infrastructure/services/ai-kiss-executor.ts +96 -0
- package/src/features/ai-kiss/infrastructure/services/index.ts +6 -0
- package/src/features/ai-kiss/presentation/hooks/index.ts +9 -0
- package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +157 -0
- package/src/features/ai-kiss/presentation/index.ts +5 -0
- package/src/features/anime-selfie/domain/index.ts +5 -0
- package/src/features/anime-selfie/domain/types/anime-selfie.types.ts +72 -0
- package/src/features/anime-selfie/domain/types/index.ts +15 -0
- package/src/features/anime-selfie/index.ts +28 -0
- package/src/features/anime-selfie/infrastructure/index.ts +5 -0
- package/src/features/anime-selfie/infrastructure/services/anime-selfie-executor.ts +95 -0
- package/src/features/anime-selfie/infrastructure/services/index.ts +6 -0
- package/src/features/anime-selfie/presentation/hooks/index.ts +9 -0
- package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +138 -0
- package/src/features/anime-selfie/presentation/index.ts +5 -0
- package/src/features/background/domain/types/index.ts +15 -0
- package/src/features/background/domain/types/replace-background.types.ts +82 -0
- package/src/features/background/index.ts +31 -3
- package/src/features/background/infrastructure/index.ts +5 -0
- package/src/features/background/infrastructure/services/index.ts +6 -0
- package/src/features/background/infrastructure/services/replace-background-executor.ts +95 -0
- package/src/features/background/presentation/hooks/index.ts +6 -1
- package/src/features/background/presentation/hooks/useReplaceBackgroundFeature.ts +160 -0
- package/src/features/face-swap/domain/index.ts +5 -0
- package/src/features/face-swap/domain/types/face-swap.types.ts +72 -0
- package/src/features/face-swap/domain/types/index.ts +14 -0
- package/src/features/face-swap/index.ts +27 -1
- package/src/features/face-swap/infrastructure/index.ts +5 -0
- package/src/features/face-swap/infrastructure/services/face-swap-executor.ts +96 -0
- package/src/features/face-swap/infrastructure/services/index.ts +6 -0
- package/src/features/face-swap/presentation/hooks/index.ts +9 -0
- package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +157 -0
- package/src/features/face-swap/presentation/index.ts +5 -0
- package/src/features/photo-restoration/domain/types/index.ts +2 -5
- package/src/features/photo-restoration/domain/types/photo-restore.types.ts +14 -0
- package/src/features/photo-restoration/index.ts +3 -8
- package/src/features/photo-restoration/infrastructure/services/index.ts +1 -6
- package/src/features/photo-restoration/infrastructure/services/photo-restore-executor.ts +64 -30
- package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +11 -6
- package/src/features/remove-background/domain/index.ts +5 -0
- package/src/features/remove-background/domain/types/index.ts +14 -0
- package/src/features/remove-background/domain/types/remove-background.types.ts +69 -0
- package/src/features/remove-background/index.ts +27 -0
- package/src/features/remove-background/infrastructure/index.ts +5 -0
- package/src/features/remove-background/infrastructure/services/index.ts +6 -0
- package/src/features/remove-background/infrastructure/services/remove-background-executor.ts +95 -0
- package/src/features/remove-background/presentation/hooks/index.ts +9 -0
- package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +137 -0
- package/src/features/remove-background/presentation/index.ts +5 -0
- package/src/features/remove-object/domain/index.ts +5 -0
- package/src/features/remove-object/domain/types/index.ts +14 -0
- package/src/features/remove-object/domain/types/remove-object.types.ts +77 -0
- package/src/features/remove-object/index.ts +27 -0
- package/src/features/remove-object/infrastructure/index.ts +5 -0
- package/src/features/remove-object/infrastructure/services/index.ts +6 -0
- package/src/features/remove-object/infrastructure/services/remove-object-executor.ts +99 -0
- package/src/features/remove-object/presentation/hooks/index.ts +9 -0
- package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +168 -0
- package/src/features/remove-object/presentation/index.ts +5 -0
- package/src/features/upscaling/domain/types/index.ts +0 -1
- package/src/features/upscaling/domain/types/upscale.types.ts +14 -0
- package/src/features/upscaling/index.ts +3 -11
- package/src/features/upscaling/infrastructure/services/index.ts +1 -6
- package/src/features/upscaling/infrastructure/services/upscale-executor.ts +64 -30
- package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +12 -7
- package/src/index.ts +39 -0
- package/src/types/jsx.d.ts +19 -0
- package/src/features/face-swap/domain/entities.ts +0 -48
- package/src/features/photo-restoration/domain/types/provider.types.ts +0 -23
- package/src/features/photo-restoration/infrastructure/services/photo-restore-provider-registry.ts +0 -77
- package/src/features/upscaling/domain/types/provider.types.ts +0 -23
- package/src/features/upscaling/infrastructure/services/upscale-provider-registry.ts +0 -77
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preview Helpers
|
|
3
|
+
* Utility functions for creation preview/thumbnail extraction
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationOutput } from "../entities/Creation";
|
|
7
|
+
|
|
8
|
+
// Re-export for convenience
|
|
9
|
+
export type { CreationOutput } from "../entities/Creation";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get preview URL from creation output
|
|
13
|
+
* Priority: thumbnailUrl > imageUrl > first imageUrls item > videoUrl > null
|
|
14
|
+
*/
|
|
15
|
+
export function getPreviewUrl(output?: CreationOutput): string | null {
|
|
16
|
+
if (!output) return null;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
output.thumbnailUrl ||
|
|
20
|
+
output.imageUrl ||
|
|
21
|
+
output.imageUrls?.[0] ||
|
|
22
|
+
output.videoUrl ||
|
|
23
|
+
null
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get all available media URLs from creation output
|
|
29
|
+
*/
|
|
30
|
+
export function getAllMediaUrls(output?: CreationOutput): string[] {
|
|
31
|
+
if (!output) return [];
|
|
32
|
+
|
|
33
|
+
const urls: string[] = [];
|
|
34
|
+
|
|
35
|
+
if (output.imageUrl) urls.push(output.imageUrl);
|
|
36
|
+
if (output.imageUrls) urls.push(...output.imageUrls);
|
|
37
|
+
if (output.videoUrl) urls.push(output.videoUrl);
|
|
38
|
+
if (output.audioUrl) urls.push(output.audioUrl);
|
|
39
|
+
|
|
40
|
+
return urls;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if creation has downloadable content
|
|
45
|
+
*/
|
|
46
|
+
export function hasDownloadableContent(output?: CreationOutput): boolean {
|
|
47
|
+
if (!output) return false;
|
|
48
|
+
|
|
49
|
+
return !!(
|
|
50
|
+
output.imageUrl ||
|
|
51
|
+
(output.imageUrls && output.imageUrls.length > 0) ||
|
|
52
|
+
output.videoUrl ||
|
|
53
|
+
output.audioUrl
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Check if creation has video content
|
|
59
|
+
*/
|
|
60
|
+
export function hasVideoContent(output?: CreationOutput): boolean {
|
|
61
|
+
return !!output?.videoUrl;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Check if creation has audio content
|
|
66
|
+
*/
|
|
67
|
+
export function hasAudioContent(output?: CreationOutput): boolean {
|
|
68
|
+
return !!output?.audioUrl;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get primary media URL (for download/share)
|
|
73
|
+
*/
|
|
74
|
+
export function getPrimaryMediaUrl(output?: CreationOutput): string | null {
|
|
75
|
+
if (!output) return null;
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
output.videoUrl ||
|
|
79
|
+
output.imageUrl ||
|
|
80
|
+
output.imageUrls?.[0] ||
|
|
81
|
+
output.audioUrl ||
|
|
82
|
+
null
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Helpers
|
|
3
|
+
* Utility functions for creation status
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationStatus } from "../types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Design system color keys for status
|
|
10
|
+
*/
|
|
11
|
+
export type StatusColorKey = "success" | "primary" | "warning" | "error" | "textSecondary";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get design system color key for status
|
|
15
|
+
*/
|
|
16
|
+
export function getStatusColorKey(status: CreationStatus): StatusColorKey {
|
|
17
|
+
switch (status) {
|
|
18
|
+
case "completed":
|
|
19
|
+
return "success";
|
|
20
|
+
case "processing":
|
|
21
|
+
return "primary";
|
|
22
|
+
case "queued":
|
|
23
|
+
return "warning";
|
|
24
|
+
case "pending":
|
|
25
|
+
return "warning";
|
|
26
|
+
case "failed":
|
|
27
|
+
return "error";
|
|
28
|
+
default:
|
|
29
|
+
return "textSecondary";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get status color from colors object
|
|
35
|
+
*/
|
|
36
|
+
export function getStatusColor(
|
|
37
|
+
status: CreationStatus,
|
|
38
|
+
colors: Record<string, string>,
|
|
39
|
+
): string {
|
|
40
|
+
const key = getStatusColorKey(status);
|
|
41
|
+
return colors[key] || colors.textSecondary;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get i18n key for status text
|
|
46
|
+
*/
|
|
47
|
+
export function getStatusTextKey(status: CreationStatus): string {
|
|
48
|
+
return `creations.status.${status}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get default status text (fallback)
|
|
53
|
+
*/
|
|
54
|
+
export function getStatusText(status: CreationStatus): string {
|
|
55
|
+
switch (status) {
|
|
56
|
+
case "completed":
|
|
57
|
+
return "Completed";
|
|
58
|
+
case "processing":
|
|
59
|
+
return "In Progress";
|
|
60
|
+
case "queued":
|
|
61
|
+
return "Queued";
|
|
62
|
+
case "pending":
|
|
63
|
+
return "Pending";
|
|
64
|
+
case "failed":
|
|
65
|
+
return "Failed";
|
|
66
|
+
default:
|
|
67
|
+
return status;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Check if creation is in progress
|
|
73
|
+
*/
|
|
74
|
+
export function isInProgress(status: CreationStatus): boolean {
|
|
75
|
+
return status === "processing" || status === "pending" || status === "queued";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Check if creation is completed
|
|
80
|
+
*/
|
|
81
|
+
export function isCompleted(status: CreationStatus): boolean {
|
|
82
|
+
return status === "completed";
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if creation has failed
|
|
87
|
+
*/
|
|
88
|
+
export function isFailed(status: CreationStatus): boolean {
|
|
89
|
+
return status === "failed";
|
|
90
|
+
}
|
|
@@ -1,25 +1,77 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Creations Domain
|
|
4
3
|
* AI-generated creations gallery with filtering, sharing, and management
|
|
5
|
-
*
|
|
6
|
-
* Architecture:
|
|
7
|
-
* - Extends BaseRepository from @umituz/react-native-firestore
|
|
8
|
-
* - Fully dynamic path structure (configurable per app)
|
|
9
|
-
* - Fully dynamic document mapping (configurable per app)
|
|
10
|
-
* - App-agnostic: Works with any app, no app-specific code
|
|
11
|
-
*
|
|
12
|
-
* This package is designed to be used across hundreds of apps.
|
|
13
|
-
*
|
|
14
|
-
* Usage:
|
|
15
|
-
* import {
|
|
16
|
-
* CreationsGalleryScreen,
|
|
17
|
-
* CreationsHomeCard,
|
|
18
|
-
* useCreations,
|
|
19
|
-
* createCreationsRepository,
|
|
20
|
-
* } from '@umituz/react-native-ai-creations';
|
|
21
4
|
*/
|
|
22
5
|
|
|
6
|
+
// eslint-disable-next-line no-console
|
|
7
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] creations/index.ts - Module loading");
|
|
8
|
+
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// DOMAIN LAYER - Types
|
|
11
|
+
// =============================================================================
|
|
12
|
+
|
|
13
|
+
export type {
|
|
14
|
+
CreationTypeId,
|
|
15
|
+
CreationStatus,
|
|
16
|
+
CreationCategory,
|
|
17
|
+
CreationFilter,
|
|
18
|
+
FilterOption,
|
|
19
|
+
CreationStats,
|
|
20
|
+
} from "./domain/types";
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
ALL_CREATION_STATUSES,
|
|
24
|
+
ALL_CREATION_CATEGORIES,
|
|
25
|
+
ALL_CREATION_TYPES,
|
|
26
|
+
IMAGE_CREATION_TYPES,
|
|
27
|
+
VIDEO_CREATION_TYPES,
|
|
28
|
+
VOICE_CREATION_TYPES,
|
|
29
|
+
DEFAULT_CREATION_FILTER,
|
|
30
|
+
MEDIA_FILTER_OPTIONS,
|
|
31
|
+
STATUS_FILTER_OPTIONS,
|
|
32
|
+
getTypesForCategory,
|
|
33
|
+
getCategoryForType,
|
|
34
|
+
isTypeInCategory,
|
|
35
|
+
isVideoCreationType,
|
|
36
|
+
isImageCreationType,
|
|
37
|
+
isVoiceCreationType,
|
|
38
|
+
getMediaTypeForCreation,
|
|
39
|
+
calculateCreationStats,
|
|
40
|
+
} from "./domain/types";
|
|
41
|
+
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// DOMAIN LAYER - Utils
|
|
44
|
+
// =============================================================================
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
// Status helpers
|
|
48
|
+
getStatusColorKey,
|
|
49
|
+
getStatusColor,
|
|
50
|
+
getStatusTextKey,
|
|
51
|
+
getStatusText,
|
|
52
|
+
isInProgress,
|
|
53
|
+
isCompleted,
|
|
54
|
+
isFailed,
|
|
55
|
+
type StatusColorKey,
|
|
56
|
+
// Preview helpers
|
|
57
|
+
getPreviewUrl,
|
|
58
|
+
getAllMediaUrls,
|
|
59
|
+
hasDownloadableContent,
|
|
60
|
+
hasVideoContent,
|
|
61
|
+
hasAudioContent,
|
|
62
|
+
getPrimaryMediaUrl,
|
|
63
|
+
type CreationOutput,
|
|
64
|
+
// Creation helpers
|
|
65
|
+
getTypeIcon,
|
|
66
|
+
getTypeTextKey,
|
|
67
|
+
getTypeText,
|
|
68
|
+
getCreationTitle,
|
|
69
|
+
filterBySearch,
|
|
70
|
+
sortCreations,
|
|
71
|
+
truncateText,
|
|
72
|
+
type IconName,
|
|
73
|
+
} from "./domain/utils";
|
|
74
|
+
|
|
23
75
|
// =============================================================================
|
|
24
76
|
// DOMAIN LAYER - Entities
|
|
25
77
|
// =============================================================================
|
|
@@ -28,7 +80,7 @@ export type { Creation, CreationDocument } from "./domain/entities";
|
|
|
28
80
|
export { mapDocumentToCreation } from "./domain/entities";
|
|
29
81
|
|
|
30
82
|
// =============================================================================
|
|
31
|
-
// DOMAIN LAYER -
|
|
83
|
+
// DOMAIN LAYER - Config
|
|
32
84
|
// =============================================================================
|
|
33
85
|
|
|
34
86
|
export type {
|
|
@@ -65,15 +117,37 @@ export type { ICreationsStorageService } from "./domain/services/ICreationsStora
|
|
|
65
117
|
export { useCreations } from "./presentation/hooks/useCreations";
|
|
66
118
|
export { useDeleteCreation } from "./presentation/hooks/useDeleteCreation";
|
|
67
119
|
export { useCreationsFilter } from "./presentation/hooks/useCreationsFilter";
|
|
120
|
+
export { useAdvancedFilter } from "./presentation/hooks/useAdvancedFilter";
|
|
68
121
|
|
|
69
122
|
// =============================================================================
|
|
70
123
|
// PRESENTATION LAYER - Components
|
|
71
124
|
// =============================================================================
|
|
72
125
|
|
|
126
|
+
// Core Components
|
|
127
|
+
export { CreationPreview } from "./presentation/components/CreationPreview";
|
|
128
|
+
export { CreationBadges } from "./presentation/components/CreationBadges";
|
|
129
|
+
export {
|
|
130
|
+
CreationActions,
|
|
131
|
+
type CreationAction,
|
|
132
|
+
} from "./presentation/components/CreationActions";
|
|
133
|
+
export {
|
|
134
|
+
CreationCard,
|
|
135
|
+
type CreationCardData,
|
|
136
|
+
type CreationCardCallbacks,
|
|
137
|
+
} from "./presentation/components/CreationCard";
|
|
73
138
|
export { CreationThumbnail } from "./presentation/components/CreationThumbnail";
|
|
74
|
-
|
|
75
|
-
|
|
139
|
+
|
|
140
|
+
// Filter Components
|
|
76
141
|
export { FilterChips } from "./presentation/components/FilterChips";
|
|
142
|
+
export {
|
|
143
|
+
CreationsFilterBar,
|
|
144
|
+
createMediaFilterButtons,
|
|
145
|
+
createStatusFilterButtons,
|
|
146
|
+
type FilterButton,
|
|
147
|
+
} from "./presentation/components/CreationsFilterBar";
|
|
148
|
+
|
|
149
|
+
// Gallery Components
|
|
150
|
+
export { CreationsHomeCard } from "./presentation/components/CreationsHomeCard";
|
|
77
151
|
export { EmptyState } from "./presentation/components/EmptyState";
|
|
78
152
|
export {
|
|
79
153
|
CreationsProvider,
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// eslint-disable-next-line no-console
|
|
2
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository.ts - Module loading");
|
|
3
|
+
|
|
1
4
|
import { BaseRepository, FirestorePathResolver } from "@umituz/react-native-firebase";
|
|
2
5
|
import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
|
|
3
6
|
import type { Creation } from "../../domain/entities/Creation";
|
|
@@ -36,13 +39,23 @@ export class CreationsRepository
|
|
|
36
39
|
collectionName: string,
|
|
37
40
|
options?: RepositoryOptions,
|
|
38
41
|
) {
|
|
42
|
+
// eslint-disable-next-line no-console
|
|
43
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - Constructor start");
|
|
39
44
|
super();
|
|
40
45
|
|
|
41
46
|
const documentMapper = options?.documentMapper ?? mapDocumentToCreation;
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
// eslint-disable-next-line no-console
|
|
49
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - Getting db");
|
|
50
|
+
const db = this.getDb();
|
|
51
|
+
// eslint-disable-next-line no-console
|
|
52
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - db:", db ? "available" : "null");
|
|
53
|
+
|
|
54
|
+
this.pathResolver = new FirestorePathResolver(collectionName, db);
|
|
44
55
|
this.fetcher = new CreationsFetcher(this.pathResolver, documentMapper);
|
|
45
56
|
this.writer = new CreationsWriter(this.pathResolver);
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
58
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - Constructor end");
|
|
46
59
|
}
|
|
47
60
|
|
|
48
61
|
async getAll(userId: string): Promise<Creation[]> {
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CreationActions Component
|
|
3
|
+
* Flexible action buttons for creations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useMemo } from "react";
|
|
7
|
+
import {
|
|
8
|
+
View,
|
|
9
|
+
StyleSheet,
|
|
10
|
+
TouchableOpacity,
|
|
11
|
+
ActivityIndicator,
|
|
12
|
+
} from "react-native";
|
|
13
|
+
import {
|
|
14
|
+
useAppDesignTokens,
|
|
15
|
+
AtomicIcon,
|
|
16
|
+
} from "@umituz/react-native-design-system";
|
|
17
|
+
|
|
18
|
+
export interface CreationAction {
|
|
19
|
+
/** Unique action identifier */
|
|
20
|
+
id: string;
|
|
21
|
+
/** Icon name */
|
|
22
|
+
icon: string;
|
|
23
|
+
/** Icon color (design system color key) */
|
|
24
|
+
color?: "primary" | "secondary" | "error" | "success" | "textInverse";
|
|
25
|
+
/** Show loading state */
|
|
26
|
+
loading?: boolean;
|
|
27
|
+
/** Disabled state */
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
/** Use filled background (primary color) */
|
|
30
|
+
filled?: boolean;
|
|
31
|
+
/** Action handler */
|
|
32
|
+
onPress: () => void;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface CreationActionsProps {
|
|
36
|
+
/** Array of actions to display */
|
|
37
|
+
readonly actions: CreationAction[];
|
|
38
|
+
/** Button size */
|
|
39
|
+
readonly size?: "sm" | "md" | "lg";
|
|
40
|
+
/** Layout direction */
|
|
41
|
+
readonly direction?: "row" | "column";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const SIZES = {
|
|
45
|
+
sm: { button: 28, icon: "xs" as const },
|
|
46
|
+
md: { button: 36, icon: "sm" as const },
|
|
47
|
+
lg: { button: 44, icon: "md" as const },
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function CreationActions({
|
|
51
|
+
actions,
|
|
52
|
+
size = "md",
|
|
53
|
+
direction = "row",
|
|
54
|
+
}: CreationActionsProps) {
|
|
55
|
+
const tokens = useAppDesignTokens();
|
|
56
|
+
const sizeConfig = SIZES[size];
|
|
57
|
+
|
|
58
|
+
const styles = useMemo(
|
|
59
|
+
() =>
|
|
60
|
+
StyleSheet.create({
|
|
61
|
+
container: {
|
|
62
|
+
flexDirection: direction,
|
|
63
|
+
gap: 8,
|
|
64
|
+
},
|
|
65
|
+
actionButton: {
|
|
66
|
+
width: sizeConfig.button,
|
|
67
|
+
height: sizeConfig.button,
|
|
68
|
+
borderRadius: sizeConfig.button / 2,
|
|
69
|
+
borderWidth: 1,
|
|
70
|
+
alignItems: "center",
|
|
71
|
+
justifyContent: "center",
|
|
72
|
+
backgroundColor: tokens.colors.surface,
|
|
73
|
+
borderColor: tokens.colors.borderLight,
|
|
74
|
+
},
|
|
75
|
+
actionButtonFilled: {
|
|
76
|
+
backgroundColor: tokens.colors.primary,
|
|
77
|
+
borderWidth: 0,
|
|
78
|
+
},
|
|
79
|
+
actionButtonDisabled: {
|
|
80
|
+
opacity: 0.5,
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
[tokens, sizeConfig, direction]
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (actions.length === 0) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<View style={styles.container}>
|
|
92
|
+
{actions.map((action) => (
|
|
93
|
+
<TouchableOpacity
|
|
94
|
+
key={action.id}
|
|
95
|
+
style={[
|
|
96
|
+
styles.actionButton,
|
|
97
|
+
action.filled && styles.actionButtonFilled,
|
|
98
|
+
action.disabled && styles.actionButtonDisabled,
|
|
99
|
+
]}
|
|
100
|
+
onPress={action.onPress}
|
|
101
|
+
disabled={action.disabled || action.loading}
|
|
102
|
+
activeOpacity={0.7}
|
|
103
|
+
>
|
|
104
|
+
{action.loading ? (
|
|
105
|
+
<ActivityIndicator
|
|
106
|
+
size="small"
|
|
107
|
+
color={action.filled ? tokens.colors.textInverse : tokens.colors.primary}
|
|
108
|
+
/>
|
|
109
|
+
) : (
|
|
110
|
+
<AtomicIcon
|
|
111
|
+
name={action.icon}
|
|
112
|
+
size={sizeConfig.icon}
|
|
113
|
+
color={action.color || (action.filled ? "textInverse" : "primary")}
|
|
114
|
+
/>
|
|
115
|
+
)}
|
|
116
|
+
</TouchableOpacity>
|
|
117
|
+
))}
|
|
118
|
+
</View>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CreationBadges Component
|
|
3
|
+
* Displays status and type badges overlay
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useMemo } from "react";
|
|
7
|
+
import { View, StyleSheet, Text } from "react-native";
|
|
8
|
+
import {
|
|
9
|
+
useAppDesignTokens,
|
|
10
|
+
AtomicIcon,
|
|
11
|
+
} from "@umituz/react-native-design-system";
|
|
12
|
+
import type { CreationStatus, CreationTypeId } from "../../domain/types";
|
|
13
|
+
import { getStatusColorKey, getStatusText, getTypeIcon, getTypeText } from "../../domain/utils";
|
|
14
|
+
|
|
15
|
+
interface CreationBadgesProps {
|
|
16
|
+
/** Creation status */
|
|
17
|
+
readonly status: CreationStatus;
|
|
18
|
+
/** Creation type */
|
|
19
|
+
readonly type?: CreationTypeId;
|
|
20
|
+
/** Show status badge */
|
|
21
|
+
readonly showStatus?: boolean;
|
|
22
|
+
/** Show type badge */
|
|
23
|
+
readonly showType?: boolean;
|
|
24
|
+
/** Custom status text (for i18n) */
|
|
25
|
+
readonly statusText?: string;
|
|
26
|
+
/** Custom type text (for i18n) */
|
|
27
|
+
readonly typeText?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function CreationBadges({
|
|
31
|
+
status,
|
|
32
|
+
type,
|
|
33
|
+
showStatus = true,
|
|
34
|
+
showType = true,
|
|
35
|
+
statusText,
|
|
36
|
+
typeText,
|
|
37
|
+
}: CreationBadgesProps) {
|
|
38
|
+
const tokens = useAppDesignTokens();
|
|
39
|
+
const colorKey = getStatusColorKey(status);
|
|
40
|
+
const statusColor = (tokens.colors as unknown as Record<string, string>)[colorKey] || tokens.colors.textSecondary;
|
|
41
|
+
const displayStatusText = statusText || getStatusText(status);
|
|
42
|
+
const displayTypeText = typeText || (type ? getTypeText(type) : "");
|
|
43
|
+
const typeIcon = type ? getTypeIcon(type) : "image";
|
|
44
|
+
|
|
45
|
+
const styles = useMemo(
|
|
46
|
+
() =>
|
|
47
|
+
StyleSheet.create({
|
|
48
|
+
statusBadge: {
|
|
49
|
+
position: "absolute",
|
|
50
|
+
top: 8,
|
|
51
|
+
right: 8,
|
|
52
|
+
flexDirection: "row",
|
|
53
|
+
alignItems: "center",
|
|
54
|
+
paddingHorizontal: 8,
|
|
55
|
+
paddingVertical: 4,
|
|
56
|
+
borderRadius: 12,
|
|
57
|
+
backgroundColor: statusColor + "20",
|
|
58
|
+
},
|
|
59
|
+
statusDot: {
|
|
60
|
+
width: 6,
|
|
61
|
+
height: 6,
|
|
62
|
+
borderRadius: 3,
|
|
63
|
+
marginRight: 4,
|
|
64
|
+
backgroundColor: statusColor,
|
|
65
|
+
},
|
|
66
|
+
statusText: {
|
|
67
|
+
fontSize: 10,
|
|
68
|
+
fontWeight: "600",
|
|
69
|
+
textTransform: "capitalize",
|
|
70
|
+
color: statusColor,
|
|
71
|
+
},
|
|
72
|
+
typeBadge: {
|
|
73
|
+
position: "absolute",
|
|
74
|
+
top: 8,
|
|
75
|
+
left: 8,
|
|
76
|
+
flexDirection: "row",
|
|
77
|
+
alignItems: "center",
|
|
78
|
+
paddingHorizontal: 8,
|
|
79
|
+
paddingVertical: 4,
|
|
80
|
+
borderRadius: 12,
|
|
81
|
+
backgroundColor: "rgba(0,0,0,0.6)",
|
|
82
|
+
gap: 4,
|
|
83
|
+
},
|
|
84
|
+
typeText: {
|
|
85
|
+
fontSize: 10,
|
|
86
|
+
fontWeight: "600",
|
|
87
|
+
color: "white",
|
|
88
|
+
textTransform: "capitalize",
|
|
89
|
+
},
|
|
90
|
+
}),
|
|
91
|
+
[statusColor]
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
{showStatus && (
|
|
97
|
+
<View style={styles.statusBadge}>
|
|
98
|
+
<View style={styles.statusDot} />
|
|
99
|
+
<Text style={styles.statusText}>{displayStatusText}</Text>
|
|
100
|
+
</View>
|
|
101
|
+
)}
|
|
102
|
+
|
|
103
|
+
{showType && type && (
|
|
104
|
+
<View style={styles.typeBadge}>
|
|
105
|
+
<AtomicIcon name={typeIcon} color="textInverse" size="xs" />
|
|
106
|
+
<Text style={styles.typeText}>{displayTypeText}</Text>
|
|
107
|
+
</View>
|
|
108
|
+
)}
|
|
109
|
+
</>
|
|
110
|
+
);
|
|
111
|
+
}
|