implemented scanning PDF docs for multiple 2D codes
This commit is contained in:
@@ -7,7 +7,7 @@ import { useFormState } from "react-dom";
|
||||
import { updateOrAddBill } from "../lib/actions/billActions";
|
||||
import Link from "next/link";
|
||||
import { formatYearMonth } from "../lib/format";
|
||||
import { findDecodePdf417 } from "../lib/pdf/barcodeDecoder";
|
||||
import { DecodeResult, findDecodePdf417 } from "../lib/pdf/barcodeDecoder";
|
||||
import { useLocale, useTranslations } from "next-intl";
|
||||
|
||||
// Next.js does not encode an utf-8 file name correctly when sending a form with a file attachment
|
||||
@@ -37,10 +37,12 @@ export const BillEditForm:FC<BillEditFormProps> = ({ location, bill }) => {
|
||||
|
||||
const handleAction = updateOrAddBillMiddleware.bind(null, locationID, billID, billYear, billMonth);
|
||||
|
||||
const [ isScanningPDF, setIsScanningPDF ] = React.useState<boolean>(false);
|
||||
const [ state, dispatch ] = useFormState(handleAction, initialState);
|
||||
const [ isPaid, setIsPaid ] = React.useState<boolean>(paid);
|
||||
const [ payedAmount, setPayedAmount ] = React.useState<string>(initialPayedAmount ? `${initialPayedAmount/100}` : "" );
|
||||
const [ barcodeImage, setBarcodeImage ] = React.useState<string | undefined>(initialBarcodeImage);
|
||||
const [ barcodeResults, setBarcodeResults ] = React.useState<Array<DecodeResult> | null>(null);
|
||||
|
||||
const billPaid_handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setIsPaid(event.target.checked);
|
||||
@@ -50,19 +52,39 @@ export const BillEditForm:FC<BillEditFormProps> = ({ location, bill }) => {
|
||||
setPayedAmount(event.target.value);
|
||||
}
|
||||
|
||||
const billAttachment_handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
findDecodePdf417(event)
|
||||
.then(result => {
|
||||
if(result) {
|
||||
const {
|
||||
barcodeImage,
|
||||
billInfo
|
||||
} = result;
|
||||
const billAttachment_handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setIsScanningPDF(true);
|
||||
|
||||
setPayedAmount(`${billInfo.amount/100}`);
|
||||
setBarcodeImage(barcodeImage);
|
||||
}
|
||||
});
|
||||
setPayedAmount("");
|
||||
setBarcodeImage(undefined);
|
||||
setBarcodeResults(null);
|
||||
|
||||
const results = await findDecodePdf417(event);
|
||||
if(results && results.length > 0) {
|
||||
|
||||
if(results.length === 1) {
|
||||
const {
|
||||
barcodeImage,
|
||||
billInfo
|
||||
} = results[0];
|
||||
|
||||
setPayedAmount(`${billInfo.amount/100}`);
|
||||
setBarcodeImage(barcodeImage);
|
||||
} else {
|
||||
setPayedAmount("");
|
||||
setBarcodeImage(undefined);
|
||||
setBarcodeResults(results);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setIsScanningPDF(false);
|
||||
}
|
||||
|
||||
const handleBarcodeSelectClick = (result: DecodeResult) => {
|
||||
setPayedAmount(`${result.billInfo.amount/100}`);
|
||||
setBarcodeImage(result.barcodeImage);
|
||||
setBarcodeResults(null);
|
||||
}
|
||||
|
||||
return(
|
||||
@@ -98,8 +120,36 @@ export const BillEditForm:FC<BillEditFormProps> = ({ location, bill }) => {
|
||||
: null
|
||||
}
|
||||
<div className="flex">
|
||||
<input id="billAttachment" name="billAttachment" type="file" className="file-input file-input-bordered grow file-input-xs my-2 block" onChange={billAttachment_handleChange} />
|
||||
<input id="billAttachment" name="billAttachment" type="file" className="file-input file-input-bordered grow file-input-s my-2 block max-w-[17em] md:max-w-[80em] break-words" onChange={billAttachment_handleChange} />
|
||||
</div>
|
||||
{
|
||||
isScanningPDF &&
|
||||
<div className="flex flex-row items-center w-full mt-2">
|
||||
<div className="loading loading-spinner loading-m mr-2"></div>
|
||||
<span>{t("scanning-pdf")}</span>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
// if multiple results are found, show them as a list
|
||||
// and notify the user to select the correct one
|
||||
barcodeResults && barcodeResults.length > 0 &&
|
||||
<>
|
||||
<div className="flex mt-2 ml-2">
|
||||
<label className="label-text max-w-xs break-words">{t("multiple-barcode-results-notification")}</label>
|
||||
</div>
|
||||
<div className="flex">
|
||||
<label className="label grow pt-0 ml-3">
|
||||
<ul className="list-none">
|
||||
{barcodeResults.map((result, index) => (
|
||||
<li key={index} className="cursor-pointer mt-3" onClick={() => handleBarcodeSelectClick(result)}>
|
||||
👉 { result.billInfo.description }
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</label>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
<div id="status-error" aria-live="polite" aria-atomic="true">
|
||||
{state.errors?.billAttachment &&
|
||||
state.errors.billAttachment.map((error: string) => (
|
||||
@@ -141,7 +191,6 @@ export const BillEditForm:FC<BillEditFormProps> = ({ location, bill }) => {
|
||||
<p className="text-xs my-1">{t.rich('barcode-disclaimer', { br: () => <br /> })}</p>
|
||||
</div> : null
|
||||
}
|
||||
|
||||
<textarea id="billNotes" name="billNotes" className="textarea textarea-bordered my-2 max-w-lg w-full block" placeholder={t("notes-placeholder")} defaultValue={notes ?? ''}></textarea>
|
||||
<div id="status-error" aria-live="polite" aria-atomic="true">
|
||||
{state.errors?.billNotes &&
|
||||
|
||||
Reference in New Issue
Block a user