This is all pretty straightforward. The only real problem is that
the search results only contain matching transactions *splits*. Since
transactions themselves do not have an amount, the value shown in the
_Amount_ column on the transaction list may be incorrect if a
transaction contains multiple splits and some of them do not match the
search query.
I've implemented the UI using TypeScript and Shoelace. I originally
started with Pico CSS, but I didn't really like its visuals. Since
capturing photos using the camera requires JavaScript, and that's
basically the entire point of this application, Shoelace's JavaScript
dependency (for WebComponents), is acceptable.
The photo capture uses the Media Capture Web API, which exposes the
camera directly as a video stream. We capture a frame from this stream
and save it in a canvas, which we then pass to Cropper.js to let the
user select only the relevant portion of the picture containing the
receipt itself.