Refactor image upload handling in ReceiptForm and +page components by removing direct input element clicks and replacing them with accessible labels. Update styles for improved user experience and maintainability.
This commit is contained in:
@@ -20,14 +20,9 @@
|
||||
defaultType?: string;
|
||||
} = $props();
|
||||
|
||||
let imageInputEl = $state<HTMLInputElement | null>(null);
|
||||
let imageFileName = $state<string | null>(null);
|
||||
let imageConverting = $state(false);
|
||||
|
||||
function openScanReceipt() {
|
||||
imageInputEl?.click();
|
||||
}
|
||||
|
||||
async function onImageChange(e: Event) {
|
||||
const input = e.currentTarget as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
@@ -79,25 +74,24 @@
|
||||
|
||||
<div class="space-y-2">
|
||||
<Label for="Image">Image</Label>
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
class="w-full"
|
||||
onclick={openScanReceipt}
|
||||
>
|
||||
Scan receipt
|
||||
</Button>
|
||||
<div class="relative flex flex-col gap-2">
|
||||
<input
|
||||
bind:this={imageInputEl}
|
||||
id="Image"
|
||||
name="Image"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
onchange={onImageChange}
|
||||
class="hidden"
|
||||
class="absolute opacity-0 w-0 h-0 overflow-hidden"
|
||||
tabindex="-1"
|
||||
aria-label="Scan receipt"
|
||||
/>
|
||||
<label
|
||||
for="Image"
|
||||
class="border-input bg-background hover:bg-accent hover:text-accent-foreground flex h-9 w-full cursor-pointer items-center justify-center rounded-md border px-4 py-2 text-sm font-medium shadow-xs transition-colors"
|
||||
>
|
||||
Scan receipt
|
||||
</label>
|
||||
{#if imageConverting}
|
||||
<p class="text-muted-foreground text-xs">Converting to WebP…</p>
|
||||
{:else if imageFileName}
|
||||
|
||||
@@ -133,9 +133,6 @@
|
||||
imageOpen = mq.matches;
|
||||
});
|
||||
|
||||
function openReplaceImage() {
|
||||
imageInputEl?.click();
|
||||
}
|
||||
async function onImageChange() {
|
||||
const input = imageInputEl;
|
||||
const file = input?.files?.[0] ?? null;
|
||||
@@ -237,19 +234,25 @@
|
||||
class="flex flex-col gap-4"
|
||||
>
|
||||
<input type="hidden" name="dataJson" value={buildDataJson()} />
|
||||
<div class="flex items-center gap-2">
|
||||
<Button type="button" variant="outline" size="sm" onclick={openReplaceImage}>
|
||||
{receipt.Image ? "Replace image" : "Add image"}
|
||||
</Button>
|
||||
<div class="relative flex items-center gap-2">
|
||||
<input
|
||||
id="receipt-image-input"
|
||||
bind:this={imageInputEl}
|
||||
type="file"
|
||||
name="Image"
|
||||
accept="image/*"
|
||||
capture="environment"
|
||||
onchange={onImageChange}
|
||||
class="hidden"
|
||||
class="absolute opacity-0 w-0 h-0 overflow-hidden"
|
||||
tabindex="-1"
|
||||
aria-label={receipt.Image ? "Replace image" : "Add image"}
|
||||
/>
|
||||
<label
|
||||
for="receipt-image-input"
|
||||
class="border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 cursor-pointer items-center justify-center rounded-md border px-3 text-sm font-medium shadow-xs transition-colors"
|
||||
>
|
||||
{receipt.Image ? "Replace image" : "Add image"}
|
||||
</label>
|
||||
{#if imageFileName}
|
||||
<span class="text-muted-foreground text-xs">New: {imageFileName}</span>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user