diff --git a/components/InvoiceMatchHost.tsx b/components/InvoiceMatchHost.tsx index 774052a..aae224a 100644 --- a/components/InvoiceMatchHost.tsx +++ b/components/InvoiceMatchHost.tsx @@ -7,9 +7,11 @@ import { RUN_EVENT, collectMatched, matchInvoice, + saveReviewNote, undoMatched, type InvoiceMatchResult, type MatchedLine, + type ReviewLine, } from '@/lib/invoiceCheck'; interface InvoiceMatchHostProps { @@ -31,6 +33,11 @@ export default function InvoiceMatchHost({ onCollected, onRestored }: InvoiceMat const [collected, setCollected] = useState([]); const [failedIds, setFailedIds] = useState([]); const [error, setError] = useState(''); + const [noteFor, setNoteFor] = useState(null); + const [noteText, setNoteText] = useState(''); + const [noteBusy, setNoteBusy] = useState(false); + const [noteError, setNoteError] = useState(''); + const [savedNotes, setSavedNotes] = useState([]); const running = useRef(false); const run = useCallback( @@ -44,6 +51,8 @@ export default function InvoiceMatchHost({ onCollected, onRestored }: InvoiceMat setResult(null); setCollected([]); setFailedIds([]); + setNoteFor(null); + setSavedNotes([]); try { const r = await matchInvoice(po); setResult(r); @@ -94,6 +103,26 @@ export default function InvoiceMatchHost({ onCollected, onRestored }: InvoiceMat onRestored(); }; + const saveNote = async (line: ReviewLine) => { + if (!noteText.trim()) { + setNoteError('Write the reason first.'); + return; + } + setNoteBusy(true); + setNoteError(''); + try { + await saveReviewNote(line, noteText); + setSavedNotes((prev) => [...prev, line.id]); + setNoteFor(null); + setNoteText(''); + } catch (e) { + console.warn('[invoice-match] note failed for', line.id, e); + setNoteError('Could not save the note. Try again.'); + } finally { + setNoteBusy(false); + } + }; + if (!open) return null; return ( @@ -153,6 +182,50 @@ export default function InvoiceMatchHost({ onCollected, onRestored }: InvoiceMat

{l.description}

{l.reason}

+ {savedNotes.includes(l.id) ? ( +

Note saved

+ ) : noteFor === l.id ? ( +
+ +