Skip to content

Conversation

@jsandoval81
Copy link
Collaborator

@jsandoval81 jsandoval81 commented Nov 6, 2025

Requirements List

  • None

Description List

  • Added Investigation model
  • Updated License & Licensee models with related investigation props & methods
    • Also updated encumber modal with minor layout update from latest designs
  • Updated network & store layers for API calls to add / update investigations
  • Updated LicenseeDetail page with banner to indicate a current investigation
  • Updated the LicenseCard & PrivilegeCard components to support adding & ending investigations
    • This includes chaining the encumber workflow if selected by the user

Testing List

  • yarn test:unit:all should run without errors or warnings
  • yarn serve should run without errors or warnings
  • yarn build should run without errors or warnings
  • Code review
  • Testing
    • Login as a staff with state admin permissions
    • Locate a licensee with licenses / privileges in your admin state
    • Use the 3-dot menu of the license / privilege to Add investigation
      • Workflow should match the figma designs
      • The card Discipline status should now be Investigation
      • There should be a banner at the top denoting the user is under investigation, matching the figma designs
    • Use the 3-dot menu of the license / privilege to End investigation
      • First, choose the no encumbrance option
      • Ensure the workflow completes and the licensee is no longer shown as under investigation
    • Use the 3-dot menu to Add investigation
    • Use the 3-dot menu to End investigation
      • This time, choose the encumber option and complete the encumber workflow
      • Ensure the workflow completes and the licensee is no longer shown as under investigation, but the license / privilege is now shown as encumbered
    • Additionally play with different scenarios for:
      • Starting an investigation
      • Ending an investigation with an encumbrance
      • Ending an investigation without an encumbrance

Closes #1132

Summary by CodeRabbit

  • New Features

    • Investigation workflows for licenses and privileges: start/end actions, multi-step modals, per‑investigation selection, encumbrance options, and visible "under investigation" status with a licensee alert.
  • Style

    • Responsive two‑column/static layout for detail blocks, wider action menus, section dividers, and new yellow alert color palette.
  • Accessibility

    • Improved modal keyboard focus handling and ARIA live region messaging.
  • Localization

    • Added English and Spanish translations for investigation flows and alerts.
  • Tests

    • New unit tests for Investigation model, license/licensee logic, and store actions.
  • Chores

    • API/mocks and sample data updated to support investigation create/update and WY mock data.

jusdino and others added 8 commits October 25, 2025 20:46
- Initial data layer updates
- @todo: UI updates
- @todo: Work with design on minor figma updates
- @todo: Test once backend is ready
- Staff licensee detail page banner
- @todo: Admin workflows
- @todo: Work with design on minor figma updates
- @todo: Test once backend is ready
- Initial base UI flow for privileges
- @todo: Tie together with encumbrance flow
- @todo: Apply to license UI
- @todo: Work with design on minor figma updates
- @todo: Test once backend is ready
- Start tying together with encumbrance flow
- Start applying to license UI
- @todo: Work with design on minor figma updates
- @todo: Test once backend is ready
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 6, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds investigation support across models, UI, network, store, mocks, locales and styles: new Investigation model/serializer and tests; License/Privilege/Licensee wiring and helpers; UI flows/modals to start/end investigations with focus handling; new API endpoints and mock implementations; Vuex actions/mutations and alert UI.

Changes

Cohort / File(s) Summary
Investigation model & tests
webroot/src/models/Investigation/Investigation.model.ts, webroot/src/models/Investigation/Investigation.model.spec.ts
New Investigation interface/class, serializer (fromServer), date helpers (start/update/end display, isActive, hasEndDate) and unit tests.
License model & tests
webroot/src/models/License/License.model.ts, webroot/src/models/License/License.model.spec.ts
Add investigations: Investigation[], deserialize via InvestigationSerializer, add isUnderInvestigation() helper; tests updated.
Licensee model & tests
webroot/src/models/Licensee/Licensee.model.ts, webroot/src/models/Licensee/Licensee.model.spec.ts
Add checks: hasUnderInvestigationLicenses(), hasUnderInvestigationPrivileges(), isUnderInvestigation(), underInvestigationStates() and factor into purchase eligibility; tests updated.
LicenseCard component
webroot/src/components/LicenseCard/LicenseCard.ts, webroot/src/components/LicenseCard/LicenseCard.vue, webroot/src/components/LicenseCard/LicenseCard.less
Add Add/End Investigation menu items and multi-step modals, per-investigation end-data handling, form init/validation, focus traps, and responsive static-container CSS/layout changes.
PrivilegeCard component
webroot/src/components/PrivilegeCard/PrivilegeCard.ts, webroot/src/components/PrivilegeCard/PrivilegeCard.vue, webroot/src/components/PrivilegeCard/PrivilegeCard.less
Mirror LicenseCard changes for privileges: investigation modals, modal state flags, selection handlers, encumbrance routing, focus traps, and static-container CSS/layout adjustments.
API layer
webroot/src/network/licenseApi/data.api.ts, webroot/src/network/data.api.ts
New create*Investigation and update*Investigation methods for licenses and privileges; encumbrance payload building with feature-gated NPDB category logic. (Duplicate privilege method declarations appear in diffs.)
Mocks
webroot/src/network/mocks/mock.data.api.ts, webroot/src/network/mocks/mock.data.ts
Mock implementations for create/update investigation endpoints and demo WY jurisdiction/privilege records with investigation entries; mock delays and validations added.
Vuex store
webroot/src/store/users/users.actions.ts, webroot/src/store/users/users.mutations.ts, webroot/src/store/users/users.spec.ts
New actions and mutations for create/update investigation request/failure/success lifecycles (license & privilege); tests extended to cover success and error flows.
Pages / UI alerts
webroot/src/pages/LicensingDetail/LicensingDetail.ts, webroot/src/pages/LicensingDetail/LicensingDetail.vue, webroot/src/pages/LicensingDetail/LicensingDetail.less
Add licensee investigation alert block, getters to compute localized alert content, register AlertIcon, and yellow alert styles.
Localization
webroot/src/locales/en.json, webroot/src/locales/es.json
Add ~30 investigation-related translation keys for license/privilege add/end flows, confirmations, success messages, statuses and alerts.
Styles / tokens
webroot/src/components/*/*.less, webroot/src/styles.common/_colors.less
Introduce static-container layout CSS across components and add yellow color tokens (@__yellow, @midYellow, @darkYellow, @lightYellow) for alert styling.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant UI as LicenseCard/PrivilegeCard
    participant Store as Vuex Store
    participant API as DataApi
    participant S as Server

    U->>UI: Click "Add Investigation"
    UI->>UI: open modal & initFormInputsAddInvestigation()
    U->>UI: Fill & submit form
    UI->>Store: dispatch(createInvestigationLicenseRequest/createInvestigationPrivilegeRequest)
    Store->>API: createLicenseInvestigation/createPrivilegeInvestigatio n
    API->>S: POST /investigation
    S-->>API: 200 {investigationId,...}
    API-->>Store: response
    Store-->>UI: success -> refresh data
    UI->>UI: show success, close modal
Loading
sequenceDiagram
    participant U as User
    participant UI as LicenseCard/PrivilegeCard
    participant Store as Vuex Store
    participant API as DataApi
    participant S as Server

    U->>UI: Click "End Investigation"
    UI->>UI: open modal, list investigations
    U->>UI: select investigation
    UI->>UI: init end-investigation inputs
    U->>UI: Continue -> choose With/Without Encumbrance
    alt With Encumbrance
        UI->>Store: dispatch(updateInvestigationLicenseRequest/Privilege with encumbrance)
    else Without Encumbrance
        UI->>Store: dispatch(updateInvestigationLicenseRequest/Privilege without encumbrance)
    end
    Store->>API: PATCH /investigation/{id}
    API->>S: PATCH
    S-->>API: 200
    API-->>Store: success
    Store-->>UI: success -> refresh data
    UI->>UI: show success, close modal
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Areas to focus on:

  • Modal multi-step state, focus-trap and keyboard handling in LicenseCard.ts and PrivilegeCard.ts.
  • Per-investigation form lifecycle, input initialization and validation sequencing when switching selected investigations.
  • Encumbrance payload construction and feature-gated NPDB category logic in webroot/src/network/licenseApi/data.api.ts.
  • Serializer/date mapping and isActive() logic in InvestigationSerializer and LicenseSerializer.
  • Duplicate privilege investigation method declarations/forwarders in webroot/src/network/data.api.ts and webroot/src/network/licenseApi/data.api.ts.

Possibly related PRs

Suggested reviewers

  • jlkravitz
  • isabeleliassen
  • rmolinares
  • carlsims

Poem

🐇 I hopped the menus, found a start,
I marked the case with gentle heart.
Pick a date, then choose an end,
With or without the note we send.
A cheerful rabbit cheers — investigation done!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title 'Frontend/investigative info' is vague and does not clearly summarize the main changes; it lacks specificity about what investigative functionality was added. Use a more descriptive title such as 'Add investigation management workflows to LicenseCard and PrivilegeCard components' or similar that captures the primary feature added.
Out of Scope Changes check ❓ Inconclusive While most changes align with issue #1132, the addition of color tokens (@__yellow, @midYellow, @darkyellow, @lightyellow) and Wyoming (wy) mock data with multiple investigations appear potentially out of scope and may warrant clarification on their necessity.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description includes all required sections (Requirements, Description, Testing) and provides comprehensive details about changes, model updates, and manual testing steps.
Linked Issues check ✅ Passed The code changes meet all coding requirements from issue #1132: Investigation model, UI options in card menus, investigation status display, banner on licensee detail page, selection by start date, and encumbrance chaining options are all implemented.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example:

"Create a concise high-level summary as a bullet-point list. Then include a Markdown table showing lines added and removed by each contributing author."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
webroot/src/components/LicenseCard/LicenseCard.less (1)

121-174: Separator line may render off-target (missing positioning context).

.license-menu-item.new-section::before uses position: absolute but the parent isn’t positioned; the pseudo-element can be placed relative to an unexpected ancestor.

Apply:

 .license-menu-item {
   ...
-  &.new-section {
+  &.new-section {
+    position: relative;
     margin-top: 0.4rem;
     padding-top: 1rem;
 
     &::before {
       position: absolute;
       top: 0;
       left: 0.8rem;
       width: calc(100% - 1.6rem);
       height: 1px;
       margin-bottom: 0.4rem;
       background-color: @lightGrey;
       content: '';
     }
   }
 }
🧹 Nitpick comments (6)
webroot/src/components/LicenseCard/LicenseCard.less (1)

307-335: Minor: add explicit keyboard focus styles to aid accessibility.

The clickable .unencumber-select/.end-investigation-select wrappers gain selection and hover styling but lack focus-visible feedback for keyboard users.

Consider:

.unencumber-select,
.end-investigation-select {
  &:focus-visible {
    outline: 2px solid @primaryColor;
    outline-offset: 2px;
  }
}

Also applies to: 316-330

webroot/src/pages/LicensingDetail/LicensingDetail.vue (1)

14-17: Announce alert to screen readers and mark icon decorative.

Add a polite live region and hide the icon from AT.

- <div v-if="isLicenseeUnderInvestigation" class="licensee-alert">
-     <AlertIcon v-if="$matches.tablet.min" class="alert-icon" />
+ <div
+   v-if="isLicenseeUnderInvestigation"
+   class="licensee-alert"
+   role="status"
+   aria-live="polite"
+ >
+     <AlertIcon v-if="$matches.tablet.min" class="alert-icon" aria-hidden="true" />
      {{ licenseeInvestigationAlertContent }}
   </div>
webroot/src/pages/LicensingDetail/LicensingDetail.less (1)

13-27: Set explicit text color for contrast on yellow background.

Ensure readable contrast regardless of inheritance.

.licensee-alert {
   display: flex;
   align-items: center;
   justify-content: center;
   width: 100%;
   padding: 0.8rem 2rem;
   font-weight: @fontWeightBold;
-  background-color: @midYellow;
+  background-color: @midYellow;
+  color: @black;
webroot/src/models/Licensee/Licensee.model.spec.ts (2)

1131-1168: Add a gating assertion to lock privilege purchases when under investigation.

Since Licensee.canPurchasePrivileges() returns false when isUnderInvestigation() is true, assert it here to prevent regressions.

   const licensee = new Licensee({
     licenses: [underInvestigationLicense],
     privileges: [underInvestigationPrivilege],
   });

   // Test encumbered methods
   expect(licensee.hasUnderInvestigationLicenses()).to.equal(true);
   expect(licensee.hasUnderInvestigationPrivileges()).to.equal(true);
   expect(licensee.isUnderInvestigation()).to.equal(true);
   expect(licensee.underInvestigationStates()).to.matchPattern([
     new State({ abbrev: 'al' }),
     new State({ abbrev: 'co' }),
   ]);
+  // Purchase gating
+  expect(licensee.canPurchasePrivileges()).to.equal(false);

If you prefer, I can open a follow-up PR to add this assertion and run the unit suite.


1132-1142: Naming nit (optional).

licenseNumber: 'encumbered-license' under an investigation scenario can confuse readers. Consider renaming to under-investigation-license.

webroot/src/pages/LicensingDetail/LicensingDetail.ts (1)

115-128: Trim whitespace and optionally display a concise state list.

Template-literal line breaks/indentation will appear as extra spaces/newlines. Also, you can reuse Licensee.getStateListDisplay for multiple states.

get licenseeInvestigationAlertContent(): string {
  const investigationStates = this.licensee?.underInvestigationStates() || [];
- const statesContent = (investigationStates.length === 1)
-     ? investigationStates[0].name()
-     : this.$t('licensing.underInvestigationAlert1MultipleLocations');
- let alertContent = '';
+ const stateNames = investigationStates.map((s) => s.name());
+ const statesContent = (stateNames.length <= 1)
+   ? (stateNames[0] || '')
+   : (this.licensee?.getStateListDisplay(stateNames, 3) // e.g., "AL, CO +"
+       || this.$t('licensing.underInvestigationAlert1MultipleLocations'));
+ let alertContent = '';

  if (investigationStates.length) {
-   alertContent += `${this.$t('licensing.underInvestigationAlert1', { locations: statesContent })}
-   ${this.$t('licensing.underInvestigationAlert2')}`;
+   alertContent += `${this.$t('licensing.underInvestigationAlert1', { locations: statesContent })} ${this.$t('licensing.underInvestigationAlert2')}`.trim();
  }

  return alertContent;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 137ac54 and f616bfc.

📒 Files selected for processing (25)
  • webroot/src/components/LicenseCard/LicenseCard.less (6 hunks)
  • webroot/src/components/LicenseCard/LicenseCard.ts (10 hunks)
  • webroot/src/components/LicenseCard/LicenseCard.vue (3 hunks)
  • webroot/src/components/PrivilegeCard/PrivilegeCard.less (7 hunks)
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts (13 hunks)
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue (3 hunks)
  • webroot/src/locales/en.json (1 hunks)
  • webroot/src/locales/es.json (1 hunks)
  • webroot/src/models/Investigation/Investigation.model.spec.ts (1 hunks)
  • webroot/src/models/Investigation/Investigation.model.ts (1 hunks)
  • webroot/src/models/License/License.model.spec.ts (12 hunks)
  • webroot/src/models/License/License.model.ts (6 hunks)
  • webroot/src/models/Licensee/Licensee.model.spec.ts (6 hunks)
  • webroot/src/models/Licensee/Licensee.model.ts (3 hunks)
  • webroot/src/network/data.api.ts (2 hunks)
  • webroot/src/network/licenseApi/data.api.ts (2 hunks)
  • webroot/src/network/mocks/mock.data.api.ts (2 hunks)
  • webroot/src/network/mocks/mock.data.ts (4 hunks)
  • webroot/src/pages/LicensingDetail/LicensingDetail.less (1 hunks)
  • webroot/src/pages/LicensingDetail/LicensingDetail.ts (3 hunks)
  • webroot/src/pages/LicensingDetail/LicensingDetail.vue (1 hunks)
  • webroot/src/store/users/users.actions.ts (2 hunks)
  • webroot/src/store/users/users.mutations.ts (4 hunks)
  • webroot/src/store/users/users.spec.ts (4 hunks)
  • webroot/src/styles.common/_colors.less (1 hunks)
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-08-21T16:36:48.723Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1019
File: webroot/src/components/PrivilegeCard/PrivilegeCard.vue:270-278
Timestamp: 2025-08-21T16:36:48.723Z
Learning: In PrivilegeCard component's unencumber modal (webroot/src/components/PrivilegeCard/PrivilegeCard.vue), the unencumber-select wrapper element intentionally uses space key handling to catch bubbled events from child InputCheckbox elements for custom handling actions. When adverseAction.hasEndDate() is true, items show an inactive-category div and are designed to be non-interactive (not focusable), while items without end dates contain focusable InputCheckbox child elements. This design pattern is consistent with prior implementation and represents intentional UX behavior.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.less
  • webroot/src/pages/LicensingDetail/LicensingDetail.ts
  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/components/LicenseCard/LicenseCard.less
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-08-21T15:23:26.019Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1025
File: webroot/src/models/Licensee/Licensee.model.ts:242-254
Timestamp: 2025-08-21T15:23:26.019Z
Learning: In the CompactConnect codebase, the LicenseSerializer.fromServer() method maps the server response field `dateOfIssuance` to the License model's `issueDate` property. After serialization, License instances only contain `issueDate` and never have `dateOfIssuance`. When reviewing date comparisons in reducers that work with License objects, check if they're working with serialized License instances (which use `issueDate`) rather than raw server data (which uses `dateOfIssuance`).

Applied to files:

  • webroot/src/models/License/License.model.ts
  • webroot/src/models/License/License.model.spec.ts
📚 Learning: 2025-10-29T19:11:33.003Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1167
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/investigation.py:85-95
Timestamp: 2025-10-29T19:11:33.003Z
Learning: InvestigationData extends CCDataClass which provides the licenseTypeAbbreviation property as a computed property (returns license type abbreviation if the instance has both 'compact' and 'licenseType' fields). Therefore, InvestigationData instances have access to licenseTypeAbbreviation through inheritance, and it does not need to be explicitly set when creating new investigation records.

Applied to files:

  • webroot/src/models/License/License.model.ts
  • webroot/src/pages/LicensingDetail/LicensingDetail.ts
  • webroot/src/models/Licensee/Licensee.model.spec.ts
  • webroot/src/models/Licensee/Licensee.model.ts
  • webroot/src/models/License/License.model.spec.ts
  • webroot/src/network/data.api.ts
  • webroot/src/network/mocks/mock.data.api.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/models/Investigation/Investigation.model.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
  • webroot/src/network/licenseApi/data.api.ts
📚 Learning: 2025-08-21T15:23:30.649Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1025
File: webroot/src/models/Licensee/Licensee.model.ts:242-254
Timestamp: 2025-08-21T15:23:30.649Z
Learning: In the CompactConnect frontend codebase, the LicenseSerializer.fromServer() method maps server response field `dateOfIssuance` to the License model field `issueDate`. After serialization, License objects only contain `issueDate` and never `dateOfIssuance`, so reducer logic only needs to check for null `issueDate` values.

Applied to files:

  • webroot/src/models/License/License.model.ts
  • webroot/src/models/License/License.model.spec.ts
📚 Learning: 2025-06-24T00:02:39.944Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/components/LicenseCard/LicenseCard.ts:414-443
Timestamp: 2025-06-24T00:02:39.944Z
Learning: In LicenseCard component's clickUnencumberItem method (webroot/src/components/LicenseCard/LicenseCard.ts), complex event handling for checkbox interactions is intentionally designed to ensure consistent behavior across checkbox input, wrapper label, and outer selection parent elements for custom UI requirements. This complexity should be preserved rather than simplified.

Applied to files:

  • webroot/src/pages/LicensingDetail/LicensingDetail.ts
  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/components/LicenseCard/LicenseCard.less
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-07-03T15:35:57.893Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 905
File: webroot/src/components/UpdateHomeJurisdiction/UpdateHomeJurisdiction.vue:32-41
Timestamp: 2025-07-03T15:35:57.893Z
Learning: In the CompactConnect frontend codebase, the team prefers to keep non-dynamic text directly in Vue templates rather than moving it to computed properties in TypeScript modules, as this approach prevents cluttering the TS files with template labels.

Applied to files:

  • webroot/src/pages/LicensingDetail/LicensingDetail.ts
📚 Learning: 2025-08-12T22:51:48.937Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1009
File: webroot/src/pages/LicenseeProof/LicenseeProof.less:158-165
Timestamp: 2025-08-12T22:51:48.937Z
Learning: In webroot/src/pages/LicenseeProof/LicenseeProof.vue, the .max-gap elements inside .licenses-container are intentionally hard-coded as empty elements that serve as space placeholders for tablet+ screen widths. On mobile, they are hidden completely using the :empty pseudo-class. This is an intentional design pattern where the developers have full control over keeping these elements truly empty.

Applied to files:

  • webroot/src/pages/LicensingDetail/LicensingDetail.less
  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/components/LicenseCard/LicenseCard.less
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue
  • webroot/src/pages/LicensingDetail/LicensingDetail.vue
📚 Learning: 2025-08-29T18:29:16.953Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1042
File: webroot/src/pages/MfaResetStartLicensee/MfaResetStartLicensee.vue:141-146
Timestamp: 2025-08-29T18:29:16.953Z
Learning: In the MfaResetStartLicensee component, license type keys (like "audiologist") are displayed directly in the summary using CSS `text-transform: capitalize` because the keys are human-readable strings, rather than using separate display name lookups.

Applied to files:

  • webroot/src/pages/LicensingDetail/LicensingDetail.less
📚 Learning: 2025-08-13T20:28:33.191Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1011
File: webroot/src/models/Licensee/Licensee.model.ts:276-279
Timestamp: 2025-08-13T20:28:33.191Z
Learning: The two-year encumbrance wait period feature only applies to privileges, not licenses. The logic should only check if privilege encumbrances that are no longer active have lift dates within the past two years.

Applied to files:

  • webroot/src/models/Licensee/Licensee.model.ts
📚 Learning: 2025-08-20T17:27:40.673Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1009
File: webroot/src/models/License/License.model.spec.ts:599-601
Timestamp: 2025-08-20T17:27:40.673Z
Learning: The `dateDisplay` utility function in the License model can handle both date-only strings (serverDateFormat) and datetime strings (serverDatetimeFormat) correctly. When testing date display methods like `activeFromDateDisplay()`, use the format that matches the expected parsing behavior rather than the input format.

Applied to files:

  • webroot/src/models/License/License.model.spec.ts
📚 Learning: 2025-08-29T18:16:12.078Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1042
File: webroot/src/store/user/user.mutations.ts:269-272
Timestamp: 2025-08-29T18:16:12.078Z
Learning: The CONFIRM_MFA_LICENSEE_ACCOUNT_REQUEST mutation intentionally sets isLoadingAccount = false (rather than true like other REQUEST mutations) because the MfaResetConfirmLicensee page handles its own loading UI with a custom LoadingSpinner component and isLoading state, rather than triggering the global app loading state.

Applied to files:

  • webroot/src/store/users/users.spec.ts
  • webroot/src/store/users/users.mutations.ts
📚 Learning: 2025-07-10T19:52:40.366Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 922
File: webroot/src/components/UserAccount/UserAccount.ts:250-267
Timestamp: 2025-07-10T19:52:40.366Z
Learning: In focus trap implementations for modals, when there's only one focusable element (like in a success state), it's correct for both firstTabIndex and lastTabIndex to reference the same element. This keeps focus appropriately trapped on that single element. Optional chaining operators (?.focus()) provide adequate null safety for DOM element access in focus management code.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
📚 Learning: 2025-08-29T17:54:57.683Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1042
File: webroot/src/locales/es.json:958-958
Timestamp: 2025-08-29T17:54:57.683Z
Learning: Spanish translations in webroot/src/locales/es.json are currently generated using Google Translate and are considered nice-to-have. The team plans to use professional translation services if formal Spanish support is needed in the future. Don't spend time on nuanced translation quality issues for Spanish locale files.

Applied to files:

  • webroot/src/locales/es.json
📚 Learning: 2025-06-09T19:57:51.519Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 851
File: webroot/src/pages/RegisterLicensee/RegisterLicensee.ts:0-0
Timestamp: 2025-06-09T19:57:51.519Z
Learning: In the RegisterLicensee component, when handling DOM element availability issues, the developer prefers using Vue Watchers over retry mechanisms with requestAnimationFrame to avoid infinite recursion risks and maintain Vue's reactive patterns.

Applied to files:

  • webroot/src/pages/LicensingDetail/LicensingDetail.vue
📚 Learning: 2025-06-18T21:57:02.978Z
Learnt from: jusdino
Repo: csg-org/CompactConnect PR: 864
File: backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py:256-262
Timestamp: 2025-06-18T21:57:02.978Z
Learning: The `licenseJurisdiction` field is a required field in the provider data API response from the `/v1/providers/users/me` endpoint, so it can be accessed directly without defensive programming checks.

Applied to files:

  • webroot/src/network/mocks/mock.data.ts
🧬 Code graph analysis (15)
webroot/src/models/License/License.model.ts (1)
webroot/src/models/Investigation/Investigation.model.ts (2)
  • Investigation (32-87)
  • InvestigationSerializer (92-106)
webroot/src/models/Licensee/Licensee.model.spec.ts (5)
webroot/src/models/License/License.model.ts (1)
  • License (73-193)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
webroot/src/models/State/State.model.ts (1)
  • State (21-49)
webroot/src/app.config.ts (1)
  • serverDateFormat (157-157)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • Licensee (64-396)
webroot/src/models/Licensee/Licensee.model.ts (3)
webroot/src/models/License/License.model.ts (1)
  • License (73-193)
webroot/src/models/State/State.model.ts (1)
  • State (21-49)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
webroot/src/models/License/License.model.spec.ts (2)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
webroot/src/app.config.ts (1)
  • serverDateFormat (157-157)
webroot/src/store/users/users.spec.ts (1)
webroot/src/store/users/users.state.ts (1)
  • state (17-24)
webroot/src/store/users/users.mutations.ts (1)
webroot/src/store/users/users.state.ts (1)
  • state (17-24)
webroot/src/store/users/users.actions.ts (5)
webroot/src/network/data.api.ts (1)
  • dataApi (689-689)
webroot/src/network/mocks/mock.data.api.ts (1)
  • dataApi (809-809)
webroot/src/pages/LicensingDetail/LicensingDetail.ts (2)
  • compact (63-67)
  • licenseeId (92-94)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • licenseeId (147-149)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • licenseeId (135-137)
webroot/src/network/data.api.ts (1)
webroot/src/network/licenseApi/data.api.ts (1)
  • licenseDataApi (634-634)
webroot/src/network/mocks/mock.data.api.ts (6)
webroot/src/pages/LicensingDetail/LicensingDetail.ts (2)
  • compact (63-67)
  • licenseeId (92-94)
webroot/src/pages/PublicLicensingDetail/PublicLicensingDetail.ts (2)
  • compact (51-55)
  • licenseeId (57-59)
webroot/src/pages/PrivilegeDetail/PrivilegeDetail.ts (2)
  • compact (83-87)
  • licenseeId (75-77)
webroot/src/pages/PublicPrivilegeDetail/PublicPrivilegeDetail.ts (2)
  • compact (60-62)
  • licenseeId (56-58)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • licenseeId (147-149)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • licenseeId (135-137)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (3)
webroot/src/models/FormInput/FormInput.model.ts (2)
  • FormInput (59-170)
  • input (109-117)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • isEndInvestigationSubmitEnabled (295-297)
webroot/src/models/Investigation/Investigation.model.ts (2)
webroot/src/models/_helpers/index.ts (1)
  • deleteUndefinedProperties (24-24)
webroot/src/app.config.ts (1)
  • serverDateFormat (157-157)
webroot/src/models/Investigation/Investigation.model.spec.ts (2)
webroot/src/models/Investigation/Investigation.model.ts (2)
  • Investigation (32-87)
  • InvestigationSerializer (92-106)
webroot/src/app.config.ts (2)
  • serverDateFormat (157-157)
  • displayDateFormat (163-163)
webroot/src/components/LicenseCard/LicenseCard.ts (5)
webroot/src/models/FormInput/FormInput.model.ts (1)
  • FormInput (59-170)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
webroot/src/components/StateUpload/StateUpload.ts (1)
  • compactType (68-70)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • isEndInvestigationSubmitEnabled (267-269)
webroot/src/components/Forms/InputCheckbox/InputCheckbox.ts (1)
  • input (26-34)
webroot/src/network/licenseApi/data.api.ts (6)
webroot/src/pages/LicensingDetail/LicensingDetail.ts (2)
  • compact (63-67)
  • licenseeId (92-94)
webroot/src/pages/PublicLicensingDetail/PublicLicensingDetail.ts (2)
  • compact (51-55)
  • licenseeId (57-59)
webroot/src/pages/PrivilegeDetail/PrivilegeDetail.ts (2)
  • compact (83-87)
  • licenseeId (75-77)
webroot/src/pages/PublicPrivilegeDetail/PublicPrivilegeDetail.ts (2)
  • compact (60-62)
  • licenseeId (56-58)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • licenseeId (147-149)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • licenseeId (135-137)
webroot/src/network/mocks/mock.data.ts (1)
webroot/src/app.config.ts (2)
  • serverDatetimeFormat (158-158)
  • serverDateFormat (157-157)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CheckWebroot
🔇 Additional comments (12)
webroot/src/components/LicenseCard/LicenseCard.less (2)

261-273: Structural layout updates read well.

The new .form-row.static-container and .static-input blocks improve consistency across modals. No issues found.

Also applies to: 369-393


352-357: Date style generalization LGTM.

Shared styles for .encumbrance-dates and .investigation-dates are consistent and readable.

webroot/src/styles.common/_colors.less (1)

63-68: Color token additions look good.

Yellow palette is consistent with existing naming/darken/lighten patterns.

webroot/src/models/Licensee/Licensee.model.spec.ts (1)

21-21: LGTM on investigation defaults and assertions.

The added expectations for investigation-related methods are correct and improve coverage.

Also applies to: 94-98, 206-210, 509-513, 647-651

webroot/src/network/mocks/mock.data.ts (1)

88-95: WY additions look consistent.

Permissions for WY and WY privilege with investigations align with the investigation feature set.

Also applies to: 945-992

webroot/src/pages/LicensingDetail/LicensingDetail.ts (1)

111-114: LGTM on isLicenseeUnderInvestigation.

Directly defers to model; simple and clear.

webroot/src/components/LicenseCard/LicenseCard.vue (2)

57-76: Menu additions LGTM.

Action entries for add/end investigation are surfaced correctly with admin gating.


352-439: Modal flows read clean and consistent. One follow-up: investigation-to-encumbrance chaining.

The confirm step offers “end without encumbrance” and “end with encumbrance”. Please verify the implementation keeps the investigation flag until the encumbrance is created to avoid a visible gap, per requirements.

I can inspect LicenseCard.ts and store actions if you’d like me to run a quick static trace to confirm the flag’s lifetime.

Also applies to: 441-590

webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)

38-38: LGTM! Investigation workflow well-integrated.

The investigation feature integration follows established patterns from the encumbrance/unencumbrance workflows. The implementation includes:

  • Proper state management for investigation modals and form inputs
  • Getters for investigation status that integrate correctly with discipline content display
  • Form initialization methods that follow existing conventions
  • Dual submission paths for encumbrance (standalone vs. as part of investigation end)
  • Complete add/end investigation flows with proper modal state transitions
  • Helper methods for selection and form input management

The code is consistent with existing patterns and properly handles the workflow transition from ending an investigation to optionally adding an encumbrance.

Also applies to: 72-80, 197-219, 251-269, 380-410, 570-617, 788-1015, 1030-1032

webroot/src/components/LicenseCard/LicenseCard.ts (1)

40-40: LGTM! Investigation workflow properly implemented for licenses.

The investigation feature integration in LicenseCard mirrors the PrivilegeCard implementation appropriately. The code includes:

  • Investigation state and modal management
  • Status getters that properly reflect investigation state in discipline content
  • Form initialization for add/end investigation workflows
  • Conditional encumbrance submission logic when ending investigations
  • Complete modal flows with proper state transitions
  • Helper methods consistent with PrivilegeCard patterns

The parallel implementation between License and Privilege cards maintains consistency across the codebase.

Also applies to: 77-85, 225-247, 279-297, 388-418, 514-561, 732-959, 974-976

webroot/src/locales/es.json (1)

674-703: LGTM! Spanish translations added for investigation workflows.

The Spanish translations for investigation-related UI elements have been added, covering all necessary keys for add/end investigation modals and status displays. These are data-only additions that align with the corresponding English translations.

Based on learnings

webroot/src/locales/en.json (1)

690-719: LGTM! English translations added for investigation workflows.

The English translations for investigation-related UI elements have been added, providing comprehensive coverage for:

  • Add investigation modal (titles, subtexts, submit actions, success messages)
  • End investigation modal (selection, confirmation, with/without encumbrance paths)
  • Investigation status displays and alerts

These are data-only additions that follow existing naming conventions and provide clear, user-friendly text for the new investigation workflows.

- Minor fixes
- @todo: Wire up once backend is ready
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
webroot/src/components/LicenseCard/LicenseCard.ts (1)

1010-1019: Typo has been fixed.

The previous review comment identified a typo (invevstigationinvestigation), which has been corrected in the current code.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f616bfc and 72217ad.

📒 Files selected for processing (4)
  • webroot/src/components/LicenseCard/LicenseCard.ts (10 hunks)
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts (13 hunks)
  • webroot/src/models/Investigation/Investigation.model.spec.ts (1 hunks)
  • webroot/src/models/Licensee/Licensee.model.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • webroot/src/models/Investigation/Investigation.model.spec.ts
  • webroot/src/models/Licensee/Licensee.model.ts
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/models/Investigation/Investigation.model.ts:67-86
Timestamp: 2025-11-06T18:14:40.602Z
Learning: In the Investigation model (webroot/src/models/Investigation/Investigation.model.ts), the isActive() method intentionally includes defensive logic to handle potential backend bug states where the start date (startDate) might be missing. If an investigation record exists but lacks a start date, it should still be considered active as long as it hasn't ended (updateDate is null or in the future), because the record's existence implies it was created and just has missing date metadata.
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1167
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/investigation.py:85-95
Timestamp: 2025-10-29T19:11:33.003Z
Learning: InvestigationData extends CCDataClass which provides the licenseTypeAbbreviation property as a computed property (returns license type abbreviation if the instance has both 'compact' and 'licenseType' fields). Therefore, InvestigationData instances have access to licenseTypeAbbreviation through inheritance, and it does not need to be explicitly set when creating new investigation records.
📚 Learning: 2025-11-06T18:11:58.234Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-11-06T18:14:40.602Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/models/Investigation/Investigation.model.ts:67-86
Timestamp: 2025-11-06T18:14:40.602Z
Learning: In the Investigation model (webroot/src/models/Investigation/Investigation.model.ts), the isActive() method intentionally includes defensive logic to handle potential backend bug states where the start date (startDate) might be missing. If an investigation record exists but lacks a start date, it should still be considered active as long as it hasn't ended (updateDate is null or in the future), because the record's existence implies it was created and just has missing date metadata.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-08-21T16:36:48.723Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1019
File: webroot/src/components/PrivilegeCard/PrivilegeCard.vue:270-278
Timestamp: 2025-08-21T16:36:48.723Z
Learning: In PrivilegeCard component's unencumber modal (webroot/src/components/PrivilegeCard/PrivilegeCard.vue), the unencumber-select wrapper element intentionally uses space key handling to catch bubbled events from child InputCheckbox elements for custom handling actions. When adverseAction.hasEndDate() is true, items show an inactive-category div and are designed to be non-interactive (not focusable), while items without end dates contain focusable InputCheckbox child elements. This design pattern is consistent with prior implementation and represents intentional UX behavior.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-10-29T19:11:33.003Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1167
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/investigation.py:85-95
Timestamp: 2025-10-29T19:11:33.003Z
Learning: InvestigationData extends CCDataClass which provides the licenseTypeAbbreviation property as a computed property (returns license type abbreviation if the instance has both 'compact' and 'licenseType' fields). Therefore, InvestigationData instances have access to licenseTypeAbbreviation through inheritance, and it does not need to be explicitly set when creating new investigation records.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-07-10T19:52:40.366Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 922
File: webroot/src/components/UserAccount/UserAccount.ts:250-267
Timestamp: 2025-07-10T19:52:40.366Z
Learning: In focus trap implementations for modals, when there's only one focusable element (like in a success state), it's correct for both firstTabIndex and lastTabIndex to reference the same element. This keeps focus appropriately trapped on that single element. Optional chaining operators (?.focus()) provide adequate null safety for DOM element access in focus management code.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
📚 Learning: 2025-06-24T00:02:39.944Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/components/LicenseCard/LicenseCard.ts:414-443
Timestamp: 2025-06-24T00:02:39.944Z
Learning: In LicenseCard component's clickUnencumberItem method (webroot/src/components/LicenseCard/LicenseCard.ts), complex event handling for checkbox interactions is intentionally designed to ensure consistent behavior across checkbox input, wrapper label, and outer selection parent elements for custom UI requirements. This complexity should be preserved rather than simplified.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
🧬 Code graph analysis (2)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (4)
webroot/src/models/FormInput/FormInput.model.ts (2)
  • FormInput (59-170)
  • input (109-117)
webroot/src/models/AdverseAction/AdverseAction.model.ts (1)
  • AdverseAction (35-122)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • isEndInvestigationSubmitEnabled (295-297)
webroot/src/components/LicenseCard/LicenseCard.ts (3)
webroot/src/models/FormInput/FormInput.model.ts (1)
  • FormInput (59-170)
webroot/src/models/AdverseAction/AdverseAction.model.ts (1)
  • AdverseAction (35-122)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (32-87)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CheckWebroot
🔇 Additional comments (27)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (14)

38-38: LGTM!

The Investigation model import follows the established pattern and is necessary for the investigation workflow integration.


72-76: LGTM!

The investigation modal state flags follow the established pattern used for encumbrance modals, providing appropriate states for the add/end investigation workflows.


79-80: LGTM!

The investigation data structures appropriately mirror the encumbrance pattern, with selectedInvestigation correctly using singular form to enforce the single-selection requirement from the PR objectives.


197-211: LGTM!

The isUnderInvestigation computed property and updated disciplineContent logic correctly prioritize encumbered status over investigation status, which aligns with the expected discipline state hierarchy.


217-219: LGTM!

The investigations getter follows the established pattern used by adverseActions, providing consistent access to investigation data with appropriate fallback.


251-261: LGTM!

The endInvestigationModalTitle computed property appropriately handles the three modal states (selection, confirmation, success) with correct translation keys.


267-269: LGTM!

The isEndInvestigationSubmitEnabled computed property correctly enforces that a single investigation must be selected before submission, consistent with the isUnencumberSubmitEnabled pattern and matching the LicenseCard implementation.


285-289: LGTM!

The initFormInputs method correctly routes to the new investigation form initialization methods, maintaining consistency with the existing else-if pattern.


380-410: LGTM!

The form initialization methods follow established patterns. The add-investigation form appropriately has no data inputs (investigation is created immediately), while the end-investigation form correctly generates a FormInput per investigation with appropriate labels (start date) and disabled state handling.


533-533: LGTM!

Clearing selectedInvestigation when closing the encumber modal is correct, preventing stale state after the encumbrance workflow completes.


570-617: LGTM!

The updated submitEncumberPrivilege method correctly branches based on selectedInvestigation, enabling the investigation-ending-with-encumbrance workflow while preserving the original encumbrance-only behavior. The dual-path design aligns with the PR objectives to support ending investigations with or without encumbrance.


791-1015: LGTM!

The investigation CRUD methods are well-implemented and follow established patterns:

  • Add investigation flow mirrors the encumber modal structure
  • End investigation flow appropriately mirrors the unencumber workflow with single-selection enforcement
  • The keepSelectedInvestigation parameter in closeEndInvestigationModal (line 932) is excellent design, enabling seamless transition to the encumbrance workflow when needed (line 976)
  • Error handling, loading states, and focus trap logic are consistent with existing methods

1030-1032: LGTM!

The isInvestigationSelected helper appropriately mirrors the isEncumbranceSelected pattern, providing consistent selection state checking for UI highlighting.


1066-1075: Typo from previous review has been resolved.

The mockPopulate method now correctly uses investigation throughout (the previous typo "invevstigation" has been fixed). The implementation appropriately mirrors the unencumber pattern, auto-selecting investigations without end dates for development testing.

webroot/src/components/LicenseCard/LicenseCard.ts (13)

40-40: LGTM!

The Investigation model import is correctly placed and follows the existing pattern.


77-81: LGTM!

The investigation modal state flags follow the established pattern and cover all necessary workflow states.


84-85: LGTM!

The investigation data properties follow the encumbrance pattern appropriately, with selectedInvestigation being singular to reflect single-selection behavior.


225-227: LGTM!

The isUnderInvestigation getter correctly delegates to the license model method.


229-239: LGTM!

The discipline content priority (encumbered → investigation → no discipline) is appropriate, as encumbrances represent more severe disciplinary actions than investigations.


245-247: LGTM!

The investigations getter follows the established pattern from adverseActions.


279-289: LGTM!

The modal title computation correctly reflects the investigation workflow state.


295-297: LGTM!

The submit-enabled check correctly requires a selected investigation, aligning with the single-selection design.


311-315: LGTM!

The initFormInputs method is correctly extended to handle investigation modal initialization.


388-418: LGTM!

Both investigation form initialization methods follow established patterns. The add investigation flow is appropriately minimal (no additional inputs required for creation), while the end investigation flow correctly creates form inputs for each investigation record.


735-801: LGTM!

The add investigation modal methods follow the established patterns for modal management, focus trapping, and form submission. The straightforward creation flow (no additional inputs required) is appropriate for starting an investigation.


806-959: LGTM!

The end investigation methods comprehensively implement the two-path workflow (with/without encumbrance). Key design points:

  • Single-selection enforcement (lines 840-844) correctly clears other investigation inputs when one is selected
  • The keepSelectedInvestigation parameter in closeEndInvestigationModal properly preserves investigation context when transitioning to the encumber modal
  • Focus trap logic appropriately adapts to different modal states (select, confirm, success)

974-976: LGTM!

The isInvestigationSelected helper correctly uses optional chaining and follows the established pattern.

- Minor fixes
- @todo: Wire up once backend is ready
- Add new payload prop for ending investigations
- @todo: Wire up once backend is ready
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
webroot/src/network/licenseApi/data.api.ts (1)

351-385: Consider parameterizing the investigation action.

Both update methods hardcode action: 'close' in the request body. If the backend supports other investigation actions in the future (e.g., 'suspend', 'reopen'), consider adding an action parameter to these methods for extensibility.

If 'close' is the only valid action for the foreseeable future, the current implementation is fine.

Also applies to: 493-541

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9a2b8b0 and 29dc5b3.

📒 Files selected for processing (1)
  • webroot/src/network/licenseApi/data.api.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/models/Investigation/Investigation.model.ts:67-86
Timestamp: 2025-11-06T18:14:40.602Z
Learning: In the Investigation model (webroot/src/models/Investigation/Investigation.model.ts), the isActive() method intentionally includes defensive logic to handle potential backend bug states where the start date (startDate) might be missing. If an investigation record exists but lacks a start date, it should still be considered active as long as it hasn't ended (updateDate is null or in the future), because the record's existence implies it was created and just has missing date metadata.
📚 Learning: 2025-11-06T18:11:58.234Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
📚 Learning: 2025-11-06T18:10:16.414Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
📚 Learning: 2025-10-29T19:11:33.003Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1167
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/investigation.py:85-95
Timestamp: 2025-10-29T19:11:33.003Z
Learning: InvestigationData extends CCDataClass which provides the licenseTypeAbbreviation property as a computed property (returns license type abbreviation if the instance has both 'compact' and 'licenseType' fields). Therefore, InvestigationData instances have access to licenseTypeAbbreviation through inheritance, and it does not need to be explicitly set when creating new investigation records.

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
🧬 Code graph analysis (1)
webroot/src/network/licenseApi/data.api.ts (6)
webroot/src/pages/LicensingDetail/LicensingDetail.ts (2)
  • compact (63-67)
  • licenseeId (92-94)
webroot/src/pages/PublicLicensingDetail/PublicLicensingDetail.ts (2)
  • compact (51-55)
  • licenseeId (57-59)
webroot/src/pages/PrivilegeDetail/PrivilegeDetail.ts (2)
  • compact (83-87)
  • licenseeId (75-77)
webroot/src/pages/PublicPrivilegeDetail/PublicPrivilegeDetail.ts (2)
  • compact (60-62)
  • licenseeId (56-58)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • licenseeId (147-149)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • licenseeId (135-137)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CheckWebroot
🔇 Additional comments (3)
webroot/src/network/licenseApi/data.api.ts (3)

319-336: LGTM! Investigation creation methods are well-structured.

Both createLicenseInvestigation and createPrivilegeInvestigation follow the established patterns in this file, with clear documentation and appropriate empty-body POST requests.

Also applies to: 474-491


363-385: LGTM! Encumbrance handling is consistent with existing patterns.

The optional encumbrance logic correctly implements the "end investigation with encumbrance" workflow and follows the same feature-gated NPDB category pattern used in encumberLicense and encumberPrivilege.

Also applies to: 519-541


474-541: No duplicate method declarations exist—the review concern is unfounded.

The search results confirm each method appears exactly once: createPrivilegeInvestigation at line 482 and updatePrivilegeInvestigation at line 507. The AI summary's claim about duplicates is incorrect, and no code changes are needed to address this non-existent issue.

Likely an incorrect or invalid review comment.

- Wire up to backend
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
webroot/src/components/LicenseCard/LicenseCard.ts (1)

474-478: Clear investigation context when closing the encumber modal.

If a user picks “end with encumbrance”, then closes the encumber modal before submitting, selectedInvestigation stays set. The next time they open the encumber workflow (even for a stand‑alone encumbrance) we incorrectly go down the updateInvestigationLicenseRequest branch with that stale id, tying the encumbrance to the wrong investigation or throwing an API error. Please reset the selection whenever the modal is dismissed so the encumber flow starts clean.

     closeEncumberLicenseModal(event?: Event): void {
         event?.preventDefault();
         this.isEncumberLicenseModalDisplayed = false;
         this.isEncumberLicenseModalSuccess = false;
+        this.selectedInvestigation = null;
     }
🧹 Nitpick comments (1)
webroot/src/components/LicenseCard/LicenseCard.ts (1)

399-417: Reset investigationInputs before repopulating.

Every time the “end investigation” modal opens we append new FormInput instances to investigationInputs without clearing the old ones. After a few open/close cycles that array contains multiple stale copies per investigation, which inflates validation work and makes the selection helper harder to reason about. Please wipe the array before rebuilding it.

     initFormInputsEndInvestigation(): void {
+        this.investigationInputs = [];
         this.formData = reactive({
             endInvestigationModalContinue: new FormInput({
                 isSubmitInput: true,
                 id: 'submit-modal-continue',
             }),
         });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 29dc5b3 and 6d16d0d.

📒 Files selected for processing (8)
  • webroot/src/components/LicenseCard/LicenseCard.ts (10 hunks)
  • webroot/src/components/LicenseCard/LicenseCard.vue (3 hunks)
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts (13 hunks)
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue (3 hunks)
  • webroot/src/models/Investigation/Investigation.model.spec.ts (1 hunks)
  • webroot/src/models/Investigation/Investigation.model.ts (1 hunks)
  • webroot/src/network/licenseApi/data.api.ts (2 hunks)
  • webroot/src/network/mocks/mock.data.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • webroot/src/models/Investigation/Investigation.model.spec.ts
  • webroot/src/models/Investigation/Investigation.model.ts
🧰 Additional context used
🧠 Learnings (17)
📓 Common learnings
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/models/Investigation/Investigation.model.ts:67-86
Timestamp: 2025-11-06T18:14:40.602Z
Learning: In the Investigation model (webroot/src/models/Investigation/Investigation.model.ts), the isActive() method intentionally includes defensive logic to handle potential backend bug states where the start date (startDate) might be missing. If an investigation record exists but lacks a start date, it should still be considered active as long as it hasn't ended (updateDate is null or in the future), because the record's existence implies it was created and just has missing date metadata.
📚 Learning: 2025-11-06T18:11:58.234Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/network/licenseApi/data.api.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue
  • webroot/src/network/mocks/mock.data.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-06-24T00:02:39.944Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/components/LicenseCard/LicenseCard.ts:414-443
Timestamp: 2025-06-24T00:02:39.944Z
Learning: In LicenseCard component's clickUnencumberItem method (webroot/src/components/LicenseCard/LicenseCard.ts), complex event handling for checkbox interactions is intentionally designed to ensure consistent behavior across checkbox input, wrapper label, and outer selection parent elements for custom UI requirements. This complexity should be preserved rather than simplified.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/network/mocks/mock.data.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-08-21T16:36:48.723Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1019
File: webroot/src/components/PrivilegeCard/PrivilegeCard.vue:270-278
Timestamp: 2025-08-21T16:36:48.723Z
Learning: In PrivilegeCard component's unencumber modal (webroot/src/components/PrivilegeCard/PrivilegeCard.vue), the unencumber-select wrapper element intentionally uses space key handling to catch bubbled events from child InputCheckbox elements for custom handling actions. When adverseAction.hasEndDate() is true, items show an inactive-category div and are designed to be non-interactive (not focusable), while items without end dates contain focusable InputCheckbox child elements. This design pattern is consistent with prior implementation and represents intentional UX behavior.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-11-06T18:14:40.602Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/models/Investigation/Investigation.model.ts:67-86
Timestamp: 2025-11-06T18:14:40.602Z
Learning: In the Investigation model (webroot/src/models/Investigation/Investigation.model.ts), the isActive() method intentionally includes defensive logic to handle potential backend bug states where the start date (startDate) might be missing. If an investigation record exists but lacks a start date, it should still be considered active as long as it hasn't ended (updateDate is null or in the future), because the record's existence implies it was created and just has missing date metadata.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/network/mocks/mock.data.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-06-17T19:05:36.255Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 848
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/registration.py:111-117
Timestamp: 2025-06-17T19:05:36.255Z
Learning: In CompactConnect PR #848, the user landonshumway-ia decided to leave timezone handling code in _should_allow_reregistration function as-is after testing in sandbox environment confirmed it works correctly. The user's reasoning was that reregistration is an edge case, the code has been tested and verified, and AWS is unlikely to change behavior that would break many clients. This represents a pragmatic engineering decision based on testing and risk assessment.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/network/mocks/mock.data.ts
📚 Learning: 2025-11-06T18:10:16.414Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/network/licenseApi/data.api.ts
  • webroot/src/network/mocks/mock.data.ts
📚 Learning: 2025-06-24T00:07:10.463Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/components/LicenseCard/LicenseCard.ts:509-528
Timestamp: 2025-06-24T00:07:10.463Z
Learning: In the CompactConnect frontend codebase, the project prefers to avoid early returns in frontend code when possible, as mentioned by jsandoval81 in webroot/src/components/LicenseCard/LicenseCard.ts.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-10-15T19:56:58.050Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1135
File: backend/compact-connect/lambdas/python/common/cc_common/data_model/schema/privilege/record.py:60-0
Timestamp: 2025-10-15T19:56:58.050Z
Learning: In the CompactConnect codebase, when migrating from a single field to a list field (e.g., clinicalPrivilegeActionCategory to clinicalPrivilegeActionCategories), both fields are intentionally kept as optional during the migration period to support backwards compatibility. Mutual exclusivity validation is not enforced during this phase, as the deprecated field will be removed in a follow-up PR with migration scripts.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
📚 Learning: 2025-07-08T18:40:24.408Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 882
File: backend/compact-connect/lambdas/python/common/cc_common/data_model/compact_configuration_client.py:287-359
Timestamp: 2025-07-08T18:40:24.408Z
Learning: In the CompactConnect codebase, landonshumway-ia prefers to avoid extraneous unit tests when existing test coverage is already sufficient to catch bugs. For the get_privilege_purchase_options method's live-jurisdiction filtering logic, the existing tests in the purchases test suite provide adequate coverage without needing additional edge case tests.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
📚 Learning: 2025-08-21T15:23:26.019Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1025
File: webroot/src/models/Licensee/Licensee.model.ts:242-254
Timestamp: 2025-08-21T15:23:26.019Z
Learning: In the CompactConnect codebase, the LicenseSerializer.fromServer() method maps the server response field `dateOfIssuance` to the License model's `issueDate` property. After serialization, License instances only contain `issueDate` and never have `dateOfIssuance`. When reviewing date comparisons in reducers that work with License objects, check if they're working with serialized License instances (which use `issueDate`) rather than raw server data (which uses `dateOfIssuance`).

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/network/mocks/mock.data.ts
📚 Learning: 2025-08-12T22:51:48.937Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1009
File: webroot/src/pages/LicenseeProof/LicenseeProof.less:158-165
Timestamp: 2025-08-12T22:51:48.937Z
Learning: In webroot/src/pages/LicenseeProof/LicenseeProof.vue, the .max-gap elements inside .licenses-container are intentionally hard-coded as empty elements that serve as space placeholders for tablet+ screen widths. On mobile, they are hidden completely using the :empty pseudo-class. This is an intentional design pattern where the developers have full control over keeping these elements truly empty.

Applied to files:

  • webroot/src/components/LicenseCard/LicenseCard.vue
  • webroot/src/components/PrivilegeCard/PrivilegeCard.vue
📚 Learning: 2025-10-29T19:11:33.003Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1167
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/investigation.py:85-95
Timestamp: 2025-10-29T19:11:33.003Z
Learning: InvestigationData extends CCDataClass which provides the licenseTypeAbbreviation property as a computed property (returns license type abbreviation if the instance has both 'compact' and 'licenseType' fields). Therefore, InvestigationData instances have access to licenseTypeAbbreviation through inheritance, and it does not need to be explicitly set when creating new investigation records.

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
  • webroot/src/network/mocks/mock.data.ts
  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
  • webroot/src/components/LicenseCard/LicenseCard.ts
📚 Learning: 2025-06-18T21:57:02.978Z
Learnt from: jusdino
Repo: csg-org/CompactConnect PR: 864
File: backend/compact-connect/tests/smoke/encumbrance_smoke_tests.py:256-262
Timestamp: 2025-06-18T21:57:02.978Z
Learning: The `licenseJurisdiction` field is a required field in the provider data API response from the `/v1/providers/users/me` endpoint, so it can be accessed directly without defensive programming checks.

Applied to files:

  • webroot/src/network/mocks/mock.data.ts
📚 Learning: 2025-04-29T02:52:40.532Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 769
File: backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_encumbrance.py:138-147
Timestamp: 2025-04-29T02:52:40.532Z
Learning: In CompactConnect tests, hardcoded values (like license type abbreviations 'slp') in test queries are sometimes used intentionally rather than using dynamic lookups. This is a deliberate design decision to make tests fail if default test data changes, requiring developers to consciously update related tests.

Applied to files:

  • webroot/src/network/mocks/mock.data.ts
📚 Learning: 2025-08-29T18:04:37.212Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1042
File: webroot/src/pages/MfaResetConfirmLicensee/MfaResetConfirmLicensee.ts:165-175
Timestamp: 2025-08-29T18:04:37.212Z
Learning: In the MfaResetConfirmLicensee component, the serverMessage is intentionally designed to surface backend error messages for troubleshooting and error reporting purposes, supplementing the primary friendly generic message shown in the UI.

Applied to files:

  • webroot/src/network/mocks/mock.data.ts
📚 Learning: 2025-07-10T19:52:40.366Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 922
File: webroot/src/components/UserAccount/UserAccount.ts:250-267
Timestamp: 2025-07-10T19:52:40.366Z
Learning: In focus trap implementations for modals, when there's only one focusable element (like in a success state), it's correct for both firstTabIndex and lastTabIndex to reference the same element. This keeps focus appropriately trapped on that single element. Optional chaining operators (?.focus()) provide adequate null safety for DOM element access in focus management code.

Applied to files:

  • webroot/src/components/PrivilegeCard/PrivilegeCard.ts
🧬 Code graph analysis (4)
webroot/src/network/licenseApi/data.api.ts (6)
webroot/src/pages/LicensingDetail/LicensingDetail.ts (2)
  • compact (63-67)
  • licenseeId (92-94)
webroot/src/pages/PublicLicensingDetail/PublicLicensingDetail.ts (2)
  • compact (51-55)
  • licenseeId (57-59)
webroot/src/pages/PrivilegeDetail/PrivilegeDetail.ts (2)
  • compact (83-87)
  • licenseeId (75-77)
webroot/src/pages/PublicPrivilegeDetail/PublicPrivilegeDetail.ts (2)
  • compact (60-62)
  • licenseeId (56-58)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • licenseeId (147-149)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • licenseeId (135-137)
webroot/src/network/mocks/mock.data.ts (1)
webroot/src/app.config.ts (2)
  • serverDatetimeFormat (158-158)
  • serverDateFormat (157-157)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (3)
webroot/src/models/FormInput/FormInput.model.ts (2)
  • FormInput (59-170)
  • input (109-117)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (33-93)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • isEndInvestigationSubmitEnabled (295-297)
webroot/src/components/LicenseCard/LicenseCard.ts (3)
webroot/src/models/FormInput/FormInput.model.ts (1)
  • FormInput (59-170)
webroot/src/models/Investigation/Investigation.model.ts (1)
  • Investigation (33-93)
webroot/src/components/Forms/InputCheckbox/InputCheckbox.ts (1)
  • input (26-34)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CheckWebroot

- Minor networking update
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6d16d0d and 1f95667.

📒 Files selected for processing (1)
  • webroot/src/network/licenseApi/data.api.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/components/LicenseCard/LicenseCard.ts:388-396
Timestamp: 2025-11-12T21:06:06.957Z
Learning: In the CompactConnect investigation creation flow, the backend APIs for creating investigations (both `createLicenseInvestigation` and `createPrivilegeInvestigation` in webroot/src/network/licenseApi/data.api.ts) do not accept a `startDate` parameter. The backend automatically sets the investigation creation date to the timestamp when the API request is received, so the frontend UI does not need to capture or submit an investigation start date during the creation workflow.
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/models/Investigation/Investigation.model.ts:67-86
Timestamp: 2025-11-06T18:14:40.602Z
Learning: In the Investigation model (webroot/src/models/Investigation/Investigation.model.ts), the isActive() method intentionally includes defensive logic to handle potential backend bug states where the start date (startDate) might be missing. If an investigation record exists but lacks a start date, it should still be considered active as long as it hasn't ended (updateDate is null or in the future), because the record's existence implies it was created and just has missing date metadata.
📚 Learning: 2025-11-06T18:11:58.234Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:1919-1944
Timestamp: 2025-11-06T18:11:58.234Z
Learning: In CompactConnect, the investigation event type (`updateType: 'investigation'`) in privilege/license history is intentionally not yet fully supported in the frontend UI translation and categorization logic (webroot/src/locales/*.json and webroot/src/models/LicenseHistoryItem/LicenseHistoryItem.model.ts). The server license history API needs to be updated first to return sufficient information about investigation events. Until then, the UI gracefully falls back to displaying "Unknown" for investigation events, which is acceptable as an interim solution.
<!--

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
📚 Learning: 2025-11-12T21:06:06.957Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/components/LicenseCard/LicenseCard.ts:388-396
Timestamp: 2025-11-12T21:06:06.957Z
Learning: In the CompactConnect investigation creation flow, the backend APIs for creating investigations (both `createLicenseInvestigation` and `createPrivilegeInvestigation` in webroot/src/network/licenseApi/data.api.ts) do not accept a `startDate` parameter. The backend automatically sets the investigation creation date to the timestamp when the API request is received, so the frontend UI does not need to capture or submit an investigation start date during the creation workflow.

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
📚 Learning: 2025-05-30T13:48:25.375Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 824
File: backend/compact-connect/lambdas/python/provider-data-v1/handlers/encumbrance.py:116-201
Timestamp: 2025-05-30T13:48:25.375Z
Learning: In encumbrance handling code, prefer to keep privilege and license encumbrance lifting implementations decoupled rather than extracting shared logic, as requirements between these implementations are likely to change in the future.

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
📚 Learning: 2025-11-06T18:10:16.414Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/network/mocks/mock.data.ts:772-793
Timestamp: 2025-11-06T18:10:16.414Z
Learning: In CompactConnect, licenses and privileges can have investigations from different jurisdictions. For example, a license in Nevada (NV) can legitimately have investigations with jurisdiction Wyoming (WY). This cross-jurisdiction investigation pattern is valid in the data model and represents real-world scenarios where a practitioner licensed in one state may be under investigation by another state's authorities.

Applied to files:

  • webroot/src/network/licenseApi/data.api.ts
🧬 Code graph analysis (1)
webroot/src/network/licenseApi/data.api.ts (6)
webroot/src/pages/LicensingDetail/LicensingDetail.ts (2)
  • compact (63-67)
  • licenseeId (92-94)
webroot/src/pages/PublicLicensingDetail/PublicLicensingDetail.ts (2)
  • compact (51-55)
  • licenseeId (57-59)
webroot/src/pages/PrivilegeDetail/PrivilegeDetail.ts (2)
  • compact (83-87)
  • licenseeId (75-77)
webroot/src/pages/PublicPrivilegeDetail/PublicPrivilegeDetail.ts (2)
  • compact (60-62)
  • licenseeId (56-58)
webroot/src/components/LicenseCard/LicenseCard.ts (1)
  • licenseeId (147-149)
webroot/src/components/PrivilegeCard/PrivilegeCard.ts (1)
  • licenseeId (135-137)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CheckWebroot
🔇 Additional comments (4)
webroot/src/network/licenseApi/data.api.ts (4)

319-336: LGTM!

The createLicenseInvestigation method implementation is correct. The empty request body is appropriate since the backend automatically sets the investigation creation timestamp.


351-387: Past issue resolved.

The critical issue with spreading undefined when encumbrance is omitted has been fixed. The code now correctly falls back to spreading an empty object {} at line 382, preventing the TypeError.


476-493: LGTM!

The createPrivilegeInvestigation method correctly mirrors the license variant and follows the established patterns in this API layer.


509-545: LGTM!

The updatePrivilegeInvestigation method correctly implements the privilege variant with the proper encumbrance spread fix (falling back to {} at line 540) and mirrors the license update method appropriately.

- Minor comments update
Copy link
Contributor

@ChiefStief ChiefStief left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I've got some minor optional tweaks.

@jsandoval81
Copy link
Collaborator Author

@jlkravitz This is ready for your review.

FYI - this is obviously set to merge to development, but depending on the timing of the branch updates to switch to tag deployments that could end up changing. If turns out this needs to change to main while in your review and that causes any issues, just let me know.

Copy link
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few questions/comments!

jlkravitz
jlkravitz previously approved these changes Nov 20, 2025
Copy link
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@isabeleliassen Good to merge.

@jlkravitz jlkravitz changed the base branch from development to main November 20, 2025 19:04
@jlkravitz jlkravitz dismissed their stale review November 20, 2025 19:04

The base branch was changed.

@jlkravitz jlkravitz closed this Nov 20, 2025
@jlkravitz jlkravitz reopened this Nov 20, 2025
@isabeleliassen isabeleliassen merged commit 9ee3e30 into csg-org:main Nov 20, 2025
3 of 4 checks passed
jusdino added a commit to InspiringApps/JCC-CompactConnect that referenced this pull request Nov 21, 2025
### Requirements List
- _None_

### Description List
- Added Investigation model
- Updated License & Licensee models with related investigation props &
methods
- Also updated encumber modal with minor layout update from latest
designs
- Updated network & store layers for API calls to add / update
investigations
- Updated LicenseeDetail page with banner to indicate a current
investigation
- Updated the LicenseCard & PrivilegeCard components to support adding &
ending investigations
- This includes chaining the encumber workflow if selected by the user

### Testing List
- `yarn test:unit:all` should run without errors or warnings
- `yarn serve` should run without errors or warnings
- `yarn build` should run without errors or warnings
- Code review
- Testing
    - Login as a staff with state admin permissions
    - Locate a licensee with licenses / privileges in your admin state
    - Use the 3-dot menu of the license / privilege to Add investigation
        - Workflow should match the figma designs
        - The card Discipline status should now be Investigation
- There should be a banner at the top denoting the user is under
investigation, matching the figma designs
    - Use the 3-dot menu of the license / privilege to End investigation
        - First, choose the no encumbrance option
- Ensure the workflow completes and the licensee is no longer shown as
under investigation
    - Use the 3-dot menu to Add investigation
    - Use the 3-dot menu to End investigation
- This time, choose the encumber option and complete the encumber
workflow
- Ensure the workflow completes and the licensee is no longer shown as
under investigation, but the license / privilege is now shown as
encumbered
    - Additionally play with different scenarios for:
        - Starting an investigation
        - Ending an investigation with an encumbrance
        - Ending an investigation without an encumbrance

Closes csg-org#1132 


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Investigation workflows for licenses and privileges: start/end
actions, multi-step modals, per‑investigation selection, encumbrance
options, and visible "under investigation" status with a licensee alert.

* **Style**
* Responsive two‑column/static layout for detail blocks, wider action
menus, section dividers, and new yellow alert color palette.

* **Accessibility**
* Improved modal keyboard focus handling and ARIA live region messaging.

* **Localization**
* Added English and Spanish translations for investigation flows and
alerts.

* **Tests**
* New unit tests for Investigation model, license/licensee logic, and
store actions.

* **Chores**
* API/mocks and sample data updated to support investigation
create/update and WY mock data.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Justin Frahm <justin@inspiringapps.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

current significant investigative information FE

5 participants