diff --git a/src/app/api/ai-tagging/fields/route.ts b/src/app/api/ai-tagging/fields/route.ts index ee647aa..c4155b1 100644 --- a/src/app/api/ai-tagging/fields/route.ts +++ b/src/app/api/ai-tagging/fields/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from 'next/server' import { requireLibraryAccess } from '@/lib/auth' -import { getAiFields } from '@/lib/ai-tagger' +import { getAiFields, updateExtractedText } from '@/lib/ai-tagger' export async function GET(request: NextRequest) { const { searchParams } = request.nextUrl @@ -17,3 +17,27 @@ export async function GET(request: NextRequest) { const fields = getAiFields(itemKey) return NextResponse.json(fields) } + +export async function PATCH(request: NextRequest) { + let body: { itemKey?: string; extractedText?: string } + try { + body = await request.json() + } catch { + return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 }) + } + + const { itemKey, extractedText } = body + if (!itemKey || typeof itemKey !== 'string') { + return NextResponse.json({ error: 'itemKey is required' }, { status: 400 }) + } + if (typeof extractedText !== 'string') { + return NextResponse.json({ error: 'extractedText is required' }, { status: 400 }) + } + + const libraryId = itemKey.split(':')[0] + const auth = await requireLibraryAccess(request, libraryId) + if (auth instanceof NextResponse) return auth + + updateExtractedText(itemKey, extractedText) + return NextResponse.json({ ok: true }) +} diff --git a/src/app/api/ai-tagging/translate/route.ts b/src/app/api/ai-tagging/translate/route.ts index 740d9fb..89d041a 100644 --- a/src/app/api/ai-tagging/translate/route.ts +++ b/src/app/api/ai-tagging/translate/route.ts @@ -3,14 +3,14 @@ import { requireLibraryAccess } from '@/lib/auth' import { translateItemText } from '@/lib/ai-tagger' export async function POST(request: NextRequest) { - let body: { itemKey?: string } + let body: { itemKey?: string; sourceLanguage?: string } try { body = await request.json() } catch { return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 }) } - const { itemKey } = body + const { itemKey, sourceLanguage } = body if (!itemKey || typeof itemKey !== 'string') { return NextResponse.json({ error: 'itemKey is required' }, { status: 400 }) } @@ -20,7 +20,7 @@ export async function POST(request: NextRequest) { if (auth instanceof NextResponse) return auth try { - const translatedText = await translateItemText(itemKey) + const translatedText = await translateItemText(itemKey, sourceLanguage || undefined) return NextResponse.json({ translatedText }) } catch (err) { const error = err as Error & { code?: string } diff --git a/src/components/mixed/ImageLightbox.tsx b/src/components/mixed/ImageLightbox.tsx index c49c52e..2cd1111 100644 --- a/src/components/mixed/ImageLightbox.tsx +++ b/src/components/mixed/ImageLightbox.tsx @@ -27,6 +27,9 @@ export default function ImageLightbox({ url, name, onClose, onPrev, onNext, item const [extracting, setExtracting] = useState(false) const [extractError, setExtractError] = useState(null) const [retranslating, setRetranslating] = useState(false) + const [editedExtractedText, setEditedExtractedText] = useState('') + const [savingText, setSavingText] = useState(false) + const [sourceLanguage, setSourceLanguage] = useState('') // Text overlay state const [showTextOverlay, setShowTextOverlay] = useState(false) @@ -45,6 +48,7 @@ export default function ImageLightbox({ url, name, onClose, onPrev, onNext, item .then((r) => r.json()) .then((data: { extractedText: string | null; extractedTextTranslated: string | null }) => { setExtractedText(data.extractedText) + setEditedExtractedText(data.extractedText ?? '') setTranslatedText(data.extractedTextTranslated) }) .catch(() => {}) @@ -267,6 +271,7 @@ export default function ImageLightbox({ url, name, onClose, onPrev, onNext, item } const result = await res.json() setExtractedText(result.extractedText || null) + setEditedExtractedText(result.extractedText || '') setTranslatedText(result.translatedText || null) } catch (err) { setExtractError(err instanceof Error ? err.message : 'Failed to extract text') @@ -302,12 +307,41 @@ export default function ImageLightbox({ url, name, onClose, onPrev, onNext, item

Extracted Text

-
-                        {extractedText}
-                      
+