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
+9 -7
View File
@@ -372,20 +372,22 @@ CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_payments_created_at_status ON payments(created_at, status);
create table images (
id uuid primary key default gen_random_uuid(),
r2_url text not null,
tag_names text[] not null default '{}', -- for searching and filtering
created_at timestamptz not null default now()
id uuid primary key default gen_random_uuid(),
url text not null,
thumbnail_url text not null,
tag_names text[] not null default '{}',
created_at timestamptz not null default now()
);
-- only for autocomlpete text
-- only for autocomplete text
create table tags (
id serial primary key,
name text not null unique
id serial primary key,
name text not null unique
);
-- Indexes
create index idx_images_tag_names on images using gin(tag_names);
create index idx_images_tag_names_trgm on images using gin ((tag_names::text[]) gin_trgm_ops);
create index idx_images_created_at on images(created_at desc);
create index idx_tags_name_trgm on tags using gin (name gin_trgm_ops);