dramaling-vocab-learning/frontend/hooks/flashcards/useImageGeneration.ts

69 lines
2.2 KiB
TypeScript

import { useState } from 'react'
import { useToast } from '@/components/shared/Toast'
import { imageGenerationService } from '@/lib/services/imageGeneration'
import { flashcardsService, type Flashcard } from '@/lib/services/flashcards'
interface UseImageGenerationOptions {
flashcard: Flashcard | null
onFlashcardUpdate: (updatedCard: Flashcard) => void
}
export function useImageGeneration({
flashcard,
onFlashcardUpdate
}: UseImageGenerationOptions) {
const toast = useToast()
const [isGenerating, setIsGenerating] = useState(false)
const [progress, setProgress] = useState<string>('')
const generateImage = async () => {
if (!flashcard || isGenerating) return
try {
setIsGenerating(true)
setProgress('啟動生成中...')
toast.info(`開始為「${flashcard.word}」生成例句圖片...`)
const generateResult = await imageGenerationService.generateImage(flashcard.id)
if (!generateResult.success || !generateResult.data) {
throw new Error(generateResult.error || '啟動生成失敗')
}
const requestId = generateResult.data.requestId
setProgress('Gemini 生成描述中...')
const finalStatus = await imageGenerationService.pollUntilComplete(
requestId,
(status: any) => {
const stage = status.stages.gemini.status === 'completed'
? 'Replicate 生成圖片中...' : 'Gemini 生成描述中...'
setProgress(stage)
},
5
)
if (finalStatus.overallStatus === 'completed') {
setProgress('生成完成,載入中...')
// 重新載入詞卡資料
const result = await flashcardsService.getFlashcard(flashcard.id)
if (result.success && result.data) {
onFlashcardUpdate(result.data)
}
toast.success(`${flashcard.word}」的例句圖片生成完成!`)
} else {
throw new Error('圖片生成未完成')
}
} catch (error: any) {
toast.error(`圖片生成失敗: ${error.message || '未知錯誤'}`)
} finally {
setIsGenerating(false)
setProgress('')
}
}
return {
generateImage,
isGenerating,
progress
}
}