dev #56

Merged
root merged 10 commits from dev into main 2026-05-27 00:49:30 +03:00

10 Commits

Author SHA1 Message Date
cf1fee68a9 fix(web): responsive billing table + filters on mobile
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
The payments table forced min-w-[640px] inside overflow-x-auto, so mobile
got an awkward horizontal scroll, and the 5-option status filter could
overflow the viewport. Make the table a responsive layout: on mobile each
payment renders as a labelled stacked card (column label via ::before
from data-label, header row hidden), and on sm+ it stays a normal table.
Let the segmented filters wrap instead of overflowing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:36:03 +03:00
c633e846e2 fix(payments): curate /payments/me response — stop leaking internal columns, join plan name
getMyPayments returned the raw payment row, exposing internal fields
(adminNote, iyzicoPaymentId, bankAccountId, session/intent ids) to the
end user. Replace with an explicit projection that returns only what the
billing UI needs, joins planName from the subscription's plan (was always
"-"), and surfaces Stripe receipt availability as a hasStripeReceipt
boolean instead of the raw payment intent id. Frontend reads the boolean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:31:33 +03:00
d77face831 fix(web): billing — correct cancelled status label and gate receipt button
- Subscription status is "cancelled" (and "pending") in the API; the i18n
  keys/variant map used "canceled", so the badge showed the raw
  billing.subStatus.cancelled key. Fix the spelling and add pending.
- Only show "View receipt" for Stripe payments that actually have a
  stripePaymentIntentId. Seeded/legacy completed payments have none, so
  the button used to appear and then toast "no receipt available".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:28:39 +03:00
1b9492ba49 style(api): drop non-null assertion in refund amount
Replace `input.amount!` with `input.amount ?? Number(payment.amount)`,
which is behaviour-identical (undefined amount = full refund = full
amount) but satisfies lint/style/noNonNullAssertion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:15:41 +03:00
7a8fe5e98e feat(payments): Stripe receipt link on billing rows
Add GET /payments/:id/receipt — resolves the Stripe-hosted receipt URL
from the payment intent's latest charge (ownership-scoped; returns EFT
receipt directly when present, null otherwise). Wire a "View receipt"
action on completed Stripe rows that fetches the URL on demand and opens
it, with a toast when none is available.

Closes the last billing-audit item (#8).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:14:28 +03:00
0e61a2fcc7 feat(web): billing loading skeleton shape + show-more pagination
Make the payments loading state mirror the table card (header + rows)
instead of generic bars, and paginate the list client-side (10 at a time
with a "Show more" button) so long payment histories don't render all at
once.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:07:50 +03:00
94d04d5339 refactor(web): semantic billing table + segmented filters
Replace the div-grid "table" with a real <table> (thead/th scope=col/
tbody/td) inside an overflow-x-auto wrapper, so screen readers announce
each cell under its column and every amount/status is labelled (drops the
hidden-header mobile hack). Convert the filter button rows into compact
segmented controls (fieldset/legend) and only show filters once payments
exist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:06:36 +03:00
36bd4b500b feat(web): add subscription summary card to billing page
Billing was payment history only. Add a summary card at the top showing
the current plan, status badge, and next renewal / trial-end / end date
(from /subscriptions/me), with a "Manage subscription" link — or a
"Choose a plan" CTA when there's no active subscription.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:04:58 +03:00
acada22e71 fix(web): billing — distinguish empty vs filtered, localize date, tabular nums
Show "no payments match this filter" with a clear-filters button when
filters hide everything (was the misleading "no payments yet"). Follow
the active locale for the payment date instead of hard-coding tr-TR, and
use tabular figures for date and amount columns.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:03:26 +03:00
0749a55b41 fix(web): repair EFT receipt download and add EFT payment filter
The receipt link read payment.receiptUrl, but the API returns the column
as eftReceiptUrl — so the download button never rendered (dead feature).
Use eftReceiptUrl. Also add the missing "EFT" option to the method
filter; EFT is a live method with rows and receipts but couldn't be
filtered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 00:02:23 +03:00