Skip to content

chore: polish and docs for the task-centric rework (PR 4) - #12

Closed
gdarko wants to merge 12 commits into
feat/task-centric-invoicing-uifrom
feat/task-centric-polish
Closed

gdarko wants to merge 12 commits into
feat/task-centric-invoicing-uifrom
feat/task-centric-polish

Conversation

@gdarko

@gdarko gdarko commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Summary

PR 4 of the task-centric rework: polish and documentation, on top of feat/task-centric-invoicing-ui.

  • Pluralise the invoice line composer's truncation summary: "and 1 more entry" for exactly one dropped entry, "and N more entries" otherwise. Added a unit test covering the singular case (313 tests green, was 312).
  • The quick-start floating launcher now hides on /admin/settings/... routes (tracked through the host router's afterEach) and lifts clear of the AI assistant module's own launcher button when one is present on the page.
  • Fixed a real bug in the bulk tasks flow: POST tasks/bulk returns updated as the list of changed ids, but the frontend typed and used it as a count, so a partial bulk change rendered the raw id array in place of a number and the "nothing changed" branch was unreachable. The partial-failure notify now also lists the ids the endpoint refused.
  • The module's own settings summary page only ever linked to the host settings form for the default rate, the week start day and who may see other members' time; it now lists their current values too, matching the behaviour and invoice-line cards.
  • Verified and left alone (no gap found): hide_invoiced_on_board already hides invoiced cards client-side off GET settings; the /time redirect already lands on the Week view, and no TIME_PATH constant exists anywhere to remove.
  • Rewrote the module README.md to describe the task-centric flow: the Projects and Tasks sidebar entries, the Tasks screen's List/Board/Week views, starting and stopping time from a row, a card, a task's own page or the floating launcher, the task time log, invoicing a task/selection/project into the host's invoice editor, the unbilled time page, every setting, and the abilities catalogue.
  • Updated specs/tasks-projects.md ("UI surface" rewritten task-centric, "API surface" table gained the new routes) and appended a dated DECISIONS.md entry, committed and pushed to InvoiceShelf/specs directly (private repo, separate from this PR).

What was already done (verified, not changed)

  • The /time forwarding page (PR 2) already lands on the Week view.
  • hide_invoiced_on_board (PR 1/2) is already read from GET settings and applied client-side on the board.
  • No TIME_PATH constant exists in the codebase.

Test plan

  • vendor/bin/pint --test
  • composer run lint && composer run test (313 tests, 1303 assertions)
  • pnpm run lint
  • pnpm exec tsc --noEmit
  • pnpm run build (exactly one window.__invoiceshelf_vue, zero from "vue")
  • vendor/bin/invoiceshelf-module validate-module module.json
  • vendor/bin/invoiceshelf-module validate-package .

https://claude.ai/code/session_01DCf36XDKprZifej8dc2r1E

The composer's cap on a note's length always pluralised the summary
line, so a note that trimmed exactly one entry read "and 1 more
entries". Pluralise only when more than one entry was dropped.
…e AI bubble

The floating launcher covered the bottom of long settings pages, such
as the status editor, with no way to see past it. It now hides on
/admin/settings/... routes, tracked through the host router's
afterEach rather than a prop that was never wired through. It also
lifts clear of the AI assistant module's own launcher button when one
is on the page, checked once at mount and again on every company
switch through the overlay's existing remount key.
POST tasks/bulk answers with updated as the list of ids it changed,
but the frontend typed and read it as a count, so a partial bulk
change rendered the id array where a number belonged and the "nothing
changed" branch could never trigger. The partial notify now also
names the ids the endpoint refused, instead of only how many.
The general settings card described the default rate, the week start
day and who may see other members' time, but only ever rendered a
link to the host form, not one of the three values. It now lists them
next to the link, the same way the behaviour and invoice-line cards
already do.
Rewrite the user-facing sections for the rebuilt UI: the Projects and
Tasks sidebar entries, the Tasks screen's List, Board and Week views,
starting and stopping time from a row, a card, a task's own page or
the floating launcher, the task time log, invoicing a task, a
selection or a project into the host's invoice editor, the unbilled
time page, every setting, and the abilities catalogue.
The host's module settings form translates a section's title and a field's
label and hands a select's options through as they were registered, so the
rounding direction offered three translation keys instead of Nearest, Up and
Down. The registration now resolves them, and the harness loads the module's
own translations the way its provider does, so a test can see the difference.
The server's own message states the rule for whoever called the API, so a
locked task reported a generic failure at the form and the task page. Both
now prefer the module's own sentence for that one code and keep the server's
for everything else.
A count reached the reader through a message that only had a plural form, so
one entry was reported as "1 entries" on the unbilled cards and the default
rounding increment read "1 minutes" on the settings page. The host's
translator picks a form when the message offers two, so the counted lines now
offer both.
The quick-start button looked for the AI assistant once, at mount, and the
host renders that module's header action from a script it loads alongside this
one, so the look never found it. It also could not tell a header action from a
floating bubble, and only the second one is in the way. The probe now asks the
layout whether any assistant launcher is fixed, and runs again on every
navigation.
The host names the module card and its settings modal after the entry
registered under the module slug, which was Projects. Tasks is the module
root, so it carries the slug now and Projects moves to a secondary key.
@gdarko

gdarko commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #14, which carries this stack consolidated into three commits on top of main.

@gdarko gdarko closed this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant