Skip to content

Conversation

@coodos
Copy link
Contributor

@coodos coodos commented Nov 14, 2025

Description of change

Fixes Modal UX on eID Wallet

Issue Number

Type of change

  • Fix (a change which fixes an issue)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Shows inline error banners for authentication and signing flows and adapts drawer actions when errors occur.
    • Displays an "Authenticating..." loading state and disables buttons during auth.
    • Propagates error/loading state to auth, signing, and reveal drawers for clearer feedback.
  • Bug Fixes / Behavior Changes

    • Adjusted scanner restart and drawer close behavior; declines navigate back to main when errors exist.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

Walkthrough

Adds observable error and loading stores (authError, signingError, authLoading) to the QR scan auth/sign flows, wires them into drawers, and adjusts drawer open/decline control flow to close drawers, conditionally restart scanning, or navigate to /main on errors.

Changes

Cohort / File(s) Summary
Scan logic & page
infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts, infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte
Add public writable stores authError, signingError, authLoading; initialize and manage them through auth/sign flows; update drawer sequencing and deep-link handling; expose stores to page and make decline handlers async with conditional navigation/restart.
Auth UI
infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/AuthDrawer.svelte
Add props authError and authLoading; render error banner when authError present; adjust action buttons (single "Okay" on error, otherwise Decline/Confirm with loading state).
Signing UI
infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/SigningDrawer.svelte
Add prop signingError; render error banner where applicable; replace Decline/Sign buttons with single "Okay" when signingError exists, otherwise preserve original actions with loading/labels.
Reveal UI wiring
infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/RevealDrawer.svelte (prop usage)
Receive authError and authLoading from stores (prop wiring adjusted in page component).
Controller formatting
platforms/group-charter-manager-api/src/controllers/AuthController.ts
Whitespace/formatting changes to error-response literals only; no behavioral changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Page as Scan QR Page
    participant Logic as Scan Logic
    participant Drawer as Drawer (Auth/Signing/Reveal)
    participant Router

    User->>Page: Scan QR / trigger auth or sign
    Page->>Logic: handleAuth() / handleSigning()
    rect rgb(240,248,255)
      Logic->>Logic: Clear previous errors\nSet authLoading = true (for auth)
    end

    alt Success
      Logic->>Drawer: Close/transition drawers as sequence dictates
      Logic->>Logic: Clear error stores\nSet authLoading = false
      Drawer->>User: Show success UI
    else Error
      Logic->>Logic: Set authError or signingError\nSet authLoading = false
      Logic->>Drawer: Open drawer with error props
      Drawer->>User: Show error banner + "Okay"
      User->>Page: Click "Okay"
      Page->>Router: navigate to /main
    end

    alt Decline with no error
      User->>Page: Click "Decline"
      Page->>Drawer: Close drawer
      Page->>Page: restart scanning
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Areas to inspect closely:
    • scanLogic.ts: correctness of error-setting/clearing paths and authLoading lifecycle (ensure finally blocks always reset loading).
    • Drawer open/close sequencing and race conditions when closing one drawer and opening another.
    • Async decline handlers in +page.svelte: navigation vs. state reset ordering.
    • Component prop usage: ensure all drawers receive the new props and render conditions correctly.

Possibly related PRs

Suggested reviewers

  • grv-saini-20

Poem

🐰 Hopping through code with a sniff and a cheer,
Errors now visible, loading states clear.
Drawers close tidy, scans restart on cue,
If something goes sideways, a tap sends you through.
A tiny rabbit nods — smooth flows anew. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete with missing critical details: no issue number provided, testing approach not specified, and all checklist items remain unchecked despite substantial changes to multiple components. Add the related issue number, describe how the modal UX fixes were tested, detail the specific changes made to error handling and UI state, and check off applicable checklist items.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title is vague and generic, using the term 'fix modal UX' without specifying what modal issues were addressed or which components were modified. Replace with a more specific title that clearly describes the modal fixes, such as 'feat: add error states and loading indicators to auth and signing modals'.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/eid-wallet-ux-stuff

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

🧹 Nitpick comments (3)
platforms/group-charter-manager-api/src/controllers/AuthController.ts (1)

104-108: Good UX improvement with correct status code.

The 404 status code is now semantically correct for user-not-found errors, and the details field provides helpful guidance to users—a nice UX improvement aligned with the modal UX fixes mentioned in the PR.

However, the error detection via error.message.includes("not found") is fragile and relies on exact error message format from UserService. Consider using a custom error class or error code instead for more robust detection:

// Example alternative: define a custom error type
class UserNotFoundError extends Error {
  constructor(message: string) {
    super(message);
    this.name = "UserNotFoundError";
  }
}

// Then catch it by type instead of message matching
if (error instanceof UserNotFoundError) {
  return res.status(404).json({...});
}

This approach is less brittle if UserService error messages change in the future.

infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/SigningDrawer.svelte (1)

255-279: Consider extracting the error banner into a reusable component.

The error banner markup (lines 255-279) is duplicated from the blind voting section (lines 146-174). This duplication increases maintenance burden—any styling or structural changes must be applied in multiple places.

Consider creating a shared ErrorBanner.svelte component:

<!-- ErrorBanner.svelte -->
<script lang="ts">
export let message: string;
</script>

<div class="bg-red-50 border border-red-200 rounded-lg p-4 mt-4">
    <div class="flex items-center">
        <div class="flex-shrink-0">
            <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
                <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
            </svg>
        </div>
        <div class="ml-3">
            <h3 class="text-sm font-medium text-red-800">Error</h3>
            <div class="mt-2 text-sm text-red-700">{message}</div>
        </div>
    </div>
</div>

Then use it in both places:

-{#if signingError}
-    <div class="bg-red-50 border border-red-200 rounded-lg p-4 mt-4">
-        ...
-    </div>
-{/if}
+{#if signingError}
+    <ErrorBanner message={signingError} />
+{/if}
infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (1)

308-310: Consider consolidating drawer close operations.

Lines 308-310, 319-321, and 365-367 all close the auth drawer before opening the logged-in drawer. This redundancy suggests that drawer state management might benefit from a helper function.

Consider creating a helper to ensure atomic drawer transitions:

function transitionDrawer(close: () => void, open: () => void) {
    close();
    open();
}

// Usage:
transitionDrawer(
    () => codeScannedDrawerOpen.set(false),
    () => loggedInDrawerOpen.set(true)
);

This would make the intent clearer and reduce the chance of forgetting to close one drawer when opening another.

Also applies to: 319-321, 365-367

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac398e7 and f68d6f1.

📒 Files selected for processing (5)
  • infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte (5 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/AuthDrawer.svelte (2 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/SigningDrawer.svelte (2 hunks)
  • infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (18 hunks)
  • platforms/group-charter-manager-api/src/controllers/AuthController.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (1)
platforms/pictique/src/lib/stores/posts.ts (1)
  • error (7-7)
⏰ 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: lint
  • GitHub Check: build
🔇 Additional comments (12)
platforms/group-charter-manager-api/src/controllers/AuthController.ts (2)

78-81: Formatting looks good.

The version mismatch error response is now more concise and readable. Status code and content are appropriate for this validation failure.


100-100: Also applies to: 111-111

infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/SigningDrawer.svelte (1)

284-313: LGTM! Error-aware button flow is well-structured.

The conditional rendering provides clear user guidance: when an error occurs, a single "Okay" button allows dismissal; otherwise, standard "Decline"/"Sign" actions are available. The loading state is also properly reflected in the button label.

infrastructure/eid-wallet/src/routes/(app)/scan-qr/components/AuthDrawer.svelte (1)

69-93: LGTM! Error and loading state handling is well-implemented.

The component correctly:

  • Displays an error banner when authError is set
  • Simplifies the action to a single "Okay" button on error
  • Disables both buttons during authentication
  • Shows appropriate loading feedback ("Authenticating...")

This provides clear visual feedback and prevents user actions during async operations.

Note: The error banner markup is also duplicated here. Consider the shared ErrorBanner component suggestion from the SigningDrawer review.

Also applies to: 96-125

infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte (2)

101-111: Verify that navigating to /main on error is the desired UX.

Both decline handlers now navigate to /main when an error exists, otherwise they restart scanning. This seems reasonable for unrecoverable errors, but consider whether users might want to:

  • Retry the same operation immediately
  • See more details about what went wrong
  • Have a "Try Again" button instead of navigation

The current flow is:

  1. Error occurs → user sees error message in drawer
  2. User clicks "Okay" → navigates to /main
  3. User must navigate back to scan-qr and start over

Consider whether a "Try Again" option that restarts scanning without navigation might improve UX for transient errors (like network issues).

Also applies to: 128-138


40-42: LGTM! Error and loading states properly wired through the component tree.

The new stores are correctly destructured and passed as props to the respective drawer components, ensuring error and loading states are consistently reflected in the UI.

Also applies to: 194-195, 218-218

infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (6)

236-238: LGTM! Comprehensive error handling with user-friendly messages.

The authentication flow properly:

  • Clears previous errors and sets loading state at the start
  • Categorizes errors by type (network, W3ID, redirect) and provides specific messages
  • Ensures authLoading is reset in the finally block

This provides good user feedback and prevents state leakage between operations.

Also applies to: 282-386


402-404: LGTM! Signing request error handling is thorough.

The code properly:

  • Clears previous signing errors at the start of handleSigningRequest
  • Sets specific error messages for invalid parameters, decoding failures, and parsing errors
  • Provides actionable guidance ("Please scan the QR code again")

Also applies to: 433-433, 467-467, 472-472


549-550: Excellent error categorization in handleSignVote.

The error handling distinguishes between:

  • Vault/identity errors
  • Network/connectivity errors
  • Missing redirect URLs
  • Server-side submission failures

Each category has a tailored message that helps users understand what went wrong.

Also applies to: 647-663


1045-1051: Good practice: clearing errors when drawers close.

This prevents stale error messages from appearing when drawers are reopened, ensuring users always see current state.

Also applies to: 1057-1063


1100-1105: Modal coordination improved, but verify deep link behavior.

The code now explicitly closes other drawers before opening the target drawer in handleDeepLinkData. This prevents multiple drawers from being open simultaneously.

Please verify that closing all other modals before handling a deep link doesn't interrupt ongoing operations or lose user state. For example:

  • What happens if a user is mid-authentication when a signing deep link arrives?
  • Should there be a confirmation before switching contexts?

Run manual testing with various deep link timing scenarios to ensure smooth UX.

Also applies to: 1122-1127, 1237-1242


78-80: LGTM! New error/loading stores properly integrated into the public API.

The three new stores are:

  • Correctly added to the ScanStores interface
  • Initialized with appropriate default values
  • Exported through the public stores object

This allows consumers to reactively display error and loading states throughout the UI.

Also applies to: 142-144, 1363-1365

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)
infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (2)

372-389: Consider using error codes instead of string matching.

The error categorization relies on substring matching within error messages, which is fragile and prone to false positives. If the upstream code changes error messages, this logic will break.

Consider introducing custom error classes or error codes:

class NetworkError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'NetworkError';
  }
}

class W3IDError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'W3IDError';
  }
}

// Then in error handling:
if (error instanceof NetworkError) {
  errorMessage = "Network error. Please check your connection and try again.";
} else if (error instanceof W3IDError) {
  errorMessage = "Failed to retrieve your identity. Please try again.";
}

662-688: Same string matching fragility as in handleAuth.

This error categorization has the same issues noted in the handleAuth function. Consider applying the same custom error class solution here for consistency across the codebase.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f68d6f1 and f862fc6.

📒 Files selected for processing (1)
  • infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (18 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (2)
platforms/pictique/src/lib/stores/posts.ts (1)
  • error (7-7)
infrastructure/eid-wallet/src/lib/global/controllers/security.ts (1)
  • value (167-177)
⏰ 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: build
  • GitHub Check: lint
🔇 Additional comments (13)
infrastructure/eid-wallet/src/routes/(app)/scan-qr/scanLogic.ts (13)

78-80: LGTM! Clean interface extension.

The new error and loading stores follow the existing pattern and are properly typed for their use cases.


142-144: LGTM! Proper store initialization.

The stores are initialized with appropriate default values matching their types.


236-238: LGTM! Proper state initialization.

Clearing previous errors and setting loading state at the beginning of the authentication flow ensures clean state for each attempt.


369-392: Verify that silent error handling is intentional.

The catch block sets a user-friendly error message but doesn't re-throw or propagate the error. This means the authentication failure is handled silently (user sees the error in the UI but no error is logged to monitoring systems beyond the console.error). Confirm this is the intended behavior.


403-403: LGTM! Proper error state reset.

Clearing previous auth errors when handling a new authentication request ensures users see fresh feedback for each attempt.


408-410: LGTM! Consistent error clearing.

Clearing previous signing errors at the start of the signing request flow matches the pattern established in handleAuth.


439-441: Good UX improvement with specific error messages.

The different error messages for invalid parameters, decoding failures, and parsing failures help users understand what went wrong. This is a significant improvement over generic error messages.

Also applies to: 475-477, 482-484


561-562: LGTM! Consistent error state management.

Clearing previous errors before attempting to sign ensures clean state for the operation.


1072-1076: LGTM! Prevents stale error messages.

Clearing the auth error when the drawer closes ensures users don't see outdated error messages when the drawer is reopened.


1084-1088: LGTM! Consistent error clearing pattern.

This mirrors the error clearing behavior in setCodeScannedDrawerOpen, maintaining consistency across drawer state management.


1126-1130: LGTM! Improved drawer state management.

Closing conflicting drawers before handling deep links ensures a consistent UI state and prevents multiple drawers from being open simultaneously. The early returns for in-progress operations (lines 1106-1121) correctly prevent unnecessary drawer manipulation.

Also applies to: 1148-1152, 1263-1267


1143-1143: LGTM! Proper error state initialization.

Clearing previous errors when handling new deep link requests ensures fresh error feedback for each operation.

Also applies to: 1159-1159, 1273-1273


1388-1390: LGTM! Proper store exposure.

The new stores are correctly exposed through the public API, allowing consuming components to observe and react to authentication/signing errors and loading states.

@ananyayaya129 ananyayaya129 merged commit d85ca6f into main Nov 14, 2025
4 checks passed
@ananyayaya129 ananyayaya129 deleted the fix/eid-wallet-ux-stuff branch November 14, 2025 06:31
@coderabbitai coderabbitai bot mentioned this pull request Jan 5, 2026
6 tasks
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.

4 participants