Commit graph

1091 commits

Author SHA1 Message Date
Alexandre Brandizzi
35714a917d fix(workorders): Site dialog re-syncs a site after switching back and never syncs cached data
Switching to another site and back now loads the site record again, so its
extra contacts are not dropped on Save. The dialog also waits for the site
request to settle before syncing, so a record cached before an earlier save
is never shown or written back. Half-filled extra contacts stay off the site
record, as they already stay off the work order. The save path moves into
its own hook to keep the dialog state under the complexity limit.
2026-09-25 17:01:27 -03:00
Alexandre Brandizzi
c0e484275d fix(workorders): say Site dialog saves to the work order only when the site did not load
When the site detail request fails, or the user types before it loads,
the dialog falls back to saving this work order only and never calls
updateContactInfo. The POC helper text still said contacts and notes were
saved to the site record, so a dispatcher could believe every work order
at the site now had the new contact. The helper text now follows the
site-record sync state and says the change applies to this work order
only whenever that fallback is active, including after a later refetch
succeeds.
2026-09-25 13:39:25 -03:00
Alexandre Brandizzi
7efc9e8914 fix(workorders): never let a late site load replace typed Site dialog input
The contact lock only covered a pending load. After a failed getById the
fields unlock, and a later successful refetch (focus, invalidation) still
ran the apply effect and overwrote whatever the dispatcher had typed.

The apply effect now skips once the user has typed since the last reset or
site switch, so the dialog stays on the work order's values and saves them
to the work order only; the site's unseen notes and contacts are never
written back. Picking another site still clears the marker and adopts it.
2026-09-25 13:12:27 -03:00
Alexandre Brandizzi
ad500753e1 fix(workorders): lock Site dialog contacts until the site record loads 2026-09-25 12:36:16 -03:00
Alexandre Brandizzi
cccdeceb10 fix(workorders): only edited Site dialog fields follow the site record 2026-09-25 12:32:24 -03:00
Alexandre Brandizzi
bea3540409 Merge remote-tracking branch 'origin/feat/ab/sh-331-sites-panel' into feat/ab/sh-335-wo-site-dialog 2026-09-25 12:24:54 -03:00
Alexandre Brandizzi
fe0d1a2571 fix(sites): keep the legacy contact name when an update sends no contacts 2026-09-25 12:23:18 -03:00
Alexandre Brandizzi
7eaf6bca18 Save Work Order Site dialog contact and notes edits to the site record 2026-09-25 12:19:31 -03:00
Alexandre Brandizzi
c5816f8907 fix(sites): name the site in the delete confirmation and toast 2026-09-25 11:55:09 -03:00
Alexandre Brandizzi
551f6af208 refactor(sites): read optional site fields through one helper 2026-09-25 11:45:31 -03:00
Alexandre Brandizzi
a75b9c8be6 feat(sites): Add Site modal and site detail panel with in-place edit
- Sites page: Add Site modal with Site Code, Client, address, State/Area, optional Site Phone and Email, points of contact
- Duplicate Site Code shows inline under the field and keeps the modal open
- Row opens a non-modal detail panel; Street Address links to Google Maps; key-less map preview
- Edit switches the panel in place with Site Code read-only; Save needs a valid change, Cancel makes no call
- Site Phone is sent independently of the contacts; zip and title are carried through edits
- Retire the separate new/edit location pages
2026-09-25 11:43:30 -03:00
Alexandre Brandizzi
358ec3e890
Merge pull request #261 from Sea-Haven-Industries/feat/ab/sh-392-dashboard-unassigned
Some checks are pending
Frontend checks / static (push) Waiting to run
Frontend checks / build (push) Waiting to run
Frontend checks / unit (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Frontend checks / browser-smoke (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / ci-complete (push) Blocked by required conditions
Deploy Web / Resolve target (push) Waiting to run
Deploy Web / Deploy SPA to (push) Blocked by required conditions
SH-392: Unassigned KPI tile on the Dashboard
2026-09-25 06:52:00 +00:00
Alexandre Brandizzi
2084cfa453
Merge pull request #266 from Sea-Haven-Industries/fix/ab/sh-400-vendor-readonly-uplifts
Some checks are pending
Frontend checks / static (push) Waiting to run
Frontend checks / build (push) Waiting to run
Frontend checks / unit (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Frontend checks / browser-smoke (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / ci-complete (push) Blocked by required conditions
Deploy Web / Resolve target (push) Waiting to run
Deploy Web / Deploy SPA to (push) Blocked by required conditions
Show work-order uplift requests read-only in the Vendor Portal
2026-09-25 06:20:35 +00:00
Alexandre Brandizzi
43dd95e7fd Show the requested NTE total on work-order uplift cards
A request raised from the work order stores the increase, so the vendor card
read a +90 request on a 600 NTE as "Requested $90.00 (was $600.00)". The card
now shows the new total, $690.00, for those requests; vendor requests are
unchanged.
2026-09-25 03:12:17 -03:00
Alexandre Brandizzi
9f46a91cb9
Merge pull request #260 from Sea-Haven-Industries/fix/ab/sh-383-media-contract
fix(media): apply the SH-116 media contract to every upload surface
2026-09-25 06:06:59 +00:00
Alexandre Brandizzi
33f7172598 Move uplift card action gating into a helper
Keeps UpliftRequestCard within the changed-file complexity limit.
2026-09-25 03:03:30 -03:00
Alexandre Brandizzi
b91682f53c Merge remote-tracking branch 'origin/main' into lane/pr261 2026-09-25 03:02:25 -03:00
Alexandre Brandizzi
70f8b303b5 Show work-order uplift requests read-only in the Vendor Portal
Revise and Withdraw now appear only on uplift requests the vendor raised.
Requests raised from the work order stay visible without either control.
2026-09-25 02:55:04 -03:00
Alexandre Brandizzi
52cbb87126
Merge pull request #259 from Sea-Haven-Industries/fix/ab/sh-391-adv-filter-date-range
fix(workorders): make the Advanced Filters date range narrow results (SH-391)
2026-09-25 05:53:39 +00:00
Alexandre Brandizzi
7c665464f8
Merge pull request #263 from Sea-Haven-Industries/fix/ab/sh-398-uplift-amount
Some checks are pending
Frontend checks / static (push) Waiting to run
Frontend checks / build (push) Waiting to run
Frontend checks / unit (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Frontend checks / browser-smoke (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / ci-complete (push) Blocked by required conditions
Deploy Web / Resolve target (push) Waiting to run
Deploy Web / Deploy SPA to (push) Blocked by required conditions
fix(uplifts): show one uplift amount on every approvals surface
2026-09-25 05:02:57 +00:00
Alexandre Brandizzi
56ca5b0c39 test(uplifts): assert the uplift amount on the approver e2e buttons 2026-09-25 01:58:47 -03:00
Alexandre Brandizzi
3d10ba8a0c style(uplifts): apply prettier to uplift approval tests 2026-09-25 01:53:05 -03:00
Alexandre Brandizzi
d653ca0095 fix(vendor-portal): hold uplift submit until the evidence check settles
Picking a video as uplift evidence reads its movie header before the file is stored in form state. A submit that landed inside that window validated the previous (usually empty) evidence, showed the missing-evidence error and dropped the request, forcing a second click. The submit button is now disabled and reads "Checking evidence…" while the latest pick is being checked, and the submit handler ignores submissions in that window.
2026-09-25 01:50:27 -03:00
Alexandre Brandizzi
28e30f8edb fix(uplifts): show the requested increase as the one uplift amount
The queue Amount column, the detail modal and the reject/revoke dialogs
showed requestedNTE (the resulting NTE total) while the decision toasts
showed delta (the increase), so a work order with an existing NTE named
two different figures for one request. Route every surface through one
upliftAmount helper that returns the increase, matching the prototype's
single uplift amount, and show it on both Approve buttons.
2026-09-25 01:49:24 -03:00
Alexandre Brandizzi
39ee98e09b fix(vendor-portal): advertise phone photo and video types for uplift evidence
The evidence picker filtered to PDF/JPG/PNG and its label and missing-file
messages said the same, while the pre-check (and the server, which applies
the SH-116 allowlist and work-order counts to UpliftEvidence uploads)
accepts HEIC, MP4 and MOV. On a phone the picker hid exactly the photos and
clips the validator would pass.

The evidence input now uses the same accept filter as the completion
upload, exported once from document-validation, and the label and both
missing-evidence messages name all six types.
2026-09-25 01:43:34 -03:00
Alexandre Brandizzi
ef6cde64c8 fix(vendor-portal): state the 10 MB PDF cap in the upload hint
The vendor portal hint listed the photo and video limits but not the PDF one, so a vendor rejected for an 11 MB PDF saw a limit that was never stated. PDFs are the only accepted kind whose cap was missing from the copy; a test now pins the full hint.
2026-09-24 23:49:19 -03:00
Alexandre Brandizzi
aec11782b3
Merge pull request #262 from Sea-Haven-Industries/fix/ab/sh-394-exposure-dash
Some checks are pending
Frontend checks / static (push) Waiting to run
Frontend checks / build (push) Waiting to run
Frontend checks / unit (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Frontend checks / browser-smoke (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / ci-complete (push) Blocked by required conditions
Deploy Web / Resolve target (push) Waiting to run
Deploy Web / Deploy SPA to (push) Blocked by required conditions
fix(uplifts): show a dash for Approved on WO when nothing is granted (SH-394)
2026-09-25 02:31:59 +00:00
Alexandre Brandizzi
5387a7b1c9
Merge pull request #252 from Sea-Haven-Industries/albrand/renovate-npm-minor-and-patch
chore(deps): update npm minor and patch
2026-09-25 02:12:28 +00:00
Alexandre Brandizzi
eb01c59471 test(uplifts): drop the ticket key from the Approved on WO test name 2026-09-24 23:03:42 -03:00
Alexandre Brandizzi
d573ab59a9 refactor(vendor-portal): extract document row from VendorPortalDocuments
The changed-file maintainability gate caps functions at 150 lines;
VendorPortalDocuments reached 156. Move the per-document row into
VendorPortalDocumentRow with no behavior change.
2026-09-24 23:03:23 -03:00
Alexandre Brandizzi
b8d24d75a3 test(uplifts): cover an unknown row total with nothing granted on the WO (SH-394) 2026-09-24 23:00:27 -03:00
Alexandre Brandizzi
ec3f97dcf6 fix(uplifts): show a dash for Approved on WO when nothing is granted (SH-394)
A work order with a zero granted total rendered $0.00 in the Pending
table's Approved on WO column and in the detail modal's Total line.
Both now share isGrantedAmount, so zero or unknown totals render a dash
and the column always matches the modal Total.
2026-09-24 22:54:39 -03:00
Alexandre Brandizzi
6012ebabe7 fix(media): count HEIC and untyped phone files, guard overlapping picks
Persisted HEIC files and local files with an empty or octet-stream type
were classified as "other", so they did not count toward the 10 photo /
3 video limit. Both classifiers now recognise them by extension.

The Photos & Videos uploader and Extra Docs ignore a new selection while
the previous one is still being screened, and the vendor portal drops an
earlier pick whose video check finishes after a newer pick.

Also removes ticket keys from source comments.
2026-09-24 22:51:17 -03:00
Alexandre Brandizzi
ffff03fcc2 test(visual): refresh work-order baselines for lucide-react icon updates 2026-09-24 22:48:18 -03:00
Alexandre Brandizzi
8bb4c0c512 fix(dashboard): open the Unassigned tile as the Unassigned filter option
The tile link sent the board API token __unassigned__ as the dispatcher.
The drill-down parser stores that as an Advanced Filters dispatcher id,
while the filter UI only knows __unassigned, so the banner showed a raw
__unassigned__ chip, Assigned to did not tick Unassigned, and the option
could not clear it. Send ASSIGNEE_FILTER_UNASSIGNED, as the notification
queue link already does; toBoardSearchQueryParams still maps it to
__unassigned__ for /board/search, so the rows are unchanged.
2026-09-24 22:45:10 -03:00
Alexandre Brandizzi
62e38e4b81 chore(workorders): keep ticket keys out of test names
The review contract bars Jira keys in source comments and test names;
ticket identity lives in the PR, commit and branch. The previous commit
cleaned the source files; this strips the six (SH-391) suffixes the
branch added to test names and a test comment, keeping the behavioural
wording.
2026-09-24 22:41:05 -03:00
Alexandre Brandizzi
ec83829098 Merge remote-tracking branch 'origin/main' into lane/renovate
# Conflicts:
#	e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-filters.png
#	e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-list.png
#	e2e/__screenshots__/work-orders/work-orders.visual.spec.ts/wo-new.png
#	package-lock.json
#	package.json
2026-09-24 22:35:01 -03:00
Alexandre Brandizzi
b316168930 fix(vendor-portal): pre-check the per-work-order photo/video limit
The vendor completion upload and uplift evidence checked type, size and
duration but not the 10-photo / 3-video work-order limit. Use the counts the
dispatch detail now reports (shoc-backend#173), on the same basis as the
server: a new completion version does not count the document it replaces.
When the backend does not report counts yet, the server check still applies.
2026-09-24 22:29:20 -03:00
Alexandre Brandizzi
67cb490d52 test(dashboard): refresh visual baselines for the Unassigned tile and the Services entry
Rendered by the CI Playwright container at f64447f5.
2026-09-24 22:20:14 -03:00
Alexandre Brandizzi
cfe83fc489 fix(media): read video duration from the MP4/MOV header in the browser
The browser pre-check decoded the picked file through a video element and
an object URL, which CodeQL flags as DOM text reinterpreted as HTML. Parse
the moov/mvhd movie header from file slices instead, the same way the
server enforces the 90-second limit, so both sides read one duration.
Unreadable headers still never block an upload.
2026-09-24 22:14:42 -03:00
Alexandre Brandizzi
f64447f52c chore(dashboard): keep ticket keys out of source comments 2026-09-24 22:06:24 -03:00
Alexandre Brandizzi
7984640a5f Merge remote-tracking branch 'origin/fix/ab/sh-391-adv-filter-date-range' into feat/ab/sh-392-dashboard-unassigned 2026-09-24 22:05:33 -03:00
Alexandre Brandizzi
792dc6917b Merge remote-tracking branch 'origin/main' into feat/ab/sh-392-dashboard-unassigned
# Conflicts:
#	e2e/__screenshots__/dashboard/dashboard.visual.spec.ts/dashboard-admin.png
#	e2e/__screenshots__/dashboard/dashboard.visual.spec.ts/dashboard-dispatcher.png
2026-09-24 22:05:10 -03:00
Alexandre Brandizzi
c1fd8f6d88 chore(workorders): keep ticket keys out of source comments 2026-09-24 22:03:23 -03:00
Alexandre Brandizzi
c99e81d0d7 fix(media): pre-check duration and per-work-order counts on Extra Docs
Extra Docs advertised the 90-second limit but only checked type and size.
Both dispatcher surfaces now share one screening step (type, size, count,
duration), and the Completion Doc media tab and Extra Docs count the whole
work order's photos and videos rather than only their own tab's share.
Failed local uploads no longer count toward the limit.
2026-09-24 22:01:22 -03:00
Alexandre Brandizzi
8b58eb5f64
Merge pull request #250 from Sea-Haven-Industries/fix/sh-327-uplift-denial-message
Some checks are pending
Frontend checks / static (push) Waiting to run
Frontend checks / build (push) Waiting to run
Frontend checks / unit (push) Waiting to run
Frontend checks / Visual regression (push) Waiting to run
Frontend checks / browser-smoke (push) Waiting to run
Frontend checks / governance (push) Waiting to run
Frontend checks / ci-complete (push) Blocked by required conditions
Deploy Web / Resolve target (push) Waiting to run
Deploy Web / Deploy SPA to (push) Blocked by required conditions
fix: preserve uplift denial message
2026-09-25 00:52:28 +00:00
Alexandre Brandizzi
60b0638ea3 test(dashboard): update visual baselines for the Unassigned tile (SH-392)
Rendered by the CI Playwright container (mcr.microsoft.com/playwright:v1.61.1-noble)
at fca87b67.
2026-09-24 21:52:21 -03:00
Alexandre Brandizzi
20ef4a615d
Merge pull request #251 from Sea-Haven-Industries/albrand/tanstack-query-5.103.1
fix(deps): update TanStack Query to v5.103.1
2026-09-25 00:52:21 +00:00
Alexandre Brandizzi
563f81e163
Merge pull request #257 from Sea-Haven-Industries/feat/ab/sh-207-uplift-services-nav
feat(nav): add Uplift Approvals and Services to the sidebar (SH-207, SH-304)
2026-09-25 00:50:46 +00:00
Alexandre Brandizzi
cd888d933d
Merge pull request #258 from Sea-Haven-Industries/fix/ab/sh-390-clear-completed-date
fix(workorders): clear the completed date from the board cell (SH-390)
2026-09-25 00:50:40 +00:00