Skip to content

Conversation

@jsandoval81
Copy link
Collaborator

@jsandoval81 jsandoval81 commented Dec 18, 2025

Requirements List

  • New env variables:
    • VUE_APP_API_SEARCH_ROOT=https://search.test.jcc.iaapi.io
    • VUE_APP_STATSIG_DISABLED=false

Description List

  • Added new env URI for the search API root domain
  • Added a new searchApi to the networking directory
  • Updated the license store to add the new search actions
  • Renamed the following existing components as *Legacy - and added new versions in their place:
    • Pagination
    • LicenseeList
    • LicenseeSearch
    • The *Legacy versions are left in place to support the previous limited search UI cases; the new versions are to support the newer more standard staff search UI
  • Updated the ListContainer component to support both the new and legacy paging
  • Added a new search UI for logged in staff users, following the figma designs
    • A UI-only provider search, using the existing list view as the results display
    • An export-only privilege search
    • Also included a runtime helper function to optionally log the complex search queries for help debugging as needed: ccQueryToggle()
  • Updated the InputSubmit component to have a transparent button state
  • Minor update to the PageHeader component to better handle the transparent header in desktop layouts
  • Added an env var for local environments to disable Statsig as needed
    • This helps reduce analytics console chatter in cases of ad blockers during development

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
    • The *Legacy named files haven't changed any code from their previous version, they are just renamed; so not a lot of time needs to be spent code reviewing *Legacy named files.
    • There are some typescript anys used, either existing in the Legacy files, or in spot cases in new code where time was a factor
  • Testing
    • Don't forget to add the VUE_APP_API_SEARCH_ROOT env var above
    • NOTE: The military status field is not included in the search UI in this PR. The mechanics are there but they are for the updated military status that we're adding in our next ticket. The military status search field will be enabled as part of that next ticket.
    • NOTE: Searching by Providers will only have web UI list results. Searching by Privileges will only have a direct export of results.
    • Login as a staff user and utilize the updated search UI
      • A good place to start is search all providers and get a feel for some search criteria based on the records available
      • Begin to test different combinations of the search criteria
      • Confirm the results paging for providers works as expected
      • Confirm the exports for privileges work as expected
    • Smoke test the existing logged out public search to confirm no regressions in legacy search UI
    • Smoke test the staff users list UI to confirm no regressions in legacy list UI in general

Closes #1177

Summary by CodeRabbit

  • New Features

    • Enhanced search with expanded filter options (privilege state, purchase dates, military status, investigation status, NPI)
    • Privilege export functionality for staff users
    • Search type selection to switch between provider and privilege searches
  • Improvements

    • Refined pagination controls and navigation
    • Updated search interface with improved responsive design
    • Expanded configuration options for search API

✏️ Tip: You can customize this high-level summary in your review settings.

- Renamed unusable list / paging components as Legacy
- Added new blank components that will hold new core list / paging functionality
- Implement roughed out version of standard paging for staff licensee search
- Implement roughed out version of the admin search form
- Implement roughed out version of server payload prep for the opensearch provider query
- Add search terms display to list view
- Style the new paging UI
- Updates to opensearch queries
- Added the provider vs. privilege search UI variants
- Added an export-only UI flow to the privilege search
- Moved the search API to a new network folder
- Added env param for search API URI
- Added env param for specifically disabling statsig
- Updated opensearch syntax to keyword for sort fields
- Updated queries for more complex nested search scenarios
- Started testing with privilege export CSVs
- Disabled the military status search until the next PR
- Added window function to log query output for helping with query debugging as needed
- Minor updates to pagination
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 18, 2025

📝 Walkthrough

Walkthrough

This PR implements enhanced licensee and privilege search/export functionality with a new search API infrastructure, introduces dual paging implementations (modern and legacy), refactors licensing list components with new search parameters (state variants, dates, military/investigation status, NPI), and adds UI controls for search type selection and direct export capabilities.

Changes

Cohort / File(s) Summary
Environment Configuration
.github/workflows/check-webroot.yml, webroot/.env.example, webroot/README.md, webroot/src/plugins/EnvConfig/envConfig.plugin.ts, webroot/src/plugins/Statsig/statsig.plugin.ts
Added VUE_APP_API_SEARCH_ROOT and VUE_APP_STATSIG_DISABLED environment variables; updated EnvConfig interface to expose apiUrlSearch and isStatsigDisabled; modified Statsig initialization to disable when isStatsigDisabled flag is set.
Search API Infrastructure
webroot/src/network/searchApi/data.api.ts, webroot/src/network/searchApi/interceptors.ts, webroot/src/network/data.api.ts, webroot/src/network/licenseApi/data.api.ts, webroot/src/network/mocks/mock.data.api.ts
Introduced new SearchDataApi class with Elasticsearch-like query building (prepRequestSearchParams), interceptor handling (requestSuccess, responseSuccess, responseError), and endpoints for staff search and privilege export; added wrapper methods to DataApi; extended mock API with mock search and export responses.
Licensee List Components (Modern & Legacy)
webroot/src/components/Licensee/LicenseeList/LicenseeList.ts, webroot/src/components/Licensee/LicenseeList/LicenseeList.vue, webroot/src/components/Licensee/LicenseeList/LicenseeList.less, webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts, webroot/src/components/Licensee/LicenseeListLegacy/*
Refactored LicenseeList (modern) with new API methods (handlePrivilegeDownload, prepareSearchBody), changed fetchListData to return Promise, updated paginationChange signature, added searchErrorOverride state; introduced new LicenseeListLegacy component with legacy paging support (pagingPrevKey/pagingNextKey); updated less styling with responsive width constraints and new breakpoints.
Licensee Search Components (Modern & Legacy)
webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts, webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue, webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.less, webroot/src/components/Licensee/LicenseeSearchLegacy/*
Extended LicenseeSearch with new SearchTypes enum, dual state fields (homeState/privilegeState), date range fields, military/investigation status, NPI; added mock populate, export button, search type radio group; introduced LicenseeSearchLegacy component with simpler form (firstName, lastName, state, compact); updated less styling with date-range layouts and input width variables.
Pagination Components (Modern & Legacy)
webroot/src/components/Lists/Pagination/Pagination.ts, webroot/src/components/Lists/Pagination/Pagination.vue, webroot/src/components/Lists/Pagination/Pagination.less, webroot/src/components/Lists/Pagination/Pagination.spec.ts, webroot/src/components/Lists/PaginationLegacy/*
Refactored Pagination (modern) with new callback signature (firstIndex, lastIndexExclusive instead of PageChangeConfig), simplified tests, updated pages computation algorithm; introduced PaginationLegacy component with legacy paging behavior (prevKey/nextKey support); updated styles for clickable/selected states with primary color scheme.
List Container & UI Components
webroot/src/components/Lists/ListContainer/ListContainer.ts, webroot/src/components/Lists/ListContainer/ListContainer.vue, webroot/src/components/Lists/ListContainer/ListContainer.spec.ts, webroot/src/components/Forms/InputSubmit/InputSubmit.ts, webroot/src/components/Forms/InputSubmit/InputSubmit.vue
Added isLegacyPaging prop to ListContainer with conditional rendering of Pagination vs PaginationLegacy; added isTransparent and isTextLike boolean props to InputSubmit with corresponding CSS class bindings; updated ListContainer tests to reference PaginationLegacy.
Store Management
webroot/src/store/license/license.state.ts, webroot/src/store/license/license.mutations.ts, webroot/src/store/license/license.actions.ts, webroot/src/store/license/license.spec.ts
Added isExporting boolean flag; updated search field type to union (LicenseSearchLegacy
Page Layout & Styling
webroot/src/components/Page/PageContainer/PageContainer.less, webroot/src/components/Page/PageHeader/PageHeader.less, webroot/src/styles.common/mixins/buttons.less
Added responsive rule collapsing header height to 0 on desktop breakpoint; modified button-primary mixin to use darkened grey (darken(@lightGrey, 20%)) for disabled state instead of plain grey.
Localization
webroot/src/locales/en.json, webroot/src/locales/es.json
Extended common keys with exportCsv, exportInProgress, startDate, endDate, all, any; added search-related keys (searchTypeTitle, searchPlaceholderNpi, npi, provider/providers); expanded privilege/investigation/military status options with new enums for display mapping; added searchErrorGeneral for search failure messaging.
Page Integration & Models
webroot/src/pages/PublicLicensingList/PublicLicensingList.ts, backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py, webroot/src/models/Investigation/Investigation.model.spec.ts
Changed PublicLicensingList to import LicenseeListLegacy instead of LicenseeList; added VUE_APP_API_SEARCH_ROOT to backend deployment environment variables; updated Investigation test to use local time formatting (moment() instead of moment.utc()).

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client/Component
    participant LicenseeList
    participant LicenseeSearch
    participant DataApi
    participant SearchDataApi
    participant Store
    participant Server

    Client->>LicenseeSearch: User selects provider search
    LicenseeSearch->>LicenseeSearch: updateSearchType()
    Client->>LicenseeSearch: User enters search criteria
    LicenseeSearch->>LicenseeList: emit searchParams (searchType, fields)
    LicenseeList->>LicenseeList: prepareSearchBody()
    LicenseeList->>LicenseeList: fetchListData()
    LicenseeList->>DataApi: getLicenseesSearchStaff(params)
    DataApi->>SearchDataApi: getLicenseesSearchStaff(params)
    SearchDataApi->>SearchDataApi: prepRequestSearchParams()
    SearchDataApi->>Server: POST search query (Elasticsearch)
    Server-->>SearchDataApi: licensees results
    SearchDataApi->>Store: dispatch setStoreLicensees
    Store-->>LicenseeList: updated licensees
    LicenseeList-->>Client: render results list
Loading
sequenceDiagram
    participant Client as Client/Component
    participant LicenseeSearch
    participant LicenseeList
    participant DataApi
    participant SearchDataApi
    participant Server

    Client->>LicenseeSearch: User selects privilege search
    LicenseeSearch->>LicenseeSearch: updateSearchType(SearchTypes.PRIVILEGES)
    Client->>LicenseeSearch: User enters privilege criteria
    LicenseeSearch->>LicenseeList: emit searchParams (isDirectExport: true)
    LicenseeList->>LicenseeList: fetchListData()
    LicenseeList->>LicenseeList: handlePrivilegeDownload()
    LicenseeList->>DataApi: getPrivilegesExportStaff(params)
    DataApi->>SearchDataApi: getPrivilegesExportStaff(params)
    SearchDataApi->>SearchDataApi: prepRequestSearchParams()
    SearchDataApi->>Server: POST export request
    Server-->>SearchDataApi: fileUrl
    SearchDataApi->>LicenseeList: response with fileUrl
    LicenseeList->>Store: dispatch setStoreExporting(false)
    LicenseeList-->>Client: trigger file download
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • jlkravitz
  • ChiefStief
  • isabeleliassen
  • rmolinares

Poem

🐰 A search so fine, with exports too,
Legacy pages paired with new,
Privilege queries hop along,
While dates and states make searches strong!
From API calls to styled perfection,
This PR brings the best direction!

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive Title 'Frontend/admin search update' is vague and generic, describing the general area (frontend/admin) and type (search update) without clarifying the primary change or specific objectives. Consider a more specific title that highlights the main deliverable, such as 'Add admin search UI with export capability for privilege searches' or 'Implement new staff search interface with legacy pagination support'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is mostly complete with Requirements, Description, and Testing sections filled out; all required template sections are addressed with substantive content.
Linked Issues check ✅ Passed The PR implements the main objective from #1177 (export capability for search results) through new searchApi, privilege export functionality, and updated search UI with export controls.
Out of Scope Changes check ✅ Passed All changes align with the stated objectives: new search API/UI, component renaming to legacy, paging updates, env var additions, and InputSubmit transparency feature are all documented and justified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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: 12

🧹 Nitpick comments (15)
webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.spec.ts (1)

16-17: Redundant assertion in test.

Line 17 checks if the mounted component exists by finding itself, which duplicates the check on line 16. Since wrapper is already the LicenseeSearch component, the second assertion is unnecessary.

🔎 Optional: Simplify the test by removing the redundant assertion
     it('should mount the component', async () => {
         const wrapper = await mountShallow(LicenseeSearch);

         expect(wrapper.exists()).to.equal(true);
-        expect(wrapper.findComponent(LicenseeSearch).exists()).to.equal(true);
     });
webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.ts (1)

39-39: Class name mismatch with component name.

The class is named Pagination but the component decorator specifies name: 'PaginationLegacy'. This inconsistency could cause confusion when debugging or searching the codebase.

🔎 Suggested fix:
-export default class Pagination extends mixins(MixinForm) {
+export default class PaginationLegacy extends mixins(MixinForm) {
webroot/src/network/searchApi/interceptors.ts (1)

78-82: requestError is not included in the default export.

The requestError function is exported individually but omitted from the default export object. If consumers rely on the default export for all interceptors, they'll miss requestError. This may be intentional if requestError is rarely needed.

🔎 Suggested fix if this was unintentional:
 export default {
     requestSuccess,
+    requestError,
     responseSuccess,
     responseError,
 };
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts (1)

33-33: Class name mismatch with component name.

Similar to PaginationLegacy.ts, the class is named LicenseeList but the component decorator specifies name: 'LicenseeListLegacy'. Consider renaming for consistency.

🔎 Suggested fix:
-class LicenseeList extends Vue {
+class LicenseeListLegacy extends Vue {
webroot/src/components/Lists/ListContainer/ListContainer.spec.ts (1)

12-12: Consider adding tests for the new pagination path.

All tests now reference PaginationLegacy, which aligns with the default isLegacyPaging: true behavior. However, according to the AI summary, ListContainer supports a new pagination component when isLegacyPaging is false. Consider adding tests to cover this new code path.

🔎 Example test to add:
it('should render modern Pagination when isLegacyPaging is false', async () => {
    const wrapper = await mountShallow(ListContainer, {
        props: {
            listData: ['x'],
            paginationId: 'component',
            pageChange: () => null,
            isLegacyPaging: false,
            sortOptions: []
        },
    });

    expect(wrapper.findAllComponents(Pagination).length).to.equal(2);
    expect(wrapper.findAllComponents(PaginationLegacy).length).to.equal(0);
});

Also applies to: 44-44, 60-60, 75-75, 90-90, 106-106

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

10-10: Consider removing or documenting the commented code.

The commented-out LicenseeListLegacy component doesn't affect runtime behavior, but commented code can accumulate and reduce maintainability. If this is intentionally kept for easy toggling during development, consider:

  • Adding a comment explaining why it's kept
  • Using a prop/config to switch between legacy/new list instead
  • Removing it and relying on version control
webroot/src/store/license/license.state.ts (1)

7-8: Consider importing types from .ts files instead of .vue files.

Importing interfaces from .vue files works but is unconventional. The relevant code snippets show these interfaces are defined in the corresponding .ts files (LicenseeSearchLegacy.ts and LicenseeSearch.ts). Importing from the TypeScript modules directly would be more idiomatic.

🔎 Suggested change:
-import { LicenseSearchLegacy } from '@components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue';
-import { LicenseSearch } from '@components/Licensee/LicenseeSearch/LicenseeSearch.vue';
+import { LicenseSearchLegacy } from '@components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy';
+import { LicenseSearch } from '@components/Licensee/LicenseeSearch/LicenseeSearch';
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts (1)

11-11: Misleading import alias: rename to match component name.

The import alias LicenseeList is confusing since the component being tested is LicenseeListLegacy. This could cause confusion when reading the test file.

🔎 Apply this diff to improve clarity:
-import LicenseeList from '@components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue';
+import LicenseeListLegacy from '@components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue';

Then update usages in the test file:

-describe('LicenseeList component', async () => {
+describe('LicenseeListLegacy component', async () => {
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue (1)

43-44: Consider removing this. prefix in template expressions.

Using this.licenseStore.model in Vue 3 templates is non-standard. While it works, the conventional approach is to access component properties directly without this. in templates.

🔎 Apply this diff for consistency:
-                    :listData="this.licenseStore.model"
-                    :listSize="this.licenseStore.total"
+                    :listData="licenseStore.model"
+                    :listSize="licenseStore.total"
-                            v-for="(record, index) in this.licenseStore.model"
+                            v-for="(record, index) in licenseStore.model"

Also applies to: 68-68

webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (1)

82-83: Hardcoded year 2025 in yearRange will require updates.

The yearRange starts at 2025, which will need to be updated annually. Consider making this dynamic or configurable.

🔎 Suggested approach:

You could compute a dynamic start year in the component's TypeScript file:

// In LicenseeSearch.ts
get privilegeSearchStartYear(): number {
  return 2025; // Or derive from compact configuration/launch date
}

Then use it in the template:

-                    :yearRange="[2025, new Date().getFullYear()]"
+                    :yearRange="[privilegeSearchStartYear, new Date().getFullYear()]"

Also applies to: 92-93

webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts (2)

65-77: Consider adding explicit return type annotation.

The compactOptions getter returns Array<any>, but the structure is well-defined. Consider using a more specific type for better type safety.

🔎 Suggested type improvement:
-    get compactOptions(): Array<any> {
+    get compactOptions(): Array<{ value: string, name: string | ReturnType<typeof computed> }> {

87-102: Consider refining any type usage.

The defaultSelectOption is typed as any but has a predictable shape. This aligns with the PR TODO to replace TypeScript any types.

🔎 Suggested type improvement:
-        const defaultSelectOption: any = { value: '' };
+        const defaultSelectOption: { value: string; name: string | ReturnType<typeof computed> } = { value: '', name: '' };
 
         if (!compactMemberStates.length) {
             defaultSelectOption.name = '';
         } else {
             defaultSelectOption.name = computed(() => this.$t('common.selectOption'));
         }
webroot/src/network/searchApi/data.api.ts (2)

370-378: Minor: Typo in variable name.

serverReponse should be serverResponse (missing 's'). This appears in both getLicenseesSearchStaff and getPrivilegesExportStaff.

🔎 Suggested fix:
-        const serverReponse: any = await this.api.post(`/v1/compacts/${params.compact}/providers/search`, requestParams);
-        const { total = {}, providers } = serverReponse;
+        const serverResponse: any = await this.api.post(`/v1/compacts/${params.compact}/providers/search`, requestParams);
+        const { total = {}, providers } = serverResponse;

And similarly at line 395:

-        const serverReponse: any = await this.api.post(`/v1/compacts/${params.compact}/privileges/export`, requestParams);
+        const serverResponse: any = await this.api.post(`/v1/compacts/${params.compact}/privileges/export`, requestParams);
 
-        return serverReponse;
+        return serverResponse;

399-402: Remove commented-out debug code.

The commented mock URL block appears to be leftover development code. Consider removing it to keep the codebase clean.

🔎 Suggested removal:
         return serverReponse;
-
-        // return {
-        //     downloadUrl: 'https://cdn.prod.website-files.com/66a083c22bdfd06a6aee5193/6913a447111789a56d2f13b9_IA-Logo-Primary-FullColor.svg',
-        // };
     }
webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts (1)

322-326: Consider consolidating search type state.

The selectedSearchType data property duplicates state from formData.searchType.value. Consider using a computed getter instead to avoid potential sync issues:

get selectedSearchType(): SearchTypes {
    return this.formData?.searchType?.value || SearchTypes.PROVIDER;
}

Alternatively, ensure updateSearchType() is called consistently whenever the radio input changes.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4058377 and 0494011.

📒 Files selected for processing (51)
  • .github/workflows/check-webroot.yml (2 hunks)
  • webroot/.env.example (2 hunks)
  • webroot/README.md (2 hunks)
  • webroot/src/components/Forms/InputSubmit/InputSubmit.ts (1 hunks)
  • webroot/src/components/Forms/InputSubmit/InputSubmit.vue (1 hunks)
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.less (3 hunks)
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts (1 hunks)
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.ts (7 hunks)
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.vue (3 hunks)
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.less (1 hunks)
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts (1 hunks)
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts (1 hunks)
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.less (3 hunks)
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.spec.ts (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts (9 hunks)
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (3 hunks)
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.less (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue (1 hunks)
  • webroot/src/components/Lists/ListContainer/ListContainer.spec.ts (6 hunks)
  • webroot/src/components/Lists/ListContainer/ListContainer.ts (1 hunks)
  • webroot/src/components/Lists/ListContainer/ListContainer.vue (2 hunks)
  • webroot/src/components/Lists/Pagination/Pagination.less (2 hunks)
  • webroot/src/components/Lists/Pagination/Pagination.spec.ts (1 hunks)
  • webroot/src/components/Lists/Pagination/Pagination.ts (8 hunks)
  • webroot/src/components/Lists/Pagination/Pagination.vue (2 hunks)
  • webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.less (1 hunks)
  • webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.spec.ts (1 hunks)
  • webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.ts (1 hunks)
  • webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.vue (1 hunks)
  • webroot/src/components/Page/PageContainer/PageContainer.less (1 hunks)
  • webroot/src/components/Page/PageHeader/PageHeader.less (1 hunks)
  • webroot/src/locales/en.json (8 hunks)
  • webroot/src/locales/es.json (8 hunks)
  • webroot/src/network/data.api.ts (3 hunks)
  • webroot/src/network/licenseApi/data.api.ts (1 hunks)
  • webroot/src/network/mocks/mock.data.api.ts (1 hunks)
  • webroot/src/network/searchApi/data.api.ts (1 hunks)
  • webroot/src/network/searchApi/interceptors.ts (1 hunks)
  • webroot/src/pages/LicensingList/LicensingList.ts (1 hunks)
  • webroot/src/pages/LicensingList/LicensingList.vue (1 hunks)
  • webroot/src/pages/PublicLicensingList/PublicLicensingList.ts (1 hunks)
  • webroot/src/plugins/EnvConfig/envConfig.plugin.ts (4 hunks)
  • webroot/src/plugins/Statsig/statsig.plugin.ts (1 hunks)
  • webroot/src/store/license/license.actions.ts (3 hunks)
  • webroot/src/store/license/license.mutations.ts (4 hunks)
  • webroot/src/store/license/license.spec.ts (6 hunks)
  • webroot/src/store/license/license.state.ts (3 hunks)
  • webroot/src/styles.common/mixins/buttons.less (1 hunks)
🧰 Additional context used
🧠 Learnings (25)
📚 Learning: 2025-08-29T18:44:53.901Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1042
File: webroot/src/pages/PublicDashboard/PublicDashboard.spec.ts:39-45
Timestamp: 2025-08-29T18:44:53.901Z
Learning: In webroot/src/pages/PublicDashboard/PublicDashboard.spec.ts, the test intentionally calls getCognitoConfig() without arguments to test runtime fallback behavior and improve code coverage, even though this causes a TypeScript error. This is a valid testing pattern for verifying that functions handle invalid arguments gracefully.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts
  • webroot/src/store/license/license.spec.ts
  • webroot/src/components/Lists/Pagination/Pagination.spec.ts
  • webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.spec.ts
📚 Learning: 2025-09-09T19:28:53.260Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1071
File: webroot/tests/helpers/setup.ts:153-155
Timestamp: 2025-09-09T19:28:53.260Z
Learning: In the CompactConnect project, component tests are kept minimal and focus primarily on basic functionality. The main testing effort is concentrated on the data layer (models, store, etc.). For component tests, API stub methods only need to exist to prevent runtime errors - they don't need to return specific mock data since components aren't being tested for full API integration scenarios.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts
  • webroot/src/components/Lists/Pagination/Pagination.spec.ts
📚 Learning: 2025-08-29T18:22:23.275Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1042
File: webroot/src/pages/MfaResetConfirmLicensee/MfaResetConfirmLicensee.spec.ts:12-12
Timestamp: 2025-08-29T18:22:23.275Z
Learning: In the CompactConnect frontend codebase, async describe blocks are widely used and supported in their version of Mocha. The pattern `describe('Test Suite', async () => {` is an accepted and working approach throughout their test files, so suggestions to remove the async keyword from describe blocks should not be made for this codebase.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts
📚 Learning: 2025-05-28T16:09:12.906Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/components/Forms/InputEmailList/InputEmailList.spec.ts:12-19
Timestamp: 2025-05-28T16:09:12.906Z
Learning: The CompactConnect application uses mount testing as the general component testing strategy. They focus their testing efforts on the data layer (models and store) rather than extensive component testing, and mount tests meet their coverage needs.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts
📚 Learning: 2025-05-28T16:09:24.547Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/components/StateSettingsConfig/StateSettingsConfig.spec.ts:12-19
Timestamp: 2025-05-28T16:09:24.547Z
Learning: The CompactConnect app uses mount testing as their general component testing strategy, focusing more on testing the data layer (models and store) rather than comprehensive component testing. This meets their test coverage needs and is their preferred approach.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts
📚 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/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.spec.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts
  • webroot/src/pages/LicensingList/LicensingList.vue
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue
  • webroot/src/pages/PublicLicensingList/PublicLicensingList.ts
  • webroot/src/store/license/license.mutations.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.vue
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/pages/LicensingList/LicensingList.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
  • webroot/src/store/license/license.state.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.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/Lists/PaginationLegacy/PaginationLegacy.vue
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.less
  • webroot/src/pages/LicensingList/LicensingList.vue
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.less
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue
  • webroot/src/pages/PublicLicensingList/PublicLicensingList.ts
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.vue
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.less
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.less
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/pages/LicensingList/LicensingList.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.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/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.less
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.less
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.ts
📚 Learning: 2025-09-16T18:43:23.028Z
Learnt from: ChiefStief
Repo: csg-org/CompactConnect PR: 1093
File: webroot/src/components/Icons/ExpirationExplanationIcon/ExpirationExplanationIcon.less:7-16
Timestamp: 2025-09-16T18:43:23.028Z
Learning: In the CompactConnect codebase, _reset.less applies `position: relative;` globally to almost all HTML elements, so additional position: relative declarations on individual components are redundant.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.less
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.less
📚 Learning: 2025-08-13T18:20:12.967Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1010
File: webroot/src/components/Icons/DownloadFile/DownloadFile.vue:8-20
Timestamp: 2025-08-13T18:20:12.967Z
Learning: In the CompactConnect codebase, SVG icons in the webroot/src/components/Icons/ directory are designed to be styled by their parent components via CSS, not with inline SVG attributes. This allows the same icon to be reused with different sizes, colors, and stroke properties across different components. Accessibility attributes like aria-hidden are handled at the parent container level, not on the SVG element itself.

Applied to files:

  • webroot/src/components/Lists/Pagination/Pagination.less
📚 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/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
  • webroot/src/store/license/license.state.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.ts
📚 Learning: 2025-05-28T16:13:19.506Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/components/Forms/InputEmailList/InputEmailList.vue:26-30
Timestamp: 2025-05-28T16:13:19.506Z
Learning: In the InputEmailList component (webroot/src/components/Forms/InputEmailList/InputEmailList.vue), the formInput.labelSubtext property rendered with v-html contains only developer-controlled content, not user-controlled content, so XSS concerns do not apply.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue
  • webroot/src/components/Forms/InputSubmit/InputSubmit.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue
  • webroot/src/components/Lists/Pagination/Pagination.vue
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.vue
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.vue
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts
  • webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.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/license/license.mutations.ts
  • webroot/src/store/license/license.spec.ts
📚 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/store/license/license.spec.ts
📚 Learning: 2025-11-06T18:11:58.272Z
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.272Z
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/store/license/license.spec.ts
  • webroot/src/locales/es.json
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
  • webroot/src/locales/en.json
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.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-08-13T18:24:06.298Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1010
File: webroot/src/components/MilitaryDocumentRow/MilitaryDocumentRow.vue:19-21
Timestamp: 2025-08-13T18:24:06.298Z
Learning: In MilitaryAffiliationInfoBlock, the militaryDocumentHeader() getter returns an object with wrapper functions that provide translated labels for header display, including firstDownloadLink: () => this.$t('common.downloadFile'). When used as a header item in MilitaryDocumentRow, these wrapper functions return appropriate column labels rather than actual data values.

Applied to files:

  • webroot/src/locales/es.json
  • webroot/src/locales/en.json
📚 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/components/Licensee/LicenseeSearch/LicenseeSearch.spec.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/Forms/InputSubmit/InputSubmit.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-08-21T19:17:21.038Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 1025
File: webroot/src/models/Licensee/Licensee.model.ts:276-312
Timestamp: 2025-08-21T19:17:21.038Z
Learning: In CompactConnect, address information should only come from License objects, not from top-level Licensee fields. The API no longer returns top-level licensee address fields, so all address data flows through individual license objects that contain fields like homeAddressStreet1, homeAddressCity, etc. The bestLicense() and bestLicenseMailingAddress() methods are used to access the most appropriate address from a licensee's collection of licenses.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
📚 Learning: 2025-06-04T22:04:14.373Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 843
File: webroot/src/components/Forms/InputDate/InputDate.ts:0-0
Timestamp: 2025-06-04T22:04:14.373Z
Learning: In the InputDate component (webroot/src/components/Forms/InputDate/InputDate.ts), immediate validation on every keystroke is intentional design behavior. The team prefers to alert users to encourage expected date format completion rather than deferring validation until the date is complete. This provides immediate feedback to guide users toward proper MM/dd/yyyy format completion.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
📚 Learning: 2025-06-19T23:43:25.512Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/components/PrivilegeCard/PrivilegeCard.ts:0-0
Timestamp: 2025-06-19T23:43:25.512Z
Learning: In Vue form components, when programmatically setting form input values, it's more efficient to validate just the specific form element being updated (e.g., `formInput.validate()`) rather than calling `validateAll()` on the entire form.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-07-10T19:50:56.745Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 922
File: webroot/src/components/UserAccount/UserAccount.ts:0-0
Timestamp: 2025-07-10T19:50:56.745Z
Learning: In the UserAccount component (webroot/src/components/UserAccount/UserAccount.ts), the email field should be disabled for staff users (`isDisabled: this.isStaff`) to maintain existing restrictions, while licensees should be able to change their email address through the new verification process. This is the intended behavior per PR #922 requirements.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
🧬 Code graph analysis (14)
webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.spec.ts (1)
webroot/tests/helpers/setup.ts (1)
  • mountShallow (265-265)
webroot/src/network/searchApi/interceptors.ts (1)
webroot/src/app.config.ts (1)
  • authStorage (98-98)
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.spec.ts (3)
webroot/tests/helpers/setup.ts (2)
  • mountShallow (265-265)
  • mountFull (266-266)
webroot/src/components/Licensee/LicenseeList/LicenseeList.ts (1)
  • fetchListData (302-321)
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts (1)
  • fetchListData (256-351)
webroot/src/store/license/license.mutations.ts (2)
webroot/src/store/license/license.state.ts (1)
  • state (21-35)
webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts (1)
  • LicenseSearchLegacy (26-31)
webroot/src/store/license/license.spec.ts (1)
webroot/src/store/license/license.state.ts (1)
  • state (21-35)
webroot/src/components/Lists/Pagination/Pagination.ts (5)
webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.ts (3)
  • currentPage (115-119)
  • pageSize (121-125)
  • pageCount (127-129)
webroot/src/components/Lists/_mixins/Pagination.mixin.ts (2)
  • currentPage (92-94)
  • pagination (84-86)
webroot/src/components/Licensee/LicenseeList/LicenseeList.ts (1)
  • paginationStore (76-78)
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts (1)
  • paginationStore (76-78)
webroot/src/components/StyleGuide/ExampleList/ExampleList.ts (1)
  • paginationStore (45-47)
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.ts (4)
webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts (1)
  • LicenseSearchLegacy (26-31)
webroot/src/store/license/license.state.ts (2)
  • state (21-35)
  • State (10-19)
webroot/src/store/pagination/pagination.state.ts (3)
  • DEFAULT_PAGE (8-8)
  • DEFAULT_PAGE_SIZE (9-9)
  • PageChangeConfig (23-27)
webroot/src/store/pagination/index.ts (1)
  • PageExhaustError (12-17)
webroot/src/network/data.api.ts (1)
webroot/src/network/searchApi/data.api.ts (1)
  • searchDataApi (405-405)
webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts (3)
webroot/src/store/license/license.state.ts (2)
  • State (10-19)
  • state (21-35)
webroot/src/models/FormInput/FormInput.model.ts (1)
  • FormInput (59-170)
webroot/src/models/Compact/Compact.model.ts (1)
  • CompactSerializer (129-139)
webroot/src/pages/LicensingList/LicensingList.ts (1)
webroot/src/pages/PublicLicensingList/PublicLicensingList.ts (1)
  • Component (12-20)
webroot/src/store/license/license.actions.ts (2)
webroot/src/network/mocks/mock.data.api.ts (1)
  • dataApi (837-837)
webroot/src/network/data.api.ts (1)
  • dataApi (712-712)
webroot/src/network/searchApi/data.api.ts (3)
webroot/src/network/licenseApi/data.api.ts (1)
  • DataApiInterface (56-58)
webroot/src/network/searchApi/interceptors.ts (4)
  • requestSuccess (16-27)
  • requestError (34-34)
  • responseSuccess (43-47)
  • responseError (54-76)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • LicenseeSerializer (402-470)
webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.spec.ts (3)
webroot/tests/helpers/setup.ts (2)
  • mountShallow (265-265)
  • mountFull (266-266)
webroot/src/components/Lists/Pagination/Pagination.ts (1)
  • pages (148-195)
webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.ts (1)
  • pages (139-155)
webroot/src/store/license/license.state.ts (2)
webroot/src/components/Licensee/LicenseeSearchLegacy/LicenseeSearchLegacy.ts (1)
  • LicenseSearchLegacy (26-31)
webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.ts (1)
  • LicenseSearch (40-55)
🪛 dotenv-linter (4.0.0)
webroot/.env.example

[warning] 8-8: [UnorderedKey] The VUE_APP_API_SEARCH_ROOT key should go before the VUE_APP_API_STATE_ROOT key

(UnorderedKey)


[warning] 17-17: [UnorderedKey] The VUE_APP_STATSIG_DISABLED key should go before the VUE_APP_STATSIG_KEY key

(UnorderedKey)

⏰ 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

- PR review updates
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: 6

🧹 Nitpick comments (5)
webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue (3)

43-44: Remove redundant this keyword in template bindings.

In Vue templates, the this keyword is implicit and not required. Removing it follows Vue conventions and improves readability.

🔎 Proposed changes
-                    :listData="this.licenseStore.model"
-                    :listSize="this.licenseStore.total"
+                    :listData="licenseStore.model"
+                    :listSize="licenseStore.total"
-                        <LicenseeRow
-                            v-for="(record, index) in this.licenseStore.model"
+                        <LicenseeRow
+                            v-for="(record, index) in licenseStore.model"

Also applies to: 68-68


68-70: Use a unique identifier as the key instead of the array index.

Using the array index as the key in v-for can lead to rendering issues if the list is manipulated. Each licensee record likely has a unique identifier (such as id or licenseId) that should be used instead.

🔎 Proposed change
                         <LicenseeRow
-                            v-for="(record, index) in licenseStore.model"
-                            :key="index"
+                            v-for="record in licenseStore.model"
+                            :key="record.id"
                             :listId="listId"
                             :item="record"

Note: Adjust record.id to match the actual unique identifier property in your record structure.


23-27: Remove redundant tabindex="0" from button.

The tabindex="0" attribute is unnecessary on button elements, as they are naturally focusable. This can be safely removed.

🔎 Proposed change
                         <button
                             class="search-toggle"
                             @click="toggleSearch()"
-                            tabindex="0"
                         >
webroot/src/network/searchApi/data.api.ts (1)

59-69: Consider type-safe window augmentation.

The current approach uses window as any to add debugging utilities. While functional, consider declaring a proper interface augmentation for better type safety.

🔎 Suggested approach

At the top of the file or in a shared types file:

declare global {
    interface Window {
        ccQueryToggle?: () => void;
        ccIsQueryLogEnabled?: boolean;
    }
}

Then replace lines 59-69:

-const appWindow = window as any;
-
-appWindow.ccQueryToggle = (): void => {
-    if (appWindow.ccIsQueryLogEnabled) {
-        appWindow.ccIsQueryLogEnabled = false;
+window.ccQueryToggle = (): void => {
+    if (window.ccIsQueryLogEnabled) {
+        window.ccIsQueryLogEnabled = false;
         console.log('CompactConnect search query logging: DISABLED');
     } else {
-        appWindow.ccIsQueryLogEnabled = true;
+        window.ccIsQueryLogEnabled = true;
         console.log('CompactConnect search query logging: ENABLED');
     }
 };
webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (1)

78-98: Hardcoded year will require annual maintenance.

The date pickers have yearRange starting at 2025, which is hardcoded. This will need updating each year and may already be outdated if privileges can be purchased earlier.

🔎 Suggested approach

Consider using a dynamic year range based on a reasonable lookback period:

-                    :yearRange="[2025, new Date().getFullYear()]"
+                    :yearRange="[new Date().getFullYear() - 5, new Date().getFullYear()]"

Or define a constant in the component if 2025 represents a significant business date (e.g., system launch year):

// In the TypeScript file
const SYSTEM_START_YEAR = 2025;
-                    :yearRange="[2025, new Date().getFullYear()]"
+                    :yearRange="[SYSTEM_START_YEAR, new Date().getFullYear()]"

This applies to both the privilege purchase date range (lines 78-98) and the encumber date range (lines 120-140).

Also applies to: 120-140

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0494011 and c9d7d9d.

📒 Files selected for processing (5)
  • backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py (1 hunks)
  • webroot/src/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (3 hunks)
  • webroot/src/locales/es.json (8 hunks)
  • webroot/src/network/searchApi/data.api.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (17)
📚 Learning: 2025-10-10T18:45:43.801Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1114
File: backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py:34-35
Timestamp: 2025-10-10T18:45:43.801Z
Learning: In backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py, the cdk.context.deploy-example.json file is intentionally minimal and serves as a template, not for actual deployments. Actual deployment environments (test, beta, prod, sandbox) contain all required environment-specific keys like statsig_key, app_env, recaptcha_public_key, and robots_meta. This is by design.

Applied to files:

  • backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py
📚 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/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.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/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
📚 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/components/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeListLegacy/LicenseeListLegacy.vue
📚 Learning: 2025-11-06T18:11:58.272Z
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.272Z
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/locales/es.json
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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-08-13T18:24:06.298Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1010
File: webroot/src/components/MilitaryDocumentRow/MilitaryDocumentRow.vue:19-21
Timestamp: 2025-08-13T18:24:06.298Z
Learning: In MilitaryAffiliationInfoBlock, the militaryDocumentHeader() getter returns an object with wrapper functions that provide translated labels for header display, including firstDownloadLink: () => this.$t('common.downloadFile'). When used as a header item in MilitaryDocumentRow, these wrapper functions return appropriate column labels rather than actual data values.

Applied to files:

  • webroot/src/locales/es.json
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-11-13T22:13:48.430Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1188
File: backend/compact-connect/tests/smoke/rollback_license_upload_smoke_tests.py:354-372
Timestamp: 2025-11-13T22:13:48.430Z
Learning: In the CompactConnect codebase, privilege records use datetime fields (not date fields) for dateOfIssuance, dateOfRenewal, and dateOfExpiration, which is intentionally different from license records that use date fields for these same attributes.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-11-12T21:06:06.981Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/components/LicenseCard/LicenseCard.ts:388-396
Timestamp: 2025-11-12T21:06:06.981Z
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/searchApi/data.api.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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-07-10T19:50:56.745Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 922
File: webroot/src/components/UserAccount/UserAccount.ts:0-0
Timestamp: 2025-07-10T19:50:56.745Z
Learning: In the UserAccount component (webroot/src/components/UserAccount/UserAccount.ts), the email field should be disabled for staff users (`isDisabled: this.isStaff`) to maintain existing restrictions, while licensees should be able to change their email address through the new verification process. This is the intended behavior per PR #922 requirements.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-06-19T23:43:25.512Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/components/PrivilegeCard/PrivilegeCard.ts:0-0
Timestamp: 2025-06-19T23:43:25.512Z
Learning: In Vue form components, when programmatically setting form input values, it's more efficient to validate just the specific form element being updated (e.g., `formInput.validate()`) rather than calling `validateAll()` on the entire form.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
🧬 Code graph analysis (2)
backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py (1)
backend/common-cdk/common_constructs/frontend_app_config_utility.py (1)
  • api_domain_name (226-228)
webroot/src/network/searchApi/data.api.ts (3)
webroot/src/network/licenseApi/data.api.ts (1)
  • DataApiInterface (56-58)
webroot/src/network/searchApi/interceptors.ts (4)
  • requestSuccess (16-27)
  • requestError (34-34)
  • responseSuccess (43-47)
  • responseError (54-76)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • LicenseeSerializer (402-470)
⏰ 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). (2)
  • GitHub Check: TestApp
  • GitHub Check: CheckWebroot
🔇 Additional comments (12)
webroot/src/locales/es.json (1)

27-28: LGTM! Previous translation issue resolved.

The Spanish translations for the new search and export functionality are accurate and semantically appropriate. The previous issue with exportInProgress (line 28) has been corrected—it now properly uses the gerund form "Exportando..." instead of the noun "Exportador...".

All new translations cover:

  • Export functionality and date filters
  • Search UI labels and provider terminology
  • Investigation and military status options with proper key/name structures
  • Server error messages

Based on learnings, Spanish translations are auto-generated and considered nice-to-have for now, with professional translation services planned for formal Spanish support if needed.

Also applies to: 82-83, 85-86, 457-458, 568-568, 576-576, 578-578, 605-605, 613-614, 620-621, 644-653, 726-726, 926-943

webroot/src/network/searchApi/data.api.ts (5)

78-120: LGTM: Axios configuration and interceptor setup.

The Axios instance configuration is appropriate for a search API with a 30-second timeout for potentially complex queries. The interceptor initialization follows the standard pattern and properly injects the store context for error handling.


127-188: LGTM: Licensee search parameter handling.

The query construction for licensee-level search parameters uses appropriate OpenSearch query types: match_phrase_prefix for name prefix matching, term for exact state/status matching, and match for NPI search.


213-242: LGTM: Date filtering logic correctly implemented.

The privilege date filtering has been correctly implemented using a should clause with minimum_should_match: 1 (lines 214-215). This properly matches privileges where either dateOfIssuance or dateOfRenewal falls within the specified range, addressing the concern raised in the previous review.


249-328: LGTM: Adverse action and investigation filtering logic.

The nested query structures for adverse actions and investigations are correctly implemented:

  • Adverse actions use should with minimum_should_match: 1 to match either licenses or privileges
  • Investigation status appropriately branches: should for "underInvestigation" (match either), must_not otherwise (exclude both)

335-356: LGTM: Pagination and sorting implementation.

The pagination logic correctly calculates zero-based from offset from one-based page numbers. The sorting appends .keyword suffix, which is the correct approach for sorting on text fields in OpenSearch.

webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (6)

15-21: LGTM!

The MockPopulate component integration is clean and properly bound.


37-42: LGTM!

The InputRadioGroup component properly replaces the previous search type selector with appropriate bindings.


56-68: LGTM!

The state selection fields are well-implemented, with the disabled state tooltip on homeState providing helpful user feedback.


99-104: Acknowledged: Military status field pending.

The TODO comment clearly indicates this field will be added in a future PR with military status updates. This is acceptable for incremental development.


105-110: LGTM!

The investigation status field is properly implemented.


141-145: LGTM!

The NPI input field is correctly implemented.

- PR review updates
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: 3

♻️ Duplicate comments (1)
webroot/src/network/searchApi/data.api.ts (1)

401-403: Remove commented-out mock code.

This commented-out mock return statement should be removed as flagged in a previous review. Dead code clutters the codebase.

🔎 Suggested fix
         return serverResponse;
-
-        // return {
-        //     downloadUrl: 'https://cdn.prod.website-files.com/66a083c22bdfd06a6aee5193/6913a447111789a56d2f13b9_IA-Logo-Primary-FullColor.svg',
-        // };
     }
🧹 Nitpick comments (1)
webroot/src/network/searchApi/data.api.ts (1)

249-289: Consider filtering by active encumbrances only.

The adverse action query filters by effectiveStartDate range but doesn't check whether the adverse action is still active. Since adverse actions have an effectiveLiftDate field that indicates when they were lifted, filtering should exclude adverse actions where effectiveLiftDate is in the past, to avoid returning providers with historical encumbrances that have already been resolved.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c9d7d9d and 56447b1.

📒 Files selected for processing (4)
  • backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py (1 hunks)
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (3 hunks)
  • webroot/src/models/Investigation/Investigation.model.spec.ts (1 hunks)
  • webroot/src/network/searchApi/data.api.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/compact-connect-ui-app/stacks/frontend_deployment_stack/deployment.py
🧰 Additional context used
🧠 Learnings (24)
📚 Learning: 2025-11-12T21:06:06.981Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/components/LicenseCard/LicenseCard.ts:388-396
Timestamp: 2025-11-12T21:06:06.981Z
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/models/Investigation/Investigation.model.spec.ts
  • webroot/src/network/searchApi/data.api.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/Investigation/Investigation.model.spec.ts
  • webroot/src/network/searchApi/data.api.ts
📚 Learning: 2025-11-06T18:14:40.626Z
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.626Z
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/models/Investigation/Investigation.model.spec.ts
📚 Learning: 2025-11-06T18:11:58.272Z
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.272Z
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/models/Investigation/Investigation.model.spec.ts
  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Investigation/Investigation.model.spec.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/Investigation/Investigation.model.spec.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 CompactConnect codebase can intelligently handle both date-only strings (serverDateFormat) and datetime strings (serverDatetimeFormat) automatically. When writing tests for date display methods, the expectation should match the parsing behavior rather than assuming the input format needs to be specified explicitly.

Applied to files:

  • webroot/src/models/Investigation/Investigation.model.spec.ts
📚 Learning: 2025-04-29T01:57:43.684Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 769
File: backend/compact-connect/lambdas/python/common/tests/resources/dynamo/provider.json:5-5
Timestamp: 2025-04-29T01:57:43.684Z
Learning: The provider.json test data contains both "providerDateOfUpdate" and "dateOfUpdate" fields which serve different purposes, and both should be maintained in the test files.

Applied to files:

  • webroot/src/models/Investigation/Investigation.model.spec.ts
📚 Learning: 2025-11-13T22:13:48.430Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1188
File: backend/compact-connect/tests/smoke/rollback_license_upload_smoke_tests.py:354-372
Timestamp: 2025-11-13T22:13:48.430Z
Learning: In the CompactConnect codebase, privilege records use datetime fields (not date fields) for dateOfIssuance, dateOfRenewal, and dateOfExpiration, which is intentionally different from license records that use date fields for these same attributes.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-07-02T21:10:06.663Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 904
File: webroot/src/components/StateSettingsList/StateSettingsList.ts:49-49
Timestamp: 2025-07-02T21:10:06.663Z
Learning: In the CompactConnect TypeScript codebase, the team generally avoids `any` types but makes an exception for server responses. They use `any` for server response data to prevent overly verbose TypeScript syntax and avoid double casting as `unknown` when updating values from the server. These server responses get reorganized as typed models elsewhere in the codebase, maintaining type safety where it matters most while keeping the code clean.

Applied to files:

  • webroot/src/network/searchApi/data.api.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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-07-10T19:50:56.745Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 922
File: webroot/src/components/UserAccount/UserAccount.ts:0-0
Timestamp: 2025-07-10T19:50:56.745Z
Learning: In the UserAccount component (webroot/src/components/UserAccount/UserAccount.ts), the email field should be disabled for staff users (`isDisabled: this.isStaff`) to maintain existing restrictions, while licensees should be able to change their email address through the new verification process. This is the intended behavior per PR #922 requirements.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-05-28T16:10:55.628Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/components/Forms/InputEmailList/InputEmailList.less:17-26
Timestamp: 2025-05-28T16:10:55.628Z
Learning: The `.add-email-help` element in the InputEmailList component (webroot/src/components/Forms/InputEmailList/InputEmailList.less) is display-only and not meant to handle interaction states like hover or focus. It should not have cursor: pointer or interactive styling.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-06-24T00:17:31.188Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 873
File: webroot/src/styles.common/_inputs.less:115-118
Timestamp: 2025-06-24T00:17:31.188Z
Learning: The team intentionally uses broad CSS selectors like `.dp__input_wrap div { position: static; }` to fix styling issues with the Vue Date-Picker library. They have experience with these styles working well, keep the library version pinned in yarn.lock, and have established processes to re-test everything when updating the library version. This approach is acceptable given their testing discipline and version control.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-05-28T16:13:19.506Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/components/Forms/InputEmailList/InputEmailList.vue:26-30
Timestamp: 2025-05-28T16:13:19.506Z
Learning: In the InputEmailList component (webroot/src/components/Forms/InputEmailList/InputEmailList.vue), the formInput.labelSubtext property rendered with v-html contains only developer-controlled content, not user-controlled content, so XSS concerns do not apply.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 Learning: 2025-06-04T22:04:14.373Z
Learnt from: rmolinares
Repo: csg-org/CompactConnect PR: 843
File: webroot/src/components/Forms/InputDate/InputDate.ts:0-0
Timestamp: 2025-06-04T22:04:14.373Z
Learning: In the InputDate component (webroot/src/components/Forms/InputDate/InputDate.ts), immediate validation on every keystroke is intentional design behavior. The team prefers to alert users to encourage expected date format completion rather than deferring validation until the date is complete. This provides immediate feedback to guide users toward proper MM/dd/yyyy format completion.

Applied to files:

  • webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/components/Licensee/LicenseeSearch/LicenseeSearch.vue
📚 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/components/Licensee/LicenseeSearch/LicenseeSearch.vue
🧬 Code graph analysis (2)
webroot/src/models/Investigation/Investigation.model.spec.ts (1)
webroot/src/app.config.ts (1)
  • serverDateFormat (175-175)
webroot/src/network/searchApi/data.api.ts (3)
webroot/src/network/licenseApi/data.api.ts (1)
  • DataApiInterface (56-58)
webroot/src/network/searchApi/interceptors.ts (4)
  • requestSuccess (16-27)
  • requestError (34-34)
  • responseSuccess (43-47)
  • responseError (54-76)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • LicenseeSerializer (402-470)
⏰ 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). (2)
  • GitHub Check: CheckWebroot
  • GitHub Check: TestApp
🔇 Additional comments (6)
webroot/src/network/searchApi/data.api.ts (1)

59-69: Debug toggle implementation looks reasonable for development.

The ccQueryToggle() function provides a useful runtime debugging capability. This is a reasonable approach for development-time query inspection.

webroot/src/components/Licensee/LicenseeSearch/LicenseeSearch.vue (4)

15-29: Dev-only tooling accepted as-is.

The MockPopulate and clear button are development-only utilities. Per previous discussion, accessibility rigor isn't required for these local development helpers.


74-96: Date inputs have proper accessibility associations.

Good use of aria-labelledby to associate the date inputs with their section labels. This addresses the previous accessibility concerns while keeping the labels as visual grouping elements.

Minor note: The yearRange starts at 2025, which may need adjustment in future years or based on data availability.


143-159: Submit button prop issue resolved.

Both InputSubmit components now correctly use the :isEnabled prop instead of the previously flagged :isDisabled. The conditional rendering for provider search vs. privilege export is clean.


97-102: Commented placeholder with clear TODO.

The military status field is appropriately commented out with a clear TODO indicating it will be added in the next PR with military status updates.

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

136-138: No changes needed. The test is self-contained—it generates test data with moment().format(serverDateFormat) and immediately asserts the serializer preserves it exactly. Since no hardcoded date values or UTC-based comparisons are involved, the test won't experience timezone-related flakiness in different CI environments. This pattern aligns with how date handling is used elsewhere in the codebase.

- PR review updates
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/searchApi/data.api.ts (1)

104-104: Add type annotation for the router parameter.

While the JSDoc indicates this should be a Router type, the parameter lacks a TypeScript type annotation. Adding the type improves type safety and IDE support.

🔎 Suggested fix
-    public initInterceptors(router) {
+    public initInterceptors(router: any) {

Or, if the Router type is available:

+import { Router } from 'vue-router';
+
 // ... 
-    public initInterceptors(router) {
+    public initInterceptors(router: Router) {
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56447b1 and 093e9d5.

📒 Files selected for processing (1)
  • webroot/src/network/searchApi/data.api.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-12-19T16:04:23.341Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1234
File: webroot/src/network/searchApi/data.api.ts:83-95
Timestamp: 2025-12-19T16:04:23.341Z
Learning: In the CompactConnect codebase, all network API files under webroot/src/network/*/data.api.ts use a specific axios.create header configuration pattern with nested get/post/put objects inside the headers config. Reviewers should not flag this pattern as an issue, since it aligns with the project’s Axios version and conventions. If enforcing general axios patterns, treat this as a project-specific exception and focus on consistency within this path.

Applied to files:

  • webroot/src/network/searchApi/data.api.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/network/searchApi/data.api.ts
📚 Learning: 2025-11-13T22:13:48.430Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1188
File: backend/compact-connect/tests/smoke/rollback_license_upload_smoke_tests.py:354-372
Timestamp: 2025-11-13T22:13:48.430Z
Learning: In the CompactConnect codebase, privilege records use datetime fields (not date fields) for dateOfIssuance, dateOfRenewal, and dateOfExpiration, which is intentionally different from license records that use date fields for these same attributes.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-11-12T21:06:06.981Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/components/LicenseCard/LicenseCard.ts:388-396
Timestamp: 2025-11-12T21:06:06.981Z
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/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-07-02T21:10:06.663Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 904
File: webroot/src/components/StateSettingsList/StateSettingsList.ts:49-49
Timestamp: 2025-07-02T21:10:06.663Z
Learning: In the CompactConnect TypeScript codebase, the team generally avoids `any` types but makes an exception for server responses. They use `any` for server response data to prevent overly verbose TypeScript syntax and avoid double casting as `unknown` when updating values from the server. These server responses get reorganized as typed models elsewhere in the codebase, maintaining type safety where it matters most while keeping the code clean.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 Learning: 2025-05-28T16:12:31.310Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/router/routes.ts:96-99
Timestamp: 2025-05-28T16:12:31.310Z
Learning: In webroot/src/router/routes.ts, the team prefers to keep router logic simple and handle route parameter validation (like state abbreviations) in the page components themselves based on user permissions, rather than adding validation at the router level.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 Learning: 2025-08-25T19:04:48.800Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1014
File: backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_account_recovery.py:288-293
Timestamp: 2025-08-25T19:04:48.800Z
Learning: In the CompactConnect project, landonshumway-ia has already provided feedback on patch cleanup patterns in test setup methods for the account recovery tests, so similar suggestions about stopping patches in setUp/tearDown should not be repeated.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
🧬 Code graph analysis (1)
webroot/src/network/searchApi/data.api.ts (3)
webroot/src/network/licenseApi/data.api.ts (1)
  • DataApiInterface (56-58)
webroot/src/network/searchApi/interceptors.ts (1)
  • requestSuccess (16-27)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • LicenseeSerializer (402-470)
⏰ 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). (2)
  • GitHub Check: CheckWebroot
  • GitHub Check: TestApp
🔇 Additional comments (1)
webroot/src/network/searchApi/data.api.ts (1)

213-242: Excellent work addressing previous feedback!

All the issues from the previous review have been resolved:

  • The date range logic now correctly uses should with minimum_should_match: 1 (lines 214-215, 240), allowing privileges to match if either dateOfIssuance OR dateOfRenewal falls within the range.
  • Variable naming typos (serverReponseserverResponse) have been fixed on lines 372 and 397.
  • Default empty array for providers has been added on line 373 to prevent potential TypeError.

The query building logic is well-structured and handles the OpenSearch nested queries correctly for privileges, adverse actions, and investigations.

Also applies to: 372-373, 397-397

@ChiefStief
Copy link
Contributor

The mobile version has ascending / descending controls. Im not aware of being able to access these in the desktop version. Not sure if that matters:
Screenshot 2025-12-19 at 2 56 33 PM (2)

@ChiefStief
Copy link
Contributor

Im not a huge fan of the way the infinity looks here. IDK if we can maybe make it bigger and / or centered with the dash
Screenshot 2025-12-19 at 3 01 01 PM (2)

@ChiefStief
Copy link
Contributor

The staff users list search doesn't seem to be filtering anything out, the front end is sending the search criteria and the backend is just returning everything all the time:

Screenshot 2025-12-19 at 3 19 33 PM (2)

@ChiefStief
Copy link
Contributor

Not related to this PR but active since doesn't seem to be fully functional here: http://localhost:3018/Search/octp/a87cc993-100d-42dc-8769-a36b0580b621

Screenshot 2025-12-19 at 3 32 27 PM (2) Screenshot 2025-12-19 at 3 32 32 PM (2)

@ChiefStief
Copy link
Contributor

Im not sure how to validate the pagination on legacy lists. Do we have an example that has multiple pages?

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 really good! I have a couple nitpicks

@jsandoval81
Copy link
Collaborator Author

@ChiefStief

  1. The mobile version has ascending / descending controls. Im not aware of being able to access these in the desktop version.

    • The desktop has them too; well one. It's a grey arrow on the Last Name column. That's what this list previously allowed sorting by. We've just kept that the same for now and will potentially introduce additional sorting after some feedback.
  2. Im not a huge fan of the way the infinity looks here. IDK if we can maybe make it bigger and / or centered with the dash

    • Do you think it's rough enough to do a design cycle? If so we can reach out. Or perhaps it's ok enough to release & get feedback along with everything else?
  3. The staff users list search doesn't seem to be filtering anything out, the front end is sending the search criteria and the backend is just returning everything all the time

  4. Not related to this PR but active since doesn't seem to be fully functional here: http://localhost:3018/Search/octp/a87cc993-100d-42dc-8769-a36b0580b621

    • I couldn't find an existing ticket for this. Do you have enough info to create a new ticket?
  5. Im not sure how to validate the pagination on legacy lists. Do we have an example that has multiple pages?

    • Locally you can modify mock data for the users list using something like const response = users.concat(users).concat(users).... This will just test some basics of the UI.
    • For e2e testing you could potentially load quite a few staff users into your sandbox

@ChiefStief
Copy link
Contributor

ChiefStief commented Jan 5, 2026

  1. Sounds good
  2. I think we could just make it a tiny bit bigger + vertically centered and it would be fine. I dont think a design cycle is needed.
  3. Yea I can make a ticket at least
  4. Yea I was specifically hoping to test with the real API e2e. I can add a bunch of staff users in that case.

@jsandoval81 jsandoval81 requested a review from jlkravitz January 5, 2026 19:30
@jsandoval81
Copy link
Collaborator Author

@jlkravitz This is ready for your review.

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.

Thought I submitted this, but I guess not. I'd still like to test locally, but leaving these here to start!

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 (2)
webroot/src/components/Licensee/LicenseeList/LicenseeList.ts (2)

118-134: Infinity symbol visual alignment noted in PR discussion.

The use of for unbounded date ranges is clear, but as noted in the PR comments, there's a visual concern about the infinity symbol's size and vertical centering with the dash. While the author asked if a design cycle is needed, consider whether a small CSS adjustment (e.g., vertical-align: middle or adjusted font-size) could address the visual issue without a full design cycle.

Also applies to: 168-184


399-423: Consider dynamic filename for privilege exports.

The hardcoded filename privilege_export.csv could be enhanced with a timestamp or search criteria summary to help users distinguish between multiple exports.

📝 Optional filename enhancement
-                tempLink.download = `privilege_export.csv`;
+                const timestamp = moment().format('YYYY-MM-DD_HHmmss');
+                tempLink.download = `privilege_export_${timestamp}.csv`;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e19cfd and e68444f.

📒 Files selected for processing (4)
  • webroot/src/components/Licensee/LicenseeList/LicenseeList.ts
  • webroot/src/components/Lists/ListContainer/ListContainer.vue
  • webroot/src/network/mocks/mock.data.api.ts
  • webroot/src/network/searchApi/data.api.ts
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-12-18T19:09:11.026Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1234
File: webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.spec.ts:68-112
Timestamp: 2025-12-18T19:09:11.026Z
Learning: In webroot/src/components/Lists/PaginationLegacy/PaginationLegacy.spec.ts, the tests for "should advance with next page (2)" and "should advance with next page (3)" intentionally share pagination state by reusing the same paginationId ('test'). This shared state is a deliberate testing pattern, not a test isolation issue.

Applied to files:

  • webroot/src/components/Lists/ListContainer/ListContainer.vue
📚 Learning: 2025-12-19T16:04:23.341Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1234
File: webroot/src/network/searchApi/data.api.ts:83-95
Timestamp: 2025-12-19T16:04:23.341Z
Learning: In the CompactConnect codebase, all network API files under webroot/src/network/*/data.api.ts use a specific axios.create header configuration pattern with nested get/post/put objects inside the headers config. Reviewers should not flag this pattern as an issue, since it aligns with the project’s Axios version and conventions. If enforcing general axios patterns, treat this as a project-specific exception and focus on consistency within this path.

Applied to files:

  • webroot/src/network/searchApi/data.api.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/network/searchApi/data.api.ts
📚 Learning: 2025-11-13T22:13:48.430Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1188
File: backend/compact-connect/tests/smoke/rollback_license_upload_smoke_tests.py:354-372
Timestamp: 2025-11-13T22:13:48.430Z
Learning: In the CompactConnect codebase, privilege records use datetime fields (not date fields) for dateOfIssuance, dateOfRenewal, and dateOfExpiration, which is intentionally different from license records that use date fields for these same attributes.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-11-12T21:06:06.981Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 1196
File: webroot/src/components/LicenseCard/LicenseCard.ts:388-396
Timestamp: 2025-11-12T21:06:06.981Z
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/searchApi/data.api.ts
📚 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/network/searchApi/data.api.ts
📚 Learning: 2025-07-02T21:10:06.663Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 904
File: webroot/src/components/StateSettingsList/StateSettingsList.ts:49-49
Timestamp: 2025-07-02T21:10:06.663Z
Learning: In the CompactConnect TypeScript codebase, the team generally avoids `any` types but makes an exception for server responses. They use `any` for server response data to prevent overly verbose TypeScript syntax and avoid double casting as `unknown` when updating values from the server. These server responses get reorganized as typed models elsewhere in the codebase, maintaining type safety where it matters most while keeping the code clean.

Applied to files:

  • webroot/src/network/searchApi/data.api.ts
📚 Learning: 2025-05-28T16:12:31.310Z
Learnt from: jsandoval81
Repo: csg-org/CompactConnect PR: 822
File: webroot/src/router/routes.ts:96-99
Timestamp: 2025-05-28T16:12:31.310Z
Learning: In webroot/src/router/routes.ts, the team prefers to keep router logic simple and handle route parameter validation (like state abbreviations) in the page components themselves based on user permissions, rather than adding validation at the router level.

Applied to files:

  • webroot/src/network/searchApi/data.api.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/searchApi/data.api.ts
📚 Learning: 2025-08-25T19:04:48.800Z
Learnt from: landonshumway-ia
Repo: csg-org/CompactConnect PR: 1014
File: backend/compact-connect/lambdas/python/provider-data-v1/tests/function/test_handlers/test_account_recovery.py:288-293
Timestamp: 2025-08-25T19:04:48.800Z
Learning: In the CompactConnect project, landonshumway-ia has already provided feedback on patch cleanup patterns in test setup methods for the account recovery tests, so similar suggestions about stopping patches in setUp/tearDown should not be repeated.

Applied to files:

  • webroot/src/network/searchApi/data.api.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/Licensee/LicenseeList/LicenseeList.ts
📚 Learning: 2025-11-06T18:11:58.272Z
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.272Z
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/Licensee/LicenseeList/LicenseeList.ts
📚 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/components/Licensee/LicenseeList/LicenseeList.ts
📚 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/components/Licensee/LicenseeList/LicenseeList.ts
🧬 Code graph analysis (3)
webroot/src/network/mocks/mock.data.api.ts (2)
webroot/src/network/mocks/mock.data.ts (1)
  • licensees (434-1261)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • LicenseeSerializer (402-470)
webroot/src/network/searchApi/data.api.ts (2)
webroot/src/network/searchApi/interceptors.ts (4)
  • requestSuccess (16-27)
  • requestError (34-34)
  • responseSuccess (43-47)
  • responseError (54-76)
webroot/src/models/Licensee/Licensee.model.ts (1)
  • LicenseeSerializer (402-470)
webroot/src/components/Licensee/LicenseeList/LicenseeList.ts (3)
webroot/src/models/State/State.model.ts (1)
  • State (21-49)
webroot/src/app.config.ts (2)
  • serverDateFormat (175-175)
  • displayDateFormat (181-181)
webroot/src/network/searchApi/data.api.ts (1)
  • SearchParamsInterfaceLocal (20-39)
⏰ 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). (2)
  • GitHub Check: TestApp
  • GitHub Check: CheckWebroot
🔇 Additional comments (14)
webroot/src/components/Lists/ListContainer/ListContainer.vue (2)

63-82: LGTM! Bottom pagination mirrors top pagination correctly.

The bottom pagination block follows the same conditional rendering pattern as the top pagination (lines 24-41), ensuring consistency throughout the component. The dual-branch approach cleanly separates legacy and modern pagination implementations.


24-41: Verify that modern Pagination doesn't require prev/next key props.

The modern Pagination component (lines 34-41 and 74-82) correctly omits pagingPrevKey and pagingNextKey props. The Pagination component uses offset-based paging (with pageChange accepting firstIndex and lastIndexExclusive), while PaginationLegacy uses cursor-based pagination (requiring the prev/next key props and passing PageChangeConfig with prevNext field). This difference is intentional and the implementation is correct.

The v-else-if condition explicitly rechecking hasRecords && !excludeTopPagination is redundant but acceptable for clarity and self-documentation.

webroot/src/components/Licensee/LicenseeList/LicenseeList.ts (4)

382-394: Correct field mapping for sorting.

The lastNamefamilyName mapping aligns with the server API expectations and correctly reverses the serialization mapping where familyName from the server is mapped to lastName in the Licensee model.


43-43: Good error handling pattern with searchErrorOverride.

The searchErrorOverride property provides a clean way to display custom error messages for privilege export failures while keeping the regular search error handling intact.

Also applies to: 241-241, 408-408, 414-414


302-321: Clear separation of provider search and privilege export flows.

The branching logic correctly routes provider searches to the standard list view and privilege searches to the export/download flow, with appropriate configuration for each path.


100-190: Well-structured display getters for search criteria.

The new display getters provide a clean, consistent pattern for formatting search parameters with proper i18n support, state name lookups, and date formatting. The implementation correctly uses the State model and translation utilities.

webroot/src/network/mocks/mock.data.api.ts (2)

552-565: Mock implementation supports pagination testing.

The mock correctly creates multi-page test data by concatenating providers and calculating a totalMatchCount that simulates 10 pages of results, which is suitable for testing pagination behavior.


568-573: LGTM!

The privilege export mock provides appropriate simulation of the download flow with a realistic wait time for an export operation.

webroot/src/network/searchApi/data.api.ts (6)

78-97: Axios configuration follows project conventions.

The nested headers structure (get/post/put inside headers config) aligns with the established pattern used throughout the CompactConnect network layer. The 30-second timeout is appropriate for search and export operations.

Based on learnings, this pattern is project-specific and should not be modified.


61-69: Useful runtime debugging utility.

The ccQueryToggle() function provides a convenient way to enable/disable query logging during development and troubleshooting, accessible directly from the browser console.


246-286: Correctly structured nested queries for adverse actions.

The double-nested query structure (licensee → licenses/privileges → adverseActions) is appropriate for OpenSearch and correctly searches across both license and privilege adverse actions using a should clause with minimum_should_match: 1.


290-325: Investigation status query logic is sound.

The conditional branching correctly uses should for "underInvestigation" status (matching any investigation) and must_not for other statuses (excluding all investigations), with proper nested query structure across both licenses and privileges.


332-340: Correct pagination calculation.

The from offset calculation pageSize * (pageNumber - 1) correctly converts 1-based page numbers to 0-based offsets for OpenSearch pagination.


213-239: Date range queries correctly handle datetime fields. The privilege dateOfIssuance and dateOfRenewal fields are DateTime fields in the backend schema (confirmed in privilege/record.py lines 88-89), and the frontend passes date-only values (YYYY-MM-DD format) from the search parameters. OpenSearch/Elasticsearch correctly interprets date-only values in range queries against datetime fields, treating them as the start and end of day respectively. The current query construction is correct and no changes are needed.

@jsandoval81 jsandoval81 requested a review from jlkravitz January 8, 2026 22:04
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!

@isabeleliassen isabeleliassen merged commit cd1318d into csg-org:main Jan 9, 2026
4 of 6 checks passed
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.

improved search/reporting FE

4 participants