import { useEffect, useState } from "react"; import { api } from "../../api"; import { IconAsk, IconCheck, IconDoc, IconEval, IconQuote, IconShield, IconSpark, IconUpload, } from "../../lib/icons"; import { useScrollReveal } from "../../lib/useScrollReveal"; import Button from "../ui/Button"; import Card from "../ui/Card"; import { EmptyState, ErrorState, LoadingState, SuccessNote } from "../ui/States"; import DocumentCard from "../DocumentCard"; import Upload from "../Upload"; import HeroPreview from "./HeroPreview"; const STEPS = [ { Icon: IconUpload, t: "Upload", d: "Drop a PDF or TXT. We extract the text and split it into overlapping, page-tagged chunks." }, { Icon: IconAsk, t: "Retrieve", d: "Your question ranks the most relevant passages with a transparent TF-IDF retriever." }, { Icon: IconQuote, t: "Cite", d: "The answer is built only from those passages — and every claim shows its source." }, ]; // Lightweight count-up for the stats band (rAF, ease-out cubic). function CountUp({ end, suffix = "", duration = 1200 }) { const [v, setV] = useState(0); useEffect(() => { if (!end) return; let raf, start; const tick = (t) => { if (!start) start = t; const p = Math.min((t - start) / duration, 1); setV(Math.round((1 - Math.pow(1 - p, 3)) * end)); if (p < 1) raf = requestAnimationFrame(tick); }; raf = requestAnimationFrame(tick); return () => cancelAnimationFrame(raf); }, [end, duration]); return ( <> {v} {suffix} ); } export default function Overview({ documents, loading, reload, onTryDemo, seeding, onOpenEval }) { const [uploading, setUploading] = useState(false); const [message, setMessage] = useState(""); const [error, setError] = useState(""); useScrollReveal([loading, documents.length]); async function onFile(file) { setError(""); setMessage(""); setUploading(true); try { const doc = await api.uploadDocument(file); await reload(); if (doc.status === "processed") { setMessage(`Uploaded "${doc.filename}" — ${doc.num_chunks} chunks ready.`); } else { setError(`"${doc.filename}" couldn't be processed: ${doc.error || "unknown error"}`); } } catch (err) { setError(err.message); } finally { setUploading(false); } } async function onDelete(doc) { if (!confirm(`Delete "${doc.filename}" and its history?`)) return; setError(""); setMessage(""); try { await api.deleteDocument(doc.id); await reload(); setMessage(`Deleted "${doc.filename}".`); } catch (err) { setError(err.message); } } function scrollToUpload() { document .getElementById("upload-zone") ?.scrollIntoView({ behavior: "smooth", block: "center" }); } return (
{/* ---- Hero ---- */}
Audit-ready finance answers

Answers you can prove.

FinanceFlow audits invoices, contracts, and payment notes for totals, due dates, payment terms, late fees, and unsupported claims — with citations you can verify. When the evidence isn't there, it says so instead of guessing.

Grounded only Cites every line Abstains when unsure
{/* ---- Works-with strip ---- */}
Reads your Invoices Contracts Statements Payment notes PDF & TXT
{/* ---- How it works ---- */}

01 / How it works

{STEPS.map(({ Icon, t, d }, i) => (
{i + 1}

{t}

{d}

))}
{/* ---- Stats band ---- */}
of answers carry a citation
0
unsupported / hallucinated answers
/25
automated tests passing in CI
{/* ---- Why it's trustworthy (bento) ---- */}

02 / Why it's trustworthy

Citation-first retrieval

Every answer shows the exact source excerpt, page, and relevance score — so you verify in one glance.

Abstains when unsure

Two retrieval gates. If the evidence is weak, it replies “Not enough information” instead of guessing.

Source-only answers

Extractive by default — it can't invent a number that isn't in your file.

Evaluation suite included

A golden dataset grades grounding on every run: 100% citation coverage, 0 unsupported answers.

{/* ---- Evaluation teaser ---- */}

We grade ourselves.

Most AI demos ask you to trust them. FinanceFlow ships a golden-dataset evaluation that scores whether it stayed grounded — and counts a correct refusal as a success.

100%
Citation coverage
0
Unsupported answers
{/* ---- Proof band (dark) ---- */}

Proof, not promises

Trust you can check.

FinanceFlow doesn’t ask you to trust it — it shows its work. Every answer links back to the exact source line, it abstains when the document doesn’t say, and a bundled evaluation grades that grounding on every run.

100% of answers carry a citation
0 unsupported / hallucinated answers
25/25 automated tests passing
{/* ---- Upload + documents (functional) ---- */}

03 / Try it with your own files

Add a document

PDF or TXT · 10 MB max
{message &&
{message}
}
{error}

Your documents

{documents.length > 0 && {documents.length} total}
{loading ? ( ) : documents.length === 0 ? ( Click Try the live demo to load sample finance documents, or drop your own file above. ) : (
{documents.map((d) => ( ))}
)}
{/* ---- Final CTA ---- */}

Stop trusting. Start verifying.

{/* ---- Footer ---- */}
); }