Skip to content

fix: extract inline input components to prevent remounting and focus …#578

Open
N-thnI wants to merge 19 commits into
Pi-Defi-world:devfrom
N-thnI:fix/inline-input-remounting
Open

fix: extract inline input components to prevent remounting and focus …#578
N-thnI wants to merge 19 commits into
Pi-Defi-world:devfrom
N-thnI:fix/inline-input-remounting

Conversation

@N-thnI

@N-thnI N-thnI commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

closes #454

Summary by CodeRabbit

  • New Features

    • Added clearer loading states and streamlined forms for minting, burning, and sending tokens.
    • Improved mobile navigation with more consistent route feedback and button behavior.
    • Added app-wide toast notifications for more visible status updates.
  • Bug Fixes

    • Updated burn and send flows to handle form validation and submission more reliably.
    • Improved focus handling and dialog behavior for accessibility.
    • Refined navigation and status badges for a smoother experience.
  • Documentation

    • Added a known-issues reference to help track current limitations.

@drips-wave

drips-wave Bot commented Jun 24, 2026

Copy link
Copy Markdown

@N-thnI Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR restructures the app-level layout by stripping app/layout.tsx to a minimal AuthProvider wrapper and moving Toaster to the locale layout. It extracts MintForm/BurnForm into stable sub-components, refactors SendPage handlers and contact rendering, fixes mobile nav guard logic, widens the useFocusTrap ref type, and cleans up tooling configuration. The CI workflow file also contains a malformed insertion.

Changes

Layout, Form Sub-components, Send Page, Nav, and Tooling

Layer / File(s) Summary
App layout restructuring and Toaster relocation
app/layout.tsx, app/[locale]/layout.tsx
app/layout.tsx is reduced to <AuthProvider>{children}</AuthProvider>; Toaster is imported and rendered in the locale layout instead.
MintForm and BurnForm sub-components
app/mint/page.tsx
FiatAccountOption, MintFormProps, BurnFormProps interfaces and MintForm/BurnForm components are defined outside MintPage to prevent remounting on state updates.
Burn page submission value source fix
app/burn/page.tsx
Recipient payload and both submitBurnRedeemSingleClient call sites now read account_number, bank_code, account_name, amountAcbu, and currency from submitted values instead of a prior data variable.
SendPage handler refactors, contact rendering, and confirm dialog
app/send/page.tsx
Replaces @tanstack/react-virtual contact rendering with a memoized SelectItem list; adds dialog/tab/recipient/amount handlers; gates transfer submission on ensureSession(); changes status badge helpers, tab header styling, and confirm button labels/disabled logic.
Mobile nav guard and button rendering refactor
components/mobile-nav.tsx
handleNav blocks navigation only when navigatingTo matches the requested href; removes showLabels/tabIndex; adds aria-current and disabled={isPending} to nav buttons.
Focus trap nullable ref type and auth context argument fix
hooks/use-focus-trap.ts, components/ui/alert-dialog.tsx, components/ui/dialog.tsx, contexts/auth-context.tsx
useFocusTrap parameter widened to RefObject<HTMLElement | null>; call sites cast contentRef; login now calls setAuth with a leading null argument.
Toast viewport positioning and wallet-storage type casts
components/ui/toast.tsx, lib/wallet-storage.ts
ToastViewport className changed to top-0 left-0 right-0 flex-col; crypto.subtle API calls in wallet-storage.ts add any casts to salt, iv, and ciphertext.
Tooling, config, and dependency cleanup
package.json, pnpm-workspace.yaml, tsconfig.json, eslint.config.js, .npmrc
Removes Vitest/testing-library/sharp devDependencies; stubs test scripts; adds allowBuilds to pnpm workspace; extends tsconfig.json exclude list; adds .kilo/** ESLint ignore; adds local pnpm store-dir.
Workflow corruption, ISSUES.md, and stray dev files
.github/workflows/frontend-qa.yml, ISSUES.md, .vscode/settings.json.bak
CI workflow has a malformed duplicate setup block and a non-standard scripts JSON appended. ISSUES.md is newly created with 167 categorized known issues. .vscode/settings.json.bak is reset to {}.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SendPage
  participant ensureSession
  participant TransferAPI
  participant BalanceRefetch

  User->>SendPage: click "Send ACBU {confirmedAmount}"
  SendPage->>ensureSession: ensureSession()
  ensureSession-->>SendPage: ok / not ok
  alt session not ok
    SendPage-->>User: early return (no submission)
  else session ok
    SendPage->>TransferAPI: submitTransfer(to, confirmedAmount)
    TransferAPI-->>SendPage: success / error
    SendPage->>BalanceRefetch: refreshBalance()
    SendPage-->>User: show success or error state
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Pi-Defi-world/acbu-frontend#391: Introduces useFocusTrap and wires it into DialogContent/AlertDialogContent; this PR updates the hook's ref type to nullable and adjusts the corresponding call sites in those same dialog components.
  • Pi-Defi-world/acbu-frontend#557: Both PRs modify app/send/page.tsx's confirm transfer flow to use confirmedAmount and add an ensureSession() pre-flight check before transfer submission.
  • Pi-Defi-world/acbu-frontend#278: Both PRs modify .github/workflows/frontend-qa.yml, with overlapping changes to the quality-gate job steps structure.

Poem

🐇 Hop, hop, the forms stand free,
No more remounts on keystroke spree!
The layout slimmed, the nav guards tight,
Focus trapped and toasts sit right.
ISSUES catalogued, the build is clean —
The tidiest warren you have seen! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes many unrelated changes in workflows, configs, docs, layouts, and dependencies beyond the input-focus fix. Split unrelated workflow, config, and dependency updates into separate PRs and keep this one limited to the focus-loss fix.
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Linked Issues check ❓ Inconclusive app/mint/page.tsx appears to extract inline components, but the summary does not confirm the same fix in app/send/page.tsx. Verify that app/send/page.tsx also moves input components out of the parent render so typing no longer remounts them.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main fix: extracting inline inputs to stop remounting and focus loss.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.0)
app/burn/page.tsx

File contains syntax errors that prevent linting: Line 3: Expected a statement but instead found '<<<<<<< HEAD'.; Line 5: Expected a statement but instead found '======='.; Line 14: Expected a statement but instead found '>>>>>>> upstream/dev'.; Line 24: Expected a statement but instead found '<<<<<<< HEAD
<<<<<<< HEAD
======='.; Line 28: Expected a statement but instead found '>>>>>>> upstream/dev

upstream/dev'.; Line 52: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '<<'.; Line 52: Expected an expression but instead found '<<'.; Line 52: Expected an expression but instead found '<<'.; Line 53: Expected a JSX attribute but instead found '.string().'.; Line 53: Expected a JSX attribute but instead found '(('.; Line 53: Expected a JSX attribute but instead found ') => !'.; Line 53: Expected a JSX attribute but instead found '('.; Line 53: Expected a JSX attribute but instead found '('.; Line 53: Expected a JSX attribute but

... [truncated 13473 characters] ...

ound '=======

export default function'.; Line 578: Expected a JSX attribute but instead found '()'.; Line 579: expected ... but instead found return; Line 579: Expected a JSX attribute but instead found '('.; Line 580: expected > but instead found <; Line 584: Unexpected token. Did you mean {'}'} or &rbrace;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 585: Unexpected token. Did you mean {'>'} or &gt;?; Line 586: expected < but instead the file ends

app/send/page.tsx

File contains syntax errors that prevent linting: Line 367: JSX fragment has no corresponding closing tag.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

app/burn/page.tsx

Parsing error: Merge conflict marker encountered.

app/send/page.tsx

Parsing error: Expected corresponding closing tag for JSX fragment.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 18

Caution

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

⚠️ Outside diff range comments (3)
.github/workflows/frontend-qa.yml (1)

39-84: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Malformed workflow YAML will break CI parsing.

Two corrupt insertions make this file invalid:

  1. Line 39 adds - name: Run component tests with no run:, immediately followed by a second steps: mapping key (line 40) and a duplicated checkout/pnpm/Node/install/typecheck/lint block (lines 41-61). A duplicate steps: key under the same job and a step without an action/run are both invalid.
  2. Lines 72-84 append a "scripts": { ... } JSON object at the top level of the workflow. This is package.json content, not a valid GitHub Actions workflow key, so the file will fail to parse entirely.

The real Run component tests/Playwright/E2E steps already exist at lines 63-70, so the inserted block is pure duplication. Remove the corrupt insertion and the trailing scripts object.

🛠️ Proposed fix
       - name: Run build (F-001: ensures TypeScript errors fail CI)
         run: pnpm build

-      - name: Run component tests
-    steps:
-      - uses: actions/checkout@v4
-
-      - name: Install pnpm
-        uses: pnpm/action-setup@v4
-        with:
-          version: 10
-
-      - name: Set up Node.js
-        uses: actions/setup-node@v4
-        with:
-          node-version: 20
-          cache: pnpm
-
-      - name: Install dependencies
-        run: pnpm install
-
-      - name: Run typecheck
-        run: pnpm typecheck
-
-      - name: Run lint
-        run: pnpm lint
-
       - name: Run component tests
         run: pnpm test

       - name: Install Playwright Browsers
         run: pnpm exec playwright install --with-deps

       - name: Run E2E smoke tests
         run: pnpm test:e2e
-
-"scripts": {
-  "build": "next build",
-  "dev": "next dev",
-  "lint": "eslint .",
-  "start": "next start",
-  "test:a11y": "playwright test accessibility.spec.ts",
-  "test:a11y:ci": "playwright test accessibility.spec.ts --reporter=github",
-  "test:a11y:report": "playwright show-report",
-  "a11y": "playwright test",
-  "typecheck": "tsc --noEmit",
-  "test": "echo \"Test passed\"",
-  "test:e2e": "echo \"E2E tests passed\""
-}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/frontend-qa.yml around lines 39 - 84, The workflow file is
invalid because a duplicated step block was inserted under the same job and a
top-level JSON "scripts" object was appended, which breaks YAML parsing. Remove
the stray “Run component tests”/checkout/pnpm/Node/install/typecheck/lint block
and the trailing scripts section, and keep only the existing valid steps in the
job that already include “Run component tests” and “Run E2E smoke tests”.
app/burn/page.tsx (1)

3-14: 🎯 Functional Correctness | 🔴 Critical

Resolve the merge conflict and collapse to one burn flow. app/burn/page.tsx still contains unresolved <<<<<<<, =======, and >>>>>>> markers plus duplicated imports/exports, so the TSX cannot parse. Keep a single BurnPage implementation and preserve the values.acbuAmount, values.currency, and trimmed recipient fields in that final path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/burn/page.tsx` around lines 3 - 14, Resolve the merge conflict in
BurnPage by removing all conflict markers and collapsing the duplicated
imports/exports into one valid module. Keep a single app/burn/page.tsx
implementation with the existing BurnPage flow, preserving the metadata export
from the Next.js branch and the burn form state/handlers that use
values.acbuAmount, values.currency, and the trimmed recipient fields. Ensure the
final file has one clean import block and one parseable TSX path with no
duplicated React setup or conflicting branches.

Source: Linters/SAST tools

app/send/page.tsx (1)

367-473: 🎯 Functional Correctness | 🔴 Critical

Close the top-level fragment. The <> opened at line 367 is never closed before );, so this TSX file won’t parse. Add </> before the return ends.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/send/page.tsx` around lines 367 - 473, The top-level fragment in the Send
page JSX is left open, which breaks parsing of the component. Close the fragment
opened before the Tabs markup in app/send/page.tsx by adding the matching
closing fragment before the return ends, and make sure the surrounding render
structure in the send page component remains properly nested around Tabs,
TabsContent, and the enclosing container.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.npmrc:
- Line 2: The tracked .npmrc contains a machine-specific pnpm store-dir setting
that should not be committed. Remove the absolute Windows path entry from .npmrc
and keep store configuration out of the repo; if needed, set it per developer
machine via a global ~/.npmrc or pnpm flags/environment instead.

In @.vscode/settings.json.bak:
- Around line 1-2: Remove the stray editor backup artifact by deleting the empty
`.vscode/settings.json.bak` file, and update the repository ignore rules so
future backup files are not tracked. Add an appropriate pattern such as `*.bak`
to the existing ignore configuration, and make sure the change is applied
alongside the backup file cleanup.

In `@app/layout.tsx`:
- Around line 72-77: The RootLayout in app/layout.tsx is missing the root
document shell and top-level wrapper stack. Update RootLayout to render the full
<html>/<body> structure and keep the shared providers/layout composition here as
well, using the RootLayout symbol and preserving AuthProvider plus the
ErrorBoundary/AppLayout/Toaster wrappers so top-level routes still inherit them.

In `@app/mint/page.tsx`:
- Around line 84-290: The extracted MintForm and BurnForm components are
currently unused because the tab panels still render the old inline JSX, so
replace that duplicated tab content with these components and pass through the
existing state/handlers from the surrounding mint page. While wiring them in,
make sure MintForm and BurnForm can access the fee labels by defining or
inlining MINT_NETWORK_FEE_TEXT and BURN_PROCESSING_FEE_TEXT in the same scope or
as props so the extracted components compile and render correctly.

In `@app/send/page.tsx`:
- Around line 170-175: The confirm dialog open-change handler is referenced with
the wrong name, causing the extracted callback to be missed. In the send page
component, use the existing handleConfirmDialogChange callback consistently
wherever the confirm dialog’s open state is wired up, and replace any remaining
handleConfirmDialogOpenChange references with the actual handler name so the
dialog uses the extracted callback correctly.
- Line 430: The new user-facing literals in the send flow are bypassing the
existing translation path and must be localized. Update the affected render
paths in send/page.tsx, including the “No transfers yet” message and the
confirm/history strings referenced in the later block, so they go through the
existing t(...) lookup instead of hardcoded English. Keep the same UI behavior,
but ensure every visible string in those flows uses the locale-aware translation
keys.
- Around line 178-202: The confirm dialog can show a stale contact because
selectedContact remains set after switching to a custom recipient, while
getToValue() uses customRecipient for the payload. Update the recipient display
logic in app/send/page.tsx so the confirmation view uses the same source of
truth as the send payload (prefer customRecipient when useContact is false,
otherwise selectedContact), and clear or ignore selectedContact when toggling
away from contact mode in the related handlers like handleUseContactChange and
getToValue.
- Around line 193-196: The Continue button logic is still referencing removed
form flow helpers; update the send page to use the extracted confirmation flow
instead. In the component that defines handleShowConfirmDialog and the memoized
isValid value, replace any remaining handleContinue calls and isFormValid()
checks with handleShowConfirmDialog and isValid respectively, including the
other Continue button usages mentioned in the review so they all follow the same
path.
- Around line 179-182: The contact selection callback was renamed to
handleContactSelect, but the Select component is still wired to the old
undefined handleContactChange reference. Update the Select usage in
send/page.tsx (including the related duplicated block) to call
handleContactSelect so it matches the actual callback defined in the component.
- Line 190: The send page has an unused debounced value that also references a
missing hook, so fix the `debouncedAmount` usage in `page.tsx` by either
importing and actually consuming `useDebounce` in the send flow or removing the
`useDebounce(amount, 300)` assignment entirely. Check the component logic around
`amount` and `debouncedAmount` so the `SendPage`/send form state compiles
cleanly and no dead code remains.
- Line 302: The dependency list for the callback in the send page uses an
undefined refetch function name, so update the effect/memo dependencies to use
the hook’s actual balance refetch symbol, refetchBalance, from the send flow.
Also add ensureSession to the dependency array since it is invoked inside the
callback, and keep the rest of the dependencies unchanged so the hook stays
correctly synchronized.
- Around line 636-642: The confirm dialog is closing immediately because the
`AlertDialogAction` in `handleConfirmTransfer` is being used as the submit
control, so `ApiErrorDisplay` can disappear before the transfer finishes. Update
the send confirmation flow in `app/send/page.tsx` by replacing that closing
action behavior with a non-closing button or by preventing the dialog’s default
close, and keep the dialog controlled open until `handleConfirmTransfer`
completes successfully. Only dismiss the dialog after a successful transfer,
while leaving it open on failure so error feedback remains visible.

In `@components/mobile-nav.tsx`:
- Around line 33-37: The duplicate-tap guard in mobile navigation is being
cleared too early inside the transition callback. Update the navigation flow in
mobile-nav.tsx around the isPending/navigatingTo.current check and the
startTransition/router.push logic so navigatingTo.current remains set until the
navigation has actually settled, then clear it afterward in a completion/settled
path rather than immediately after pushing.

In `@contexts/auth-context.tsx`:
- Line 163: The login flow in auth-context.tsx is calling setAuth with the
arguments in the wrong order, which causes the user id to be null and adds an
extra parameter. Update the login path in the setAuth call to use the same
argument order expected by setAuth (and used elsewhere in AuthContext), with the
authenticated userId and stellarAddress passed correctly so login actually sets
the session instead of clearing it.

In `@ISSUES.md`:
- Line 33: This ISSUES.md entry is now stale because item 74 has been fixed by
extracting the inline input components in app/mint/page.tsx and
app/send/page.tsx. Update the catalog entry to mark item 74 as resolved, or
remove it entirely if resolved issues are not kept, so the known-issues list
stays accurate and does not describe a bug that no longer exists.

In `@lib/wallet-storage.ts`:
- Line 61: Remove the unnecessary any casts in wallet-storage handling:
fromBase64() already produces Uint8Array, so pass salt, iv, and ciphertext
directly into the crypto.subtle.deriveKey() and decrypt() calls in
lib/wallet-storage.ts. Update the relevant logic around the wallet storage
helpers so the types remain strict and no `@typescript-eslint/no-explicit-any`
suppression is needed.

In `@package.json`:
- Around line 16-17: The package.json test scripts currently stub out pnpm test
and pnpm test:e2e with echo commands, so the QA workflow can pass without
running any real tests. Restore real test execution in the test and test:e2e
script entries, or if the suite is intentionally being removed, update the
frontend QA GitHub Actions workflow to stop invoking those commands so CI
reflects the actual coverage; use the package.json script definitions as the
main place to fix this.
- Around line 85-95: The PWA icon generation workflow is broken because
scripts/generate-pwa-icons.mjs still depends on sharp even though sharp was
removed from devDependencies. Either delete the stale icon-generation script if
it is no longer used, or restore sharp to the package manifest if the script
must remain; make sure the dependency choice matches the current usage of the
generate-pwa-icons.mjs script.

---

Outside diff comments:
In @.github/workflows/frontend-qa.yml:
- Around line 39-84: The workflow file is invalid because a duplicated step
block was inserted under the same job and a top-level JSON "scripts" object was
appended, which breaks YAML parsing. Remove the stray “Run component
tests”/checkout/pnpm/Node/install/typecheck/lint block and the trailing scripts
section, and keep only the existing valid steps in the job that already include
“Run component tests” and “Run E2E smoke tests”.

In `@app/burn/page.tsx`:
- Around line 3-14: Resolve the merge conflict in BurnPage by removing all
conflict markers and collapsing the duplicated imports/exports into one valid
module. Keep a single app/burn/page.tsx implementation with the existing
BurnPage flow, preserving the metadata export from the Next.js branch and the
burn form state/handlers that use values.acbuAmount, values.currency, and the
trimmed recipient fields. Ensure the final file has one clean import block and
one parseable TSX path with no duplicated React setup or conflicting branches.

In `@app/send/page.tsx`:
- Around line 367-473: The top-level fragment in the Send page JSX is left open,
which breaks parsing of the component. Close the fragment opened before the Tabs
markup in app/send/page.tsx by adding the matching closing fragment before the
return ends, and make sure the surrounding render structure in the send page
component remains properly nested around Tabs, TabsContent, and the enclosing
container.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 76feb16a-b23e-4ed2-b826-f634d813c36d

📥 Commits

Reviewing files that changed from the base of the PR and between 26aa16d and 983cba3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • .github/workflows/frontend-qa.yml
  • .npmrc
  • .vscode/settings.json.bak
  • ISSUES.md
  • app/[locale]/layout.tsx
  • app/burn/page.tsx
  • app/layout.tsx
  • app/mint/page.tsx
  • app/send/page.tsx
  • components/mobile-nav.tsx
  • components/ui/alert-dialog.tsx
  • components/ui/dialog.tsx
  • components/ui/toast.tsx
  • contexts/auth-context.tsx
  • eslint.config.js
  • hooks/use-focus-trap.ts
  • lib/wallet-storage.ts
  • package.json
  • pnpm-workspace.yaml
  • tsconfig.json

Comment thread .npmrc
@@ -1 +1,2 @@
@jsr:registry=https://npm.jsr.io
store-dir=E:\.pnpm-store

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Don't commit a machine-specific Windows store path. store-dir=E:\.pnpm-store is an absolute path on a Windows E: drive. This will fail or behave unexpectedly for any other contributor and for CI runners (macOS/Linux), where that path doesn't exist. This looks like a local-only setting that was committed accidentally.

Remove it from the tracked .npmrc and configure the store location per-machine (global ~/.npmrc or the PNPM_HOME/--store-dir flag) instead.

Proposed fix
 `@jsr`:registry=https://npm.jsr.io
-store-dir=E:\.pnpm-store
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
store-dir=E:\.pnpm-store
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.npmrc at line 2, The tracked .npmrc contains a machine-specific pnpm
store-dir setting that should not be committed. Remove the absolute Windows path
entry from .npmrc and keep store configuration out of the repo; if needed, set
it per developer machine via a global ~/.npmrc or pnpm flags/environment
instead.

Comment thread .vscode/settings.json.bak
Comment on lines +1 to +2
{
} No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the stray editor backup file.

.vscode/settings.json.bak is an empty {} backup artifact that shouldn't be committed. Delete it and add a .gitignore entry (e.g. *.bak) to prevent future editor backups from being tracked.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.vscode/settings.json.bak around lines 1 - 2, Remove the stray editor backup
artifact by deleting the empty `.vscode/settings.json.bak` file, and update the
repository ignore rules so future backup files are not tracked. Add an
appropriate pattern such as `*.bak` to the existing ignore configuration, and
make sure the change is applied alongside the backup file cleanup.

Comment thread app/layout.tsx
Comment on lines 72 to +77
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
const headersList = await headers();
const nonce = headersList.get('x-nonce') ?? undefined;
const lang = "en";

return (
<html lang={lang} dir="ltr" suppressHydrationWarning>
<head>
<link rel="preload" href="/placeholder-logo.svg" as="image" type="image/svg+xml" />
{/*
Print stylesheet is deferred until the browser enters print mode.
media="print" prevents the browser from downloading and parsing
this resource on non-print (screen/mobile) page loads.
*/}
<link rel="stylesheet" href="/print.css" media="print" />
<script
nonce={nonce}
dangerouslySetInnerHTML={{
__html: `
(function() {
try {
const mql = window.matchMedia('(prefers-color-scheme: dark)');
function updateTheme(e) {
document.documentElement.classList.toggle('dark', e.matches);
}
mql.addEventListener('change', updateTheme);
} catch (err) {}
})();
`,
}}
/>
</head>
<body className={`font-sans antialiased`}>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
<GlobalErrorHandler />
<OfflineIndicator />
<ErrorBoundary level="app">
<I18nProvider>
<AuthProvider>
<AppLayout>{children}</AppLayout>
<WalletSetupModal />
<Toaster />
{/*
F-065 SRI review: the only third-party script injected here is
@vercel/analytics/next, which is bundled at build time (first-party,
no external CDN fetch). The nonce above is forwarded so it passes
the strict-dynamic CSP set in middleware.ts.
*/}
<Analytics nonce={nonce} crossOrigin="anonymous" />
</AuthProvider>
</I18nProvider>
</ErrorBoundary>
</ThemeProvider>
</body>
</html>
)
}: {
children: React.ReactNode;
}) {
return <AuthProvider>{children}</AuthProvider>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify which layouts define the document shell and where AuthProvider is mounted.
rg -n '<html|<body|AuthProvider|Toaster|AppLayout|ErrorBoundary' app --glob 'layout.tsx'

Repository: Pi-Defi-world/acbu-frontend

Length of output: 1278


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== app tree ==\n'
find app -maxdepth 2 -type f | sort

printf '\n== app/layout.tsx ==\n'
cat -n app/layout.tsx | sed -n '1,140p'

printf '\n== app/[locale]/layout.tsx ==\n'
cat -n app/'[locale]'/layout.tsx | sed -n '1,140p'

Repository: Pi-Defi-world/acbu-frontend

Length of output: 6638


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
for p in [Path('app'), Path('app/[locale]')]:
    print(f'## {p}')
    for child in sorted(p.iterdir()):
        if child.is_file():
            print(child.as_posix())
PY

Repository: Pi-Defi-world/acbu-frontend

Length of output: 334


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== app tree ==\n'
find app -maxdepth 2 -type f | sort

printf '\n== app/layout.tsx ==\n'
cat -n app/layout.tsx | sed -n '1,140p'

printf '\n== app/[locale]/layout.tsx ==\n'
cat -n app/'[locale]'/layout.tsx | sed -n '1,140p'

Repository: Pi-Defi-world/acbu-frontend

Length of output: 6638


Restore the root document shell in app/layout.tsx.

  • app/layout.tsx:72-77 still needs to render <html>/<body>; moving that shell into app/[locale]/layout.tsx leaves the actual root layout incomplete.
  • Keep the shared provider/layout stack at the top level too, or routes like /mint and /burn will bypass the ErrorBoundary/AppLayout/Toaster wrapper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/layout.tsx` around lines 72 - 77, The RootLayout in app/layout.tsx is
missing the root document shell and top-level wrapper stack. Update RootLayout
to render the full <html>/<body> structure and keep the shared providers/layout
composition here as well, using the RootLayout symbol and preserving
AuthProvider plus the ErrorBoundary/AppLayout/Toaster wrappers so top-level
routes still inherit them.

Comment thread app/mint/page.tsx
Comment on lines +84 to +290
function MintForm({
fiatAccounts,
selectedFiatCurrency,
onCurrencyChange,
fiatAmount,
onFiatAmountChange,
estimatedMintAcbu,
mintError,
onConfirm,
}: MintFormProps) {
return (
<div>
<p className="text-sm text-muted-foreground mb-3">
Mint ACBU via custodial on-ramp (demo basket fiat held on the minting
contract).
</p>
{mintError && (
<p className="text-sm text-destructive mb-2">{mintError}</p>
)}
<div>
<label
htmlFor="fiat-account"
className="text-sm font-medium text-foreground mb-2 block"
>
Basket currency (demo fiat path)
</label>
<select
id="fiat-account"
value={selectedFiatCurrency}
onChange={(e) => onCurrencyChange(e.target.value)}
className="w-full px-3 py-2 border border-border rounded-lg text-sm font-medium bg-background"
>
{fiatAccounts.length === 0 ? (
<option value="" disabled>Loading currencies…</option>
) : (
fiatAccounts.map((acc) => (
<option key={acc.id} value={acc.currency}>
{acc.currency} — {acc.bank_name}
</option>
))
)}
</select>
</div>
<div className="mt-4">
<label
htmlFor="fiat-amount"
className="text-sm font-medium text-foreground mb-2 block"
>
Amount to Exchange
</label>
<div className="flex gap-2">
<span className="flex items-center text-muted-foreground font-medium">
{selectedFiatCurrency || "FIAT"}
</span>
<Input
id="fiat-amount"
type="number"
placeholder="0.00"
min="0"
step="any"
value={fiatAmount}
onChange={(e) => onFiatAmountChange(e.target.value)}
className="border-border text-lg font-semibold"
/>
</div>
</div>
{estimatedMintAcbu != null && (
<Card className="border-border bg-muted/80 p-3 mt-3">
<p className="text-xs text-muted-foreground mb-1">
Estimated ACBU (from latest rates)
</p>
<p className="text-lg font-semibold text-foreground">
≈ {formatAmount(estimatedMintAcbu)} ACBU
</p>
</Card>
)}
<Card className="border-border bg-muted p-3 mt-4">
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Network Fee</span>
<span className="font-medium text-foreground">{MINT_NETWORK_FEE_TEXT}</span>
</div>
</Card>
<Button
onClick={onConfirm}
disabled={
!fiatAmount ||
parseFloat(fiatAmount) <= 0 ||
!selectedFiatCurrency
}
className="w-full bg-primary text-primary-foreground hover:bg-primary/90 mt-6"
>
<ArrowDown className="w-4 h-4 mr-2" />
Mint ACBU
</Button>
</div>
);
}

interface BurnFormProps {
fiatAccounts: FiatAccountOption[];
selectedFiatCurrency: string;
onCurrencyChange: (currency: string) => void;
burnAmount: string;
onBurnAmountChange: (value: string) => void;
burnError: string;
balance: number | null;
balanceLoading: boolean;
onConfirm: () => void;
}

function BurnForm({
fiatAccounts,
selectedFiatCurrency,
onCurrencyChange,
burnAmount,
onBurnAmountChange,
burnError,
balance,
balanceLoading,
onConfirm,
}: BurnFormProps) {
return (
<div>
<p className="text-sm text-muted-foreground mb-3">
Burn ACBU on-chain for the selected basket slice (no simulated bank
credit).
</p>
{burnError && (
<p className="text-sm text-destructive mb-2">{burnError}</p>
)}
<div>
<label
htmlFor="burn-fiat-account"
className="text-sm font-medium text-foreground mb-2 block"
>
Basket currency (burn slice)
</label>
<select
id="burn-fiat-account"
value={selectedFiatCurrency}
onChange={(e) => onCurrencyChange(e.target.value)}
className="w-full px-3 py-2 border border-border rounded-lg text-sm font-medium bg-background"
>
{fiatAccounts.length === 0 ? (
<option value="" disabled>Loading currencies…</option>
) : (
fiatAccounts.map((acc) => (
<option key={acc.id} value={acc.currency}>
{acc.currency} — {acc.bank_name}
</option>
))
)}
</select>
</div>
<div className="mt-4">
<label
htmlFor="burn-amount"
className="text-sm font-medium text-foreground mb-2 block"
>
Amount to Burn
</label>
<div className="flex gap-2">
<span className="flex items-center text-muted-foreground font-medium">
ACBU
</span>
<Input
id="burn-amount"
type="number"
placeholder="0.00"
value={burnAmount}
onChange={(e) => onBurnAmountChange(e.target.value)}
className="border-border text-lg font-semibold"
/>
</div>
<p className="text-xs text-muted-foreground mt-2">
Available: ACBU {balanceLoading ? '...' : formatAmount(balance)}
</p>
</div>
<Card className="border-border bg-muted p-3 mt-4">
<div className="flex justify-between text-sm mb-2">
<span className="text-muted-foreground">You'll receive</span>
<span className="font-medium text-foreground">
{burnAmount && selectedFiatCurrency
? `~ ${selectedFiatCurrency} (based on current rate)`
: "—"}
</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Processing Fee</span>
<span className="font-medium text-foreground">{BURN_PROCESSING_FEE_TEXT}</span>
</div>
</Card>
<Button
onClick={onConfirm}
disabled={
!burnAmount ||
parseFloat(burnAmount) <= 0 ||
!selectedFiatCurrency
}
className="w-full bg-primary text-primary-foreground hover:bg-primary/90 mt-6"
>
<ArrowUp className="w-4 h-4 mr-2" />
Burn & Redeem
</Button>
</div>
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the extracted forms are used and their referenced constants exist.
rg -n '\b(MintForm|BurnForm|MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b' app/mint/page.tsx

Repository: Pi-Defi-world/acbu-frontend

Length of output: 397


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file context and find where MintForm/BurnForm are rendered.
printf '\n== file outline ==\n'
ast-grep outline app/mint/page.tsx --view expanded || true

printf '\n== render usages ==\n'
rg -n -C 3 '\b(MintForm|BurnForm)\b' app/mint/page.tsx

printf '\n== fee text definitions ==\n'
rg -n -C 2 '\b(MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b' app/mint/page.tsx

Repository: Pi-Defi-world/acbu-frontend

Length of output: 2023


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether these constants are defined anywhere in the repo.
rg -n '\bMINT_NETWORK_FEE_TEXT\b|\bBURN_PROCESSING_FEE_TEXT\b' .

Repository: Pi-Defi-world/acbu-frontend

Length of output: 390


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file context and find where MintForm/BurnForm are rendered.
printf '\n== file outline ==\n'
ast-grep outline app/mint/page.tsx --view expanded || true

printf '\n== render usages ==\n'
rg -n -C 3 '\b(MintForm|BurnForm)\b' app/mint/page.tsx

printf '\n== fee text definitions ==\n'
rg -n -C 2 '\b(MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b' app/mint/page.tsx

printf '\n== repo-wide definitions ==\n'
rg -n '\bMINT_NETWORK_FEE_TEXT\b|\bBURN_PROCESSING_FEE_TEXT\b' .

Repository: Pi-Defi-world/acbu-frontend

Length of output: 2277


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the surrounding render section in app/mint/page.tsx.
nl -ba app/mint/page.tsx | sed -n '280,420p'

Repository: Pi-Defi-world/acbu-frontend

Length of output: 205


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the page render section and look for component usage in the tab content.
sed -n '299,460p' app/mint/page.tsx

printf '\n== component references in render section ==\n'
sed -n '299,460p' app/mint/page.tsx | rg -n '\b(MintForm|BurnForm|MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b'

Repository: Pi-Defi-world/acbu-frontend

Length of output: 7125


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the page render section and look for component usage in the tab content.
sed -n '299,460p' app/mint/page.tsx

printf '\n== component references in render section ==\n'
sed -n '299,460p' app/mint/page.tsx | rg -n '\b(MintForm|BurnForm|MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b'

Repository: Pi-Defi-world/acbu-frontend

Length of output: 7125


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the JSX returned by MintPage and look for actual component usage.
printf '== return section ==\n'
sed -n '460,760p' app/mint/page.tsx

printf '\n== JSX component tags ==\n'
rg -n -C 2 '<(MintForm|BurnForm)\b' app/mint/page.tsx

printf '\n== unresolved fee constants definitions ==\n'
rg -n -C 2 'const\s+(MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b|function\s+(MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b|let\s+(MINT_NETWORK_FEE_TEXT|BURN_PROCESSING_FEE_TEXT)\b' app/mint/page.tsx

Repository: Pi-Defi-world/acbu-frontend

Length of output: 14626


Wire the extracted forms into the tab content

MintForm and BurnForm are still unused because the tab panels keep rendering the inline form JSX. MINT_NETWORK_FEE_TEXT and BURN_PROCESSING_FEE_TEXT are also undefined in the extracted components, so define or inline those values when wiring them in.

🧰 Tools
🪛 ESLint

[error] 84-84: 'MintForm' is defined but never used.

(@typescript-eslint/no-unused-vars)


[error] 194-194: 'BurnForm' is defined but never used.

(@typescript-eslint/no-unused-vars)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/mint/page.tsx` around lines 84 - 290, The extracted MintForm and BurnForm
components are currently unused because the tab panels still render the old
inline JSX, so replace that duplicated tab content with these components and
pass through the existing state/handlers from the surrounding mint page. While
wiring them in, make sure MintForm and BurnForm can access the fee labels by
defining or inlining MINT_NETWORK_FEE_TEXT and BURN_PROCESSING_FEE_TEXT in the
same scope or as props so the extracted components compile and render correctly.

Source: Linters/SAST tools

Comment thread app/send/page.tsx
Comment on lines +170 to +175
const handleConfirmDialogChange = useCallback((open: boolean) => {
if (!open && !sending) {
setConfirmedAmount("");
}
setShowConfirmDialog(open);
}, [sending]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Use the extracted confirm dialog handler.

handleConfirmDialogOpenChange is not defined; the extracted callback is named handleConfirmDialogChange.

Proposed fix
-      <AlertDialog open={showConfirmDialog} onOpenChange={handleConfirmDialogOpenChange}>
+      <AlertDialog open={showConfirmDialog} onOpenChange={handleConfirmDialogChange}>

Also applies to: 587-587

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/send/page.tsx` around lines 170 - 175, The confirm dialog open-change
handler is referenced with the wrong name, causing the extracted callback to be
missed. In the send page component, use the existing handleConfirmDialogChange
callback consistently wherever the confirm dialog’s open state is wired up, and
replace any remaining handleConfirmDialogOpenChange references with the actual
handler name so the dialog uses the extracted callback correctly.

Comment thread contexts/auth-context.tsx
const login = useCallback(
(userId: string, stellarAddress: string | null = null) => {
setAuth(userId, stellarAddress);
setAuth(null, userId, stellarAddress);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Fix login to pass setAuth arguments in the correct order.

Line 163 currently logs users out instead of in (userId becomes null) and passes an extra argument.

Proposed fix
   const login = useCallback(
     (userId: string, stellarAddress: string | null = null) => {
-      setAuth(null, userId, stellarAddress);
+      setAuth(userId, stellarAddress);
     },
     [setAuth]
   );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
setAuth(null, userId, stellarAddress);
setAuth(userId, stellarAddress);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contexts/auth-context.tsx` at line 163, The login flow in auth-context.tsx is
calling setAuth with the arguments in the wrong order, which causes the user id
to be null and adds an extra parameter. Update the login path in the setAuth
call to use the same argument order expected by setAuth (and used elsewhere in
AuthContext), with the authenticated userId and stellarAddress passed correctly
so login actually sets the session instead of clearing it.

Comment thread ISSUES.md
14. **International transfer preview rate uses stale or wrong data** – app/currency/page.tsx: The international tab multiplies ACBU by the local currency rate from `/rates`, but the actual cross-border rate includes intermediary and settlement fees that the frontend doesn't know about. The preview is misleadingly optimistic.
15. **Error boundary `error.tsx` does not log errors to backend** – app/error.tsx, app/global-error.tsx: React error boundaries catch crashes but only render a fallback UI. The error detail (component stack, route, user ID) is never POSTed to an error-tracking endpoint, leaving production crashes invisible.
73. **No `loading.js` or Suspense boundary on the `/send` page** – app/send/page.tsx: The send money page fetches balance and rates on mount but has no Suspense boundary. Users on slow connections stare at a blank screen with no loading indicator.
74. **Form input loses focus on every keystroke due to state-update re-render** – app/mint/page.tsx, app/send/page.tsx: Input components may be defined inline in the parent component's render function, causing React to unmount and remount the input on every keystroke. The keyboard dismisses on mobile and the cursor jumps to the end.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale known-issue entry: this PR resolves item 74.

Item 74 documents exactly the inline-input remount/focus-loss bug that this PR fixes by extracting the input components in app/mint/page.tsx and app/send/page.tsx. Update or remove this entry (or mark it resolved) so the catalog stays accurate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ISSUES.md` at line 33, This ISSUES.md entry is now stale because item 74 has
been fixed by extracting the inline input components in app/mint/page.tsx and
app/send/page.tsx. Update the catalog entry to mark item 74 as resolved, or
remove it entirely if resolved issues are not kept, so the known-issues list
stays accurate and does not describe a bug that no longer exists.

Comment thread lib/wallet-storage.ts
{
name: 'PBKDF2',
salt,
salt: salt as any,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify types feeding crypto APIs are BufferSource-compatible and locate any remaining casts.
set -euo pipefail

echo "== locate fromBase64 definition =="
rg -n --no-heading "function fromBase64|const fromBase64|export .*fromBase64" lib app components

echo "== inspect wallet-storage around crypto calls =="
sed -n '1,220p' lib/wallet-storage.ts

echo "== search for explicit any in wallet-storage and related crypto usage =="
rg -n --no-heading "as any|subtle\\.deriveKey|subtle\\.decrypt" lib/wallet-storage.ts

Repository: Pi-Defi-world/acbu-frontend

Length of output: 6748


Remove the any casts in lib/wallet-storage.tsfromBase64() already returns Uint8Array, so salt, iv, and ciphertext can be passed directly to crypto.subtle.deriveKey() / decrypt(). The current casts only suppress type safety and trip @typescript-eslint/no-explicit-any.

🧰 Tools
🪛 ESLint

[error] 61-61: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/wallet-storage.ts` at line 61, Remove the unnecessary any casts in
wallet-storage handling: fromBase64() already produces Uint8Array, so pass salt,
iv, and ciphertext directly into the crypto.subtle.deriveKey() and decrypt()
calls in lib/wallet-storage.ts. Update the relevant logic around the wallet
storage helpers so the types remain strict and no
`@typescript-eslint/no-explicit-any` suppression is needed.

Source: Linters/SAST tools

Comment thread package.json
Comment on lines +16 to +17
"test": "echo \"No tests\"",
"test:e2e": "echo \"No e2e tests\""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

CI will report green even though no tests run. The QA workflow still invokes pnpm test and pnpm test:e2e, but both now resolve to echo "No tests" / echo "No e2e tests", which always exit 0. Combined with the removed Vitest devDependencies, this silently disables the entire component/E2E test layer while keeping CI green. The frontend QA GitHub Actions workflow runs pnpm typecheck, pnpm lint, pnpm build, pnpm test, and pnpm test:e2e.

If tests are intentionally being removed, consider also removing the corresponding CI steps so the pipeline accurately reflects coverage; otherwise restore a real test runner.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 16 - 17, The package.json test scripts currently
stub out pnpm test and pnpm test:e2e with echo commands, so the QA workflow can
pass without running any real tests. Restore real test execution in the test and
test:e2e script entries, or if the suite is intentionally being removed, update
the frontend QA GitHub Actions workflow to stop invoking those commands so CI
reflects the actual coverage; use the package.json script definitions as the
main place to fix this.

Comment thread package.json
Comment on lines +85 to +95
"eslint": "^10.4.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "5.2.0",
"globals": "^17.5.0",
"jsdom": "^29.0.2",
"playwright": "^1.59.1",
"postcss": "^8.5",
"sharp": "^0.34.5",
"tailwindcss": "^4.1.9",
"tw-animate-css": "1.3.3",
"typescript": "^5",
"typescript-eslint": "^8.58.2",
"vite-tsconfig-paths": "^6.1.1",
"vitest": "^4.1.5"
},
"packageManager": "pnpm@10.15.0+sha512.486ebc259d3e999a4e8691ce03b5cac4a71cbeca39372a9b762cb500cfdf0873e2cb16abe3d951b1ee2cf012503f027b98b6584e4df22524e0c7450d9ec7aa7b",
"pnpm": {
"overrides": {
"@stellar/stellar-sdk": "^15.0.1"
},
"peerDependencyRules": {
"allowedVersions": {
"eslint-plugin-react>eslint": "^10",
"@trezor/connect-plugin-stellar>@stellar/stellar-sdk": "^15.0.1"
}
}
"typescript-eslint": "^8.58.2"
}
}
} No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -a 'generate-pwa-icons' || echo "script not found (removed)"
rg -n "from 'sharp'|require\(.sharp" --glob '!node_modules' || echo "no sharp references remaining"

Repository: Pi-Defi-world/acbu-frontend

Length of output: 245


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== package.json relevant sections ==\n'
sed -n '1,180p' package.json | cat -n

printf '\n== scripts/generate-pwa-icons.mjs ==\n'
wc -l scripts/generate-pwa-icons.mjs
cat -n scripts/generate-pwa-icons.mjs

Repository: Pi-Defi-world/acbu-frontend

Length of output: 5493


Remove the stale icon-generation script or restore sharp
scripts/generate-pwa-icons.mjs still imports sharp and will fail if run, but sharp is no longer in devDependencies. Delete the script too, or add the dependency back if it’s still needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` around lines 85 - 95, The PWA icon generation workflow is
broken because scripts/generate-pwa-icons.mjs still depends on sharp even though
sharp was removed from devDependencies. Either delete the stale icon-generation
script if it is no longer used, or restore sharp to the package manifest if the
script must remain; make sure the dependency choice matches the current usage of
the generate-pwa-icons.mjs script.

@Junman140

Copy link
Copy Markdown
Member

@N-thnI resolve conflict

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.

Form input loses focus on every keystroke due to state-update re-render

4 participants