fix: user photo upload now INSIDE the main edit form (one Save = file+fields, no JS); admin resource FQNs corrected (relative Filament\Forms refs = panel-wide 500)

This commit is contained in:
2026-08-10 14:47:07 +10:00
parent fc7f3bf675
commit ef20af0d92
2 changed files with 28 additions and 18 deletions

View File

@@ -110,11 +110,33 @@ func (a *App) EditTag(w http.ResponseWriter, r *http.Request) {
return
}
// Optional file upload: if a photo file is present, store it and use it;
// otherwise fall back to the photo_url text value.
photoURL := strings.TrimSpace(r.FormValue("photo_url"))
if err := r.ParseMultipartForm(10 << 20); err == nil {
if file, header, ferr := r.FormFile("photo"); ferr == nil {
ct := header.Header.Get("Content-Type")
if strings.HasPrefix(ct, "image/") && a.Storage != nil {
ext := strings.ToLower(filepath.Ext(header.Filename))
if ext == "" {
ext = ".jpg"
}
key := fmt.Sprintf("tags/%d%s", tag.ID, ext)
if perr := a.Storage.Put(r.Context(), key, file, header.Size, ct); perr == nil {
photoURL = "/photos/" + key
}
file.Close()
} else if ferr == nil {
file.Close()
}
}
}
params := db.UpdateTagDetailsParams{
ID: tag.ID,
ItemType: textOrNil(strings.TrimSpace(r.FormValue("item_type"))),
Description: textOrNil(strings.TrimSpace(r.FormValue("description"))),
PhotoUrl: textOrNil(strings.TrimSpace(r.FormValue("photo_url"))),
PhotoUrl: textOrNil(photoURL),
Phone: textOrNil(strings.TrimSpace(r.FormValue("phone"))),
Address: textOrNil(strings.TrimSpace(r.FormValue("address"))),
Notes: textOrNil(strings.TrimSpace(r.FormValue("notes"))),

View File

@@ -8,7 +8,7 @@
{{if .Error}}<p class="mt-4 rounded bg-red-50 px-4 py-2 text-sm text-red-700 border border-red-200">{{.Error}}</p>{{end}}
<form method="post" action="/account/tags/{{.Data.ID}}/edit" class="mt-6 space-y-4 rounded-xl border border-stone-200 bg-white p-6 shadow-sm">
<form method="post" action="/account/tags/{{.Data.ID}}/edit" enctype="multipart/form-data" class="mt-6 space-y-4 rounded-xl border border-stone-200 bg-white p-6 shadow-sm">
<div>
<label class="block text-sm font-medium">Item type</label>
<select name="item_type" class="mt-1 w-full rounded border border-stone-300 px-3 py-2">
@@ -25,7 +25,10 @@
<textarea name="description" rows="3" class="mt-1 w-full rounded border border-stone-300 px-3 py-2">{{if .Data.Description.Valid}}{{.Data.Description.String}}{{end}}</textarea>
</div>
<div>
<label class="block text-sm font-medium">Photo URL</label>
<label class="block text-sm font-medium">Photo</label>
{{if .Data.PhotoUrl.Valid}}<img src="{{.Data.PhotoUrl.String}}" alt="Current photo" class="mb-2 h-24 w-24 rounded-lg object-cover">{{end}}
<input type="file" name="photo" accept="image/*" class="mt-1 text-sm">
<p class="mt-1 text-xs text-stone-500">Choose a photo and press Save — or paste an image URL below.</p>
<input name="photo_url" type="text" value="{{if .Data.PhotoUrl.Valid}}{{.Data.PhotoUrl.String}}{{end}}" class="mt-1 w-full rounded border border-stone-300 px-3 py-2" placeholder="https://…">
</div>
<div>
@@ -50,20 +53,5 @@
</div>
</form>
<!-- Standalone photo upload (outside the main form — nested forms are invalid HTML) -->
<div class="mt-4 rounded-xl border border-stone-200 bg-white p-4 shadow-sm">
<h2 class="text-sm font-bold">Photo</h2>
<div id="photo-thumb" class="mt-2">
{{if .Data.PhotoUrl.Valid}}<img src="{{.Data.PhotoUrl.String}}" alt="Current photo" class="mb-2 h-32 w-32 rounded-lg object-cover">{{end}}
</div>
<div class="mt-2">
<form method="post" enctype="multipart/form-data" hx-encoding="multipart/form-data" hx-post="/account/tags/{{.Data.ID}}/photo" hx-target="#photo-thumb" hx-swap="innerHTML" class="flex gap-2">
<input type="file" name="photo" accept="image/*" class="text-sm">
<button type="submit" class="rounded bg-stone-900 px-3 py-1.5 text-xs font-semibold text-white hover:bg-stone-700">Upload photo</button>
<span class="htmx-indicator self-center text-xs text-stone-400">Uploading…</span>
</form>
<p class="mt-1 text-xs text-stone-500">Upload a photo — it shows on your public tag page and in the admin.</p>
</div>
</div>
</div>
{{end}}