Catch up web/README.md and two stale comments to current code
web/README.md's Layout section hadn't been touched since early in the session: it was missing ManageMenu.vue, CardManageMenu.vue, StatusManager.vue, useDialog.ts, and four of the ten views (ProjectExploreView, ProjectKanbanView, CardView, CardConfigureView) entirely, still described CardRow as inline-editable-with-a-delete- button, and still claimed the top-level <RouterView> was keyed by plain route.path (true before this session's Explore/Kanban route split, wrong after -- see App.vue's routeKey). The Inbox section also still gated the post-drag cards refresh on route.name === 'project' alone, from before Explore itself could send a card there. Also fixed two lingering "all tasks" references (the tab's name before it became "Explore") in a stores/cards.ts comment and a style.css one. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+38
-19
@@ -30,21 +30,38 @@ build app` from the parent directory.
|
|||||||
|
|
||||||
```
|
```
|
||||||
src/main.ts App bootstrap; resolves the stored session before mount
|
src/main.ts App bootstrap; resolves the stored session before mount
|
||||||
src/router/index.ts Routes + guard (redirects to /login when unauthenticated)
|
src/router/index.ts Routes + guard (redirects to /login when unauthenticated) -- a
|
||||||
|
project's Explore/Kanban are nested children of ProjectView
|
||||||
src/stores/auth.ts Pinia store: token in localStorage, magic-link + fetchMe
|
src/stores/auth.ts Pinia store: token in localStorage, magic-link + fetchMe
|
||||||
src/stores/projects.ts Pinia store: the user's projects (fetch + create)
|
src/stores/projects.ts Pinia store: the user's projects (fetch + create)
|
||||||
src/stores/cards.ts Pinia store: one project's cards (CRUD; no reordering -- see lib/cardOrder.ts)
|
src/stores/cards.ts Pinia store: one project's cards -- load/add/patch-in-place;
|
||||||
|
delete and reordering happen elsewhere (ManageMenu.vue,
|
||||||
|
lib/cardOrder.ts)
|
||||||
src/stores/inbox.ts Pinia store: the caller's global inbox (fetch + create)
|
src/stores/inbox.ts Pinia store: the caller's global inbox (fetch + create)
|
||||||
src/lib/api.ts fetch wrapper, bearer token, typed ApiError
|
src/lib/api.ts fetch wrapper, bearer token, typed ApiError, notFoundOr()
|
||||||
src/lib/cardOrder.ts reorderColumn() -- PUT /api/cards/order, shared by the sidebar and kanban board
|
(a caught error -> a 404-aware user-facing message)
|
||||||
|
src/lib/cardOrder.ts reorderColumn() -- PUT /api/cards/order, shared by the sidebar
|
||||||
|
and kanban board
|
||||||
src/lib/webauthn.ts base64url <-> ArrayBuffer + the register/login passkey ceremonies
|
src/lib/webauthn.ts base64url <-> ArrayBuffer + the register/login passkey ceremonies
|
||||||
|
src/composables/useDialog.ts Escape-to-close + focus-on-open for a dialog or menu --
|
||||||
|
shared by ManageMenu.vue and StatusManager's reassign modal
|
||||||
src/components/AppSidebar.vue left nav: Dashboard link, project dropdown, Inbox + form
|
src/components/AppSidebar.vue left nav: Dashboard link, project dropdown, Inbox + form
|
||||||
src/components/CardRow.vue editable text + status chip + delete, one card
|
src/components/CardRow.vue one row in the Explore list: links to the card's own
|
||||||
src/components/KanbanCard.vue small draggable card for the board columns and the inbox
|
view + a status chip -- no inline editing, no delete (both
|
||||||
|
live on that view now)
|
||||||
|
src/components/KanbanCard.vue small draggable card, itself a link to the card's own
|
||||||
|
view; used by the kanban board and the inbox
|
||||||
src/components/PasskeyNotice.vue dismissible "add a passkey" banner across the top of the page
|
src/components/PasskeyNotice.vue dismissible "add a passkey" banner across the top of the page
|
||||||
src/components/ProjectManageMenu.vue "Manage" dropdown + delete-project modal, shared by ProjectView and ProjectConfigureView
|
src/components/ManageMenu.vue generic "Manage" dropdown + delete-confirmation modal,
|
||||||
src/views/ DashboardView, ProjectView, ProjectConfigureView, LoginView,
|
shared by both entity pairs below
|
||||||
ProfileView, VerifyEmailView
|
src/components/ProjectManageMenu.vue / CardManageMenu.vue thin wrappers over
|
||||||
|
ManageMenu.vue supplying what's project-/card-specific: routes,
|
||||||
|
labels, and what deleting actually does
|
||||||
|
src/components/StatusManager.vue a project's status list -- drag to reorder, add, delete
|
||||||
|
with reassignment; used by ProjectConfigureView
|
||||||
|
src/views/ DashboardView, LoginView, ProfileView, VerifyEmailView,
|
||||||
|
ProjectView (layout) + ProjectExploreView + ProjectKanbanView,
|
||||||
|
ProjectConfigureView, CardView, CardConfigureView
|
||||||
```
|
```
|
||||||
|
|
||||||
Signed-in "app" routes (`meta.requiresAuth`) render inside a persistent shell:
|
Signed-in "app" routes (`meta.requiresAuth`) render inside a persistent shell:
|
||||||
@@ -54,9 +71,10 @@ divider, a project `<select>`, another divider, then the **Inbox** (see below).
|
|||||||
The dropdown is a `v-model`-bound writable `computed` (`selectedProjectId`):
|
The dropdown is a `v-model`-bound writable `computed` (`selectedProjectId`):
|
||||||
its getter reads the open project from `route.params.id`, so it tracks
|
its getter reads the open project from `route.params.id`, so it tracks
|
||||||
whichever project is current; its setter `router.push`es to the chosen one, so
|
whichever project is current; its setter `router.push`es to the chosen one, so
|
||||||
it also works as a project switcher from anywhere. `<RouterView
|
it also works as a project switcher from anywhere. `App.vue`'s top-level
|
||||||
:key="route.path">` remounts the view on every path change so switching
|
`<RouterView>` is keyed so switching projects (or cards) always does a fresh
|
||||||
projects always does a fresh load.
|
load -- see [Project detail](#project-detail) for why that key isn't simply
|
||||||
|
the path.
|
||||||
|
|
||||||
Below `768px` (`style.css`'s one layout breakpoint) the sidebar becomes an
|
Below `768px` (`style.css`'s one layout breakpoint) the sidebar becomes an
|
||||||
off-canvas drawer instead of sitting beside the page: `position: fixed`,
|
off-canvas drawer instead of sitting beside the page: `position: fixed`,
|
||||||
@@ -117,13 +135,14 @@ handful of conventions worth knowing before adding to it:
|
|||||||
A card with no project lives in the caller's inbox (`useInboxStore`), rendered
|
A card with no project lives in the caller's inbox (`useInboxStore`), rendered
|
||||||
in the sidebar under the project list -- not per-project, and not tied to
|
in the sidebar under the project list -- not per-project, and not tied to
|
||||||
whatever page is open. It's a `vuedraggable` list in the same `"kanban"` drag
|
whatever page is open. It's a `vuedraggable` list in the same `"kanban"` drag
|
||||||
group as every project's kanban columns (below), so a card can be dragged
|
group as a project's Kanban columns and Explore list (below), so a card can
|
||||||
straight out of the sidebar into any status column of whichever project is
|
be dragged straight out of the sidebar into any status column of whichever
|
||||||
currently open, or the other way. `AppSidebar`'s `onInboxChange` persists a
|
project is currently open (or Explore can send one the other way, though not
|
||||||
drop via `reorderColumn(null, null, ids)`, then reloads the inbox and, if a
|
receive one -- see [Explore](#explore)). `AppSidebar`'s `onInboxChange`
|
||||||
project view is currently mounted (`route.name === 'project'`), that project's
|
persists a drop via `reorderColumn(null, null, ids)`, then reloads the inbox
|
||||||
cards too -- either side of a drag could have been the inbox. A small form
|
and, if a project's Explore or Kanban route is currently open, that
|
||||||
under the list adds a card straight to the inbox.
|
project's cards too -- either side of a drag could have been the inbox. A
|
||||||
|
small form under the list adds a card straight to the inbox.
|
||||||
|
|
||||||
Empty (no cards) is shown as a subtle dashed drop-area rather than blank
|
Empty (no cards) is shown as a subtle dashed drop-area rather than blank
|
||||||
space -- `.kanban__cards:empty` in `style.css`, so it's pure CSS keyed off the
|
space -- `.kanban__cards:empty` in `style.css`, so it's pure CSS keyed off the
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ type CardPatch = Partial<Pick<Card, 'text' | 'complete'>>
|
|||||||
|
|
||||||
export const useCardsStore = defineStore('cards', () => {
|
export const useCardsStore = defineStore('cards', () => {
|
||||||
// One project's cards, grouped by status then position. Views re-sort as
|
// One project's cards, grouped by status then position. Views re-sort as
|
||||||
// needed (the "all tasks" list is alphabetical). Moving a card in or out of
|
// needed (Explore's list is alphabetical). Moving a card in or out of this
|
||||||
// this project (including via the inbox) goes through lib/cardOrder.ts,
|
// project (including via the inbox) goes through lib/cardOrder.ts, not
|
||||||
// not this store -- callers re-load() afterwards.
|
// this store -- callers re-load() afterwards.
|
||||||
const cards = ref<Card[]>([])
|
const cards = ref<Card[]>([])
|
||||||
const projectId = ref<number | null>(null)
|
const projectId = ref<number | null>(null)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|||||||
+1
-1
@@ -1036,7 +1036,7 @@ button[type="submit"]:disabled:not(.btn-icon),
|
|||||||
|
|
||||||
/* A small square icon button, bordered like the compact field it sits
|
/* A small square icon button, bordered like the compact field it sits
|
||||||
beside -- every "add to X" form (a kanban column, the inbox, the status
|
beside -- every "add to X" form (a kanban column, the inbox, the status
|
||||||
list, the "all tasks" new-card form) used a full "Add" label until there
|
list, Explore's own new-card form) used a full "Add" label until there
|
||||||
were enough of them on screen at once to feel cluttered, then a borderless
|
were enough of them on screen at once to feel cluttered, then a borderless
|
||||||
ghost icon on its own looked adrift next to that field. Excluded
|
ghost icon on its own looked adrift next to that field. Excluded
|
||||||
(":not(.btn-icon)" above and on the .field-row/.kanban__new overrides)
|
(":not(.btn-icon)" above and on the .field-row/.kanban__new overrides)
|
||||||
|
|||||||
Reference in New Issue
Block a user