diff --git a/app/(dashboard)/transactions/page.tsx b/app/(dashboard)/transactions/page.tsx
index 7e38c0f5..21855669 100644
--- a/app/(dashboard)/transactions/page.tsx
+++ b/app/(dashboard)/transactions/page.tsx
@@ -22,6 +22,7 @@ import BankSyncStatusChip from '@/components/transactions/BankSyncStatusChip'
import { ContextPicker, type ContextPickerItem } from '@/components/common/ContextPicker'
import { AttnLine } from '@/components/ui/attn-line'
import BankSyncNowButton from '@/components/transactions/BankSyncNowButton'
+import BankSyncSinceLastVisit from '@/components/transactions/BankSyncSinceLastVisit'
import TransactionInboxCard from '@/components/transactions/TransactionInboxCard'
import TransactionHistoryList from '@/components/transactions/TransactionHistoryList'
import InboxZeroState from '@/components/transactions/InboxZeroState'
@@ -2663,6 +2664,7 @@ export default function TransactionsPage() {
)}
+
{
+ .then(({ count: rowCount, error }) => {
if (cancelled) return
+ // A failed query must not advance the marker: that would silently
+ // swallow the notification for rows that DID arrive in the window.
+ if (error) return
if (rowCount && rowCount > 0) {
setCount(rowCount)
} else {
diff --git a/extensions/general/enable-banking/components/BankSyncProgressDialog.tsx b/extensions/general/enable-banking/components/BankSyncProgressDialog.tsx
index 8c7bded6..4d391752 100644
--- a/extensions/general/enable-banking/components/BankSyncProgressDialog.tsx
+++ b/extensions/general/enable-banking/components/BankSyncProgressDialog.tsx
@@ -83,6 +83,34 @@ export function BankSyncProgressDialog({
// grace period the user may background the (still-running) sync.
const blockClose = state.kind === 'syncing' && !overGrace
+ // The payoff: once the first sync lands, name the work now waiting so the
+ // moment points onward instead of stranding the user on the settings panel.
+ // Same authenticated endpoint the dashboard pane refetches; best-effort.
+ const [workCounts, setWorkCounts] = useState<{ book: number; matches: number } | null>(null)
+ useEffect(() => {
+ if (!open || state.kind !== 'done' || state.summary.imported === 0) {
+ // A later sync must not inherit the previous run's numbers.
+ setWorkCounts(null)
+ return
+ }
+ let cancelled = false
+ fetch('/api/worklist/counts')
+ .then((res) => (res.ok ? res.json() : null))
+ .then((json: { data?: { counts?: Record } } | null) => {
+ if (cancelled || !json?.data?.counts) return
+ setWorkCounts({
+ book: json.data.counts.book_transaction ?? 0,
+ matches: json.data.counts.suggested_match ?? 0,
+ })
+ })
+ .catch(() => {
+ // The CTA degrades to a plain link; the numbers are a nicety.
+ })
+ return () => {
+ cancelled = true
+ }
+ }, [open, state])
+
return (
+
)}
{state.kind === 'failed' && (
@@ -162,22 +190,47 @@ export function BankSyncProgressDialog({
)}
-
+ {state.kind === 'done' && state.summary.imported > 0 ? (
+ <>
+
+
+ >
+ ) : (
+
+ )}
)
}
-function DoneBody({ summary }: { summary: SyncProgressSummary }) {
+function DoneBody({
+ summary,
+ workCounts,
+}: {
+ summary: SyncProgressSummary
+ workCounts: { book: number; matches: number } | null
+}) {
const requestedDays = daysBetween(summary.requested_from)
const returnedDays =
summary.returned_min_date && summary.returned_max_date
@@ -199,6 +252,12 @@ function DoneBody({ summary }: { summary: SyncProgressSummary }) {
Datum: {summary.returned_min_date} → {summary.returned_max_date}
)}
+ {workCounts && workCounts.book > 0 && (
+
+ {workCounts.book} att bokföra
+ {workCounts.matches > 0 && <> · {workCounts.matches} matchar fakturor>}
+
+ )}