feat(catalogue): coller une image depuis le presse-papier (Ctrl+V)

Écoute l'événement paste sur window quand le formulaire est ouvert.
Si le presse-papier contient une image, déclenche le même upload
que le bouton fichier. Indice visuel "ou Ctrl+V" affiché sous le bouton.
Les deux méthodes (fichier + coller) coexistent.

v0.4.13

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 13:18:09 +02:00
parent 4e5e6f7c36
commit fa1a642240
2 changed files with 30 additions and 10 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "homehub-frontend",
"private": true,
"version": "0.4.12",
"version": "0.4.13",
"type": "module",
"scripts": {
"dev": "vite",
@@ -147,9 +147,7 @@ export default function CatalogueModal({ stores, onClose }: CatalogueModalProps)
}
}
async function handlePhotoChange(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0]
if (!file) return
async function uploadFile(file: File) {
setUploading(true)
setError(null)
try {
@@ -167,6 +165,11 @@ export default function CatalogueModal({ stores, onClose }: CatalogueModalProps)
}
}
async function handlePhotoChange(e: React.ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0]
if (file) await uploadFile(file)
}
async function handleSave() {
if (!form.name.trim()) return
setSaving(true)
@@ -200,6 +203,18 @@ export default function CatalogueModal({ stores, onClose }: CatalogueModalProps)
const isFormOpen = creating || editing !== null
const previewSrc = form.thumbnail_path ?? form.image_path
useEffect(() => {
if (!isFormOpen) return
function onPaste(e: ClipboardEvent) {
const item = Array.from(e.clipboardData?.items ?? []).find(i => i.type.startsWith('image/'))
if (!item) return
const file = item.getAsFile()
if (file) void uploadFile(file)
}
window.addEventListener('paste', onPaste)
return () => window.removeEventListener('paste', onPaste)
}, [isFormOpen])
return (
<Modal title="Catalogue d'articles" onClose={onClose} width={580}>
{error && (
@@ -226,12 +241,17 @@ export default function CatalogueModal({ stores, onClose }: CatalogueModalProps)
}}>📷</div>
)}
<input ref={photoRef} type="file" accept="image/*" capture="environment" style={{ display: 'none' }} onChange={handlePhotoChange} />
<button
type="button"
onClick={() => photoRef.current?.click()}
disabled={uploading}
style={{ padding: '6px 14px', borderRadius: 8, border: '1px solid var(--bg-5)', background: 'var(--bg-4)', color: 'var(--ink-2)', cursor: 'pointer', fontFamily: 'var(--font-ui)', fontSize: 13 }}
>{uploading ? '…' : previewSrc ? 'Changer' : 'Ajouter photo'}</button>
<div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
<button
type="button"
onClick={() => photoRef.current?.click()}
disabled={uploading}
style={{ padding: '6px 14px', borderRadius: 8, border: '1px solid var(--bg-5)', background: 'var(--bg-4)', color: 'var(--ink-2)', cursor: 'pointer', fontFamily: 'var(--font-ui)', fontSize: 13 }}
>{uploading ? '…' : previewSrc ? 'Changer' : 'Ajouter photo'}</button>
{!uploading && (
<span style={{ color: 'var(--ink-4)', fontSize: 11, fontFamily: 'var(--font-ui)', paddingLeft: 4 }}>ou Ctrl+V pour coller</span>
)}
</div>
{previewSrc && (
<button
type="button"