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;
|
defaultType?: string;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let imageInputEl = $state<HTMLInputElement | null>(null);
|
|
||||||
let imageFileName = $state<string | null>(null);
|
let imageFileName = $state<string | null>(null);
|
||||||
let imageConverting = $state(false);
|
let imageConverting = $state(false);
|
||||||
|
|
||||||
function openScanReceipt() {
|
|
||||||
imageInputEl?.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onImageChange(e: Event) {
|
async function onImageChange(e: Event) {
|
||||||
const input = e.currentTarget as HTMLInputElement;
|
const input = e.currentTarget as HTMLInputElement;
|
||||||
const file = input.files?.[0];
|
const file = input.files?.[0];
|
||||||
@@ -79,25 +74,24 @@
|
|||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<Label for="Image">Image</Label>
|
<Label for="Image">Image</Label>
|
||||||
<div class="flex flex-col gap-2">
|
<div class="relative flex flex-col gap-2">
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
class="w-full"
|
|
||||||
onclick={openScanReceipt}
|
|
||||||
>
|
|
||||||
Scan receipt
|
|
||||||
</Button>
|
|
||||||
<input
|
<input
|
||||||
bind:this={imageInputEl}
|
|
||||||
id="Image"
|
id="Image"
|
||||||
name="Image"
|
name="Image"
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
capture="environment"
|
capture="environment"
|
||||||
onchange={onImageChange}
|
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}
|
{#if imageConverting}
|
||||||
<p class="text-muted-foreground text-xs">Converting to WebP…</p>
|
<p class="text-muted-foreground text-xs">Converting to WebP…</p>
|
||||||
{:else if imageFileName}
|
{:else if imageFileName}
|
||||||
|
|||||||
@@ -133,9 +133,6 @@
|
|||||||
imageOpen = mq.matches;
|
imageOpen = mq.matches;
|
||||||
});
|
});
|
||||||
|
|
||||||
function openReplaceImage() {
|
|
||||||
imageInputEl?.click();
|
|
||||||
}
|
|
||||||
async function onImageChange() {
|
async function onImageChange() {
|
||||||
const input = imageInputEl;
|
const input = imageInputEl;
|
||||||
const file = input?.files?.[0] ?? null;
|
const file = input?.files?.[0] ?? null;
|
||||||
@@ -237,19 +234,25 @@
|
|||||||
class="flex flex-col gap-4"
|
class="flex flex-col gap-4"
|
||||||
>
|
>
|
||||||
<input type="hidden" name="dataJson" value={buildDataJson()} />
|
<input type="hidden" name="dataJson" value={buildDataJson()} />
|
||||||
<div class="flex items-center gap-2">
|
<div class="relative flex items-center gap-2">
|
||||||
<Button type="button" variant="outline" size="sm" onclick={openReplaceImage}>
|
|
||||||
{receipt.Image ? "Replace image" : "Add image"}
|
|
||||||
</Button>
|
|
||||||
<input
|
<input
|
||||||
|
id="receipt-image-input"
|
||||||
bind:this={imageInputEl}
|
bind:this={imageInputEl}
|
||||||
type="file"
|
type="file"
|
||||||
name="Image"
|
name="Image"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
capture="environment"
|
capture="environment"
|
||||||
onchange={onImageChange}
|
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}
|
{#if imageFileName}
|
||||||
<span class="text-muted-foreground text-xs">New: {imageFileName}</span>
|
<span class="text-muted-foreground text-xs">New: {imageFileName}</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user