@hed-hog/finance 0.0.233 → 0.0.235

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.
@@ -54,6 +54,7 @@ import {
54
54
  Download,
55
55
  Edit,
56
56
  Eye,
57
+ Loader2,
57
58
  MoreHorizontal,
58
59
  Paperclip,
59
60
  Plus,
@@ -101,6 +102,10 @@ function NovoTituloSheet({
101
102
  const [uploadedFileName, setUploadedFileName] = useState('');
102
103
  const [isUploadingFile, setIsUploadingFile] = useState(false);
103
104
  const [isExtractingFileData, setIsExtractingFileData] = useState(false);
105
+ const [extractionConfidence, setExtractionConfidence] = useState<
106
+ number | null
107
+ >(null);
108
+ const [extractionWarnings, setExtractionWarnings] = useState<string[]>([]);
104
109
  const [uploadProgress, setUploadProgress] = useState(0);
105
110
 
106
111
  const normalizeFilenameForDisplay = (filename: string) => {
@@ -165,6 +170,8 @@ function NovoTituloSheet({
165
170
  form.reset();
166
171
  setUploadedFileId(null);
167
172
  setUploadedFileName('');
173
+ setExtractionConfidence(null);
174
+ setExtractionWarnings([]);
168
175
  setOpen(false);
169
176
  showToastHandler?.('success', 'Título criado com sucesso');
170
177
  } catch {
@@ -176,6 +183,8 @@ function NovoTituloSheet({
176
183
  form.reset();
177
184
  setUploadedFileId(null);
178
185
  setUploadedFileName('');
186
+ setExtractionConfidence(null);
187
+ setExtractionWarnings([]);
179
188
  setUploadProgress(0);
180
189
  setOpen(false);
181
190
  };
@@ -229,6 +238,9 @@ function NovoTituloSheet({
229
238
  centroCustoId?: string;
230
239
  metodo?: string;
231
240
  descricao?: string | null;
241
+ confidence?: number | null;
242
+ confidenceLevel?: 'low' | 'high' | null;
243
+ warnings?: string[];
232
244
  }>({
233
245
  url: '/finance/accounts-payable/installments/extract-from-file',
234
246
  method: 'POST',
@@ -238,6 +250,14 @@ function NovoTituloSheet({
238
250
  });
239
251
 
240
252
  const extracted = extraction.data || {};
253
+ setExtractionConfidence(
254
+ typeof extracted.confidence === 'number' ? extracted.confidence : null
255
+ );
256
+ setExtractionWarnings(
257
+ Array.isArray(extracted.warnings)
258
+ ? extracted.warnings.filter(Boolean)
259
+ : []
260
+ );
241
261
 
242
262
  if (extracted.documento) {
243
263
  form.setValue('documento', extracted.documento, {
@@ -298,6 +318,8 @@ function NovoTituloSheet({
298
318
  'Dados da fatura extraídos e preenchidos automaticamente'
299
319
  );
300
320
  } catch {
321
+ setExtractionConfidence(null);
322
+ setExtractionWarnings([]);
301
323
  showToastHandler?.(
302
324
  'error',
303
325
  'Não foi possível extrair os dados automaticamente'
@@ -308,6 +330,8 @@ function NovoTituloSheet({
308
330
  } catch {
309
331
  setUploadedFileId(null);
310
332
  setUploadedFileName('');
333
+ setExtractionConfidence(null);
334
+ setExtractionWarnings([]);
311
335
  setUploadProgress(0);
312
336
  showToastHandler?.('error', 'Não foi possível enviar o arquivo');
313
337
  } finally {
@@ -370,10 +394,16 @@ function NovoTituloSheet({
370
394
 
371
395
  setUploadedFileId(null);
372
396
  setUploadedFileName('');
397
+ setExtractionConfidence(null);
398
+ setExtractionWarnings([]);
373
399
  setUploadProgress(0);
374
400
  void uploadRelatedFile(file);
375
401
  }}
376
- disabled={isUploadingFile || form.formState.isSubmitting}
402
+ disabled={
403
+ isUploadingFile ||
404
+ isExtractingFileData ||
405
+ form.formState.isSubmitting
406
+ }
377
407
  />
378
408
  </div>
379
409
  {isUploadingFile && (
@@ -390,10 +420,36 @@ function NovoTituloSheet({
390
420
  </p>
391
421
  )}
392
422
  {isExtractingFileData && (
393
- <p className="text-xs text-muted-foreground">
394
- Extraindo dados da fatura com IA...
395
- </p>
423
+ <div className="rounded-md border border-primary/30 bg-primary/5 p-3">
424
+ <div className="flex items-center gap-2 text-sm font-medium text-primary">
425
+ <Loader2 className="h-4 w-4 animate-spin" />
426
+ Analisando documento com IA
427
+ </div>
428
+ <p className="mt-1 text-xs text-muted-foreground">
429
+ Os campos serão preenchidos automaticamente em instantes.
430
+ Revise os dados antes de salvar.
431
+ </p>
432
+ </div>
396
433
  )}
434
+ {!isExtractingFileData &&
435
+ extractionConfidence !== null &&
436
+ extractionConfidence < 70 && (
437
+ <div className="rounded-md border border-destructive/30 bg-destructive/5 p-3">
438
+ <div className="text-sm font-medium text-destructive">
439
+ Confiança da extração:{' '}
440
+ {Math.round(extractionConfidence)}%
441
+ </div>
442
+ <p className="mt-1 text-xs text-muted-foreground">
443
+ Revise principalmente valor e vencimento antes de
444
+ salvar.
445
+ </p>
446
+ {extractionWarnings.length > 0 && (
447
+ <p className="mt-1 text-xs text-muted-foreground">
448
+ {extractionWarnings[0]}
449
+ </p>
450
+ )}
451
+ </div>
452
+ )}
397
453
  </div>
398
454
 
399
455
  <FormField
@@ -609,8 +665,22 @@ function NovoTituloSheet({
609
665
  <Button type="button" variant="outline" onClick={handleCancel}>
610
666
  {t('common.cancel')}
611
667
  </Button>
612
- <Button type="submit" disabled={form.formState.isSubmitting}>
613
- {t('common.save')}
668
+ <Button
669
+ type="submit"
670
+ disabled={
671
+ form.formState.isSubmitting ||
672
+ isUploadingFile ||
673
+ isExtractingFileData
674
+ }
675
+ >
676
+ {(isUploadingFile || isExtractingFileData) && (
677
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
678
+ )}
679
+ {isExtractingFileData
680
+ ? 'Preenchendo com IA...'
681
+ : isUploadingFile
682
+ ? 'Enviando arquivo...'
683
+ : t('common.save')}
614
684
  </Button>
615
685
  </div>
616
686
  </form>
@@ -54,6 +54,7 @@ import {
54
54
  Download,
55
55
  Edit,
56
56
  Eye,
57
+ Loader2,
57
58
  MoreHorizontal,
58
59
  Paperclip,
59
60
  Plus,
@@ -100,6 +101,10 @@ function NovoTituloSheet({
100
101
  const [uploadedFileName, setUploadedFileName] = useState('');
101
102
  const [isUploadingFile, setIsUploadingFile] = useState(false);
102
103
  const [isExtractingFileData, setIsExtractingFileData] = useState(false);
104
+ const [extractionConfidence, setExtractionConfidence] = useState<
105
+ number | null
106
+ >(null);
107
+ const [extractionWarnings, setExtractionWarnings] = useState<string[]>([]);
103
108
  const [uploadProgress, setUploadProgress] = useState(0);
104
109
 
105
110
  const normalizeFilenameForDisplay = (filename: string) => {
@@ -164,6 +169,8 @@ function NovoTituloSheet({
164
169
  form.reset();
165
170
  setUploadedFileId(null);
166
171
  setUploadedFileName('');
172
+ setExtractionConfidence(null);
173
+ setExtractionWarnings([]);
167
174
  setOpen(false);
168
175
  showToastHandler?.('success', 'Título criado com sucesso');
169
176
  } catch {
@@ -175,6 +182,8 @@ function NovoTituloSheet({
175
182
  form.reset();
176
183
  setUploadedFileId(null);
177
184
  setUploadedFileName('');
185
+ setExtractionConfidence(null);
186
+ setExtractionWarnings([]);
178
187
  setUploadProgress(0);
179
188
  setOpen(false);
180
189
  };
@@ -228,6 +237,9 @@ function NovoTituloSheet({
228
237
  centroCustoId?: string;
229
238
  canal?: string;
230
239
  descricao?: string | null;
240
+ confidence?: number | null;
241
+ confidenceLevel?: 'low' | 'high' | null;
242
+ warnings?: string[];
231
243
  }>({
232
244
  url: '/finance/accounts-receivable/installments/extract-from-file',
233
245
  method: 'POST',
@@ -237,6 +249,14 @@ function NovoTituloSheet({
237
249
  });
238
250
 
239
251
  const extracted = extraction.data || {};
252
+ setExtractionConfidence(
253
+ typeof extracted.confidence === 'number' ? extracted.confidence : null
254
+ );
255
+ setExtractionWarnings(
256
+ Array.isArray(extracted.warnings)
257
+ ? extracted.warnings.filter(Boolean)
258
+ : []
259
+ );
240
260
 
241
261
  if (extracted.documento) {
242
262
  form.setValue('documento', extracted.documento, {
@@ -297,6 +317,8 @@ function NovoTituloSheet({
297
317
  'Dados da fatura extraídos e preenchidos automaticamente'
298
318
  );
299
319
  } catch {
320
+ setExtractionConfidence(null);
321
+ setExtractionWarnings([]);
300
322
  showToastHandler?.(
301
323
  'error',
302
324
  'Não foi possível extrair os dados automaticamente'
@@ -307,6 +329,8 @@ function NovoTituloSheet({
307
329
  } catch {
308
330
  setUploadedFileId(null);
309
331
  setUploadedFileName('');
332
+ setExtractionConfidence(null);
333
+ setExtractionWarnings([]);
310
334
  setUploadProgress(0);
311
335
  showToastHandler?.('error', 'Não foi possível enviar o arquivo');
312
336
  } finally {
@@ -344,10 +368,16 @@ function NovoTituloSheet({
344
368
 
345
369
  setUploadedFileId(null);
346
370
  setUploadedFileName('');
371
+ setExtractionConfidence(null);
372
+ setExtractionWarnings([]);
347
373
  setUploadProgress(0);
348
374
  void uploadRelatedFile(file);
349
375
  }}
350
- disabled={isUploadingFile || form.formState.isSubmitting}
376
+ disabled={
377
+ isUploadingFile ||
378
+ isExtractingFileData ||
379
+ form.formState.isSubmitting
380
+ }
351
381
  />
352
382
  </div>
353
383
  {isUploadingFile && (
@@ -364,10 +394,36 @@ function NovoTituloSheet({
364
394
  </p>
365
395
  )}
366
396
  {isExtractingFileData && (
367
- <p className="text-xs text-muted-foreground">
368
- Extraindo dados da fatura com IA...
369
- </p>
397
+ <div className="rounded-md border border-primary/30 bg-primary/5 p-3">
398
+ <div className="flex items-center gap-2 text-sm font-medium text-primary">
399
+ <Loader2 className="h-4 w-4 animate-spin" />
400
+ Analisando documento com IA
401
+ </div>
402
+ <p className="mt-1 text-xs text-muted-foreground">
403
+ Os campos serão preenchidos automaticamente em instantes.
404
+ Revise os dados antes de salvar.
405
+ </p>
406
+ </div>
370
407
  )}
408
+ {!isExtractingFileData &&
409
+ extractionConfidence !== null &&
410
+ extractionConfidence < 70 && (
411
+ <div className="rounded-md border border-destructive/30 bg-destructive/5 p-3">
412
+ <div className="text-sm font-medium text-destructive">
413
+ Confiança da extração:{' '}
414
+ {Math.round(extractionConfidence)}%
415
+ </div>
416
+ <p className="mt-1 text-xs text-muted-foreground">
417
+ Revise principalmente valor e vencimento antes de
418
+ salvar.
419
+ </p>
420
+ {extractionWarnings.length > 0 && (
421
+ <p className="mt-1 text-xs text-muted-foreground">
422
+ {extractionWarnings[0]}
423
+ </p>
424
+ )}
425
+ </div>
426
+ )}
371
427
  </div>
372
428
 
373
429
  <FormField
@@ -577,8 +633,22 @@ function NovoTituloSheet({
577
633
  <Button type="button" variant="outline" onClick={handleCancel}>
578
634
  {t('common.cancel')}
579
635
  </Button>
580
- <Button type="submit" disabled={form.formState.isSubmitting}>
581
- {t('common.save')}
636
+ <Button
637
+ type="submit"
638
+ disabled={
639
+ form.formState.isSubmitting ||
640
+ isUploadingFile ||
641
+ isExtractingFileData
642
+ }
643
+ >
644
+ {(isUploadingFile || isExtractingFileData) && (
645
+ <Loader2 className="mr-2 h-4 w-4 animate-spin" />
646
+ )}
647
+ {isExtractingFileData
648
+ ? 'Preenchendo com IA...'
649
+ : isUploadingFile
650
+ ? 'Enviando arquivo...'
651
+ : t('common.save')}
582
652
  </Button>
583
653
  </div>
584
654
  </form>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hed-hog/finance",
3
- "version": "0.0.233",
3
+ "version": "0.0.235",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "dependencies": {
@@ -10,13 +10,13 @@
10
10
  "@nestjs/jwt": "^11",
11
11
  "@nestjs/mapped-types": "*",
12
12
  "@hed-hog/api-locale": "0.0.11",
13
- "@hed-hog/api-pagination": "0.0.5",
14
13
  "@hed-hog/api-prisma": "0.0.4",
14
+ "@hed-hog/api-pagination": "0.0.5",
15
+ "@hed-hog/tag": "0.0.235",
15
16
  "@hed-hog/api-types": "0.0.1",
16
- "@hed-hog/tag": "0.0.233",
17
17
  "@hed-hog/api": "0.0.3",
18
- "@hed-hog/contact": "0.0.233",
19
- "@hed-hog/core": "0.0.233"
18
+ "@hed-hog/contact": "0.0.235",
19
+ "@hed-hog/core": "0.0.235"
20
20
  },
21
21
  "exports": {
22
22
  ".": {