Conversation
The typed client wraps the task, task status, board, project member and time entry endpoints over the axios instance the host injects, alongside the host contact lookup the project header needs for a customer name. The base path moves out of the projects client so both files build their URLs from one constant. Money stays in integer minor units and durations in minutes on the wire; support/format gains the duration, initials and overdue helpers the board and the project totals render with. sortablejs is a runtime dependency and is bundled into dist/, which is how an npm dependency reaches an install.
The drawer is the one editor for a task, shared by the board and every list: name, project, status, assignee, priority, due date, estimate, billable flag and a rate override, with hours converted to minutes and major units to minor units on the way out. A 422 renders under its field. The customer is read-only, because a task with a project takes the project's. The project id is the source of truth behind the project picker, so a page that fixes the project and hides the picker still saves the task under it, and editing a task whose project is not in the loaded list never clears it. The list is a server-side BaseTable over the tasks endpoint with search, status and assignee filters, and it tells its parent when a write lands so a project's totals can catch up.
Three pages register through the host page contract, from their own registration file so a later slice of the module never edits the same lines. Their strings live in their own message bundle, which the host merges into the module's namespace recursively. The board reads every column in one request and drags with sortablejs. A drop is undone in the DOM first, so the model stays the only writer, then the neighbours in the target column become the before and after ids the move endpoint orders by; the returned board position is applied and a failed move puts both columns back. Each column opens the drawer preset to itself. The project detail carries the header, the actions and four tabs rendered through router-view: totals and a budget bar, the task list, a read-only time table and the member editor. The tabs read the active route off the host router, because a module bundle cannot call useRoute, and landing on the page itself settles on the Overview child so the body is never empty. Only the detail endpoint carries totals, so every write re-reads the project rather than keeping what it returned.
dist/ ships with the package so an install never has to build. The bundle still destructures the host's Vue once and imports nothing from "vue", and carries sortablejs, which has no Vue dependency of its own.
Contributor
Author
|
Superseded by #14, which carries this stack consolidated into three commits on top of main. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Slice 2 of the module's UI (M4): the project detail page, the task drawer, the
task list and the Kanban board. Based on
feat/ui-projects, which carries theprojects index this builds on.
What is here
Project detail
projects/:id, with Overview, Tasks, Time and Membersrendered through
<router-view>as registered children. The header shows thename, identifier, status badge, the customer name looked up through the host
contact endpoint (falling back to
#id), Edit through the existing projectmodal and Archive/Restore. Overview renders the task counts, logged and
billable minutes, billable and unbilled amounts and a budget bar when the
project has one.
Board
board, filtered by project and assignee, every column in onerequest. Cards carry the name, number, project identifier, priority, assignee
initials, due date (red when overdue) and the billable flag. Drag uses
sortablejs directly; a "New task" button per column opens the drawer preset to
that column, and clicking a card opens it for editing.
Task drawer, shared by the board and every list: name, description,
project, read-only customer, status, assignee, priority, due date, estimate in
hours, billable and a rate override in major units, plus delete with a
confirm. Hours become minutes and major units become minor units on the way
out, and a 422 renders under its field.
Task list, a server-side
BaseTableover the tasks endpoint, used by theproject Tasks tab and by an all-tasks page at
tasks.The projects index rows now link to the detail page and its header links to
the board.
Notes
writer of the card's position. The neighbours in the target column become
the
before_idandafter_idthe move endpoint orders by, the returnedboard_positionis applied, and a failed move puts both columns back with anotification.
page settles on its Overview child when it is the target itself. Without
that, a link straight to the project would render an empty body.
GET projects/{id}carries the totals, so every write on the detailpage re-reads the project rather than keeping what the write returned.
(
registrations/board.ts,messages/board.ts,api/board.ts,types/task.ts,types/task-status.ts,types/board.ts,types/project-member.ts,types/time-entry.ts), soinit.tsgains oneimport and one call and
messages.tsis untouched.api.tsexports itsbase path, and
support/format.tsgains three helpers at the end.sortablejsis a runtime dependency bundled intodist/; it has no Vuedependency of its own.
dist/init.jsstill destructures the host's Vueexactly once and imports nothing from
"vue".Checks
pnpm run lint,pnpm exec tsc --noEmit,pnpm run build,validate-moduleandvalidate-packageall pass, anddist/is committed.Driven in the running app: the projects index, the detail heading and its four
tabs, a task created through the drawer, a card dragged between columns and
reordered inside one (both persisted across a reload), attaching and detaching
a project member, archive and restore, and the all-tasks page. No console
errors.
https://claude.ai/code/session_01DCf36XDKprZifej8dc2r1E