Files
solopm-server/plans/13-frontend.md
T

5.7 KiB
Raw Blame History

13 — Frontend (Vue 3 SPA)

Vue 3 + TypeScript + Vite + Pinia + Vue Router + Tailwind, pnpm, in web/. Styling authority is 14-design-system.md. All API access through one typed client; all live updates through one SSE module.

Structure

  • web/src/api/client.ts — typed fetch wrapper (base /api/v1, JSON, error envelope → typed ApiError, cookie credentials)
  • web/src/api/sse.ts — EventSource wrapper: connect after login, auto-reconnect with backoff, dispatch frames to the realtime store, expose onReconnect hooks (pages refetch)
  • web/src/router/index.ts — routes below; global guard redirects unauthenticated → /login (bootstraps via GET /me)
  • Layout: AppShell (fixed sidebar + navbar + <router-view>), auth pages bare
  • Vite dev proxy: /api, /files, /webhooks → Go server port

Routes & pages

  • /login — email/password + OAuth buttons (hidden per config)
  • /register — sign-up (notes that first user becomes admin)
  • /oauth/callback — post-OAuth landing, bootstraps session, redirects
  • /Dashboard: favorite + recent projects, "assigned to me" issue list, cross-project activity feed
  • /inbox — notification inbox (unread filter, mark read/all)
  • /search — full search page (type tabs)
  • /projects — project cards (favorites first, status/priority badges, favorite toggle)
  • /projects/:idProject overview: description (markdown), members, links, attachments, dependencies (both directions), activity feed
  • /projects/:id/issuesIssue table: sortable columns, FilterBar, URL-synced filters/sort, row click → detail
  • /projects/:id/boardKanban: 7 fixed status columns, drag-and-drop (optimistic), card = #N, title, labels, assignee avatar, points badge, blocked indicator, epic color strip
  • /projects/:id/issues/:numIssue detail: editable title/description, sidebar (status, priority, points, assignee, epic, dates, labels, watchers, watch toggle), sub-issues list (+create), blockers list, attachments, links, activity feed comments with resolve, MarkdownEditor for comments
  • /projects/:id/epics — epic list with progress bars (counts + points), status filter
  • /projects/:id/epics/:epicId — epic detail: description, status, color, ordered issue list (drag to reorder, attach existing / create new)
  • /projects/:id/wiki — page list; /projects/:id/wiki/:slug — view; /projects/:id/wiki/:slug/edit + /projects/:id/wiki/new — edit/create with preview
  • /projects/:id/settings — tabs: general (fields, status, git URL, transfer, delete) | members | labels | webhooks (incoming secret, outgoing CRUD + delivery log) | export | danger zone — owner-gated tabs hidden for members
  • /settings — tabs: profile | security (password) | tokens (PAT create/reveal-once/revoke) | notifications (email_mode)
  • /admin/users — admin only: user list, admin toggle, delete
  • 404 page; project-scope 404s render "not found or no access"

Pinia stores

  • auth — me, bootstrap, login/logout, guards
  • projects — list + current project (members, labels, dependencies)
  • issues — table query state (filters/sort/page, URL-synced), detail cache
  • board — per-status ordered lists, optimistic move (rank computed client-side between neighbors, PATCH sent, rollback on error)
  • epics — list + detail + ordering
  • comments — per-issue comments + resolve state
  • wiki — page list + current page
  • notifications — unread count, inbox, mark-read
  • realtime — SSE connection state; routes data frames: if the pointed-at resource is in an active store (current board/table/detail/feed), patch or refetch it; notification frames → notifications store + toast
  • search — palette state, recents (localStorage)
  • ui — toasts, modals, sidebar collapse

Shared components

  • KanbanBoard / KanbanColumn / IssueCard — drag via vuedraggable or a small pointer-events implementation; column headers show count
  • IssueTable + FilterBar (status/assignee/label/priority/epic pickers + text search) + SortHeader
  • MarkdownEditor — textarea + write/preview tabs, @ mention autocomplete (project members), # issue autocomplete, paste/drop image → attachment upload
  • MarkdownView — markdown-it + DOMPurify, mention chips, #N router-links, code highlight
  • ActivityFeed — renders audit entries (icon + actor + verb + target + relative time)
  • NotificationBell — unread badge, dropdown of latest 10, link to /inbox
  • CommandPalette — Cmd/Ctrl+K overlay (10-search.md)
  • Badges/pills: StatusBadge (per-status colors), PriorityBadge, PointsBadge, LabelPill (label color), EpicPill (epic color)
  • UserAvatar (initials fallback) + AssigneePicker + MemberPicker
  • EpicProgressBar (counts + points tooltip)
  • WatchButton, FavoriteStar
  • AttachmentUploader (drag-drop zone) + AttachmentList (image preview, download, delete)
  • DatePicker, ConfirmDialog, ToastHost, EmptyState (illustrated, per design system)

Behaviors

  • Optimistic updates for board drags and inline status/assignee edits; rollback + toast on API error
  • URL is the source of truth for table filters/sort (shareable, refresh-safe)
  • SSE reconnect → refetch active page data + unread count (09-notifications-realtime.md)
  • Keyboard: Cmd/Ctrl+K palette; c new issue on board/table pages; Esc closes modals
  • Every list has loading skeletons + designed empty states; destructive actions use ConfirmDialog
  • Route titles set per page (SoloPM — {project} — {page})