Skip to content

feat(ImprovePwAI3UX): admin per-user credit detail page with refund s…#647

Draft
EmilFattakhov wants to merge 5 commits intomainfrom
ImprovePwAI3UX
Draft

feat(ImprovePwAI3UX): admin per-user credit detail page with refund s…#647
EmilFattakhov wants to merge 5 commits intomainfrom
ImprovePwAI3UX

Conversation

@EmilFattakhov
Copy link
Copy Markdown
Member

@EmilFattakhov EmilFattakhov commented Apr 1, 2026

…upport

  • Capture receipt.from (EVM wallet address) at intent confirmation time and store it in a new intents.from_address column (migration included)
  • Add purchased_credits.refunded_at column (migration included)
  • Repository: markAsRefunded() zeros remaining bytes + sets refunded_at; getByUserPublicId() joins purchased_credits with intents to return price + wallet data per batch
  • Use cases: getUserBatches (admin-only, by userPublicId) + refundBatch (idempotent)
  • API routes: GET /credits/batches/user/:userPublicId and POST /credits/batches/:id/refund
  • Frontend: AdminUserCredits component shows full purchase history per user with date, status, expiry, original/consumed/remaining bytes, AI3 paid, EVM wallet address, and a "Mark Refunded" button per batch
  • AllBatchesTable User column is now a clickable link to the new per-user page
  • New Next.js page: /[chain]/drive/admin/credits/[userPublicId]
  • Added ROUTES.adminUserCredits helper to @auto-drive/ui

…upport

- Capture receipt.from (EVM wallet address) at intent confirmation time and
  store it in a new intents.from_address column (migration included)
- Add purchased_credits.refunded + refunded_at columns (migration included)
- Repository: markAsRefunded() zeros remaining bytes + sets refunded/refunded_at;
  getByUserPublicId() joins purchased_credits with intents to return price +
  wallet data per batch
- Use cases: getUserBatches (admin-only, by userPublicId) + refundBatch (idempotent)
- API routes: GET /credits/batches/user/:userPublicId and POST /credits/batches/:id/refund
- Frontend: AdminUserCredits component shows full purchase history per user
  with date, status, expiry, original/consumed/remaining bytes, AI3 paid,
  EVM wallet address, and a "Mark Refunded" button per batch
- AllBatchesTable User column is now a clickable link to the new per-user page
- New Next.js page: /[chain]/drive/admin/credits/[userPublicId]
- Added ROUTES.adminUserCredits helper to @auto-drive/ui

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify bot commented Apr 1, 2026

Deploy Preview for auto-drive-storage ready!

Name Link
🔨 Latest commit 1c4925e
🔍 Latest deploy log https://app.netlify.com/projects/auto-drive-storage/deploys/69ccfe3fae725a0008b0b4ce
😎 Deploy Preview https://deploy-preview-647--auto-drive-storage.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

EmilFattakhov and others added 4 commits April 1, 2026 11:02
refunded_at being non-null is already the canonical signal that a refund
occurred. The separate refunded boolean was redundant — remove it from the
migration, DB type, model, and frontend type. All refund-state checks now
read batch.refundedAt !== null.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolved conflict in apps/frontend/src/services/api.ts — kept all ToU,
Deletion admin methods from main alongside the new getUserCreditBatches
and refundCreditBatch methods from this branch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… active

account.pendingUploadCredits = freeRemaining + purchasedRemaining, but
uploadLimit is only the free quota. This caused uploadUsed to go negative
(e.g. -75 MiB/100 MiB) and the progress bar to misrepresent usage.

Fixes:
- SideNavBar: creditSummary is always loaded for logged-in users, so
  purchasedBytesRemaining is now derived regardless of the feature flag.
  freeRemaining = pendingUploadCredits - purchasedBytesRemaining is passed
  as uploadPending so the progress bar and used/limit label track only the
  free allocation. The purchasedBytesRemaining prop is still gated by
  hasBuyCreditsFeature for the display section.
- AccountInformation: when the user has purchased credits, the primary "left"
  label now shows total available (free + purchased) — the figure that governs
  whether an upload will succeed. The right-side used/limit and progress bar
  continue to reflect the free allocation so the user can see both at a glance.
  Negative uploadUsed (free quota exhausted) renders as 0 in the text and
  100% in the bar, which is correct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…idation

- Replace raw MiB number input (which caused "0200" leading-zeros bug) with
  a text input + MB / GB / TB segmented unit toggle. Internal value stays in
  MiB; the display converts automatically when switching units.
- Remove editable AI3 amount field — dual coupled inputs were confusing and
  allowed inconsistent state. AI3 amount, USD equivalent, and Total are now
  read-only display rows derived from the storage amount.
- Add real-time cap validation: shows an amber warning with the maximum
  purchasable amount when the entered size would exceed the user's credit cap,
  and disables the Confirm Purchase button until the amount is valid.
- "After Purchase" summary now falls back to current balance when no amount
  is entered, instead of showing 0B.
- Unit conversion on toggle: switching MB→GB converts the current value so
  the underlying purchase size stays constant (e.g. 1024 MB → 1 GB).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant