-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDetectThenAnalyze.tsx
More file actions
74 lines (66 loc) · 2.69 KB
/
Copy pathDetectThenAnalyze.tsx
File metadata and controls
74 lines (66 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
'use client';
/**
* Confirm the document type before spending credits.
*
* `detect` costs 1 credit per 5 calls whatever the page count, because it only reads page
* 1 — so it is cheap enough to run on every upload. Extraction costs 1 per page, which is
* why asking first is worth it for a 40-page PDF nobody has looked at.
*/
import { useState } from 'react';
import { unwrap, useAnalyze, useDetect } from '@devrobotlab/visionapi-react';
import type { DetectResponse } from '@devrobotlab/visionapi-react';
export function DetectThenAnalyze() {
const [file, setFile] = useState<File | null>(null);
const [guess, setGuess] = useState<DetectResponse | null>(null);
const { detect, isLoading: isDetecting } = useDetect();
const { analyze, data, isLoading: isAnalyzing, error } = useAnalyze();
return (
<section>
<input
type="file"
accept="image/*,application/pdf"
onChange={async (event) => {
const picked = event.target.files?.[0] ?? null;
setFile(picked);
setGuess(null);
if (picked) setGuess(await detect(picked).catch(() => null));
}}
/>
{isDetecting && <p>Working out what this is…</p>}
{guess && (
// `fallback` means nothing matched confidently and the generic preset was
// substituted. That is "shape unknown", not a match — say so rather than pretending.
guess.fallback ? (
<p>
We could not tell what this is
{guess.detections[0] && ` — closest guess: ${guess.detections[0].preset}`}. Extract
it as a generic document?
<button onClick={() => file && analyze(file, { preset: 'document' })}>Extract anyway</button>
</p>
) : (
<p>
This looks like a <strong>{guess.recommended}</strong>.
<button
disabled={isAnalyzing}
onClick={() => file && analyze(file, { preset: guess.recommended })}
>
Extract it
</button>
{guess.detections.length > 1 && (
<select onChange={(event) => file && analyze(file, { preset: event.target.value })}>
<option>…or pick another</option>
{guess.detections.map((candidate) => (
<option key={candidate.preset} value={candidate.preset} title={candidate.reason}>
{candidate.preset} ({candidate.confidence})
</option>
))}
</select>
)}
</p>
)
)}
{error && <p role="alert">{error.userMessage}</p>}
{data && <pre>{JSON.stringify(unwrap(data.result, { dropNull: true }), null, 2)}</pre>}
</section>
);
}