@umituz/react-native-ai-generation-content 1.83.47 → 1.83.49

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.83.47",
3
+ "version": "1.83.49",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -49,6 +49,7 @@ export const CREATION_FIELDS = {
49
49
  // AI provider metadata
50
50
  REQUEST_ID: "requestId" as const,
51
51
  MODEL: "model" as const,
52
+ PROVIDER: "provider" as const,
52
53
  } as const;
53
54
 
54
55
  /** Union type of all field names */
@@ -25,8 +25,8 @@ export interface Creation {
25
25
  readonly uri: string;
26
26
  readonly type: string;
27
27
  readonly prompt?: string;
28
+ readonly provider?: string;
28
29
  readonly metadata?: Record<string, unknown>;
29
- readonly originalUri?: string;
30
30
  readonly createdAt: Date;
31
31
  readonly isShared: boolean;
32
32
  readonly isFavorite: boolean;
@@ -53,12 +53,8 @@ interface FirebaseTimestamp {
53
53
  export interface CreationDocument {
54
54
  readonly uri?: string;
55
55
  readonly prompt?: string;
56
+ readonly provider?: string;
56
57
  readonly metadata?: Record<string, unknown>;
57
- readonly originalImage?: string;
58
- readonly originalImageUrl?: string;
59
- readonly transformedImage?: string;
60
- readonly transformedImageUrl?: string;
61
- readonly transformationType?: string;
62
58
  readonly type?: string;
63
59
  readonly status?: string;
64
60
  readonly output?: CreationOutput | null;
@@ -92,21 +88,15 @@ export function mapDocumentToCreation(
92
88
  ): Creation {
93
89
  const creationDate = toDate(data.createdAt) ?? new Date();
94
90
 
95
- // Get URI from output or direct fields
96
- const uri = data.output?.imageUrl ||
97
- data.output?.videoUrl ||
98
- data.transformedImageUrl ||
99
- data.transformedImage ||
100
- data.uri ||
101
- "";
91
+ const uri = data.output?.imageUrl || data.output?.videoUrl || data.uri || "";
102
92
 
103
93
  return {
104
94
  id,
105
95
  uri,
106
- type: data.transformationType || data.type || "unknown",
96
+ type: data.type || "unknown",
107
97
  prompt: data.prompt,
98
+ provider: data.provider,
108
99
  metadata: data.metadata,
109
- originalUri: data.originalImageUrl || data.originalImage,
110
100
  createdAt: creationDate,
111
101
  isShared: data.isShared ?? false,
112
102
  isFavorite: data.isFavorite ?? false,
@@ -25,6 +25,7 @@ export async function createCreation(
25
25
  ...(creation.status !== undefined && { status: creation.status }),
26
26
  ...(creation.output !== undefined && { output: creation.output }),
27
27
  ...(creation.prompt !== undefined && { prompt: creation.prompt }),
28
+ ...(creation.provider !== undefined && { provider: creation.provider }),
28
29
  ...(creation.requestId !== undefined && { requestId: creation.requestId }),
29
30
  ...(creation.model !== undefined && { model: creation.model }),
30
31
  ...(creation.startedAt !== undefined && { startedAt: creation.startedAt }),
@@ -17,6 +17,9 @@ export const PHOTO_KEY_PREFIX = "photo_";
17
17
  /** Default style value (no custom style applied) */
18
18
  export const DEFAULT_STYLE_VALUE = "original";
19
19
 
20
+ /** Debounce interval to prevent rapid double-tap on generation start (ms) */
21
+ export const GENERATION_DEBOUNCE_MS = 500;
22
+
20
23
  /** Model input defaults */
21
24
  export const MODEL_INPUT_DEFAULTS = {
22
25
  aspectRatio: "1:1",
@@ -1,19 +1,17 @@
1
1
  /**
2
2
  * Creation Persistence Factory
3
- * Infrastructure: Creates persistence handler instance
3
+ * Creates a persistence handler bound to the creations repository
4
4
  */
5
5
 
6
6
  import { createCreationsRepository } from "../../../../creations/infrastructure/adapters";
7
- import type { CreationPersistenceConfig, ProcessingCreationData, CompletedCreationData } from "./creation-persistence.types";
7
+ import type { ProcessingCreationData, CompletedCreationData } from "./creation-persistence.types";
8
8
  import { saveAsProcessing } from "./creation-save-operations";
9
9
  import { updateToCompleted, updateToFailed, updateRequestId } from "./creation-update-operations";
10
10
 
11
- /**
12
- * Creates a creation persistence handler for a wizard flow
13
- */
14
- export function createCreationPersistence(config: CreationPersistenceConfig = {}) {
15
- const { collectionName = "creations" } = config;
16
- const repository = createCreationsRepository(collectionName);
11
+ const COLLECTION_NAME = "creations";
12
+
13
+ export function createCreationPersistence() {
14
+ const repository = createCreationsRepository(COLLECTION_NAME);
17
15
 
18
16
  return {
19
17
  saveAsProcessing: (userId: string, data: ProcessingCreationData) =>
@@ -3,10 +3,6 @@
3
3
  * Domain: Value objects for creation persistence
4
4
  */
5
5
 
6
- export interface CreationPersistenceConfig {
7
- readonly collectionName?: string;
8
- }
9
-
10
6
  export interface ProcessingCreationData {
11
7
  readonly scenarioId: string;
12
8
  readonly scenarioTitle: string;
@@ -25,6 +25,7 @@ export async function saveAsProcessing(
25
25
  uri: "",
26
26
  type: data.scenarioId,
27
27
  prompt: data.prompt,
28
+ provider: data.provider,
28
29
  status: "processing" as const,
29
30
  createdAt: new Date(),
30
31
  startedAt,
@@ -39,7 +40,6 @@ export async function saveAsProcessing(
39
40
  ...(data.resolution && { resolution: data.resolution }),
40
41
  ...(data.creditCost && { creditCost: data.creditCost }),
41
42
  ...(data.aspectRatio && { aspectRatio: data.aspectRatio }),
42
- ...(data.provider && { provider: data.provider }),
43
43
  ...(data.outputType && { outputType: data.outputType }),
44
44
  },
45
45
  });
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { ICreationsRepository } from "../../../../creations/domain/repositories";
7
+ import type { Creation, CreationOutput } from "../../../../creations/domain/entities/Creation";
7
8
  import type { CompletedCreationData } from "./creation-persistence.types";
8
9
 
9
10
 
@@ -16,10 +17,11 @@ export async function updateToCompleted(
16
17
  creationId: string,
17
18
  data: CompletedCreationData
18
19
  ): Promise<void> {
19
- const output: { imageUrl?: string; videoUrl?: string; thumbnailUrl?: string } = {};
20
- if (data.imageUrl) output.imageUrl = data.imageUrl;
21
- if (data.videoUrl) output.videoUrl = data.videoUrl;
22
- if (data.thumbnailUrl) output.thumbnailUrl = data.thumbnailUrl;
20
+ const output: CreationOutput = {
21
+ ...(data.imageUrl && { imageUrl: data.imageUrl }),
22
+ ...(data.videoUrl && { videoUrl: data.videoUrl }),
23
+ ...(data.thumbnailUrl && { thumbnailUrl: data.thumbnailUrl }),
24
+ };
23
25
 
24
26
  const completedAt = new Date();
25
27
  const durationMs =
@@ -33,7 +35,7 @@ export async function updateToCompleted(
33
35
  output,
34
36
  completedAt,
35
37
  ...(durationMs !== undefined && { durationMs }),
36
- } as Partial<import("../../../../creations/domain/entities/Creation").Creation>);
38
+ } as Partial<Creation>);
37
39
 
38
40
  if (typeof __DEV__ !== "undefined" && __DEV__) {
39
41
  console.log("[CreationPersistence] Updated to completed", { creationId });
@@ -53,7 +55,7 @@ export async function updateToFailed(
53
55
  status: "failed" as const,
54
56
  metadata: { error },
55
57
  completedAt: new Date(),
56
- } as Partial<import("../../../../creations/domain/entities/Creation").Creation>);
58
+ } as Partial<Creation>);
57
59
 
58
60
  if (typeof __DEV__ !== "undefined" && __DEV__) {
59
61
  console.log("[CreationPersistence] Updated to failed", { creationId, error });
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Generation-specific handlers: complete, error, dismiss
3
+ */
4
+
5
+ import { useCallback } from "react";
6
+ import { AlertType, AlertMode, useAlert } from "@umituz/react-native-design-system";
7
+ import type { Creation } from "../../../../creations/domain/entities/Creation";
8
+ import { isCreation } from "./typeGuards";
9
+ import { classifyError } from "../../../../../infrastructure/utils/error-classification";
10
+ import type { GenerationErrorInfo } from "../components/WizardFlow.types";
11
+
12
+ interface UseGenerationHandlersProps {
13
+ readonly skipResultStep: boolean;
14
+ readonly t: (key: string) => string;
15
+ readonly nextStep: () => void;
16
+ readonly setResult: (result: unknown) => void;
17
+ readonly setCurrentCreation: (creation: Creation | null) => void;
18
+ readonly onGenerationComplete?: (result: unknown) => void;
19
+ readonly onGenerationError?: (error: string, errorInfo?: GenerationErrorInfo) => void;
20
+ readonly onBack?: () => void;
21
+ }
22
+
23
+ export function useGenerationHandlers(props: UseGenerationHandlersProps) {
24
+ const { skipResultStep, t, nextStep, setResult, setCurrentCreation, onGenerationComplete, onGenerationError, onBack } = props;
25
+
26
+ const alert = useAlert();
27
+
28
+ const handleGenerationComplete = useCallback(
29
+ (result: unknown) => {
30
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
31
+ console.log("[handleGenerationComplete] Called", { isCreation: isCreation(result), skipResultStep });
32
+ }
33
+ setResult(result);
34
+ setCurrentCreation(isCreation(result) ? result : null);
35
+ onGenerationComplete?.(result);
36
+ if (!skipResultStep) nextStep();
37
+ },
38
+ [setResult, setCurrentCreation, nextStep, onGenerationComplete, skipResultStep],
39
+ );
40
+
41
+ const handleGenerationError = useCallback(
42
+ (errorMessage: string) => {
43
+ const safeErrorMessage = errorMessage?.trim() || "error.generation.unknown";
44
+ const displayMessage = safeErrorMessage.startsWith("error.") ? t(safeErrorMessage) : safeErrorMessage;
45
+ const errorClassification = classifyError(errorMessage);
46
+ const errorInfo: GenerationErrorInfo = {
47
+ message: safeErrorMessage,
48
+ shouldRefund: errorClassification.retryable ?? false,
49
+ errorType: errorClassification.type,
50
+ };
51
+
52
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
53
+ console.log("[handleGenerationError] Called", { errorType: errorClassification.type, shouldRefund: errorInfo.shouldRefund });
54
+ }
55
+
56
+ alert.show(AlertType.ERROR, AlertMode.MODAL, t("common.error"), displayMessage);
57
+ onGenerationError?.(safeErrorMessage, errorInfo);
58
+ onBack?.();
59
+ },
60
+ [alert, t, onGenerationError, onBack],
61
+ );
62
+
63
+ const handleDismissGenerating = useCallback(() => {
64
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
65
+ console.log("[handleDismissGenerating] User dismissed generating screen");
66
+ }
67
+ alert.show(AlertType.INFO, AlertMode.TOAST, t("generator.backgroundTitle"), t("generator.backgroundMessage"));
68
+ onBack?.();
69
+ }, [alert, t, onBack]);
70
+
71
+ return { handleGenerationComplete, handleGenerationError, handleDismissGenerating };
72
+ }
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Navigation and step transition handlers
3
+ */
4
+
5
+ import { useCallback, useRef } from "react";
6
+ import { StepType, type StepDefinition } from "../../../../../domain/entities/flow-config.types";
7
+ import type { UploadedImage } from "../../../../../presentation/hooks/generation/useAIGenerateState";
8
+ import { GENERATION_DEBOUNCE_MS } from "../../infrastructure/strategies/wizard-strategy.constants";
9
+
10
+ interface UseNavigationHandlersProps {
11
+ readonly currentStepIndex: number;
12
+ readonly flowSteps: StepDefinition[];
13
+ readonly customData: Record<string, unknown>;
14
+ readonly nextStep: () => void;
15
+ readonly previousStep: () => void;
16
+ readonly setCustomData: (stepId: string, data: unknown) => void;
17
+ readonly onGenerationStart?: (data: Record<string, unknown>, proceed: () => void, onError?: (error: string) => void) => void;
18
+ readonly handleGenerationError: (error: string) => void;
19
+ readonly onBack?: () => void;
20
+ }
21
+
22
+ function isPlainObjectData(data: unknown): data is Record<string, unknown> {
23
+ return !!data && typeof data === "object" && !("nativeEvent" in data) && !Array.isArray(data);
24
+ }
25
+
26
+ export function useNavigationHandlers(props: UseNavigationHandlersProps) {
27
+ const {
28
+ currentStepIndex, flowSteps, customData, nextStep, previousStep,
29
+ setCustomData, onGenerationStart, handleGenerationError, onBack,
30
+ } = props;
31
+
32
+ const lastGenerationAttemptRef = useRef(0);
33
+
34
+ const handleBack = useCallback(() => {
35
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
36
+ console.log("[handleBack] Called", { currentStepIndex, isFirstStep: currentStepIndex === 0 });
37
+ }
38
+ if (currentStepIndex === 0) onBack?.();
39
+ else previousStep();
40
+ }, [currentStepIndex, previousStep, onBack]);
41
+
42
+ const handleNextStep = useCallback((additionalData?: Record<string, unknown>) => {
43
+ const nextStepDef = flowSteps[currentStepIndex + 1];
44
+ const mergedData = isPlainObjectData(additionalData) ? { ...customData, ...additionalData } : customData;
45
+
46
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
47
+ console.log("[handleNextStep] Called", {
48
+ currentStepIndex,
49
+ nextStepType: nextStepDef?.type,
50
+ nextStepId: nextStepDef?.id,
51
+ totalSteps: flowSteps.length,
52
+ hasOnGenerationStart: !!onGenerationStart,
53
+ dataKeys: Object.keys(mergedData),
54
+ });
55
+ }
56
+
57
+ if (nextStepDef?.type === StepType.GENERATING && onGenerationStart) {
58
+ const now = Date.now();
59
+ if (now - lastGenerationAttemptRef.current < GENERATION_DEBOUNCE_MS) {
60
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
61
+ console.log("[handleNextStep] Debounced - too rapid");
62
+ }
63
+ return;
64
+ }
65
+ lastGenerationAttemptRef.current = now;
66
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
67
+ console.log("[handleNextStep] Calling onGenerationStart");
68
+ }
69
+ onGenerationStart(mergedData, nextStep, handleGenerationError);
70
+ return;
71
+ }
72
+ nextStep();
73
+ }, [currentStepIndex, flowSteps, customData, onGenerationStart, nextStep, handleGenerationError]);
74
+
75
+ const handlePhotoContinue = useCallback(
76
+ (stepId: string, image: UploadedImage) => {
77
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
78
+ console.log("[handlePhotoContinue] Called", { stepId, hasImage: !!image, currentStepIndex });
79
+ }
80
+ setCustomData(stepId, image);
81
+ handleNextStep({ [stepId]: image });
82
+ },
83
+ [setCustomData, handleNextStep, currentStepIndex],
84
+ );
85
+
86
+ return { handleBack, handleNextStep, handlePhotoContinue };
87
+ }
@@ -1,161 +1,69 @@
1
- import { useCallback, useRef } from "react";
2
- import { AlertType, AlertMode, useAlert } from "@umituz/react-native-design-system";
3
- import { StepType, type StepDefinition } from "../../../../../domain/entities/flow-config.types";
4
- import type { UploadedImage } from "../../../../../presentation/hooks/generation/useAIGenerateState";
5
- import type { Creation } from "../../../../creations/domain/entities/Creation";
6
- import { isCreation } from "./typeGuards";
7
- import { classifyError } from "../../../../../infrastructure/utils/error-classification";
8
- import type { GenerationErrorInfo } from "../components/WizardFlow.types";
1
+ /**
2
+ * Wizard Flow Handlers - Composition Hook
3
+ * Combines generation, navigation, and rating handlers
4
+ */
9
5
 
10
- interface UseWizardFlowHandlersProps {
11
- readonly currentStepIndex: number;
12
- readonly flowSteps: StepDefinition[];
13
- readonly customData: Record<string, unknown>;
14
- readonly skipResultStep: boolean;
15
- readonly userId?: string;
16
- readonly currentCreation: Creation | null;
17
- readonly repository: { rate: (uid: string, id: string, rating: number, desc: string) => Promise<boolean> };
18
- readonly t: (key: string) => string;
19
- readonly nextStep: () => void;
20
- readonly previousStep: () => void;
21
- readonly setResult: (result: unknown) => void;
22
- readonly setCustomData: (stepId: string, data: unknown) => void;
23
- readonly setCurrentCreation: (creation: Creation | null) => void;
24
- readonly setHasRated: (hasRated: boolean) => void;
25
- readonly setShowRatingPicker: (show: boolean) => void;
26
- readonly onGenerationStart?: (data: Record<string, unknown>, proceed: () => void, onError?: (error: string) => void) => void;
27
- readonly onGenerationComplete?: (result: unknown) => void;
28
- readonly onGenerationError?: (error: string, errorInfo?: GenerationErrorInfo) => void;
29
- readonly onBack?: () => void;
30
- }
6
+ import { useCallback } from "react";
7
+ import { AlertType, AlertMode, useAlert } from "@umituz/react-native-design-system";
8
+ import type { UseWizardFlowHandlersProps } from "./wizard-flow-handlers.types";
9
+ import { useGenerationHandlers } from "./useGenerationHandlers";
10
+ import { useNavigationHandlers } from "./useNavigationHandlers";
31
11
 
32
12
  export function useWizardFlowHandlers(props: UseWizardFlowHandlersProps) {
33
13
  const {
14
+ currentStepIndex, flowSteps, customData, userId, currentCreation,
15
+ repository, t, nextStep, previousStep, setCustomData,
16
+ onGenerationStart, onBack,
17
+ } = props;
18
+
19
+ const alert = useAlert();
20
+
21
+ const generation = useGenerationHandlers({
22
+ skipResultStep: props.skipResultStep,
23
+ t,
24
+ nextStep,
25
+ setResult: props.setResult,
26
+ setCurrentCreation: props.setCurrentCreation,
27
+ onGenerationComplete: props.onGenerationComplete,
28
+ onGenerationError: props.onGenerationError,
29
+ onBack,
30
+ });
31
+
32
+ const navigation = useNavigationHandlers({
34
33
  currentStepIndex,
35
34
  flowSteps,
36
35
  customData,
37
- skipResultStep,
38
- userId,
39
- currentCreation,
40
- repository,
41
- t,
42
36
  nextStep,
43
37
  previousStep,
44
- setResult,
45
38
  setCustomData,
46
- setCurrentCreation,
47
- setHasRated,
48
- setShowRatingPicker,
49
39
  onGenerationStart,
50
- onGenerationComplete,
51
- onGenerationError,
40
+ handleGenerationError: generation.handleGenerationError,
52
41
  onBack,
53
- } = props;
54
-
55
- const alert = useAlert();
56
- // Guard: prevent multiple onGenerationStart calls from auto-advancing steps
57
- const generationStartedRef = useRef(false);
58
-
59
- const handleGenerationComplete = useCallback(
60
- (result: unknown) => {
61
- generationStartedRef.current = false;
62
- setResult(result);
63
- setCurrentCreation(isCreation(result) ? result : null);
64
- onGenerationComplete?.(result);
65
- if (!skipResultStep) nextStep();
66
- },
67
- [setResult, setCurrentCreation, nextStep, onGenerationComplete, skipResultStep],
68
- );
69
-
70
- const handleGenerationError = useCallback(
71
- (errorMessage: string) => {
72
- generationStartedRef.current = false;
73
- const safeErrorMessage = errorMessage?.trim() || "error.generation.unknown";
74
- const displayMessage = safeErrorMessage.startsWith("error.") ? t(safeErrorMessage) : safeErrorMessage;
75
-
76
- // Classify error to determine refund eligibility
77
- const errorClassification = classifyError(errorMessage);
78
- const errorInfo: GenerationErrorInfo = {
79
- message: safeErrorMessage,
80
- shouldRefund: errorClassification.retryable ?? false,
81
- errorType: errorClassification.type,
82
- };
83
-
84
- alert.show(AlertType.ERROR, AlertMode.MODAL, t("common.error"), displayMessage);
85
- onGenerationError?.(safeErrorMessage, errorInfo);
86
- onBack?.();
87
- },
88
- [alert, t, onGenerationError, onBack],
89
- );
90
-
91
- const handleDismissGenerating = useCallback(() => {
92
- alert.show(AlertType.INFO, AlertMode.TOAST, t("generator.backgroundTitle"), t("generator.backgroundMessage"));
93
- onBack?.();
94
- }, [alert, t, onBack]);
95
-
96
- const handleBack = useCallback(() => {
97
- if (currentStepIndex === 0) onBack?.();
98
- else previousStep();
99
- }, [currentStepIndex, previousStep, onBack]);
100
-
101
- const handleNextStep = useCallback((additionalData?: Record<string, unknown>) => {
102
- const nextStepDef = flowSteps[currentStepIndex + 1];
103
- // Merge additionalData to avoid stale closure issue
104
- // When called from handlePhotoContinue, customData in closure may not include the just-set value
105
- // Guard: Only merge plain objects (ignore SyntheticEvents from onPress handlers)
106
- const isPlainObject = additionalData && typeof additionalData === "object" && !("nativeEvent" in additionalData) && !Array.isArray(additionalData);
107
- const mergedData = isPlainObject ? { ...customData, ...additionalData } : customData;
108
- if (typeof __DEV__ !== "undefined" && __DEV__) {
109
- console.log("[handleNextStep] Called", {
110
- currentStepIndex,
111
- nextStepType: nextStepDef?.type,
112
- nextStepId: nextStepDef?.id,
113
- totalSteps: flowSteps.length,
114
- hasOnGenerationStart: !!onGenerationStart,
115
- dataKeys: Object.keys(mergedData),
116
- });
117
- }
118
- if (nextStepDef?.type === StepType.GENERATING && onGenerationStart) {
119
- if (generationStartedRef.current) return;
120
- generationStartedRef.current = true;
121
- onGenerationStart(mergedData, nextStep, handleGenerationError);
122
- return;
123
- }
124
- nextStep();
125
- }, [currentStepIndex, flowSteps, customData, onGenerationStart, nextStep, handleGenerationError]);
126
-
127
- const handlePhotoContinue = useCallback(
128
- (stepId: string, image: UploadedImage) => {
129
- if (typeof __DEV__ !== "undefined" && __DEV__) {
130
- console.log("[handlePhotoContinue] Called", { stepId, hasImage: !!image, currentStepIndex });
131
- }
132
- setCustomData(stepId, image);
133
- // Pass the just-set data to avoid stale closure issue
134
- handleNextStep({ [stepId]: image });
135
- },
136
- [setCustomData, handleNextStep, currentStepIndex],
137
- );
42
+ });
138
43
 
139
44
  const handleSubmitRating = useCallback(
140
45
  async (rating: number, description: string) => {
141
46
  if (!currentCreation?.id || !userId) return;
47
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
48
+ console.log("[handleSubmitRating] Called", { creationId: currentCreation.id, rating });
49
+ }
142
50
  const success = await repository.rate(userId, currentCreation.id, rating, description);
143
51
  if (success) {
144
- setHasRated(true);
52
+ props.setHasRated(true);
145
53
  alert.show(AlertType.SUCCESS, AlertMode.TOAST, t("result.rateSuccessTitle"), t("result.rateSuccessMessage"));
146
54
  }
147
- setShowRatingPicker(false);
55
+ props.setShowRatingPicker(false);
148
56
  },
149
- [currentCreation, userId, repository, alert, t, setHasRated, setShowRatingPicker],
57
+ [currentCreation, userId, repository, alert, t, props.setHasRated, props.setShowRatingPicker],
150
58
  );
151
59
 
152
60
  return {
153
- handleGenerationComplete,
154
- handleGenerationError,
155
- handleDismissGenerating,
156
- handleBack,
157
- handleNextStep,
158
- handlePhotoContinue,
61
+ handleGenerationComplete: generation.handleGenerationComplete,
62
+ handleGenerationError: generation.handleGenerationError,
63
+ handleDismissGenerating: generation.handleDismissGenerating,
64
+ handleBack: navigation.handleBack,
65
+ handleNextStep: navigation.handleNextStep,
66
+ handlePhotoContinue: navigation.handlePhotoContinue,
159
67
  handleSubmitRating,
160
68
  };
161
69
  }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Types for Wizard Flow Handlers
3
+ */
4
+
5
+ import type { StepDefinition } from "../../../../../domain/entities/flow-config.types";
6
+ import type { Creation } from "../../../../creations/domain/entities/Creation";
7
+ import type { GenerationErrorInfo } from "../components/WizardFlow.types";
8
+
9
+ export interface UseWizardFlowHandlersProps {
10
+ readonly currentStepIndex: number;
11
+ readonly flowSteps: StepDefinition[];
12
+ readonly customData: Record<string, unknown>;
13
+ readonly skipResultStep: boolean;
14
+ readonly userId?: string;
15
+ readonly currentCreation: Creation | null;
16
+ readonly repository: { rate: (uid: string, id: string, rating: number, desc: string) => Promise<boolean> };
17
+ readonly t: (key: string) => string;
18
+ readonly nextStep: () => void;
19
+ readonly previousStep: () => void;
20
+ readonly setResult: (result: unknown) => void;
21
+ readonly setCustomData: (stepId: string, data: unknown) => void;
22
+ readonly setCurrentCreation: (creation: Creation | null) => void;
23
+ readonly setHasRated: (hasRated: boolean) => void;
24
+ readonly setShowRatingPicker: (show: boolean) => void;
25
+ readonly onGenerationStart?: (data: Record<string, unknown>, proceed: () => void, onError?: (error: string) => void) => void;
26
+ readonly onGenerationComplete?: (result: unknown) => void;
27
+ readonly onGenerationError?: (error: string, errorInfo?: GenerationErrorInfo) => void;
28
+ readonly onBack?: () => void;
29
+ }