receipts/js/receipt-form.ts

92 lines
2.7 KiB
TypeScript

import "@shoelace-style/shoelace/dist/components/button/button.js";
import "@shoelace-style/shoelace/dist/components/details/details.js";
import "@shoelace-style/shoelace/dist/components/icon/icon.js";
import "@shoelace-style/shoelace/dist/components/input/input.js";
import "@shoelace-style/shoelace/dist/components/textarea/textarea.js";
import "./shoelace.js";
import "./camera.ts";
import CameraInput from "./camera.ts";
import SlButton from "@shoelace-style/shoelace/dist/components/button/button.js";
import { notify, notifyError } from "./alert";
import { getResponseError } from "./ajaxUtil.js";
const form = document.forms[0];
const cameraInput = form.querySelector("camera-input") as CameraInput;
const btnSubmit = form.querySelector("sl-button[type='submit']") as SlButton;
const btnUpload = form.querySelector(
"sl-button[class='choose-file']",
) as SlButton;
const inpImage = form.photo as HTMLInputElement;
const imgPreview = document.getElementById("upload-preview") as HTMLImageElement;
form.addEventListener("submit", async (evt) => {
evt.preventDefault();
btnSubmit.loading = true;
const data = new FormData(form);
if (!inpImage.files?.length) {
data.delete("photo");
const blob = await cameraInput.getBlob();
if (blob) {
data.append("photo", blob, "photo.jpg");
}
}
let r: Response;
try {
r = await fetch("", {
method: "POST",
body: data,
});
} catch (e) {
notifyError(`Failed to submit form: ${e}`);
return;
} finally {
btnSubmit.loading = false;
}
if (r.ok) {
notify("Successfully uploaded receipt", undefined, undefined, null);
window.location.href = "/receipts";
} else {
const err = await getResponseError(r);
notifyError(err);
}
});
cameraInput.addEventListener("ready", ((evt: CustomEvent) => {
btnSubmit.disabled = !evt.detail.hasPhoto;
btnUpload.disabled = !!evt.detail.hasPhoto;
if (!!evt.detail.hasPhoto) {
inpImage.value = "";
imgPreview.src = "";
}
}) as EventListener);
const cameraDetails = document.querySelector(
"sl-details[summary='Take Photo']",
)!;
let cameraInitialized = false;
cameraDetails.addEventListener("sl-show", () => {
if (!cameraInitialized) {
cameraInitialized = true;
cameraInput.startCamera();
}
});
btnUpload.addEventListener("click", (evt) => {
evt.preventDefault();
form.photo.showPicker();
});
inpImage.addEventListener("change", () => {
if (inpImage.files) {
const file = inpImage.files[0];
if (file) {
btnSubmit.disabled = false;
imgPreview.src = URL.createObjectURL(file);
}
}
});