Commit Graph

25 Commits

Author SHA1 Message Date
bvandeusen f2f74efff1 fc3f: artistDirectory Pinia store — cursor scroll + q + platform filters
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 22:14:53 -04:00
bvandeusen 581f4aea79 fc3e: posts Pinia store — cursor scroll + filters + detail fetch
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:55:29 -04:00
bvandeusen 397c21c88e feat(fc3c): downloads Pinia store + sources.checkNow action + vitests
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 20:45:45 -04:00
bvandeusen 408971a798 fix(fc3b): SourceFormDialog + SubscriptionsView read platforms store; drop sources.loadPlatforms
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:39:44 -04:00
bvandeusen e83747b085 feat(fc3b): platforms + credentials Pinia stores + vitests
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:37:45 -04:00
bvandeusen ded5e5f642 feat(fc3a): sources Pinia store + vitest
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 12:56:22 -04:00
bvandeusen cba662a900 feat(attachments): downloadable attachments in ProvenancePanel + PostInfoHeader
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 11:17:14 -04:00
bvandeusen b33253429a feat(provenance): gallery store post_id filter (mutually exclusive with tag_id)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:16:09 -04:00
bvandeusen 7bfd700671 feat(provenance): provenance store (cached image/post lookups)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 20:15:42 -04:00
bvandeusen 4fb176faf6 feat(reader): seriesReader store + pure scroll/progress/clamp helpers
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:29:57 -04:00
bvandeusen b19aff198e feat(series): seriesManage Pinia store + pure moveItem reorder helper
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 23:36:44 -04:00
bvandeusen 35e26d6226 fix(bulk): node-safe toast (globalThis.window) + common-tags test matches non-empty spec guard
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:15:23 -04:00
bvandeusen 349d8e50ef feat(bulk): gallerySelection Pinia store with order, mode, bulk actions
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 18:03:54 -04:00
bvandeusen 1d1574e586 feat(frontend): tagDirectory rename and merge store actions
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 13:41:20 -04:00
bvandeusen 861e8baeb8 feat(fc2c-i): pinia stores for showcase, tag directory, artist 2026-05-15 21:12:19 -04:00
bvandeusen 6cf82970a1 feat(fc2b): ml / allowlist / aliases Pinia stores
Thin wrappers over the FC-2b API: ml (settings GET/PATCH, backfill +
recompute triggers), allowlist (list, threshold patch, remove with
optimistic local update), aliases (list, remove with optimistic update).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:56:45 -04:00
bvandeusen 2a21ede912 feat(fc2b): wire SuggestionsPanel + rename into TagPanel; reject-on-remove
TagPanel now renders SuggestionsPanel below the current-tags area and
adds a per-chip kebab → Rename… (TagRenameDialog). modal store's
removeTag now also POSTs suggestions/dismiss after the delete so removing
an auto-applied tag records a per-image rejection and the allowlist
maintenance sweep won't re-apply it (closes the remove→re-apply loop
identified in the spec).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:56:22 -04:00
bvandeusen a8cc6a27dc feat(fc2b): suggestions store + modal panel components
Store: load per-image suggestions, accept (creates the tag first for
raw/creates_new_tag suggestions, then accepts by id), aliasAccept,
dismiss (client-side hide for raw tags), success toasts folded in.
Panel: people/sources groups always open, General collapsed by default;
alias picker dialog wired; shimmer skeleton while loading. SuggestionItem
shows score %, +new badge for raw tags, kebab menu. AliasPickerDialog
referenced (lands in Task 15).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 07:55:10 -04:00
bvandeusen 90686e6deb chore(fc2a): polish pass — toasts, loading skeletons, focus guards, mobile breakpoints
AppSnackbar mounts once at the app root and exposes a window.__fcToast
function the stores call from error paths. This avoids prop-drilling a
toast emitter through every component while keeping the snackbar
component itself testable in isolation.

GalleryGrid renders shimmer-skeleton placeholders on initial load so the
first paint isn't empty. Skeleton uses the same auto-fill grid columns
as the real items so layout doesn't shift when content arrives.

Modal arrow nav now ignores text-entry elements so typing in the tag
autocomplete doesn't navigate prev/next. Small-screen breakpoint
(<600px) tightens gallery thumbnails to 120px min.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:36:25 -04:00
bvandeusen 89fee260a6 feat(fc2a): add tag store, TagAutocomplete, and FandomPicker
TagAutocomplete: kind selector + debounced (200ms) search + keyboard nav
(up/down/enter/esc). When the operator types a character that doesn't
exist, the create flow first opens FandomPicker so the new character tag
lands with a valid fandom_id (otherwise the API rejects it).

FandomPicker lists existing fandoms (cached after first load) with an
inline create-new affordance, so the operator never has to leave the modal
to manage fandom hierarchies.

Tag store also exposes a kind→icon→color mapping that the TagPanel reuses
in Task 22 — keeping chip colors visually distinct per kind without per-app
accent collisions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:34:17 -04:00
bvandeusen 8358d09348 feat(fc2a): real modal store + usePanZoom composable
modal store loads image detail (with neighbors) on open, exposes goPrev/
goNext that re-fetch the next image, and implements optimistic tag
remove with rollback on API failure. createAndAdd is the bridge between
the autocomplete UI and a brand-new tag.

usePanZoom is a small composable: click-to-toggle 2x zoom centered on
click point, wheel-to-zoom up to 4x, drag-to-pan when zoomed. Pointer
events are used (touch + mouse + pen unified). Caller spreads handlers
onto the element it wants pannable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:33:14 -04:00
bvandeusen 899b193085 feat(fc2a): add TimelineSidebar and assemble GalleryView
GalleryView wires the grid + timeline + modal together. The URL is the
source of truth for which image (if any) is open — clicking an item pushes
?image=N; closing the modal pops it. This makes deep links shareable and
the back button work intuitively.

Below 900px viewport, the timeline drops below the grid as a horizontal
strip so it doesn't compete with thumbnail space on mobile.

Modal store + ImageViewer are placeholders here; real implementations land
in Batch 5 (Tasks 19–22).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:32:50 -04:00
bvandeusen da89fe6be2 feat(fc2a): add gallery Pinia store, GalleryItem, and EmptyState
Gallery store handles cursor pagination, date-group merging across pages,
tag filter, timeline buckets, and jump-to-month. Stale response detection
via an inflightId counter prevents out-of-order page additions when the
user toggles filters quickly.

GalleryItem is a square thumbnail card with hover/focus accent outline,
keyboard activation (Enter/Space → open), video badge for video MIME types,
and a broken-image fallback if the thumbnail URL fails to load.

EmptyState points operators to /settings?tab=import so the empty path is
self-guiding.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:31:53 -04:00
bvandeusen af9f42ef68 feat(fc2a): add useApi composable, import store, extend system store with stats
useApi centralizes fetch error handling — every API call throws ApiError
on non-2xx with the parsed body attached, so components don't repeat the
'check response.ok' boilerplate.

import store wraps import settings, batch status, task list (with cursor
pagination), and the trigger/retry/clear admin actions. system store
gains a refreshStats() that powers the Settings overview tab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:29:49 -04:00
bvandeusen bcd9a23501 feat: add SPA app shell, router, system store, and route placeholders
Nav lists every FC-2 and FC-3 surface with a placeholder view that names
the sub-project that will fill it. System store polls /api/health on mount
and renders a status pip in the nav footer.

Favicon uses Curator's aged amber accent (#A87338).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 07:36:01 -04:00