cd2efe3587
Phase 1 of frontend_tasks.md - stop showing fabricated/broken UI:
- Dashboard now fetches real stats (projects, tasks, users, pending
approvals, API keys, developer stats, pending reviews, admin
activity) instead of hardcoded numbers. Added services/developer.ts
and services/review.ts wrappers for previously-unused backend
endpoints.
- Wired ActivityFeed into every project's Overview page in place of
the "coming soon" placeholder.
- Registered the missing /projects/:id/technical-specs route (view
and service already existed, just unreachable).
- Fixed AssetDeleteConfirmDialog's raw styled divs to use the shared
Alert component and wired it into AssetBrowser, matching
ShotBrowser's impact-summary + type-to-confirm safety pattern
(asset deletion was previously less safe than shot deletion).
- Fixed a shared bug in both delete dialogs where the impact-summary
section never rendered (watch on the open prop needed
{ immediate: true }).
- Replaced native confirm()/alert() with styled AlertDialog/Dialog in
NoteItem, TaskAttachments, and UserMenu's keyboard-shortcuts item.
- Removed dead-end UI: Google OAuth stub buttons, UserMenu items
pointing at non-existent routes, the /developer/docs dead link, and
the no-op action button on the API Keys placeholder page.
- Removed leftover debug console logging across 8 files.
Added frontend_report.md (full audit) and frontend_tasks.md (phased
checklist) as the reference for this and future phases.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
9.7 KiB
9.7 KiB
Frontend Improvement Tasks
Derived from frontend_report.md. Checklist form for tracking progress — check items off as they land. Ordered by phase (do Phase 1 before Phase 2, etc.); within a phase, order doesn't matter much.
Phase 1 — Truth-in-UI & dead code ✅ (done)
- Wire
views/DashboardView.vuestats to real API data where an endpoint exists (projects, active projects, overdue tasks, total users, pending approvals, API keys, developer stats, pending reviews, admin system activity). Addedservices/developer.tsandservices/review.tswrappers. - Replace fixed-lookup episode progress with real computed progress —
components/episode/EpisodeCard.vue:117-128andcomponents/episode/EpisodeList.vue:267-278— deferred: backend has nocompleted_shots/progressfield yet (backend/schemas/episode.py,backend/routers/episodes.py) - Fix task-status usage counts always showing 0 —
components/settings/CustomTaskStatusManager.vue:275-295— deferred: needs a newGET /projects/{id}/task-statuses/countsbackend endpoint - Register the missing route:
/projects/:projectId/technical-specsinrouter/index.ts - Delete confirmed-dead files (or finish wiring them in):
components/shot/ShotColumnVisibilityControl.vue— deletedcomponents/asset/ColumnVisibilityControl.vue— deletedcomponents/project/ShotsTable.vue— deletedcomponents/examples/FileUploadExample.vue— deletedviews/GlobalSettingsView.vue— deletedviews/HomeView.vue— deletedcomponents/asset/AssetDeleteConfirmDialog.vue— fixed (raw divs → sharedAlertcomponent) and wired intoAssetBrowser.vue, mirroringShotBrowser.vue's patterncomponents/activity/ActivityFeed.vue— wired intoProjectOverviewView.vuein place of "coming soon" text;TaskActivityTimeline.vue— deleted (notaskIdavailable at that call site)
- Replace native
confirm()/alert()with styled dialogs:components/task/NoteItem.vue:178→AlertDialogcomponents/task/TaskAttachments.vue:201→AlertDialogcomponents/layout/UserMenu.vuekeyboard-shortcutsalert()→Dialog
- Remove leftover debug logging (all 8 files/line-ranges)
- Removed Google OAuth stub buttons (
LoginView.vue,RegisterView.vue) — no OAuth backend exists, so the buttons were pure dead ends /developer/api-keys,/developer/projects,/developer/tasks,/developer/analytics,views/ReviewsView.vue— left as-is: their empty states are honest ("No API keys" etc.), not misleading, so out of scope for a truth-in-UI pass. Only fixed the one dead action button onAPIKeysView.vue(removedaction-text/@actionsince it did nothing).- Removed dead-end UserMenu items (
/settings/preferences,/help, notifications toggle) and the/developer/docsdead link (AppSidebar.vue,DashboardView.vue) — no real destination existed for any of them
Bonus fixes surfaced during verification (approved mid-implementation):
- Fixed two pre-existing backend bugs that 500'd once real data was wired up:
backend/routers/reviews.py(joinedload("reviewer")string →joinedload(Review.reviewer)) andbackend/utils/activity.py(wrongmodels.submissionimport path →models.task). - Fixed a pre-existing bug shared by both
ShotDeleteConfirmDialog.vueandAssetDeleteConfirmDialog.vue: theirwatch(() => props.open, ...)lacked{ immediate: true }, so the impact-summary section never rendered since the dialog only mounts once already open. Deletion itself worked fine either way — this was purely cosmetic, but it was the whole point of the "impact summary" safety feature.
Phase 2 — Close feature gaps (asset vs. shot parity)
- Add user-assignment popover to
components/asset/EditableTaskStatus.vue(shot version atcomponents/shot/EditableTaskStatus.vueis the reference) - Add column-locking toggle to
components/asset/AssetTableToolbar.vue(shot version hasLock/Unlocktoggle) - Add row-actions ("…") menu to
components/task/columns.ts(shot/asset already have one) - Implement the six stubbed asset detail-panel actions in
components/asset/AssetBrowser.vue:571-574, 680-703: create task, select task, create note, upload reference, publish version — or hide the affordances until built - Implement shot detail-panel task stubs in
components/shot/ShotBrowser.vue:848-856: create task, select task - Consolidate
components/project/ProjectMembersManager.vueandcomponents/project/ProjectMemberManagement.vueinto one component - Wire the consolidated member-management component into
ProjectDetailView.vue:149-151("Manage Members" is currently a no-op)
Phase 3 — Unify controls
- Extract
ColumnToggleListcomponent (built onDropdownMenuCheckboxItem, not hand-rolled div+Check) and point at it from:components/ui/sidebar/SidebarColumnSwitch.vuecomponents/shot/ShotTableToolbar.vuecomponents/asset/AssetTableToolbar.vuecomponents/task/TaskTableToolbar.vue
- Extract shared
EntityTableToolbar(search, column-visibility trigger, detail-panel toggle, clear-filters) to de-duplicate the three toolbar files - Extract
SegmentedTogglecomponent for the three hand-built view-mode switches (shot grid/list/table, asset grid/list, task all/shots/assets) - Standardize delete confirmation on the shot pattern (
Dialog+Alert+ impact summary + type-to-confirm) for any cascading delete; fix asset's dialog to match or consciously keep it lighter - Swap hand-rolled checkbox-divs for real
Checkbox/DropdownMenuCheckboxItemin:SidebarColumnSwitch.vueShotTableToolbar.vueAssetTableToolbar.vueTaskTableToolbar.vueShotTaskStatusFilter.vueasset/TaskStatusFilter.vue
- Replace ad hoc
size="sm" class="h-8 w-8 p-0"withsize="icon-sm"across toolbar/browser icon buttons - Decide one convention (icon+label vs. icon-only+tooltip) for primary "create" CTAs and apply consistently (shot/asset create buttons currently lack tooltips project/episode create buttons have)
- Standardize row-actions/bulk-actions on
DropdownMenu/DropdownMenuItem; replace ad hoc<button>list incomponents/task/TaskBulkActionsMenu.vue - Extract
DetailPanelShell(header/close button, loading state, error state, Tabs scaffold, slide-in transition) forShotDetailPanel.vue,AssetDetailPanel.vue,TaskDetailPanel.vueto share; add missing error state to Task's panel
Phase 4 — Architecture & tooling investment
- Add a shared
useAsyncAction-style composable (isLoading/error/run(fn)) and adopt it acrossstores/*.tsto cut repeated try/catch/finally boilerplate - Replace
stores/taskStatuses.ts's polling-based in-flight request de-dup (100mssetIntervalloop, lines 96-117) with promise memoization - Extend a similar TTL/cache strategy to
stores/assets.ts,stores/tasks.ts,stores/projects.ts,stores/episodes.ts(currently no caching — every view re-fetches on mount) - De-duplicate
assets.ts's optimistic-update/rollback logic between single (lines 156-234) and bulk (lines 236-356) task-status updates into one parameterized function - Add
markRaw()around icon components stored in reactive state —stores/projects.tsassignProjectIcon - Audit
deep: truewatchers, especiallyviews/ProjectsView.vue:770(watches the full, non-markRaw'd projects array) - Fix N+1 project-member fetch: hoist
getProjectMembers()call out ofEditableTaskStatus.vue(mounted per row × task-type column) into a shared store/cache or parent-passed prop - Add table virtualization (e.g.
@tanstack/vue-virtual) toShotsDataTable.vue,AssetsDataTable.vue,TasksDataTable.vue - Introduce a shared
EmptyStatecomponent and standardize onSkeletonfor loading states (currently: 5 files useSkeleton, 62 use ad hoc spinners; 31 files hand-roll empty-state text) - Add toast-on-error for currently-silent secondary loads: episodes/task-types/task-statuses/project-context in
ShotBrowser.vue(lines 474-508),stores/notifications.ts:fetchStats, router auth-init failure (router/index.ts:190-196) - Centralize a
usePermission()/can()composable to consolidate role/admin checks currently duplicated across ~20 components outside the router guard - Consider splitting the largest files into smaller pieces:
views/project/ShotDetailView.vue(1658 lines),views/admin/DeletedItemsManagementView.vue(1279 lines), and evaluate a shared "entity browser" composable forShotBrowser.vue/AssetBrowser.vue's ~70% structural overlap - Move ad hoc domain types out of
services/*.tsintotypes/for discoverability (currently onlyauth.ts,notification.ts,activity.tslive intypes/)
Phase 5 — Testing & quality gates
- Add Vitest + Vue Test Utils
- Write first tests for the highest-risk untested logic:
stores/assets.tsoptimistic-update/rollback,stores/auth.tstoken lifecycle - Add an ESLint config (flag
any, unused locals, enforce consistent import/style rules) - Re-enable
noUnusedLocalsintsconfig.json(currently explicitly disabled) - Introduce a typed
ApiErrorhelper to replace ad hocerr.response?.data?.detailaccess at the 104catch (err: any)sites (fix incrementally as files are touched, not all at once) - Accessibility fixes: remove checkbox-inside-
SelectItemanti-pattern (also fixes the double-toggle bug), add keyboard support to hand-rolled clickable<div>s (SubmissionCard.vue,EditableTaskStatus.vue)
Full context, rationale, and file-by-file findings for every item above are in frontend_report.md.