Skip to content

Frontend/privilege verification enhancements #857

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

rmolinares
Copy link
Collaborator

@rmolinares rmolinares commented Jun 12, 2025

Requirements List

  • yarn install --ignore-engines

Description List

  • General updates to the Privilege Verification screen in accordance with latest Figma designs
    • Add privilege ID number
    • Sort privileges list by recent continuously active start date
    • Frontend now generates QR code and explicit link to the public practitioner page
    • Hide navigation bar on mobile (mirroring desktop behavior)
    • Update abbreviated privilege license type to full description
    • Update translation files with new copy
    • Update existing tests to pass based on changes

Testing List

  • yarn test:unit:all should run without errors or warnings
  • yarn serve should run without errors or warnings
  • yarn build should run without errors or warnings
  • Code review
  • Testing
    • Log in as practitioner and proceed to their Privilege Verification screen
      • Confirm that underneath each privilege is the privilege ID
      • Confirm that the privilege license type is no longer abbreviated, and instead displayed as full name
      • Confirm that if practitioner has multiple privileges that they appear sorted by recent continuously active start date
      • Confirm that below the QR code appears with explicit link below
        • Confirm that scanning QR code and clicking the explicit link both open a new browser tab to the practitioner's public page
      • Confirm that in mobile screens the app nav bar no longer is present, mirroring the desktop experience

Closes #816

Summary by CodeRabbit

  • New Features

    • Added QR code generation to the Licensee Proof page, allowing users to access a QR code linking to their public profile.
    • Introduced new layout and styling enhancements for display names, IDs, and QR code sections on the Licensee Proof page.
    • Added new English and Spanish localization strings for public profile links and QR code descriptions.
  • Improvements

    • License display names now show the full license type by default, with an option to display abbreviations.
    • Privileges are now sorted by most recent issue date.
    • The Licensee Verification page header is now hidden on phone devices for a cleaner view.
    • New layout variation added for pages without a header to improve vertical spacing.
  • Chores

    • Updated dependencies to include QR code generation support and related type definitions.
    • Added a CSS custom property for the primary color to support dynamic theming.

Copy link
Contributor

coderabbitai bot commented Jun 12, 2025

"""

Walkthrough

This update introduces QR code generation and public profile linking to the LicenseeProof page, displays full license type names, and shows privilege ID numbers. It updates styles and localization for these features, modifies the License model's display logic, and adjusts the PageContainer to handle header visibility for the LicenseeVerification route. New dependencies for QR code functionality are added.

Changes

File(s) Change Summary
webroot/package.json Added qrcode library and its TypeScript types to dependencies.
webroot/src/components/Page/PageContainer/PageContainer.ts, .vue, .less Added 'LicenseeVerification' to routes without header on phone; updated CSS and class bindings for headerless layout.
webroot/src/locales/en.json, es.json Added localization strings for QR code and public profile link in both English and Spanish; updated "activeDate" string.
webroot/src/models/License/License.model.ts, .spec.ts Updated displayName to support full license type names or abbreviations; updated tests to reflect new logic and add delimiter/abbreviation test cases.
webroot/src/pages/LicenseeProof/LicenseeProof.ts, .vue, .less Implemented QR code generation and display; added privilege ID and full license type name; updated styles and template for new features.
webroot/src/styles.common/_colors.less Added CSS custom property for primary color; removed unused variable.
webroot/src/router/routes.ts Changed webpack chunk name for LicenseeVerification route from "licenseeDashboard" to "licenseeProof".

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LicenseeProofComponent
    participant QRCodeLibrary
    participant Router
    participant EnvConfig

    User->>LicenseeProofComponent: Page loads
    LicenseeProofComponent->>Router: Resolve public profile route
    Router-->>LicenseeProofComponent: Return route path
    LicenseeProofComponent->>EnvConfig: Get domain
    EnvConfig-->>LicenseeProofComponent: Return domain
    LicenseeProofComponent->>QRCodeLibrary: Generate QR code for public profile URL
    QRCodeLibrary-->>LicenseeProofComponent: Return QR code data URL
    LicenseeProofComponent-->>User: Display QR code and public profile link
Loading

Assessment against linked issues

Objective Addressed Explanation
Add privilege ID number (#816)
"Active" column shows most recent continuously active start date (#816)
QR code and public practitioner page link added based on designs (#816)
Change to show full license type (not abbreviation) (#816)
Fix bug from #813 (comment) (#816)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Possibly related PRs

Suggested reviewers

  • carlsims
  • jlkravitz
  • isabeleliassen

Poem

A rabbit hopped in, with code in its paw,
QR codes and profiles—oh, what it saw!
License types spelled out, no more LPC,
Privilege IDs shining for all to see.
With colors and links, the proof page anew—
🐇✨ Hopping forward, this update’s for you!
"""


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c680f46 and 9168be0.

📒 Files selected for processing (1)
  • webroot/src/router/routes.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • webroot/src/router/routes.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: CheckWebroot
✨ 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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🔭 Outside diff range comments (1)
webroot/src/components/Page/PageContainer/PageContainer.ts (1)

47-54: 💡 Verification agent

❓ Verification inconclusive

Header-visibility logic appears inverted for non-phone break-points
includePageHeader returns true only when isPhone is true. That means the page header is never rendered on tablet / desktop, even when the route is not in nonHeaderRouteNames. Verify this is intentional – the new requirement only calls for hiding nav on mobile, not suppressing the header everywhere.

return (this.isPhone && !nonHeaderRouteNames.includes(this.currentRouteName));

If desktop/tablet should still show the header, drop the this.isPhone && guard.


Header rendering disabled on tablet/desktop breakpoints
The includePageHeader getter only returns true when isPhone is true, so on tablet and desktop the page header never appears—even for routes not in nonHeaderRouteNames. If the goal is to hide the header only on mobile and still show it elsewhere (except on logout or verification routes), drop the this.isPhone guard:

- return this.isPhone && !nonHeaderRouteNames.includes(this.currentRouteName);
+ return !nonHeaderRouteNames.includes(this.currentRouteName);

• File: webroot/src/components/Page/PageContainer/PageContainer.ts (lines 47–54)

🧹 Nitpick comments (8)
webroot/package.json (1)

31-32: Pin the new QR-code dependencies for reproducible builds

All fixed-production deps in this file (e.g. axios, vue) are version-pinned, whereas the newly-added libraries are added with the caret range.
To stay consistent with the existing lock-down strategy and avoid unexpected breakages from a future 1.x of qrcode, pin both libs:

-    "qrcode": "^1.5.4",
+    "qrcode": "1.5.4",

-    "@types/qrcode": "^1.5.5",
+    "@types/qrcode": "1.5.5",

After changing, run yarn install && yarn audit to confirm no new advisories appear.

Also applies to: 52-53

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

80-85: Consider a fallback for the exported CSS variable

--primary-color is compiled to the literal value of @primaryColor, which means theming the color at runtime requires overriding the variable and keeping this Less value in sync.

If the intent is to allow dynamic override, expose the variable first and then consume it elsewhere, e.g.

:root {
  --primary-color: @primaryColor; // default
}

/* usage */
.some-class {
  color: var(--primary-color, @primaryColor);
}

This keeps existing styling intact while letting themes override --primary-color without recompilation.

webroot/src/models/License/License.model.ts (1)

144-148: Minor optimisation & readability for displayName

this.issueState?.name() is invoked twice and the intent of the boolean flag is not self-evident. A small refactor improves clarity and avoids the duplicate call:

-    public displayName(delimiter = ' - ', displayAbbrev = false): string {
-        const licenseTypeToShow = displayAbbrev ? this.licenseTypeAbbreviation() : this.licenseType;
-
-        return `${this.issueState?.name() || ''}${this.issueState?.name() && licenseTypeToShow ? delimiter : ''}${licenseTypeToShow || ''}`;
-    }
+    public displayName(delimiter = ' - ', displayAbbrev = false): string {
+        const stateName = this.issueState?.name() || '';
+        const licenseTypeToShow = displayAbbrev ? this.licenseTypeAbbreviation() : this.licenseType;
+
+        return `${stateName}${stateName && licenseTypeToShow ? delimiter : ''}${licenseTypeToShow || ''}`;
+    }

Also consider replacing the positional displayAbbrev flag with an options object for future extensibility (e.g. { delimiter: ' - ', abbrev: true }).

webroot/src/components/Page/PageContainer/PageContainer.less (1)

33-40: Missing print-media override for .no-page-header
You added margin/padding tweaks for normal display but not for @media print (which is defined earlier in the same rule). Printed output for the verification page will therefore have an extra margin-top: @appHeaderHeight, shifting everything down. Add a print override similar to the one that exists for the base rule.

webroot/src/components/Page/PageContainer/PageContainer.vue (1)

8-12: Class binding order nit
Because both no-top-pad and no-page-header can manipulate top spacing, consider placing the more specific no-page-header class first to guarantee cascade priority when both evaluate to true.

-    'no-top-pad': !shouldPadTop,
-    'no-page-header': !includePageHeader
+    'no-page-header': !includePageHeader,
+    'no-top-pad': !shouldPadTop
webroot/src/pages/LicenseeProof/LicenseeProof.ts (2)

95-119: Harden publicProfileUrl construction and avoid fragile string concatenation

  1. domain may or may not include protocol / trailing slash, leading to malformed URLs.
  2. new URL() already accepts a base URL – you don’t need manual string interpolation.
  3. If $router.resolve() fails, you silently fall back to '', but the watcher will keep retrying.
-        const { domain } = this.$envConfig;
+        const { domain } = this.$envConfig || {};
         ...
-                const resolved = this.$router.resolve({
+                const { href } = this.$router.resolve({
                     name: 'LicenseeDetailPublic',
                     params: { compact: compactType, licenseeId }
                 });
-                const urlObj = new URL(`${domain}${resolved.href}`);
-                url = urlObj.toString();
+                url = new URL(href, domain).toString();

Consider early–returning when domain is missing, and log a warning to aid troubleshooting.


129-147: Cache CSS variable read to avoid repeated layout thrash

getComputedStyle(document.documentElement) is called every time a QR code is regenerated (watcher + mounted).
Move the colour lookup outside the function (module-level or mounted) and pass it in, or memoise the result.

Also consider a secondary fallback (e.g., default palette constant) when the CSS var is absent.

webroot/src/pages/LicenseeProof/LicenseeProof.less (1)

161-185: Add responsive max-width to QR code image to avoid overflow on narrow viewports

When the QR code is rendered inside .qr-code-section, extremely small mobile screens or print in portrait orientation may clip the image.
A quick fix:

.qr-code-section {
    img {
        max-width: 100%;
        height: auto;
    }
}

This keeps the QR code legible without breaking layout.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a580a0c and fe11b1a.

⛔ Files ignored due to path filters (1)
  • webroot/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (12)
  • webroot/package.json (2 hunks)
  • webroot/src/components/Page/PageContainer/PageContainer.less (1 hunks)
  • webroot/src/components/Page/PageContainer/PageContainer.ts (1 hunks)
  • webroot/src/components/Page/PageContainer/PageContainer.vue (1 hunks)
  • webroot/src/locales/en.json (1 hunks)
  • webroot/src/locales/es.json (1 hunks)
  • webroot/src/models/License/License.model.spec.ts (4 hunks)
  • webroot/src/models/License/License.model.ts (1 hunks)
  • webroot/src/pages/LicenseeProof/LicenseeProof.less (2 hunks)
  • webroot/src/pages/LicenseeProof/LicenseeProof.ts (5 hunks)
  • webroot/src/pages/LicenseeProof/LicenseeProof.vue (3 hunks)
  • webroot/src/styles.common/_colors.less (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
webroot/src/pages/LicenseeProof/LicenseeProof.ts (1)
webroot/src/models/License/License.model.ts (1)
  • License (67-189)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: CheckWebroot
🔇 Additional comments (3)
webroot/src/locales/en.json (1)

687-690: Guard against missing translations in other locale files

publicProfileLink and qrCodeAlt were only added to the English bundle here.
Please ensure the same keys exist in every supported locale (es.json, etc.) to prevent runtime undefined strings when users switch languages.

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

132-134: Tests accurately reflect new displayName behaviour

The added assertions cover both default and abbreviated display modes across delimiters—good coverage. ✔️

Also applies to: 160-162, 218-219, 566-567

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

62-63: Consistency: use full license type description everywhere
Figma spec calls for the full license type description (not abbreviation). license.displayName(', ') may still return the abbreviated version depending on model logic. Confirm the helper already switched to full names, otherwise users will still see short forms here.

@rmolinares rmolinares requested a review from jsandoval81 June 12, 2025 17:21
Copy link
Collaborator

@jsandoval81 jsandoval81 left a comment

Choose a reason for hiding this comment

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

This is looking really good 👍 Just a few minor items below.

@jsandoval81 jsandoval81 self-requested a review June 14, 2025 23:54
@jsandoval81
Copy link
Collaborator

@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.

looks great! @isabeleliassen good to merge

@isabeleliassen isabeleliassen self-requested a review June 17, 2025 18:24
@isabeleliassen isabeleliassen merged commit b972f64 into csg-org:development Jun 17, 2025
2 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.

privilege proof update FE
4 participants