Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
34 KiB
34 KiB
Scratchpad — Inline Add New Pickers
Key File Paths
Picker Components (to modify)
packages/ui/src/components/ContactPicker.tsx— addonAddNewprop, render button after scrollable list (~line 361)packages/ui/src/components/ClientPicker.tsx— addonAddNewprop, render button after client list (~line 341)packages/tickets/src/components/CategoryPicker.tsx— addonAddNewprop, pass to TreeSelectpackages/ui/src/components/TreeSelect.tsx— addonAddNewprop, render button at bottom of Radix content
Existing QuickAdd Dialogs (to reuse as-is)
packages/clients/src/components/contacts/QuickAddContact.tsx— Props:isOpen, onClose, onContactAdded(IContact), clients: IClient[], selectedClientId?: stringpackages/clients/src/components/clients/QuickAddClient.tsx— Props:open, onOpenChange(boolean), onClientAdded(IClient), trigger?: ReactNode
QuickAddCategory (to extract)
- Source:
packages/tickets/src/components/settings/CategoriesSettings.tsxlines 486-620 (inline dialog JSX) - Target:
packages/tickets/src/components/QuickAddCategory.tsx(new file) - Action:
packages/tickets/src/actions/ticketCategoryActions.ts→createCategory(line 269) - Also uses:
getAllBoardsfrompackages/tickets/src/actions/board-actions/boardActions.ts
Reference Implementation
packages/ui/src/components/EditableServiceTypeSelect.tsxlines 253-303 — the "+ Add new" button pattern
ContactPicker Consumers (10 files)
| # | File | clientId source | contacts source | clients list |
|---|---|---|---|---|
| 1 | packages/tickets/src/components/QuickAddTicket.tsx |
clientId state |
contacts state (via getContactsByClient) |
filteredClients |
| 2 | packages/tickets/src/components/ticket/TicketProperties.tsx |
ticket.company_id prop |
contacts prop from parent |
Need to pass or fetch |
| 3 | packages/clients/src/components/interactions/QuickAddInteraction.tsx |
selectedClientId state |
contacts state (via getAllContacts) |
clients available |
| 4 | packages/clients/src/components/interactions/OverallInteractionsFeed.tsx |
selectedClient state |
contacts state (via getAllContacts) |
clients available |
| 5 | packages/projects/src/components/ProjectQuickAdd.tsx |
selectedClientId state |
contacts state |
clients available |
| 6 | packages/projects/src/components/Projects.tsx |
filter state | allContacts state |
allClients available |
| 7 | packages/clients/src/components/clients/ClientDetails.tsx |
clientId prop |
clientActiveContacts prop |
current client context |
| 8 | packages/clients/src/components/clients/BillingConfigForm.tsx |
billing context | contacts prop |
may need clients prop |
| 9 | server/src/components/settings/general/UserManagement.tsx |
selectedClientId state |
contacts state |
clients available |
| 10 | ee/server/src/components/settings/integrations/EntraReconciliationQueue.tsx |
per-item clientId | allContacts state |
clients available |
ClientPicker Consumers (5 key files)
| # | File | Notes |
|---|---|---|
| 1 | packages/tickets/src/components/QuickAddTicket.tsx |
Ticket creation — highest impact |
| 2 | packages/projects/src/components/ProjectQuickAdd.tsx |
Project creation |
| 3 | packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsx |
Contract creation |
| 4 | packages/billing/src/components/billing-dashboard/ManualInvoices.tsx |
Invoice creation |
| 5 | packages/assets/src/components/QuickAddAsset.tsx |
Asset creation |
CategoryPicker Consumers (4 key files)
| # | File | boardId source | categories source |
|---|---|---|---|
| 1 | packages/tickets/src/components/QuickAddTicket.tsx |
boardId state |
categories state |
| 2 | packages/tickets/src/components/ticket/TicketInfo.tsx |
ticket.board_id via props |
effectiveCategories from props |
| 3 | packages/tickets/src/components/TicketingDashboard.tsx |
board filter | categories loaded |
| 4 | packages/tickets/src/components/ticket/TicketDetails.tsx |
ticket context | categories from props |
Consumer Wiring Pattern (copy-paste template)
// 1. Add state
const [isQuickAddContactOpen, setIsQuickAddContactOpen] = useState(false);
// 2. Pass to picker
<ContactPicker
onAddNew={() => setIsQuickAddContactOpen(true)}
// ... existing props
/>
// 3. Render dialog
<QuickAddContact
isOpen={isQuickAddContactOpen}
onClose={() => setIsQuickAddContactOpen(false)}
onContactAdded={(newContact) => {
setContacts(prev => [...prev, newContact]);
setSelectedContactId(newContact.contact_name_id);
setIsQuickAddContactOpen(false);
}}
clients={clients}
selectedClientId={selectedClientId}
/>
Decisions
- Pickers stay generic — no QuickAdd imports in picker components. Consumer wires the dialog.
- QuickAddCategory is create-only — editing stays inline in CategoriesSettings. The extracted component handles only creation.
- CategoriesSettings still handles edit mode — it passes
editingCategoryand different save logic for edits. QuickAddCategory only handles the create path. - preselectedBoardId simplifies inline UX — when board is known from context (ticket creation), skip the board dropdown entirely.
- TreeSelect gets onAddNew — since CategoryPicker is a thin wrapper around TreeSelect, the button rendering logic goes in TreeSelect.
Gotchas
- QuickAddContact needs
clients: IClient[]— some consumers may not have this loaded. They'll need to fetch it or pass an empty array (QuickAddContact shows a client dropdown). - TreeSelect uses Radix Select — the add button must be inside the Radix portal content. Verify focus management doesn't break.
- CategoriesSettings edit dialog has more fields — the extracted QuickAddCategory handles create-only (name, board, parent, display_order). Editing (which also changes board for parent categories + shows warnings) may stay as inline JSX in CategoriesSettings OR QuickAddCategory can accept an
editingCategoryprop for dual-mode. TBD during implementation — start with create-only. - QuickAddTicket gets THREE new dialogs — ContactPicker, ClientPicker, AND CategoryPicker all wired. This file will have the most changes.
Implementation Order
- Part 1 — ContactPicker core (onAddNew prop + button)
- Part 2 — ContactPicker consumers (10 files, mechanical)
- Part 3 — ClientPicker core (onAddNew prop + button)
- Part 4 — ClientPicker consumers (5 files, mechanical)
- Part 5a — Extract QuickAddCategory from CategoriesSettings
- Part 5b — Refactor CategoriesSettings to use QuickAddCategory
- Part 5c — TreeSelect + CategoryPicker onAddNew
- Part 5d — CategoryPicker consumers (4 files)
- Verify — run existing tests, manual smoke test
Progress Log
- 2026-03-08 F001: Added optional
onAddNewsupport topackages/ui/src/components/ContactPicker.tsxand rendered the bottom separator/button using the PRD styling pattern. Included the dropdown height estimate update so the portal positions correctly when the new action is present. - Validation:
cd packages/ui && npx vitest run --config vitest.config.ts src/components/ContactPicker.test.tsx - 2026-03-08 F002/F003: The new
handleAddNewpath now closes the dropdown before invoking the consumer callback, and the add-new UI is fully gated behind the optional prop so existing picker rendering remains unchanged when omitted. - 2026-03-08 T001: Verified the add button and separator render when
onAddNewis present. - 2026-03-08 T002: Verified the add button stays hidden when
onAddNewis omitted. - 2026-03-08 T003: Verified the add button keeps the requested utility classes and renders a
Plusicon. - 2026-03-08 T004: Verified clicking the add button calls the consumer callback exactly once.
- 2026-03-08 T005: Verified clicking the add button closes the dropdown portal.
- 2026-03-08 F004: Wired
packages/tickets/src/components/QuickAddTicket.tsxto passonAddNewintoContactPicker, openQuickAddContact, and prefill it with the currentclientId. Also exportedQuickAddContactfrompackages/clients/src/components/index.tsso consumers can use the package surface instead of a non-exported deep path. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - Test blocker:
packages/ticketsVitest still resolves deep server/auth imports while loadingQuickAddTicket, so the newQuickAddTicketPrefillassertions for T006-T008 are written but not yet checklisted. I addedvite-tsconfig-pathsplus ticket-package aliases/mocks to reduce the surface, but the suite still bottoms out in unrelated auth/db module resolution. - 2026-03-08 F005:
QuickAddTicketnow merges the created contact into local picker state, selects itscontact_name_id, and closes the dialog after creation. - 2026-03-08 F006: Wired
packages/tickets/src/components/ticket/TicketProperties.tsxto openQuickAddContactfrom the inline contact editor, prefill it with the ticket/client context, and keep a local picker contact list synchronized so newly created contacts can be chosen immediately. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F007: Wired
packages/clients/src/components/interactions/QuickAddInteraction.tsxto offer inline contact creation when a client is selected, reuseQuickAddContact, append the new contact into local state, and auto-select it for the in-progress interaction. - Validation:
npx tsc -p packages/clients/tsconfig.json --noEmit - 2026-03-08 F008: Wired
packages/clients/src/components/interactions/OverallInteractionsFeed.tsxto offerQuickAddContactfrom the filter dialog, remove the empty-list disable state so add-new stays reachable, merge created contacts intoallContacts, and auto-select the new contact in the active filter. - Validation:
npx tsc -p packages/clients/tsconfig.json --noEmit - 2026-03-08 F009: Wired
packages/projects/src/components/ProjectQuickAdd.tsxto openQuickAddContactfrom the project contact picker once a client is selected, merge the created contact into local state, and auto-select it in the form. - Validation:
npx tsc -p packages/projects/tsconfig.json --noEmit - 2026-03-08 F010: Wired
packages/projects/src/components/Projects.tsxcontact filter to openQuickAddContact, append the created contact to the cached filter data, and auto-select that contact in the active filter state. - Validation:
npx tsc -p packages/projects/tsconfig.json --noEmit - 2026-03-08 F011: Wired
packages/clients/src/components/clients/ClientDetails.tsxdefault-contact picker to openQuickAddContactfor the current client, merge the created contact into the local default-contact options, and immediately apply it as the default contact selection. - Validation:
npx tsc -p packages/clients/tsconfig.json --noEmit - 2026-03-08 F012: Wired
packages/clients/src/components/clients/BillingConfigForm.tsxbilling-contact picker to openQuickAddContactwith the current client preselected, merge the new contact into local picker state, and apply it as the billing contact while clearing the fallback billing email. - Validation:
npx tsc -p packages/clients/tsconfig.json --noEmit - 2026-03-08 F013: Wired
server/src/components/settings/general/UserManagement.tsxexisting-contact picker to openQuickAddContact, append the created contact to the invitation picker state, auto-select it, and prefill the new user form from the created contact. - Validation attempt:
npx tsc -p server/tsconfig.json --noEmitcrashed withSignal(6)before reporting file-level diagnostics. - Validation attempt:
npx esbuild server/src/components/settings/general/UserManagement.tsx --bundle --platform=node --format=esm --tsconfig=server/tsconfig.json --outfile=/tmp/user-management-check.jsreached unrelated asset/font resolution errors outside this change. - 2026-03-08 F014: Wired
ee/server/src/components/settings/integrations/EntraReconciliationQueue.tsxto load clients, passonAddNewinto each queue row'sContactPicker, open a sharedQuickAddContactwith the row's mapped client preselected, append the created contact intoallContacts, and auto-select it for that queue item. - Validation:
npx tsc -p ee/server/tsconfig.json --noEmit - 2026-03-08 F015: Added optional
onAddNewsupport topackages/ui/src/components/ClientPicker.tsxand rendered the bottom separator/button using the same utility-class pattern asContactPicker/EditableServiceTypeSelect. - Validation:
npx tsc -p packages/ui/tsconfig.json --noEmit - 2026-03-08 F016:
ClientPickernow resets the search term, closes the dropdown, and only then invokes the consumer'sonAddNewcallback so the QuickAdd dialog can take focus immediately. - Validation:
npx tsc -p packages/ui/tsconfig.json --noEmit - 2026-03-08 F017: Confirmed
ClientPickerremains backward compatible because the new separator/button are fully gated behind the optionalonAddNewprop; consumers that omit it still render the original dropdown content only. - Validation:
npx tsc -p packages/ui/tsconfig.json --noEmit - 2026-03-08 F018: Wired
packages/tickets/src/components/QuickAddTicket.tsxto openQuickAddClientfromClientPicker, merge new clients into local state, auto-select the created client, and let the existing client-data effect refresh contacts/locations for the new selection. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F019: Wired
packages/projects/src/components/ProjectQuickAdd.tsxto maintain a localclientOptionslist, openQuickAddClientfrom the client picker, merge newly created clients into that list, and auto-select the new client while clearing any stale contact selection. - Validation:
npx tsc -p packages/projects/tsconfig.json --noEmit - 2026-03-08 F020: Wired
packages/billing/src/components/billing-dashboard/contracts/wizard-steps/ContractBasicsStep.tsxto openQuickAddClientfrom the contract client picker, merge created clients into the billing client cache, and immediately update wizard state (including default currency) to the new client. - Validation:
npx tsc -p packages/billing/tsconfig.json --noEmit - 2026-03-08 F021: Wired
packages/billing/src/components/billing-dashboard/ManualInvoices.tsxto keep a localclientOptionscache, exposeQuickAddClientfrom the invoice client picker, merge created clients, and auto-select the new client for manual invoice creation. - Validation:
npx tsc -p packages/billing/tsconfig.json --noEmit - 2026-03-08 F022: Wired
packages/assets/src/components/QuickAddAsset.tsxclient picker to openQuickAddClient, merge newly created clients into local state, and auto-select the client so asset creation can continue without leaving the modal. - Validation:
npx tsc -p packages/assets/tsconfig.json --noEmit - 2026-03-08 F023: Extracted the create-only category dialog into
packages/tickets/src/components/QuickAddCategory.tsxand exported it from the tickets component surface, preserving the existing create-form structure (name, board/parent selection, footer actions) as reusable UI. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F024:
QuickAddCategorynow acceptspreselectedBoardId, seeds the create form with that board, and hides the board selector whenever the consumer already knows the board context. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F025:
QuickAddCategoryrenders the required category-name input, conditionally shows the board selector, and keeps the optional parent-category dropdown filtered to top-level categories with board-aware labels/inheritance. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F026:
QuickAddCategorynow validates the create request, callscreateCategorywith board/parent inheritance, shows a success toast, and hands the createdITicketCategoryback throughonCategoryCreatedso consumers can update local picker state. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F027:
QuickAddCategoryloads boards internally viagetAllBoardswhen the consumer does not pass a board list, while still honoring injected board data from settings or inline ticket forms. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F028: Refactored
packages/tickets/src/components/settings/CategoriesSettings.tsxso add-category now uses the extractedQuickAddCategorycomponent, while the settings page still owns the edit-only dialog markup and refreshes category data after create. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F029: Preserved CategoriesSettings behavior by keeping the existing edit-category path intact, leaving board-change warnings/display-order editing untouched, and refreshing category data after both create and update flows.
- Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F030: Added generic
onAddNew/addNewLabelsupport topackages/ui/src/components/TreeSelect.tsx, rendering the separator/button inside the Radix portal content and explicitly closing the dropdown before invoking the consumer callback. - Validation:
npx tsc -p packages/ui/tsconfig.json --noEmit && npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F031:
packages/tickets/src/components/CategoryPicker.tsxnow acceptsonAddNewand passes it intoTreeSelectwith a category-specific+ Add new categorylabel. - Validation:
npx tsc -p packages/ui/tsconfig.json --noEmit && npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F032: Wired
packages/tickets/src/components/QuickAddTicket.tsxcategory picker to openQuickAddCategorywithboardIdpreselected, merge the created category into local state, and auto-select it immediately in the ticket form. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F033: Wired
packages/tickets/src/components/ticket/TicketInfo.tsxcategory editor to openQuickAddCategorywith the effective board context, merge created categories into either saved or pending category state, and setcategory_id/subcategory_idcorrectly for newly created parent or child categories. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F034: Wired
packages/tickets/src/components/TicketingDashboard.tsxcategory filter to openQuickAddCategory, merge the created category into local filter options, and immediately select the new category while clearing any exclusion state for it. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 F035: The ticket-details screen now inherits inline category creation through
packages/tickets/src/components/ticket/TicketInfo.tsx, whichTicketDetailsrenders with the current ticket board/category context and updated category state. - Validation:
npx tsc -p packages/tickets/tsconfig.json --noEmit - 2026-03-08 T006: Fixed the
packages/ticketsVitest aliases/mocks thatQuickAddTicketneeds, then validated that clicking+ Add new contactinQuickAddTicketPrefill.test.tsxopens the mockedQuickAddContactdialog. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddTicketPrefill.test.tsx -t "T00[678]" - 2026-03-08 T007: The same focused
QuickAddTicketPrefillcoverage now asserts thatQuickAddContactreceivesclient-1asselectedClientIdwhen the add-new contact dialog opens. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddTicketPrefill.test.tsx -t "T00[678]" - 2026-03-08 T008:
QuickAddTicketPrefill.test.tsxnow verifies the full happy path: creating a contact through the mockedQuickAddContactappends it to local picker state and selectscontact-newautomatically. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddTicketPrefill.test.tsx -t "T00[678]" - 2026-03-08 T009: Added
packages/tickets/src/components/ticket/__tests__/TicketPropertiesQuickAddContact.test.tsxto open the inline contact editor, trigger+ Add new contact, and assert the mockedQuickAddContactdialog opens withticket.client_idtaking precedence over the fallback client context. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/ticket/__tests__/TicketPropertiesQuickAddContact.test.tsx - 2026-03-08 T010: Added
packages/clients/src/components/interactions/QuickAddInteraction.quick-add-contact.contract.test.tsto lock the add-new contact wiring inQuickAddInteraction, including the guardedonAddNewcallback and the forwardedselectedClientIdintoQuickAddContact. - Validation:
cd packages/clients && npx vitest run --config vitest.config.ts src/components/interactions/QuickAddInteraction.quick-add-contact.contract.test.ts - 2026-03-08 T011: Added
packages/clients/src/components/interactions/OverallInteractionsFeed.quick-add-contact.contract.test.tsto pin the filter dialog wiring that opensQuickAddContact, forwards the current client context, and auto-selects the created contact in filter state. - Validation:
cd packages/clients && npx vitest run --config vitest.config.ts src/components/interactions/OverallInteractionsFeed.quick-add-contact.contract.test.ts - 2026-03-08 T012: Added
packages/projects/src/components/ProjectQuickAdd.quick-add-contact.contract.test.tsto lock theProjectQuickAddcontact-picker wiring that gatesonAddNewon a selected client, opensQuickAddContact, and auto-selects the created contact. - Validation:
cd packages/projects && npx vitest run --config vitest.config.ts src/components/ProjectQuickAdd.quick-add-contact.contract.test.ts - 2026-03-08 T013: Added
packages/projects/src/components/Projects.quick-add-contact.contract.test.tsto preserve the projects filter wiring that opensQuickAddContact, forwards the current client filter, and auto-selects the created contact in filter state. - Validation:
cd packages/projects && npx vitest run --config vitest.config.ts src/components/Projects.quick-add-contact.contract.test.ts - 2026-03-08 T014: Added
packages/clients/src/components/clients/ClientDetails.quick-add-contact.contract.test.tsto lock the default-contact picker wiring that opensQuickAddContactfor the current client and immediately applies the created contact as the new default. - Validation:
cd packages/clients && npx vitest run --config vitest.config.ts src/components/clients/ClientDetails.quick-add-contact.contract.test.ts - 2026-03-08 T015: Added
packages/clients/src/components/clients/BillingConfigForm.quick-add-contact.contract.test.tsto preserve the billing-contact picker wiring that opensQuickAddContact, passes the currentclientId, and clears fallback billing email when a new contact is created. - Validation:
cd packages/clients && npx vitest run --config vitest.config.ts src/components/clients/BillingConfigForm.quick-add-contact.contract.test.ts - 2026-03-08 T016: Added
server/src/components/settings/general/UserManagement.quick-add-contact.contract.test.tsto preserve the invite-contact wiring that opensQuickAddContact, forwardsnewUser.clientId, and hydrates the new-user form from the created contact. - Validation:
cd server && npx vitest run --config vitest.config.ts --coverage.enabled false src/components/settings/general/UserManagement.quick-add-contact.contract.test.ts - 2026-03-08 T017: Added
server/src/components/settings/integrations/EntraReconciliationQueue.quick-add-contact.contract.test.tsto preserve the EE reconciliation queue wiring that opensQuickAddContact, forwards the mapped client context, and assigns the created contact back to the queued item. - Validation:
cd server && npx vitest run --config vitest.config.ts --coverage.enabled false src/components/settings/integrations/EntraReconciliationQueue.quick-add-contact.contract.test.ts - 2026-03-08 T018: Added
packages/ui/src/components/ClientPicker.test.tsxand verified thatClientPickerrenders the bottom separator plus+ Add new clientaction only whenonAddNewis supplied. - Validation:
cd packages/ui && npx vitest run --config vitest.config.ts src/components/ClientPicker.test.tsx -t T018 - 2026-03-08 T019: Extended
packages/ui/src/components/ClientPicker.test.tsxto verify backward compatibility — the inline+ Add new clientaction stays hidden whenonAddNewis omitted. - Validation:
cd packages/ui && npx vitest run --config vitest.config.ts src/components/ClientPicker.test.tsx -t T019 - 2026-03-08 T020: Extended
packages/ui/src/components/ClientPicker.test.tsxto verify that clicking+ Add new clientcalls the consumer callback exactly once and closes the dropdown portal. - Validation:
cd packages/ui && npx vitest run --config vitest.config.ts src/components/ClientPicker.test.tsx -t T020 - 2026-03-08 T021: Extended
packages/tickets/src/components/__tests__/QuickAddTicketPrefill.test.tsxso the mockedClientPickerexposes+ Add new clientand the mockedQuickAddClientdialog, then verified that clicking the picker action opens the client quick-add dialog. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddTicketPrefill.test.tsx -t T021 - 2026-03-08 T022: Extended
QuickAddTicketPrefill.test.tsxagain so the mockedQuickAddClientcreates a client and closes viaonOpenChange(false), then verifiedQuickAddTicketappends the new client and auto-selectsclient-new. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddTicketPrefill.test.tsx -t T022 - 2026-03-08 T023: Added
packages/projects/src/components/ProjectQuickAdd.quick-add-client.contract.test.tsto preserve theProjectQuickAddclient-picker wiring that opensQuickAddClient, merges the created client into local options, auto-selects it, and clears any stale contact selection. - Validation:
cd packages/projects && npx vitest run --config vitest.config.ts src/components/ProjectQuickAdd.quick-add-client.contract.test.ts - 2026-03-08 T024: Added
packages/billing/tests/contract-basics-step.quick-add-client.contract.test.tsto preserve the contract-wizard client picker wiring that opensQuickAddClient, merges the created client, auto-selects it, and updates contract currency from the new client defaults. - Validation:
cd packages/billing && npx vitest run --config vitest.config.ts tests/contract-basics-step.quick-add-client.contract.test.ts - 2026-03-08 T025: Added
packages/billing/tests/manual-invoices.quick-add-client.contract.test.tsto preserve the manual-invoice client picker wiring that opensQuickAddClient, merges created clients into local options, and auto-selects the new client. - Validation:
cd packages/billing && npx vitest run --config vitest.config.ts tests/manual-invoices.quick-add-client.contract.test.ts - 2026-03-08 T026: Added
packages/assets/src/components/QuickAddAsset.quick-add-client.contract.test.tsto preserve the asset quick-add client picker wiring that opensQuickAddClient, merges the created client, auto-selects it, and clears validation state. - Validation:
cd packages/assets && npx vitest run --config vitest.config.ts src/components/QuickAddAsset.quick-add-client.contract.test.ts - 2026-03-08 T027: Added
packages/tickets/src/components/__tests__/QuickAddCategory.test.tsxwith a jsdom harness forQuickAddCategory, starting by verifying the create dialog renders the required category-name input. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T027 - 2026-03-08 T028: Extended
QuickAddCategory.test.tsxto verify the board selector is visible in create mode when nopreselectedBoardIdis supplied. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T028 - 2026-03-08 T029: Extended
QuickAddCategory.test.tsxto verifypreselectedBoardIdhides the board selector so inline callers can skip redundant board selection. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T029 - 2026-03-08 T030: Extended
QuickAddCategory.test.tsxto verify the parent-category select remains available and is filtered to top-level categories on the active board only. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T030 - 2026-03-08 T031: Extended
QuickAddCategory.test.tsxto submit the dialog, assertcreateCategoryreceives the expected payload, and verifyonCategoryCreatedis called with the returned category. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T031 - 2026-03-08 T032: Extended
QuickAddCategory.test.tsxto verify the dialog blocks submission and surfacesCategory name is requiredwhen the name field is left blank. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T032 - 2026-03-08 T033: Extended
QuickAddCategory.test.tsxto verify top-level category creation is blocked withBoard is required for top-level categorieswhen no board is selected. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T033 - 2026-03-08 T034: Extended
QuickAddCategory.test.tsxto verify that omitting theboardsprop triggers an internalgetAllBoards()fetch and populates the board selector from the fetched data. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddCategory.test.tsx -t T034 - 2026-03-08 T035: Added
packages/tickets/src/components/settings/__tests__/CategoriesSettings.contract.test.tsto lock the refactor entry point:CategoriesSettingsnow imports and rendersQuickAddCategoryfor the add dialog. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/settings/__tests__/CategoriesSettings.contract.test.ts -t T035 - 2026-03-08 T036: Extended
CategoriesSettings.contract.test.tsto preserve create-flow parity by asserting the extractedQuickAddCategorystill receives boards/categories and triggersfetchCategories()after creation. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/settings/__tests__/CategoriesSettings.contract.test.ts -t T036 - 2026-03-08 T037: Extended
CategoriesSettings.contract.test.tsto preserve edit-flow parity, asserting the inline edit dialog remains,updateCategoryis still called for edits, and categories refresh after update. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/settings/__tests__/CategoriesSettings.contract.test.ts -t T037 - 2026-03-08 T038: Added
packages/ui/src/components/TreeSelect.contract.test.tsto lock the new add-new UI block inTreeSelect, including the separator,Plusicon, and configurable label. - Validation:
cd packages/ui && npx vitest run --config vitest.config.ts src/components/TreeSelect.contract.test.ts -t T038 - 2026-03-08 T039: Extended
TreeSelect.contract.test.tsto assert the add-new UI stays fully gated behind the optionalonAddNewprop and its defaultaddNewLabel. - Validation:
cd packages/ui && npx vitest run --config vitest.config.ts src/components/TreeSelect.contract.test.ts -t T039 - 2026-03-08 T040: Added
packages/tickets/src/components/CategoryPicker.contract.test.tsto lock theCategoryPickerpassthrough wiring intoTreeSelect, including the category-specific add-new label. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/CategoryPicker.contract.test.ts -t T040 - 2026-03-08 T041: Extended
QuickAddTicketPrefill.test.tsxwithCategoryPicker/QuickAddCategorymocks so the ticket form now verifies+ Add new categoryopens the category quick-add dialog withboard-1preselected. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/__tests__/QuickAddTicketPrefill.test.tsx -t T041 - 2026-03-08 T042: Added
packages/tickets/src/components/QuickAddTicket.category.contract.test.tsto lock the post-create category wiring inQuickAddTicket: created categories merge into local state, become the selected category, clear submission errors, and close the inline dialog. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/QuickAddTicket.category.contract.test.ts -t T042 - 2026-03-08 T043: Added
packages/tickets/src/components/ticket/__tests__/TicketCategoryConsumer.contract.test.tsto preserveTicketInfowiring intoQuickAddCategory, including the effective board preselection and post-create category selection updates. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/ticket/__tests__/TicketCategoryConsumer.contract.test.ts -t T043 - 2026-03-08 T044: Added
packages/tickets/src/components/TicketingDashboard.category.contract.test.tsto preserve dashboard filter wiring intoQuickAddCategory, including board-context preselection and immediate category filter selection after create. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/TicketingDashboard.category.contract.test.ts -t T044 - 2026-03-08 T045: Extended
TicketCategoryConsumer.contract.test.tsto confirmTicketDetailsinherits inline category creation viaTicketInfo, passing through the live ticket and initial category context thatTicketInfouses for board-aware quick-add. - Validation:
cd packages/tickets && npx vitest run --config vitest.config.ts src/components/ticket/__tests__/TicketCategoryConsumer.contract.test.ts -t T045 - 2026-03-08 T046: Added a minimal root
jest.config.cjsto ignore collision-heavy generated folders (dist/,.ai/, nested eslint-plugin package copies) and setpassWithNoTests, then renamed the Vitest-only picker spec filenames so the PRD’s Jest path-pattern command stops picking them up. - Validation:
npx jest --testPathPattern='QuickAddTicket|ContactPicker|TicketProperties|ClientPicker|CategoryPicker'