Conversation
PM-4664: restore PM engagements permission warning
[codex] PM-4648: keep task editor behavior tied to challenge type
PM-4559: align first multi-prize prize input
# Conflicts: # src/apps/work/src/pages/engagements/EngagementEditorPage/components/EngagementEditorForm.spec.tsx # src/apps/work/src/pages/engagements/EngagementEditorPage/components/EngagementEditorForm.tsx
PM-4490 Add names to bulk lookup
PM-4477 Show failed submissions in appeals response tab
What was broken Challenges in the work app could still be launched when the parent project billing account was inactive, expired, or had no remaining funds. Root cause The work app only showed an expired billing-account notice and did not gate launch actions with the same billing-account lifecycle and funds checks enforced by the legacy work-manager flow. What was changed The work app now enriches project billing-account data with billing-accounts API lifecycle and remaining-funds fields, uses a shared helper to classify invalid billing-account states, blocks launch attempts before saving when the billing account is inactive, expired, or depleted, and updates the project notice text to match the detected issue. Any added/updated tests Added challenge launch gating coverage for inactive billing accounts, added shared billing-account helper tests for inactive, expired, depleted, and valid accounts, and updated the project billing-account service spec for the new enrichment behavior.
What was broken The previous PM-4680 fix hid the editable task timeline inside ChallengeEditorForm, but task identity still fell back to unresolved type metadata and the page treated every existing challenge as edit mode. QA still saw timelines in task edit mode, and task view routes could also be misclassified as edit mode. Root cause ChallengeEditorPage passed isEditMode for every existing challenge instead of only the edit route. Inside ChallengeEditorForm, the task-only UI relied on resolved challenge type metadata and could overwrite a persisted task flag before that metadata was available. What was changed ChallengeEditorPage now passes edit mode only on true edit routes. ChallengeEditorForm now derives a single task-state flag from resolved type metadata plus the persisted task marker, uses that flag to hide the editable timeline in task edit mode, keeps task-only controls aligned with the same fallback, and preserves the persisted task flag until type metadata resolves. Any added/updated tests Updated ChallengeEditorPage.spec.tsx to cover edit-versus-view mode wiring into the details form. Updated ChallengeEditorForm.spec.tsx to cover the persisted task-flag fallback when challenge type metadata is unavailable in edit mode.
What was broken The challenge submissions tab in the work app showed a View history action for each submission even though the table already lists every submission for that member in place. Root cause (if identifiable) The submissions table still exposed a history modal workflow that duplicated the information already presented in the submissions list. What was changed Removed the View history button from the submissions actions column. Removed the now-unused submission history modal wiring from the challenge submissions section. Any added/updated tests Updated the SubmissionsTable spec to verify the actions column no longer renders a submission history action and still renders the remaining download actions.
What was broken Valid manual reviewer cards could show the scorecard-required validation message during create flows even when a matching scorecard was already selected. Root cause (if identifiable) The manual reviewer scorecard validation effect could run once before the first scorecard fetch entered a loading state. That early pass treated the still-empty scorecard list as authoritative and could leave stale field validation behind valid selections. What was changed The human-review tab now starts scorecard validation in a loading state until the first scorecard fetch resolves, and it explicitly clears any stale scorecard field error once a selected scorecard is confirmed as valid. Any added/updated tests Updated HumanReviewTab.spec.tsx to surface field-level select errors in the test harness and added a regression that keeps a valid selected scorecard while clearing the stale required error after scorecards load.
What was broken Completed challenges in work manager still exposed Edit actions in the challenge list and on the read-only challenge page. The legacy flow could not save those edits, and the new flow blocked save attempts for completed challenges. Root cause The work manager UI rendered Edit actions whenever an edit route existed, without checking whether the resolved challenge status was already COMPLETED. What was changed Updated the work challenge list row to hide Edit for completed challenges by reusing the shared completed-status helper. Updated the challenge view header to suppress the read-only Edit action when the resolved challenge status is COMPLETED. Updated the ChallengeEditorPage README so the documented view-mode behavior matches the UI. Any added/updated tests Added ChallengeCard coverage for completed versus non-completed challenges. Updated ChallengeEditorPage coverage to verify the read-only Edit action is hidden for completed challenges.
What was broken In the read-only challenge view, the review section lived inside a disabled fieldset. That made the AI review tab non-interactive and hid AI review details behind the default human tab. The view also lacked the human and AI review summary shown in work manager. Root cause The disabled fieldset wrapped the entire challenge editor, including the review tab switcher. The new platform-ui review form only rendered editable tab panels and never surfaced a view-only summary. What was changed Moved the read-only review section outside the parent disabled fieldset while keeping the review panels inside their own disabled fieldset. Kept the tab switcher interactive in view mode and added a read-only review configuration summary for human reviewers, AI workflows, review flow, and estimated cost. Updated the challenge editor docs to describe the read-only review behavior. Any added/updated tests Added a ReviewersField read-only tab regression test. Added ReviewConfigurationSummary coverage for human and AI summary rendering. Ran yarn test:no-watch --runInBand; unrelated existing failures remain in src/apps/wallet-admin/src/home/tabs/payments/PaymentsListView.spec.tsx.
What was broken The Create TaaS Project form marked Role and Workload as required, but leaving either select empty did not show an inline validation message. Root cause The schema raised validation errors on the nested select object properties instead of the parent `role` and `workLoad` fields that the form components read for error text. What was changed Updated the TaaS project schema so missing Role and Workload selections fail validation on the parent field with the existing field-specific messages. Added a focused regression spec to lock the error path to `jobs[0].role` and `jobs[0].workLoad`. Any added/updated tests Added `src/apps/work/src/lib/schemas/taas-project.schema.spec.ts`.
What was broken After saving changes from the challenge edit page, the work app kept the user on the edit route instead of returning to the read-only challenge view. Root cause The editor only handled the create flow that redirects new drafts into edit mode. Existing challenge saves never resolved or navigated to the matching /view route. What was changed Manual saves now resolve the matching /view route from the current /edit pathname and navigate there after a successful update. Added a focused regression test for the edit-to-view redirect and updated the challenge editor README to document the behavior. Any added/updated tests Added a ChallengeEditorForm regression test that saves from /projects/:projectId/challenges/:challengeId/edit and asserts navigation to the corresponding /view route. Ran the focused ChallengeEditorForm spec, yarn lint, and yarn run build. CI=true yarn test:no-watch --runInBand is still blocked by pre-existing failures in src/apps/wallet-admin/src/home/tabs/payments/PaymentsListView.spec.tsx, reproduced unchanged on clean dev.
What was broken The earlier PM-4559 follow-up removed the blank delete placeholder from the first Challenge Prizes row, but QA still reported that the first textbox in multi-prize mode stopped short instead of lining up with the USD/Points selector. Root cause The multi-prize prize editor still relied on implicit stretch sizing through nested flex and grid containers. In the QA layout the challenge-prizes column and row wrappers could shrink to the removable-row content width, which left the first row visually short even after its blank delete cell was removed. What was changed Explicitly stretched the challenge-prizes column and prize-row wrappers to the full available width in the Prizes & Billing grid, kept the first-row no-delete-column behavior, and documented that multi-prize layout behavior in the challenge editor README. Any added/updated tests Updated ChallengePrizesField.spec.tsx with an interaction regression that adds a second prize and verifies the first row still does not reserve a blank delete column.
What was broken Editing a challenge with saved AI workflows could trigger repeated AI review config fetches in the work app. As the page rerendered in edit mode, the AI review section reloaded the same persisted config and spammed the network tab. Root cause (if identifiable) AiReviewTab treated the parent onConfigPersisted callback as an effect dependency. The parent recreates that callback from watched form state, so ordinary rerenders were interpreted as a signal to rerun the persisted config load and autosave effects. What was changed Stored the latest onConfigPersisted callback in a ref so load and autosave flows can still notify the parent without being retriggered by callback identity changes. Removed the callback prop from the persisted config load and autosave effect dependency arrays. Added a regression test for rerendering AiReviewTab with a new callback and updated the challenge editor README to document that ordinary parent rerenders do not refetch the same AI config. Any added/updated tests Added coverage in AiReviewTab.spec.tsx for parent callback rerenders. Ran AiReviewTab.spec.tsx and ReviewersField.spec.tsx, plus yarn lint and yarn run build.
What was broken: The previous PM-4564 fix removed the Gantt toggle from the shared work challenge schedule section, so challenge view pages lost the way to switch into the Gantt visualization. Root cause: ChallengeScheduleSection is used by both edit and view modes. Removing the toggle from that shared component fixed edit mode, but it also removed the control from read-only challenge view. The read-only form wrapper also meant the view-mode toggle had to remain outside the disabled fieldset to stay clickable. What was changed: Restored the Gantt toggle and visualization only when the schedule section is rendered in read-only challenge view mode. Moved the timeline section outside the disabled form fieldset while still passing disabled state into the schedule section so view mode stays read-only and the toggle remains clickable. Kept edit mode unchanged so the Gantt toggle still does not appear on the challenge editor. Any added/updated tests: Updated ChallengeScheduleSection.component.spec.tsx to verify editor mode hides the toggle and read-only mode can switch to the Gantt visualization. Updated ChallengeEditorForm.spec.tsx to verify the read-only schedule section stays outside the disabled fieldset while still receiving disabled props.
What was broken The manual AI workflow cards in the work app rendered headings like "Workflow1" and "Workflow2" without a space before the workflow number. Root cause The heading rendered the static label text and numeric index as adjacent JSX children, so the UI output concatenated them. What was changed Updated the AI workflow heading to render a single formatted string with a space before the workflow number. Added a focused component test that verifies the heading renders as "Workflow 1" and no longer renders "Workflow1". Any added/updated tests Updated `AiReviewTab.spec.tsx` with a manual workflow heading regression test.
What was broken The new work app manual reviewer cards no longer rendered the legacy Review Type dropdown, so the human review setup UI no longer matched work-manager. Root cause The manual reviewer card rewrite in platform-ui did not carry reviewer opportunity type through the typed reviewer model and normalization path, and HumanReviewTab stopped rendering the selector. What was changed Restored the Review Type select on manual reviewer cards with the legacy option list and a Regular Review fallback for legacy rows. Persisted reviewer type data through the work app reviewer model, default reviewer normalization, challenge form serialization, and schema typing. Updated the reviewer card layout styles and ChallengeEditorPage README to reflect the restored field. Any added/updated tests Updated HumanReviewTab.spec.tsx to cover the restored Review Type dropdown and to verify new manual reviewer cards default to REGULAR_REVIEW.
What was broken Project Manager users could not see the edit project action or open existing project edit flows in the work app, which blocked them from updating projects. Root cause The shared project-management permission helper only allowed admins, copilots, and talent managers into edit checks. Project Manager roles were excluded even when the user had manager membership on the project. What was changed Updated the shared project-management permission helper so project creation rules stay unchanged, but existing project edit checks now allow Project Manager roles when they have manager or copilot membership on the project. Updated the helper documentation to describe the split between create and edit access. Any added/updated tests Added Project Manager edit allow/deny coverage to permissions.utils.spec.ts.
What was broken Project Manager users could open the Projects page, but the New Project action was hidden and the create route redirected them back to the list. Root cause (if identifiable) The shared work-app project permission helper only treated copilots and talent managers as eligible to create projects when no project context was present. What was changed Updated the project management permission helper so Project Manager roles can create new projects while keeping existing project edit access membership-based. Added a Projects list regression test to verify the New Project action renders for Project Manager users. Any added/updated tests Updated permissions.utils.spec.ts to cover Project Manager create access and preserve membership requirements for editing. Added ProjectsListPage.spec.tsx to cover the Projects page header action.
What was broken Point-based challenges in the work app were folding point-denominated placement prizes into the dollar billing summary. That inflated the estimated challenge total and the derived challenge fee with non-USD values. Root cause The shared challenge total helper summed every prize set as if it were billable USD and reused the first-place prize for reviewer-derived dollar math even when the placement prize type was POINT. What was changed Updated the shared challenge total calculation to match legacy work-manager behavior for point-based challenges: only the USD copilot prize contributes to the dollar total, and reviewer-derived dollar totals use a zero first-place value when the placement prize type is POINT. Updated the challenge editor README to document the point-based billing summary behavior. Any added/updated tests Added a prize utility test covering point-based challenge totals and a ChallengeFeeField test proving that point placement prizes only bill against the USD copilot fee.
What was broken Opening Edit Assignment from the assignments page after a fresh load showed empty form fields the first time, even when the assignment already had saved details. Root cause The modal keeps its own local form state, but it was mounted before an assignment was selected. That state was only reset on cancel/save, so the first open kept the initial empty values instead of syncing from the selected assignment. What was changed Reset the modal state whenever the edit modal opens so it rehydrates from the current assignment before rendering. Exported the edit modal as a named symbol to support a focused regression test without changing page behavior. Any added/updated tests Added a regression spec for the assignments-page edit modal that renders it closed with no assignment, opens it with a saved assignment, and verifies the persisted values are populated on the first open. Validated with `yarn test:no-watch --runTestsByPath src/apps/work/src/pages/engagements/EngagementPaymentPage/EngagementPaymentPage.spec.tsx`, `yarn lint`, and `yarn run build`. A full `yarn test:no-watch` run still reports three pre-existing failures in `src/apps/wallet-admin/src/home/tabs/payments/PaymentsListView.spec.tsx`.
What was broken The Work app All Engagements page did not show the most recently created engagements first, which made new engagements appear lower in the list. Root cause The page explicitly overrode the engagements API default ordering with anticipated start ascending, and the same hidden client-side sort reapplied that incorrect order after local filtering. What was changed The All Engagements page now requests and applies createdAt descending as its default sort, and the local sort helper now handles createdAt explicitly so filtered results stay newest-first. Any added/updated tests Updated the EngagementsListPage fetch assertions to expect createdAt descending and added a rendering test that verifies newer engagements appear before older ones.
What was broken The manual AI workflow editor in the new work manager UI showed the "Use as gating workflow" checkbox without the helper definition that exists in the legacy work manager. That left both checked and unchecked states unclear. Root cause The platform-ui rewrite kept the checkbox control but did not carry over the explanatory helper copy from the legacy manual workflow card. What was changed Added persistent helper text under the gating checkbox in AiReviewTab so every workflow explains that submissions below the threshold are locked. When the workflow is marked as gating, the helper also adds the "Pass/fail gate." copy used by the legacy work manager. Added aria-describedby wiring and small styling updates so the helper text is associated with the checkbox and laid out cleanly. Any added/updated tests Updated AiReviewTab.spec.tsx to cover both checked and unchecked gating workflow states. Validated with yarn test:no-watch --runInBand --runTestsByPath src/apps/work/src/pages/challenges/ChallengeEditorPage/components/ReviewersField/AiReviewTab.spec.tsx, yarn lint, and yarn run build. yarn test:no-watch --runInBand still fails on pre-existing wallet-admin tests in src/apps/wallet-admin/src/home/tabs/payments/PaymentsListView.spec.tsx, and the same failures reproduce on an untouched dev worktree.
What was broken: Copilot users could still land on an unscoped challenges request on the dashboard and see the platform-wide challenge list instead of only their member-scoped challenges. Root cause: The earlier PM-4538 fixes restored `memberId` forwarding, but the page still let the dashboard fire before the logged-in member id was available. That first request went out without member scope. What was changed: Added an `enabled` flag to `useFetchChallenges` and updated `ChallengesListPage` to wait for the logged-in member id before issuing a non-privileged dashboard fetch. The page now keeps the loading state until member scope is ready instead of sending a global request. Any added/updated tests: Added a hook regression test for the disabled-fetch path and a page regression test that verifies dashboard challenge loading waits for member scope.
PM-4813: show all assigned reviewers in view mode
What was broken Mark Complete only appeared after opening the edit route for active task challenges in the new work app, so the read-only challenge view did not match the legacy work-manager behavior. Root cause ChallengeEditorPage passed the edit-mode flag into shouldShowCompleteTaskAction, and that helper required the flag to be true before it would render the action. What was changed The complete-task visibility check now keys off whether the challenge already exists, which keeps the action available on the details tab for both view and edit routes. The page now passes isExistingChallenge into the helper, and the challenge editor README documents the view-route availability. Any added/updated tests Added a read-only view regression test for active task challenges in ChallengeEditorPage.spec.tsx. Extended ChallengeEditorPage.utils.spec.ts to cover the non-existing-challenge case for the complete-task helper.
What was broken The earlier PM-4813 fix corrected one view-mode summary case for repeated reviewer rows, but design challenge drafts still lost reviewer data after save and refresh. Approval reviewers could render as raw user ids or disappear, edit mode reopened with blank assigned members, and persisted copilot assignments could drop out as well. Root cause (if identifiable) The reviewer summary, reviewer form hydration, and copilot field were all reconstructing persisted assignments differently. Legacy design drafts can store approval rows under the generic Reviewer role, reviewer resources can come back with only handles, and copilot assignments can come back as user ids. Those payload shapes were not normalized consistently, so the UI either showed ids directly or failed to rehydrate the saved assignments. What was changed Added a shared reviewer-assignment allocator so the summary view, challenge form hydration, and manual reviewer tab all consume persisted reviewer resources the same way. Added compatibility fallback from phase-specific reviewer roles to the generic Reviewer role, and resolved handle-only reviewer resources plus userId-only reviewer and copilot assignments back to handles. Backfilled reviewer member ids, handles, and role ids into edit-mode form state without dirtying the draft so saved reviewer rows reopen with the same assignments. Updated the Challenge Editor reviewer documentation to describe the compatibility behavior. Any added/updated tests Updated ChallengeEditorForm.spec.tsx to cover launching a read-only draft when approval assignments are stored under the generic Reviewer role. Updated HumanReviewTab.spec.tsx to cover hydrating approval reviewers from handle-only generic reviewer resources. Updated ReviewConfigurationSummary.spec.tsx to cover approval fallback plus resolved handle rendering. Added CopilotField.spec.tsx to cover project-member and profile-lookup normalization from persisted user ids back to copilot handles.
PM-4838: show Mark Complete on task challenge view pages
PM-4813: restore reviewer assignments after draft save
What was broken Design challenge review rows could lose assigned members in view mode when persisted resources mixed phase-specific reviewer roles with legacy generic Reviewer assignments. Once a specific pool such as Approver was exhausted, later rows stopped showing members even though fallback reviewer resources still existed. Root cause (if identifiable) The shared reviewer assignment allocator stopped at the first matching role group. If that group had already consumed its available resources, or could only partially fill the row, it returned before continuing into later fallback groups. What was changed Updated the shared reviewer assignment allocator to keep filling each reviewer row from later fallback role groups after a phase-specific pool runs out, while preserving sequential consumption across rows. Added a focused allocator regression test and a read-only summary regression covering mixed Approver and Reviewer resources. Updated the challenge editor README and allocator documentation to describe the fallback allocation behavior. Any added/updated tests Added reviewerAssignments.utils.spec.ts. Updated ReviewConfigurationSummary.spec.tsx.
PM-4813: preserve reviewer fallback assignments in view mode
What was broken Refreshing a saved design challenge could blank out the selected copilot and the assigned manual reviewers even though those resources were already persisted. Reviewer rows reopened without their assignments, which also left scorecard validation errors visible despite the saved scorecard still being selected. Root cause (if identifiable) The refresh hydration path only restored copilot resources by member handle and only rebuilt reviewer assignments from persisted member ids. Persisted resources that only exposed a copilot member id or only exposed reviewer member handles were treated as unassigned when the form reset from fetched challenge data. What was changed - added a copilot hydration fallback that restores the saved value from member-id-only copilot resources - resolved handle-only reviewer resources back to user ids before the challenge form resets or resyncs from persisted resources - reused the same reviewer hydration logic for the initial refresh reset and the later resource-sync effect - updated the challenge editor README to document the persisted assignment behavior Any added/updated tests - added a ChallengeEditorForm spec covering member-id-only copilot resources during refresh hydration - added a ChallengeEditorForm spec covering handle-only reviewer resources during refresh hydration
Talent search UI : Clear button clears skills, css updates
…spec.tsx Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
PM-4788 Add Topgear payment type in wallet-admin
Fix handle all caps
PM-4840: restore persisted copilot and reviewer assignments on refresh
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR bundles the “Prod - April release” updates across multiple apps, introducing the new Work app, improving review/engagement flows, and adding several UI/UX enhancements plus supporting utilities and tests.
Changes:
- Add the new Work app (routing, layout/nav, UI components, config) and wire it into platform routing.
- Improve Review and Engagements behavior (legacy-safe matching/resolution, additional guards, sanitized rich-text rendering) with expanded unit test coverage.
- Enhance Admin/Wallet/Profiles/Accounts UX and functionality (email activity dialog, responsive tables/filter bars, trait action selection guard, payment type adjustments).
Reviewed changes
Copilot reviewed 229 out of 740 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/apps/work/src/lib/components/PaymentFormModal/PaymentFormModal.module.scss | Adds Work payment form modal styling. |
| src/apps/work/src/lib/components/Pagination/index.ts | Exposes Work Pagination component barrel export. |
| src/apps/work/src/lib/components/Pagination/Pagination.tsx | Adds Work pagination wrapper over Admin pagination. |
| src/apps/work/src/lib/components/Pagination/Pagination.spec.tsx | Adds unit tests for Work Pagination behavior. |
| src/apps/work/src/lib/components/Pagination/Pagination.module.scss | Adds Work pagination styling. |
| src/apps/work/src/lib/components/NavTabs/index.ts | Exposes Work NavTabs barrel export. |
| src/apps/work/src/lib/components/NavTabs/config/tabs-config.ts | Defines role-based Work tab configuration logic. |
| src/apps/work/src/lib/components/NavTabs/config/tabs-config.spec.ts | Adds tests for Work tabs visibility rules. |
| src/apps/work/src/lib/components/NavTabs/config/index.ts | Barrel export for NavTabs config. |
| src/apps/work/src/lib/components/NavTabs/NavTabs.tsx | Implements Work tabs navigation component. |
| src/apps/work/src/lib/components/NavTabs/NavTabs.module.scss | Adds responsive styling for Work tabs. |
| src/apps/work/src/lib/components/LoadingSpinner/index.ts | Exposes Work LoadingSpinner barrel export. |
| src/apps/work/src/lib/components/LoadingSpinner/LoadingSpinner.tsx | Adds Work wrapper around UI LoadingSpinner. |
| src/apps/work/src/lib/components/LoadingSpinner/LoadingSpinner.module.scss | Adds Work loading spinner sizing styles. |
| src/apps/work/src/lib/components/Layout/index.ts | Exports Work Layout and related components. |
| src/apps/work/src/lib/components/Layout/Layout.tsx | Adds Work layout wrapper with conditional NavTabs. |
| src/apps/work/src/lib/components/Layout/Layout.module.scss | Adds Work layout styling and layout slots. |
| src/apps/work/src/lib/components/InviteUserModal/index.ts | Exposes invite modal barrel export for Work. |
| src/apps/work/src/lib/components/InviteUserModal/InviteUserModal.module.scss | Adds invite modal styles for Work. |
| src/apps/work/src/lib/components/GroupSuccessModal/index.ts | Exposes group success modal barrel export. |
| src/apps/work/src/lib/components/GroupSuccessModal/GroupSuccessModal.tsx | Adds group creation success modal UI. |
| src/apps/work/src/lib/components/GroupSuccessModal/GroupSuccessModal.module.scss | Styles group success modal. |
| src/apps/work/src/lib/components/ErrorMessage/index.ts | Exposes Work error message component. |
| src/apps/work/src/lib/components/ErrorMessage/ErrorMessage.tsx | Adds error banner with optional retry. |
| src/apps/work/src/lib/components/ErrorMessage/ErrorMessage.module.scss | Styles the Work error banner. |
| src/apps/work/src/lib/components/EngagementsFilter/index.ts | Exposes engagements filter component. |
| src/apps/work/src/lib/components/EngagementsFilter/EngagementsFilter.module.scss | Adds Work engagements filter styling. |
| src/apps/work/src/lib/components/EngagementCard/index.ts | Exposes Work engagement card barrel export. |
| src/apps/work/src/lib/components/EngagementCard/EngagementCard.tsx | Adds engagement summary card with links/actions. |
| src/apps/work/src/lib/components/EngagementCard/EngagementCard.module.scss | Styles the Work engagement card. |
| src/apps/work/src/lib/components/ConfirmationModal/index.ts | Exposes Work confirmation modal barrel export. |
| src/apps/work/src/lib/components/ConfirmationModal/ConfirmationModal.tsx | Adds generic confirmation modal UI. |
| src/apps/work/src/lib/components/ConfirmationModal/ConfirmationModal.module.scss | Styles confirmation modal. |
| src/apps/work/src/lib/components/CompleteAssignmentModal/index.ts | Exposes complete-assignment modal export. |
| src/apps/work/src/lib/components/CompleteAssignmentModal/CompleteAssignmentModal.tsx | Adds modal to mark assignment completed. |
| src/apps/work/src/lib/components/CompleteAssignmentModal/CompleteAssignmentModal.module.scss | Styles complete assignment modal. |
| src/apps/work/src/lib/components/ChallengesTable/index.ts | Exposes Work challenges table export. |
| src/apps/work/src/lib/components/ChallengesTable/ChallengesTable.module.scss | Adds Work challenges table styling. |
| src/apps/work/src/lib/components/ChallengesFilter/index.ts | Exposes Work challenges filter export. |
| src/apps/work/src/lib/components/ChallengesFilter/ChallengesFilter.spec.tsx | Adds tests for challenges filter reset button. |
| src/apps/work/src/lib/components/ChallengesFilter/ChallengesFilter.module.scss | Adds responsive grid styling for filter UI. |
| src/apps/work/src/lib/components/ChallengeTag/index.ts | Exposes challenge tag component export. |
| src/apps/work/src/lib/components/ChallengeTag/ChallengeTag.tsx | Adds logic for challenge type tag abbreviation. |
| src/apps/work/src/lib/components/ChallengeTag/ChallengeTag.module.scss | Styles challenge type tags. |
| src/apps/work/src/lib/components/ChallengeStatus/index.ts | Exposes challenge status component export. |
| src/apps/work/src/lib/components/ChallengeStatus/ChallengeStatus.tsx | Adds status pill rendering with status map. |
| src/apps/work/src/lib/components/ChallengeStatus/ChallengeStatus.module.scss | Styles status pill colors. |
| src/apps/work/src/lib/components/ChallengeCard/index.ts | Exposes Work challenge row/card export. |
| src/apps/work/src/lib/components/ChallengeCard/ChallengeCard.spec.tsx | Adds tests for editing links visibility by status. |
| src/apps/work/src/lib/components/ChallengeCard/ChallengeCard.module.scss | Styles Work challenge table row actions. |
| src/apps/work/src/lib/components/ArtifactsModal/index.ts | Exposes artifacts modal barrel export. |
| src/apps/work/src/lib/components/ArtifactsModal/ArtifactsModal.tsx | Adds submission artifacts modal with downloads. |
| src/apps/work/src/lib/components/ArtifactsModal/ArtifactsModal.module.scss | Styles artifacts modal and table. |
| src/apps/work/src/lib/components/ApplicationDetailModal/index.ts | Exposes application detail modal export. |
| src/apps/work/src/lib/components/ApplicationDetailModal/ApplicationDetailModal.spec.tsx | Adds tests for application detail fields rendering. |
| src/apps/work/src/lib/components/ApplicationDetailModal/ApplicationDetailModal.module.scss | Styles application detail modal layout. |
| src/apps/work/src/lib/components/AddUserModal/index.ts | Exposes add-user modal export. |
| src/apps/work/src/lib/components/AddUserModal/AddUserModal.module.scss | Styles add-user modal. |
| src/apps/work/src/lib/components/AcceptApplicationModal/index.ts | Exports accept application modal + form type. |
| src/apps/work/src/lib/components/AcceptApplicationModal/AcceptApplicationModal.module.scss | Styles accept application modal. |
| src/apps/work/src/index.ts | Exposes Work routes and root route for platform routing. |
| src/apps/work/src/config/routes.config.ts | Adds Work route IDs and subdomain-root resolver. |
| src/apps/work/src/config/index.config.ts | Adds Work constants (roles, paging, per-page options). |
| src/apps/work/src/config/access.config.ts | Adds explicit Work access role list. |
| src/apps/work/src/config/access.config.spec.ts | Adds tests for Work access role allowlist. |
| src/apps/work/src/WorkApp.tsx | Adds Work app composition with providers/layout. |
| src/apps/work/index.ts | Exposes Work app package entry exports. |
| src/apps/work/README.md | Documents Work app structure and routing/providers. |
| src/apps/wallet/src/lib/components/points-table/PointsTable.module.scss | Improves wallet points table horizontal scrolling. |
| src/apps/wallet/src/lib/components/payments-table/PaymentTable.module.scss | Improves wallet payment table horizontal scrolling. |
| src/apps/wallet/src/lib/components/info-row/InfoRow.module.scss | Improves responsive wallet info row layout. |
| src/apps/wallet/src/lib/components/filter-bar/FilterBar.module.scss | Improves responsive wallet filter bar layout. |
| src/apps/wallet/src/home/tabs/home/Home.module.scss | Improves wallet home responsiveness. |
| src/apps/wallet/src/home/tabs/WalletTabs.module.scss | Ensures wallet tabs container uses full width. |
| src/apps/wallet-admin/src/lib/models/WinningDetail.ts | Extends winning/payment metadata model for new fields. |
| src/apps/wallet-admin/src/lib/components/payments-table/PaymentTable.module.scss | Improves wallet-admin table scrolling. |
| src/apps/wallet-admin/src/lib/components/payment-view/PaymentView.module.scss | Adds sectioning and remarks styling in payment view. |
| src/apps/wallet-admin/src/lib/components/info-row/InfoRow.module.scss | Improves wallet-admin responsive info row layout. |
| src/apps/wallet-admin/src/lib/components/filter-bar/FilterBar.tsx | Adds selection-scoped actions prop for bulk flows. |
| src/apps/wallet-admin/src/lib/components/filter-bar/FilterBar.module.scss | Improves responsive layout & fixes minor CSS issue. |
| src/apps/wallet-admin/src/home/tabs/home/Home.module.scss | Improves wallet-admin home responsiveness. |
| src/apps/wallet-admin/src/home/tabs/WalletAdminTabs.module.scss | Ensures wallet-admin tabs container uses full width. |
| src/apps/talent-search/src/routes/search-results-page/letsTalkUrl.ts | Adds helper to derive lets-talk URL from env. |
| src/apps/talent-search/src/routes/search-results-page/letsTalkUrl.spec.ts | Tests lets-talk URL helper. |
| src/apps/talent-search/src/routes/search-results-page/SearchResultsPage.tsx | Adds minimum skill guard messaging & dynamic lets-talk link. |
| src/apps/talent-search/src/routes/search-page/SearchPage.tsx | Blocks navigation when too few skills are selected. |
| src/apps/talent-search/src/lib/services/use-fetch-talent-matches.ts | Adds minimum search guard and improved loading semantics. |
| src/apps/talent-search/src/lib/services/use-fetch-talent-matches.spec.ts | Tests for new search guard/loading logic. |
| src/apps/talent-search/src/config/constants.ts | Adds SKILL_SEARCH_MINIMUM constant. |
| src/apps/talent-search/src/components/search-input/SearchInput.tsx | Enforces min skills and updates submit/click behavior. |
| src/apps/review/src/pages/reviews/components/ReviewViewer/ReviewViewer.tsx | Adjusts edit scorecard permission logic. |
| src/apps/review/src/lib/utils/winnerMatching.ts | Adds robust winner/submission matching helper. |
| src/apps/review/src/lib/utils/submitterReviewResolution.ts | Adds submitter review row building with legacy fallbacks. |
| src/apps/review/src/lib/utils/submitterReviewResolution.spec.ts | Tests submitter review resolution behavior. |
| src/apps/review/src/lib/utils/submissionResolution.ts | Improves submission lookup/matching and identifier normalization. |
| src/apps/review/src/lib/utils/submissionResolution.spec.ts | Tests legacy ID resolution and matching behavior. |
| src/apps/review/src/lib/utils/screeningAssignments.ts | Adds helpers for viewer screening assignment detection. |
| src/apps/review/src/lib/utils/screeningAssignments.spec.ts | Tests screening assignment helper functions. |
| src/apps/review/src/lib/utils/reviewSelection.spec.ts | Adds tests for review selection across legacy identifiers. |
| src/apps/review/src/lib/utils/reviewScoring.ts | Adds role-based threshold access helper. |
| src/apps/review/src/lib/utils/reviewScoring.spec.ts | Tests role-based threshold access helper. |
| src/apps/review/src/lib/utils/reviewPhaseGuards.ts | Improves phase key normalization and legacy review tab isolation. |
| src/apps/review/src/lib/utils/reviewPhaseGuards.spec.ts | Tests specification vs standard review tab matching. |
| src/apps/review/src/lib/utils/reviewFetchPolicy.ts | Adds policy to force review fetching for legacy/past challenges. |
| src/apps/review/src/lib/utils/reviewFetchPolicy.spec.ts | Tests review fetch policy. |
| src/apps/review/src/lib/utils/metadataMatching.ts | Allows specification review phases for review matching. |
| src/apps/review/src/lib/utils/metadataMatching.spec.ts | Tests specification review phase allowance. |
| src/apps/review/src/lib/utils/challengeResultSubmissions.spec.ts | Tests winner submission backfill/dedup behavior. |
| src/apps/review/src/lib/utils/approvalReviewRows.ts | Adds approval tab rows builder across sources. |
| src/apps/review/src/lib/services/scorecards.service.ts | Adds fetchScorecards service with normalization. |
| src/apps/review/src/lib/models/SubmissionInfo.model.ts | Extends SubmissionInfo with legacy id/placement/handle. |
| src/apps/review/src/lib/models/Screening.model.ts | Adds screeningReviews detail structure. |
| src/apps/review/src/lib/models/BackendChallengeInfo.model.ts | Uses contest-type normalizer for winners mapping. |
| src/apps/review/src/lib/models/BackendChallengeInfo.model.spec.ts | Tests contest winner filtering for legacy type strings. |
| src/apps/review/src/lib/hooks/useFetchSubmissionReviews.utils.ts | Adds helper to update appeal response and recompute score. |
| src/apps/review/src/lib/hooks/useFetchSubmissionReviews.utils.spec.ts | Tests appeal response score update helper. |
| src/apps/review/src/lib/hooks/useFetchSubmissionReviews.ts | Refactors appeal response updating and review payload logic. |
| src/apps/review/src/lib/hooks/useFetchScorecards.ts | Switches SWR to shared fetchScorecards service. |
| src/apps/review/src/lib/hooks/useFetchChallengeResults.spec.ts | Tests winner matching fallbacks. |
| src/apps/review/src/lib/constants.ts | Adds normalized submission-type helpers. |
| src/apps/review/src/lib/components/TableIterativeReview/TableIterativeReview.module.scss | Adds layout classes for iterative review action cells. |
| src/apps/review/src/lib/components/TableCheckpointSubmissions/TableCheckpointSubmissions.tsx | Uses new screening assignment helpers for action rendering. |
| src/apps/review/src/lib/components/Scorecard/ScorecardViewer/ScorecardViewer.tsx | Fixes score selection and effect dependencies. |
| src/apps/review/src/lib/components/PageWrapper/PageWrapper.tsx | Adds optional title action and conditional breadcrumb rendering. |
| src/apps/review/src/lib/components/PageWrapper/PageWrapper.module.scss | Styles title action container. |
| src/apps/review/src/lib/components/FieldMarkdownEditor/FieldMarkdownEditor.tsx | Adds option to hide error message rendering. |
| src/apps/review/src/lib/components/ChallengeDetailsContent/TabContentScreening.tsx | Allows AI screening phase selection. |
| src/apps/review/src/lib/components/ChallengeDetailsContent/TabContentReview.tsx | Improves phase-specific review filtering and submitter appeals data. |
| src/apps/review/src/lib/components/ChallengeDetailsContent/ChallengeDetailsContent.tsx | Expands supported tab keys and phase filtering behavior. |
| src/apps/reports/src/pages/bulk-member-lookup/BulkMemberLookupPage.tsx | Adds first/last name and contact number columns. |
| src/apps/profiles/src/hooks/useFetchActiveTracks.spec.tsx | Fixes typing import and mocks core hook for tests. |
| src/apps/profiles/src/components/tc-achievements/StatsSummaryBlock/StatsSummaryBlock.tsx | Hides volatility for unsupported tracks reliably. |
| src/apps/profiles/src/components/tc-achievements/StatsSummaryBlock/StatsSummaryBlock.spec.tsx | Adds tests for volatility hiding/visibility. |
| src/apps/platform/src/platform.routes.tsx | Wires Work routes into platform route list. |
| src/apps/engagements/src/pages/engagement-list/EngagementListPage.tsx | Adds includePrivate gating and request param wiring. |
| src/apps/engagements/src/pages/engagement-list/EngagementListPage.spec.tsx | Tests includePrivate behavior by role. |
| src/apps/engagements/src/pages/engagement-detail/EngagementDetailPage.tsx | Sanitizes markdown source and enables raw HTML rendering. |
| src/apps/engagements/src/lib/services/engagements.service.ts | Adds includePrivate param to engagements request. |
| src/apps/engagements/src/components/member-experience-list/MemberExperienceList.tsx | Sorts member experiences newest-first. |
| src/apps/engagements/src/components/member-experience-list/MemberExperienceList.spec.tsx | Tests newest-first sorting behavior. |
| src/apps/engagements/src/components/feedback-form/FeedbackForm.tsx | Clarifies rating label text. |
| src/apps/engagements/src/components/engagement-card/EngagementCard.tsx | Sanitizes markdown source and enables raw HTML rendering. |
| src/apps/engagements/src/components/assignment-card/AssignmentCard.tsx | Sanitizes markdown, improves snippet generation, and refactors contact handling. |
| src/apps/engagements/src/components/assignment-card/AssignmentCard.spec.tsx | Adds rehype-raw mock for updated markdown pipeline. |
| src/apps/customer-portal/src/pages/talent-search/components/TalentResultCard/index.ts | Adds barrel export for TalentResultCard. |
| src/apps/customer-portal/src/pages/profile-completion/ProfileCompletionPage/ProfileCompletionPage.tsx | Uses shared skill autocomplete and adds tooltip for remaining skills. |
| src/apps/customer-portal/src/lib/services/talentSearch.service.ts | Adds member search service for customer portal. |
| src/apps/customer-portal/src/lib/services/index.ts | Barrel exports customer-portal services. |
| src/apps/customer-portal/src/lib/index.ts | Exposes services via customer-portal lib entry. |
| src/apps/copilots/src/services/projects.ts | Normalizes project id values to string across fetch paths. |
| src/apps/copilots/src/services/members.ts | Allows member lookup by numeric or string user ids. |
| src/apps/copilots/src/services/copilot-requests.ts | Fixes startDate precedence when mapping response data. |
| src/apps/copilots/src/pages/copilot-opportunity-details/tabs/copilot-applications/CopilotApplications.tsx | Improves member/user id matching and handle fallback. |
| src/apps/copilots/src/pages/copilot-opportunity-details/tabs/copilot-applications/CopilotApplicationAction.tsx | Validates application id before assigning. |
| src/apps/copilots/src/pages/copilot-opportunity-details/index.tsx | Uses normalized id comparison and correct selected application. |
| src/apps/copilots/src/models/CopilotApplication.ts | Widens application id/user id types for mixed payloads. |
| src/apps/admin/src/payments/payment-types.ts | Adds shared payment winning type and options. |
| src/apps/admin/src/payments/payment-types.spec.ts | Tests payment type options list. |
| src/apps/admin/src/payments/PaymentsPage.tsx | Updates payment type union to PAYMENT/POINTS. |
| src/apps/admin/src/lib/utils/access.ts | Switches UserRole import to enum module path. |
| src/apps/admin/src/lib/services/user.service.ts | Adds SendGrid email activity fetch + normalization. |
| src/apps/admin/src/lib/services/submissions.service.ts | Adds manual submission upload via multipart form. |
| src/apps/admin/src/lib/services/payments.service.ts | Reuses shared payment type/options and updates type union. |
| src/apps/admin/src/lib/services/challenge-management.service.ts | Adds helper to load/normalize submitter resources for a challenge. |
| src/apps/admin/src/lib/models/index.ts | Exports new MemberSendgridEmail model. |
| src/apps/admin/src/lib/models/MemberSendgridEmail.model.ts | Defines normalized SendGrid email activity model. |
| src/apps/admin/src/lib/hooks/useManageChallengeSubmissions.ts | Refactors fetch flow and adds explicit refresh API. |
| src/apps/admin/src/lib/components/common/FieldHtmlEditor/FieldHtmlEditor.tsx | Restricts TinyMCE plugins list. |
| src/apps/admin/src/lib/components/UsersTable/UsersTable.tsx | Adds “View Emails” action and dialog integration. |
| src/apps/admin/src/lib/components/UsersTable/UsersTable.module.scss | Expands action column width to fit new button. |
| src/apps/admin/src/lib/components/DialogUserEmails/index.ts | Adds barrel exports for DialogUserEmails. |
| src/apps/admin/src/lib/components/DialogUserEmails/DialogUserEmails.module.scss | Styles user email activity dialog and table. |
| src/apps/admin/src/lib/components/ChallengeList/reviewUiLink.ts | Adds helpers for review UI link building/enabling. |
| src/apps/admin/src/lib/components/ChallengeList/ChallengeList.tsx | Fixes Review UI link and gate logic; refines enablement checks. |
| src/apps/admin/src/lib/components/ChallengeList/ChallengeList.spec.ts | Tests review UI helper utilities. |
| src/apps/admin/src/challenge-management/ManageSubmissionPage/ManageSubmissionPage.module.scss | Adds styles for manual upload section in admin submissions. |
| src/apps/admin/src/challenge-management/ChallengeDetailsPage/ChallengeDetailsPage.tsx | Refactors submitter loading to use new service helper. |
| src/apps/accounts/src/settings/tabs/tools/trait-action.utils.ts | Adds helper to pick create vs update trait action. |
| src/apps/accounts/src/settings/tabs/tools/trait-action.utils.spec.ts | Tests trait action selection helper. |
| src/apps/accounts/src/settings/tabs/tools/subscriptions/Subscriptions.tsx | Uses helper to avoid duplicate trait create calls. |
| src/apps/accounts/src/settings/tabs/tools/software/Software.tsx | Uses helper to avoid duplicate trait create calls. |
| src/apps/accounts/src/settings/tabs/tools/service-provider/ServiceProvider.tsx | Uses helper to avoid duplicate trait create calls. |
| src/apps/accounts/src/settings/tabs/tools/devices/Devices.tsx | Uses helper to avoid duplicate trait create calls. |
| package.json | Adds CodeMirror-related dependencies and fflate. |
| .env.production | Adds Work app API env vars for production. |
| .env.development | Adds Work app API env vars for development. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| setActiveTab(tabId) | ||
| setIsOpen(false) | ||
| navigate(tabId) |
There was a problem hiding this comment.
In React Router v6, navigate('challenges') is relative by default, so clicking a tab from a nested route can incorrectly navigate to a nested path (e.g., /projects/123/challenges). Since tab ids represent top-level route segments, navigate should use an absolute target (e.g., navigate(/${tabId})) or incorporate the Work app root prefix so tab switching is stable from any current location.
| navigate(tabId) | |
| navigate(`/${tabId}`) |
| <li | ||
| key={tab.id} | ||
| className={isActive ? `${styles.active}` : ''} | ||
| data-tab-id={tab.id} | ||
| data-tab-url={tab.url || undefined} | ||
| onClick={handleTabClick} | ||
| > |
There was a problem hiding this comment.
Clickable <li> elements are not keyboard-accessible by default (no focus, no Enter/Space handling) and do not convey button/tab semantics to assistive tech. Use a semantic interactive element (e.g., <button> inside the <li>) or add appropriate roles (role='tab'), tabIndex, and onKeyDown handlers so tabs can be operated via keyboard.
| {PAGINATION_PER_PAGE_OPTIONS.map(option => ( | ||
| <option key={option} value={option}>{option}</option> | ||
| ))} |
There was a problem hiding this comment.
PAGINATION_PER_PAGE_OPTIONS is treated as an array of numbers/strings here, but in this PR PAGINATION_PER_PAGE_OPTIONS is defined elsewhere as an array of { label, value } objects. If the runtime value is object-based, this will render [object Object] and Number(event.target.value) will not behave as intended. Align the options contract by either mapping option.value/option.label here (and updating the prop types/tests) or switching the constant to a primitive array.
| { | ||
| headers: { | ||
| 'Content-Type': 'multipart/form-data', | ||
| }, | ||
| }, |
There was a problem hiding this comment.
When sending FormData, manually setting Content-Type: multipart/form-data commonly breaks uploads because the required boundary parameter is not added. Most HTTP clients/browsers will set the correct header automatically. Remove the explicit Content-Type header and let xhrPostAsync/the underlying client set it.
| { | |
| headers: { | |
| 'Content-Type': 'multipart/form-data', | |
| }, | |
| }, |
| <Markdown | ||
| rehypePlugins={[rehypeRaw as any]} | ||
| remarkPlugins={[ | ||
| remarkFrontmatter, | ||
| [remarkGfm, { singleTilde: false }], | ||
| remarkBreaks, | ||
| ]} | ||
| > | ||
| {engagement.description} | ||
| {sanitizeRichTextSource(engagement.description)} |
There was a problem hiding this comment.
Using rehypeRaw enables rendering raw HTML inside markdown. This is only safe if sanitizeRichTextSource fully sanitizes all dangerous HTML/attributes/URLs expected by rehypeRaw. To harden this, prefer adding a rehype-sanitize step with an explicit schema (or ensure sanitizeRichTextSource implements equivalent strict sanitization) so any sanitizer regression doesn’t become an XSS in the UI.
| @@ -1,4 +1,4 @@ | |||
| import { UserRole } from '~/libs/core' | |||
| import { UserRole } from '~/libs/core/lib/profile/profile-functions/profile-factory/user-role.enum' | |||
There was a problem hiding this comment.
This deep import couples admin to an internal ~/libs/core file path, which is brittle and can break with refactors/re-exports. Prefer importing UserRole from a stable public export surface (e.g., ~/libs/core) by adding/reusing an export there, so consumers don’t depend on internal directory structure.
| import { UserRole } from '~/libs/core/lib/profile/profile-functions/profile-factory/user-role.enum' | |
| import { UserRole } from '~/libs/core' |
| const remainingPageRequests = Array.from( | ||
| { length: Math.max(firstPageResponse.totalPages - 1, 0) }, | ||
| (_ignoredValue, index) => getChallengeResources(challengeId, { | ||
| page: index + 2, | ||
| perPage, | ||
| roleId, | ||
| }), | ||
| ) | ||
| const remainingPageResponses = await Promise.all( | ||
| remainingPageRequests, | ||
| ) | ||
|
|
||
| return [ | ||
| ...firstPageResponse.data, | ||
| ...remainingPageResponses.flatMap(response => response.data), | ||
| ] |
There was a problem hiding this comment.
This issues Promise.all requests for every remaining page per role, which can generate a large burst of concurrent calls for challenges with many resources/pages. Consider adding a simple concurrency limit or sequential paging per role to reduce load on the API and avoid client-side throttling/timeouts.
| const remainingPageRequests = Array.from( | |
| { length: Math.max(firstPageResponse.totalPages - 1, 0) }, | |
| (_ignoredValue, index) => getChallengeResources(challengeId, { | |
| page: index + 2, | |
| perPage, | |
| roleId, | |
| }), | |
| ) | |
| const remainingPageResponses = await Promise.all( | |
| remainingPageRequests, | |
| ) | |
| return [ | |
| ...firstPageResponse.data, | |
| ...remainingPageResponses.flatMap(response => response.data), | |
| ] | |
| const resources = [...firstPageResponse.data] | |
| for (let page = 2; page <= firstPageResponse.totalPages; page += 1) { | |
| const pageResponse = await getChallengeResources(challengeId, { | |
| page, | |
| perPage, | |
| roleId, | |
| }) | |
| resources.push(...pageResponse.data) | |
| } | |
| return resources |
| margin: $sp-6 auto !important; | ||
| } | ||
|
|
||
| .contantentLayoutInner { |
There was a problem hiding this comment.
The class name contantentLayoutInner appears to be a typo and will be easy to propagate across the codebase. Rename it to contentLayoutInner (and update the corresponding styles.* usage) to keep naming consistent and reduce confusion.
| .contantentLayoutInner { | |
| .contentLayoutInner { |
https://topcoder.atlassian.net/browse/PM-3933
https://topcoder.atlassian.net/browse/PM-4622