fix: Nordea Business CSV variants, API keys UI polish, transaction categorization (#183)

* fix: MCP OAuth 303 redirect, send dialog auto-close, bank details null payload

- OAuth authorize: use 303 See Other instead of default 307, which
  preserved POST method and caused Claude's callback to return 405
- SendInvoiceDialog: close dialog and show toast after email send
  instead of leaving a success message that requires manual close
- BankDetailsSetupDialog: omit empty fields from payload instead of
  sending null, which fails Zod validation on non-nullable schema fields

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: remove dead sentMessage state and fix stale comment

Remove sentMessage state, its success banner JSX, and the CheckCircle2
import — all unreachable after the dialog now auto-closes on email send.
Fix stale "to null" comment in BankDetailsSetupDialog.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: support Nordea Business CSV variants, polish API keys UI, fix transaction categorization

- Extend Nordea Business bank file parser to handle three CSV export
  formats (classic, Betalare/Mottagare variant, Bokföringsdatum variant)
  with proper detection guards against SEB/LF misidentification
- Rework ApiKeysPanel: add CopyBlock component, destructive confirm on
  revoke, collapsible API-key-based connection methods, Claude.ai OAuth
  instructions as recommended path, simplified scope badges
- Stop deriving is_business from category on manual transaction creation;
  set null so categorization flow handles it correctly
- Show categorize button when journal_entry_id is missing regardless of
  is_business value

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address PR review — await clipboard, fix zero-scope label, simplify condition

- Await navigator.clipboard.writeText and catch failures
- Change zero-scope label from "Enbart läs" to "Inga behörigheter"
- Simplify redundant ternary condition in TransactionHistoryList

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: repair broken ternary in TransactionHistoryList JSX

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-04-07 11:11:47 +02:00
committed by GitHub
co-authored by Claude Opus 4.6
parent e42da5c32b
commit a25e75be25
6 changed files with 325 additions and 100 deletions
+1 -3
View File
@@ -78,15 +78,13 @@ export default function TransactionForm({ onSubmit, isLoading }: TransactionForm
const isIncome = categories.find((c) => c.value === watchCategory)?.isIncome
const onFormSubmit = (data: FormData) => {
const isBusiness = data.category ? data.category !== 'private' : undefined
onSubmit({
date: data.date,
description: data.description,
amount: data.amount,
currency: data.currency,
category: data.category as TransactionCategory,
is_business: isBusiness,
is_business: undefined,
notes: data.notes,
})
}
@@ -138,7 +138,7 @@ export default function TransactionHistoryList({
Bokförd
</Badge>
</>
) : transaction.is_business === null ? (
) : (
<>
<span>·</span>
<button
@@ -149,7 +149,7 @@ export default function TransactionHistoryList({
Ej bokförd
</button>
</>
) : null}
)}
{transaction.potential_invoice && !transaction.invoice_id && (
<>
<span>·</span>
@@ -167,7 +167,7 @@ export default function TransactionHistoryList({
</div>
</div>
<div className="flex items-center gap-3">
{transaction.is_business === null && !transaction.journal_entry_id && (
{!transaction.journal_entry_id && (
<Button
size="sm"
variant="default"