feat: improve recipe preview image UI with replace/remove buttons
Replace drop-zone with action buttons (Sostituisci/Rimuovi) when image exists, matching the task editor pattern. Add upload overlay with spinner on the image during file upload. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -258,69 +258,97 @@
|
|||||||
<div class="tmf-card-body space-y-4">
|
<div class="tmf-card-body space-y-4">
|
||||||
|
|
||||||
<!-- Current image preview -->
|
<!-- Current image preview -->
|
||||||
<div x-show="currentFilePath"
|
<template x-if="currentFilePath">
|
||||||
class="relative rounded-lg overflow-hidden bg-[var(--bg-secondary)] border border-[var(--border-color)]">
|
<div class="space-y-3">
|
||||||
<img x-bind:src="currentFilePath ? ('/maker/api/files/' + currentFilePath) : ''"
|
<div class="relative rounded-lg overflow-hidden bg-[var(--bg-secondary)] border border-[var(--border-color)]">
|
||||||
class="block mx-auto max-h-64 object-contain p-2"
|
<img x-bind:src="'/maker/api/files/' + currentFilePath"
|
||||||
loading="lazy">
|
class="block mx-auto max-h-64 object-contain p-2"
|
||||||
<!-- Remove button -->
|
:class="{ 'opacity-40': uploadingFile }"
|
||||||
<button @click.stop="currentFilePath = ''"
|
loading="lazy">
|
||||||
type="button"
|
<!-- Upload overlay on image -->
|
||||||
class="absolute top-2 right-2 p-1.5 rounded-full bg-red-500/80 hover:bg-red-600 text-white transition-colors"
|
<div x-show="uploadingFile"
|
||||||
title="{{ _('Rimuovi immagine') }}">
|
class="absolute inset-0 flex flex-col items-center justify-center bg-white/60 dark:bg-black/50">
|
||||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
<svg class="w-8 h-8 animate-spin text-primary" fill="none" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
||||||
</svg>
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
||||||
</button>
|
</svg>
|
||||||
</div>
|
<span class="text-sm font-medium text-[var(--text-primary)] mt-2">{{ _('Caricamento in corso...') }}</span>
|
||||||
|
</div>
|
||||||
<!-- Upload area -->
|
</div>
|
||||||
<div class="drop-zone p-6 text-center cursor-pointer relative"
|
<!-- Action buttons -->
|
||||||
:class="{ 'drag-over': dragOver }"
|
<div class="flex items-center gap-2 flex-wrap">
|
||||||
@dragover.prevent="dragOver = true"
|
<label class="btn btn-secondary text-sm gap-1.5 cursor-pointer"
|
||||||
@dragleave.prevent="dragOver = false"
|
:class="{ 'opacity-50 pointer-events-none': uploadingFile }">
|
||||||
@drop.prevent="handleDrop($event)"
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||||
@click="$refs.fileInput.click()">
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/>
|
||||||
|
</svg>
|
||||||
<input type="file"
|
{{ _('Sostituisci') }}
|
||||||
x-ref="fileInput"
|
<input type="file"
|
||||||
@change="uploadFile($event.target.files[0]); $event.target.value = ''"
|
accept="image/*,application/pdf"
|
||||||
accept="image/*,application/pdf"
|
class="hidden"
|
||||||
class="hidden">
|
:disabled="uploadingFile"
|
||||||
|
@change="uploadFile($event.target.files[0]); $event.target.value = ''">
|
||||||
<!-- Uploading spinner -->
|
</label>
|
||||||
<div x-show="uploadingFile" class="flex flex-col items-center gap-3 py-4">
|
<button @click.stop="currentFilePath = ''"
|
||||||
<svg class="w-8 h-8 animate-spin text-primary" fill="none" viewBox="0 0 24 24">
|
type="button"
|
||||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
:disabled="uploadingFile"
|
||||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
class="btn btn-secondary text-sm gap-1.5 text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20">
|
||||||
</svg>
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||||
<span class="text-sm text-[var(--text-secondary)]">{{ _('Caricamento in corso...') }}</span>
|
<path stroke-linecap="round" stroke-linejoin="round" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/>
|
||||||
|
</svg>
|
||||||
|
{{ _('Rimuovi') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- Upload prompt -->
|
<!-- Upload area (only when no image) -->
|
||||||
<div x-show="!uploadingFile" class="flex flex-col items-center gap-3 py-4">
|
<template x-if="!currentFilePath">
|
||||||
<div class="w-12 h-12 rounded-full bg-primary-50 dark:bg-primary-900/30 flex items-center justify-center">
|
<div class="drop-zone p-6 text-center cursor-pointer relative"
|
||||||
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
:class="{ 'drag-over': dragOver }"
|
||||||
<path stroke-linecap="round" stroke-linejoin="round"
|
@dragover.prevent="dragOver = true"
|
||||||
d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"/>
|
@dragleave.prevent="dragOver = false"
|
||||||
|
@drop.prevent="handleDrop($event)"
|
||||||
|
@click="$refs.fileInput.click()">
|
||||||
|
|
||||||
|
<input type="file"
|
||||||
|
x-ref="fileInput"
|
||||||
|
@change="uploadFile($event.target.files[0]); $event.target.value = ''"
|
||||||
|
accept="image/*,application/pdf"
|
||||||
|
class="hidden">
|
||||||
|
|
||||||
|
<!-- Uploading spinner -->
|
||||||
|
<div x-show="uploadingFile" class="flex flex-col items-center gap-3 py-4">
|
||||||
|
<svg class="w-8 h-8 animate-spin text-primary" fill="none" viewBox="0 0 24 24">
|
||||||
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
||||||
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
<span class="text-sm text-[var(--text-secondary)]">{{ _('Caricamento in corso...') }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center">
|
|
||||||
<span x-show="!currentFilePath" class="inline-block px-4 py-2 rounded-lg bg-primary text-white text-sm font-semibold mb-2">
|
<!-- Upload prompt -->
|
||||||
{{ _('Carica Immagine o PDF') }}
|
<div x-show="!uploadingFile" class="flex flex-col items-center gap-3 py-4">
|
||||||
</span>
|
<div class="w-12 h-12 rounded-full bg-primary-50 dark:bg-primary-900/30 flex items-center justify-center">
|
||||||
<span x-show="currentFilePath" class="inline-block px-4 py-2 rounded-lg bg-[var(--bg-tertiary)] text-[var(--text-primary)] text-sm font-semibold mb-2 border border-[var(--border-color)]">
|
<svg class="w-6 h-6 text-primary" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24">
|
||||||
{{ _('Sostituisci Immagine') }}
|
<path stroke-linecap="round" stroke-linejoin="round"
|
||||||
</span>
|
d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5"/>
|
||||||
<p class="text-xs text-[var(--text-muted)]">
|
</svg>
|
||||||
{{ _('Trascina qui oppure clicca. Formati: PNG, JPG, WebP, PDF (max 50MB)') }}
|
</div>
|
||||||
</p>
|
<div class="text-center">
|
||||||
<p class="text-xs text-[var(--text-muted)] mt-1">
|
<span class="inline-block px-4 py-2 rounded-lg bg-primary text-white text-sm font-semibold mb-2">
|
||||||
{{ _('Usata come thumbnail nella lista ricette') }}
|
{{ _('Carica Immagine') }}
|
||||||
</p>
|
</span>
|
||||||
|
<p class="text-xs text-[var(--text-muted)]">
|
||||||
|
{{ _('Trascina qui oppure clicca. Formati: PNG, JPG, WebP, PDF (max 50MB)') }}
|
||||||
|
</p>
|
||||||
|
<p class="text-xs text-[var(--text-muted)] mt-1">
|
||||||
|
{{ _('Usata come thumbnail nella lista ricette') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user