Portfolio: add filtering, URL sharing, and improved tag input

- Add category filters with dynamic counts that reduce as filters
  applied
- Add ?filter[category]=value URL params for filterable links
- Add ?img= timestamp param that bypasses filters to show specific image
- Update URL when opening/navigating/closing modal for shareable links
- Backend: add /api/portfolio/filters endpoint with filter logic
- Backend: add timestamp lookup fallback for GetImage endpoint
  Frontend:
- Portfolio page: filter dropdowns, keyboard nav, mobile improvements
- ImageUpload: live tag suggestions from API, arrow/Tab navigation,
  confirmation modal before upload, mobile-optimized touch targets
- Add scrollbar-hide utility and fix filter dropdown overflow
- Move Clear all button, add vertical separator on desktop
This commit is contained in:
2026-02-20 00:32:09 +00:00
parent dfd552b02f
commit 9259de9393
15 changed files with 1560 additions and 290 deletions
+26 -7
View File
@@ -1,4 +1,4 @@
> **Last Updated:** January 2025
> **Last Updated:** February 2026
> **Status:** Work in Progress
---
@@ -59,7 +59,7 @@
#### Not Yet Wired
- [ ] Social auth (`handlers/auth/social.go` exists, not imported)
- [ ] Analytics (`handlers/admin/analytics.go` exists, not imported)
- [ ] Portfolio/images (`handlers/portfolio/images.go` exists, not imported)
- [x] Portfolio/images - NOW WIRED: `/api/portfolio/images`, `/api/portfolio/tags`, `/api/portfolio/filters`, `/api/portfolio/images/{id}`
- [ ] Guest user endpoint (`/api/users/guest` - needed for walk-in bookings)
#### Unit Tests & CI/CD
@@ -75,7 +75,7 @@
- [x] Prices (`/prices`)
- [x] Contact (`/contact`)
- [x] Book (`/book`) - Full wizard with service selection, date/time, customer details
- [ ] Portfolio (`/portfolio`) - Stubbed, needs S3/R2 integration for images
- [x] Portfolio (`/portfolio`) - S3/R2 storage with tag filtering, category filters, pagination, ?img= featured image, admin upload
- [x] Today (`/today`) - Admin only, real-time schedule view
- [x] Account (`/account`)
- [x] Login (`/login`)
@@ -130,7 +130,7 @@
- [x] CalDAV ready
- [ ] Email/SMS reminders - not yet implemented
- [ ] Square payment - placeholder only
- [ ] S3/R2 image hosting - not configured
- [x] S3/R2 image hosting - Rustfs for dev, Cloudflare R2 for prod via build tags
---
@@ -242,6 +242,25 @@ flowchart TD
| DELETE | `/api/scheduling/exceptional-groups` | Delete exception group |
| PUT | `/api/scheduling/exceptional-applications` | Apply exceptions to dates |
### Portfolio Endpoints
| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/portfolio/images` | List images with pagination, filter by tag/tags, filter by category:value |
| GET | `/api/portfolio/tags` | List all tags for autocomplete (public) |
| GET | `/api/portfolio/filters` | Get filter categories with counts. Supports tag filtering. Unselected categories show counts reduced by other filters. |
| GET | `/api/portfolio/images/{id}` | Get single image by UUID or timestamp (fallback to URL pattern match) |
| POST | `/api/portfolio/images` | Upload new image with thumbnail and tags (admin only) |
| DELETE | `/api/portfolio/images/{id}` | Delete image (admin only) |
**Portfolio Frontend Features:**
- `/portfolio` page with tag-based filtering and category filters
- Category filters: `?filter[color]=red&filter[season]=summer`
- Tag search: `?tag=toby` or `?tags=toby,summer`
- Featured image: `?img=<id|timestamp>` - loads image directly, bypasses filters
- Filter UI: scrollable dropdowns, keyboard navigation, mobile-optimized
- Admin upload: ImageUpload component with live tag suggestions, keyboard nav, confirmation modal
---
## Database Schema
@@ -287,6 +306,8 @@ admin_notification_reason: pending_booking | cancelled_booking | rescheduled_boo
| `payments` | Payment transactions |
| `business_settings` | Business configuration |
| `admin_notifications` | Admin notification queue |
| `images` | Portfolio gallery images with tags |
| `tags` | Image tag autocomplete |
| `user_notification_preferences` | User notification preferences (email/sms/push) |
### Key Functions
@@ -332,7 +353,6 @@ admin_notification_reason: pending_booking | cancelled_booking | rescheduled_boo
| **User notification preferences** | [x] DB table ready, waiting on user notification system |
| **User notifications** | Notification system for regular users (booking confirmations, reminders) |
| **Remove debug logs** | `console.log` in BookingFlow.svelte:600 and BookingCreateModal.svelte:224 |
| **S3/R2 image hosting** | Portfolio image storage with admin upload |
| **Loyalty display component** | Show stamps in account/bookings |
| **Email/SMS reminders** | Scheduled notification jobs |
| **Prometheus metrics** | Monitoring integration |
@@ -342,8 +362,7 @@ admin_notification_reason: pending_booking | cancelled_booking | rescheduled_boo
| Task | Description |
| ----------------------- | ----------------------------------- |
| **Social auth** | Wire `handlers/auth/social.go` |
| **Analytics** | Wire `handlers/admin/analytics.go` |
| **Portfolio API** | Wire `handlers/portfolio/images.go` |
| **Analytics** | Wire `handlers/admin/analytics.go` |
| **nginx config review** | Finalize production config |
| **CI/CD pipeline** | Gitea Actions workflow |
| And many more | |