before gemiin

This commit is contained in:
2026-02-22 22:18:32 +01:00
parent fb33540bb0
commit 9db5cbf236
147 changed files with 7948 additions and 531 deletions

View File

@@ -27,8 +27,9 @@
class="text-blue text-xs hover:underline truncate">🔗 Boutique</a>
<a v-if="t.video_url" :href="t.video_url" target="_blank" rel="noopener noreferrer"
class="text-aqua text-xs hover:underline truncate">🎬 Vidéo</a>
<a v-if="t.notice_fichier_url" :href="t.notice_fichier_url" target="_blank" rel="noopener noreferrer"
class="text-aqua text-xs hover:underline truncate">📄 Notice</a>
<p v-if="t.notice_texte" class="text-text-muted text-xs whitespace-pre-line">{{ t.notice_texte }}</p>
<a v-else-if="t.notice_fichier_url" :href="t.notice_fichier_url" target="_blank" rel="noopener noreferrer"
class="text-aqua text-xs hover:underline truncate">📄 Notice (fichier)</a>
<div v-if="t.photo_url || t.video_url" class="mt-auto pt-2 space-y-2">
<img v-if="t.photo_url" :src="t.photo_url" alt="photo outil"
@@ -79,14 +80,8 @@
<video v-if="videoPreview" :src="videoPreview" controls muted
class="mt-2 w-full h-36 object-cover rounded border border-bg-hard bg-bg" />
</div>
<div>
<label class="text-text-muted text-xs block mb-1">Notice (fichier texte)</label>
<input type="file" accept=".txt,.md,text/plain" @change="onNoticeSelected"
class="bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" />
<div v-if="noticeFileName || form.notice_fichier_url" class="text-text-muted text-xs mt-1 truncate">
{{ noticeFileName || fileNameFromUrl(form.notice_fichier_url || '') }}
</div>
</div>
<textarea v-model="form.notice_texte" placeholder="Notice (texte libre)..."
class="bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow resize-none h-24" />
<div class="flex gap-2 justify-end">
<button type="button" @click="closeForm" class="px-4 py-2 text-text-muted hover:text-text text-sm">Annuler</button>
<button type="submit" class="bg-yellow text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90">
@@ -110,10 +105,8 @@ const showForm = ref(false)
const editId = ref<number | null>(null)
const photoFile = ref<File | null>(null)
const videoFile = ref<File | null>(null)
const noticeFile = ref<File | null>(null)
const photoPreview = ref('')
const videoPreview = ref('')
const noticeFileName = ref('')
const form = reactive({
nom: '',
categorie: '',
@@ -123,14 +116,10 @@ const form = reactive({
prix_achat: undefined as number | undefined,
photo_url: '',
video_url: '',
notice_texte: '',
notice_fichier_url: '',
})
function fileNameFromUrl(url: string) {
if (!url) return ''
return url.split('/').pop() || url
}
function resetForm() {
Object.assign(form, {
nom: '',
@@ -141,6 +130,7 @@ function resetForm() {
prix_achat: undefined,
photo_url: '',
video_url: '',
notice_texte: '',
notice_fichier_url: '',
})
}
@@ -150,10 +140,8 @@ function openCreate() {
resetForm()
photoFile.value = null
videoFile.value = null
noticeFile.value = null
photoPreview.value = ''
videoPreview.value = ''
noticeFileName.value = ''
showForm.value = true
}
@@ -171,13 +159,6 @@ function onVideoSelected(event: Event) {
if (file) videoPreview.value = URL.createObjectURL(file)
}
function onNoticeSelected(event: Event) {
const input = event.target as HTMLInputElement
const file = input.files?.[0] || null
noticeFile.value = file
noticeFileName.value = file?.name || ''
}
function startEdit(t: Tool) {
editId.value = t.id!
Object.assign(form, {
@@ -189,14 +170,13 @@ function startEdit(t: Tool) {
prix_achat: t.prix_achat,
photo_url: t.photo_url || '',
video_url: t.video_url || '',
notice_texte: t.notice_texte || '',
notice_fichier_url: t.notice_fichier_url || '',
})
photoFile.value = null
videoFile.value = null
noticeFile.value = null
photoPreview.value = t.photo_url || ''
videoPreview.value = t.video_url || ''
noticeFileName.value = fileNameFromUrl(t.notice_fichier_url || '')
showForm.value = true
}
@@ -205,10 +185,8 @@ function closeForm() {
editId.value = null
photoFile.value = null
videoFile.value = null
noticeFile.value = null
photoPreview.value = ''
videoPreview.value = ''
noticeFileName.value = ''
}
async function uploadFile(file: File): Promise<string> {
@@ -229,6 +207,7 @@ async function submitTool() {
prix_achat: form.prix_achat,
photo_url: form.photo_url || undefined,
video_url: form.video_url || undefined,
notice_texte: form.notice_texte || undefined,
notice_fichier_url: form.notice_fichier_url || undefined,
}
@@ -238,11 +217,10 @@ async function submitTool() {
saved = await toolsStore.create(payload)
}
if (saved.id && (photoFile.value || videoFile.value || noticeFile.value)) {
if (saved.id && (photoFile.value || videoFile.value)) {
const patch: Partial<Tool> = {}
if (photoFile.value) patch.photo_url = await uploadFile(photoFile.value)
if (videoFile.value) patch.video_url = await uploadFile(videoFile.value)
if (noticeFile.value) patch.notice_fichier_url = await uploadFile(noticeFile.value)
if (Object.keys(patch).length) await toolsStore.update(saved.id, patch)
}