Commit Graph
6 Commits
Author SHA1 Message Date
Jakob WennbergandClaude Fable 5 be9d630347 feat(home): concept Hem with Att göra + Fortsätt (UI migration PR 11) (#1132)
* feat(home): concept scene 14: greeting + Att gora/Fortsatt panes

Hem becomes the founder-approved two-panel layout: serif time-of-day
greeting with date and company, the Att gora worklist restyled to the
concept pane (eyebrow header, h-rows with count chips, hover chevrons)
and a new Fortsatt pane listing in-progress work derived purely from
draft state (lib/worklist/resume: journal drafts, invoice drafts/unsent,
mid-lifecycle salary runs; deadline boost, cap 3, tested). A completed
flow can never render as a resume row by construction: only draft-state
rows are fetched. KPI tiles, revenue/expense cards and the deadline/tax
widgets leave the page per dev_docs/last_session_resume.md section 8,
which also prunes their fetches (journal-line YTD aggregation, unpaid
totals, deadlines): the page got faster. Banners, checklist,
build-assistant hero and the Skatteverket nudge survive.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(home): serif pane titles for Att gora and Fortsatt

Founder feedback: the uppercase eyebrow headers read as a stray font.
Both pane titles are now the Hedvig display serif (text-lg) over the
hairline, matching the page's heading language; the band headers inside
Att gora keep their small uppercase form as grouping devices.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(home): Geist pane titles for Att gora and Fortsatt

Founder call: the pane titles use the body sans (14px medium), not the
display serif.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(ui): Geist section headers + drop stale-transactions chip

Founder feedback: pane/section headers (Att gora, Fortsatt, the reports
groups Lopande/Bokslut/Skatt & moms etc) render in Geist sentence case
instead of uppercase eyebrows or serif. The global h1-h3 display-font
rule moves into @layer base so utility classes like font-sans can
actually override it (unlayered element rules beat Tailwind's layered
utilities: this was silently eating the override). Also removes the
'N aldre an 14 dagar' chip from the Bokfora transaktioner row and its
stale-count plumbing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(ui): continuous nav crossfade + floating slide-over entrance

The rail/full nav states now stay mounted and crossfade past each other
(the inactive layer absolute, faded, nudged sideways, inert) while the
aside width animates: the switch reads as one continuous motion instead
of a DOM swap. The detail slide-over floats in from the right edge
(slide-in-from-right-full, 300ms decelerating curve) per the concept,
with a quicker ease-in exit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(ui): make transitions and enter/exit animations actually run

Two silent app-wide animation killers found while chasing 'the nav still
is not smooth':

1. The codebase uses the shadcn animate-in/out vocabulary everywhere but
   no animate plugin was ever installed: Tailwind v4 silently dropped
   every such class, so popovers, dialogs, menus and the slide-over all
   appeared instantly. globals.css now defines the exact subset in use
   (accEnter/accExit keyframes + var-driven utilities), plugin-free,
   composing with duration/ease via --tw-duration/--tw-ease and
   collapsing under prefers-reduced-motion. Dialog drops its
   bracket-variant slide classes (zoom+fade carries the entrance).

2. The scrollbar auto-hide block's universal '* { transition:
   scrollbar-color ... }' was unlayered, and unlayered rules beat
   Tailwind's layered transition-* utilities regardless of specificity:
   every width/margin/color transition in the app was dead. The rule now
   lives in @layer base. Verified: the aside animates 248->64 over 300ms
   and the slide-over runs accEnter at 0.3s with the decelerating curve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(ui): finish the rr-mask session-replay masking sweep

Main's #1105 switched one amount cell from the no-op sensitive-field
class to rr-mask (rrweb's built-in text-masking class). The reskinned
tables introduced more sensitive-field cells; all 12 occurrences now use
rr-mask so financial amounts are masked in session replays.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 22:36:18 +02:00
Jakob WennbergandClaude Fable 5 1ccf7ab81f feat(transactions): concept shell and row language (UI migration PR 5) (#1124)
* feat(transactions): concept shell for scene 10 (header, toolbar, footer)

- Header: title + Importera SplitButton (import guide / manual entry,
  last-used mode persisted via ui_state.create_mode.transactions),
  replacing the three-button row
- Toolbar in concept order: [Att bokföra/Alla seg with count chip]
  [search] [Välj flera as quiet toggle] ... [source ContextPicker far
  right merging the old in-list source dropdown (bank/Skatteverket)]
- Bank sync status + sync-now + Bankavstämning move to the concept's
  footer status line together with the honest visible-row counter
  ("n att hantera")
- skv-reconnect banner and all dialogs/actions untouched

Row cards -> concept dry-table conversion follows separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(transactions): concept row language for the inbox cards

Rows read like the scene 10 table: date as the first tabular column,
description on one line, amount right (+income in sage), auto-detected
invoice matches as beige suggestion chips instead of primary pills,
tighter hairline rows at 13px. Every action unchanged: Bokför pill,
match/assistant/overflow menu, batch checkboxes, exit animations,
extraction status.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(transactions): de-bloat rows and chrome to match the concept

- Rows carry only the essentials: date, description, amount, Bokför and
  one overflow menu. The inline match and ask-assistant icon buttons
  fold into the overflow menu (all actions still one click away)
- The "n nya banktransaktioner sen ditt senaste besök" banner is removed;
  the footer sync line covers it
- The Skatteverket reconnect banner becomes the one-ochre-sentence
  AttnLine with an inline action (convention 6)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(ui): extract dry-table primitives into components/ui/dry-table

The concept table styles (TH/TD/VTH/VTD classes, quiet links, RowFoldout)
move out of JournalEntryList so the transaction inbox can render the exact
same table language.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(transactions): Synka bank nu in the Importera menu

Extracts the per-connection sync/reconnect logic into a shared useBankSync()
hook (BankSyncNowButton keeps using it) and adds the concept's first menu row
to the Importera split button: sync all active connections, with the
last-synced age as the row description. Hidden without a connection or the
bank_sync capability; the footer button stays the gated conversion surface.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(transactions): per-account source picker with balances

The context chip becomes the concept's account chooser: always visible in
inbox mode, one row per enabled cash account (PSD2 balance annotation),
an Övriga bucket for bank rows without a registered account, and a
Skattekonto row annotated with the cached saldo. The trigger reads
'Alla källor · <sum>' where the sum covers SEK ledgers + skattekonto.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(transactions): concept dry-table for the inbox

The inbox list becomes the exact Bokforing table: borderless dry-table with
hover-revealed checkboxes and chevrons, one-line rows (date, description,
amount, quiet primary pill + overflow + foldout), and a RowFoldout expansion
carrying the row detail and the full action set as quiet links. Skattekonto
rows render as chip-marked table rows with inline actions. The 'Valj flera'
toggle and the floating batch bar are replaced by the concept bulkbar that
pops in above the table once a row is selected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(i18n): singular form for bulkbar selection count

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(transactions): suggestion-first Bokfor flow (concept scene 10)

Bokfor on a row with a suggestion now goes straight to the compact
kontering confirm (QuickReview) showing the proposed verifikat; the full
template picker becomes the fallback and the 'Byt mall' path. Rows carry
the concept's 'Forslag: <mall>' chip (with D/K in the tooltip and the
foldout meta). The picker dialog is de-bloated: alternate paths (manuellt,
matcha, ignorera) collapse into quiet links. Modal scroll containers
(DialogContent, SlideOverBody) keep a visible scrollbar thumb: with the
app-wide auto-hide, a long dialog read as cut off at the fold.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(transactions): drop suggestion UI and foldout action links

Founder direction: no booking suggestions in the list for now (logic comes
later), and the foldout duplicated the overflow menu: the three dots are
the clearer surface. The foldout keeps row detail only (FX conversion,
original bank name, 1930/1630 hint, extraction status) and rows without
any detail no longer expand. The Skattekonto picker row drops its saldo
annotation; the Alla kallor sum covers bank ledgers only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(transactions): dry-table for the Alla view + pill chips app-wide

The history list joins the inbox's table language: Datum, Beskrivning,
Belopp, Status columns with Bokford as muted text + Visa verifikat quiet
link (normal state) and Ej bokford as the beige exception chip with an
inline Bokfor pill; the business/private tabs become the house seg and the
KALLA header row becomes the standard chip-picker. Skattekonto rows get
the same treatment. SEK conversion moves to a tooltip (one-line rows).

Badge itself becomes the concept chip: pill radius (99px), 11.5px, quiet
padding, replacing the boxy rounded-md look the founder flagged on the
Underlag saknas badge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(ui): audit round: viewer-disabled split options, touch fallback

Regression-audit fixes: SplitButton options support disabled+disabledTitle
so viewer-gated create paths render inert with the viewer tooltip instead
of silently no-opping (wired on Ny transaktion); the history list gets its
Kopplad till faktura indicator back; dead transactionsWithMatches memo
removed; and coarse-pointer devices now always show hover-revealed
controls (checkboxes, chevrons, quiet row actions) since touch has no
hover.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 21:41:45 +02:00
Jakob WennbergandClaude Opus 4.7 ba45b8f661 refactor(ui): editorial monochrome design refresh (#473)
* refactor(ui): editorial monochrome design refresh

Design-system layer only, no functional changes. Cascades app-wide
from 8 files in the primitives + tokens layer.

- Swap Fraunces → Hedvig Letters Serif for display typography
  (single-weight; drop font-medium from CardTitle and PageHeader)
- Token sweep: pure white background, warm beige secondary
  (40 11% 89%), achromatic primary, calibrated 45 5% 85% border,
  halved-opacity shadows
- Flatten Card: remove shadow, rounded-xl → rounded-lg, full-opacity
  border (was border-border/60)
- Flatten Button: remove shadow-sm, remove active:scale-[0.98],
  drop outline border morph, transition-all 300ms → transition-colors
  150ms
- Soften Dialog overlay (bg-black/80 → bg-black/40 with dark variant)
  and use halved --shadow-md token on DialogContent
- Sidebar: bg-card/90 → bg-background, full-opacity hairline border,
  warm-beige active state (bg-secondary), hover bg-secondary/60
- .hover-lift utility: replace translateY + box-shadow with flat
  background-color shift
- PageHeader title: text-2xl font-medium → text-3xl md:text-4xl
  (no font-medium)
- CLAUDE.md Brand & Aesthetic, Typography, and Forbidden Patterns
  sections rewritten to reflect new system

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

* refactor(ui): address PR review

- Remove dead .hover-lift utility (no callers; CLAUDE.md now bans
  hover-lift patterns, so leaving the class would contradict the docs)
- Bump Dialog overlay bg-black/40 → bg-black/50 — gives a more
  perceptible separation layer over the new pure-white background
  while keeping the lighter editorial feel

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

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 23:01:53 +02:00
Mattsson d5410a518f Mobile view fixes (#188)
* fix: make new user checklist mobile responsive

Adjust spacing, padding, typography, and indentation for small screens
so the onboarding welcome screen works well on mobile devices.

* fix: make expenses and bookkeeping verification views mobile responsive

- Expenses/new: stack form grids on mobile, replace line items table with
  card layout, full-width action buttons
- Expenses/[id]: stack header and actions, card layout for line items and
  payments, single-column info grid on mobile
- JournalEntryList: unify verification lines into card layout for all
  screen sizes, hide redundant line descriptions that duplicate account
  name or entry description, stack filter bar and action buttons on mobile

* fix: remove stray )); in provider_consents migration

Syntax error on line 35 caused MIGRATIONS_FAILED on the Supabase staging branch.

* fix: enhance mobile responsiveness for invoices page and update dialog styles
2026-04-07 15:53:30 +02:00
Jakob WennbergandClaude Opus 4.6 ceec8c02a8 feat: reverse charge VAT (ruta 20-32) + mobile UX improvements (#50)
* fix: include reversed entries in all reports (general ledger, trial balance, VAT, SIE, NE, INK2)

Reversed entries (storno) must appear alongside their original posted entries
in reports for a complete audit trail. Previously, filtering by status='posted'
excluded them, causing discrepancies when corrections had been made.

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

* feat: semi-manual invoice payment booking with editable journal lines

When marking an invoice as paid, users now see a dialog where they can:
- Choose which bank/cash account the payment goes to (1910, 1920, 1930, etc.)
- Review and edit the proposed journal entry lines before committing
- The happy path remains fast — lines are pre-filled correctly

Implementation:
- Pure proposePaymentLines() function for line computation (accrual + cash)
- PaymentBookingDialog with AccountCombobox, balance validation, date picker
- API accepts optional custom lines, falls back to auto-generation without them
- 18 tests (8 unit + 10 API) all passing

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

* fix: address Greptile review — validation fallback, balance check, error handling

- P1: Return 400 on invalid body instead of silently falling back to
  auto-generated lines (split JSON parse from schema validation)
- P1: Add server-side balance check for custom lines before committing
  (debit must equal credit, totalDebit > 0)
- P2: Wrap PaymentBookingDialog init() in try/catch with toast on
  failure and auto-close instead of silent empty state
- Add 2 new tests: unbalanced lines → 400, invalid schema → 400

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

* fix: OAuth callback redirect for local dev and timeout resilience

- Pass redirectUri dynamically from NEXT_PUBLIC_APP_URL so OAuth
  callbacks work on localhost (not just production)
- Encode consentId/provider in OAuth state (base64url JSON) so the
  callback doesn't depend on session storage
- Add skipAuth flag to extension API routes for OAuth callbacks
  (external provider redirects have no user session cookie)
- Wrap AbortError in descriptive timeout messages in arcim-client
- Make preview endpoint resilient to partial failures (company info
  and SIE fetch are individually non-blocking)
- Simplify login page (remove unused magic link auth mode)

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

* fix: create journal entry before marking invoice as paid

Move journal entry creation before the invoice status update so that
if accounting fails, the invoice is not permanently marked paid without
a corresponding entry. Previously the error was silently swallowed.

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

* fix: update mark-paid tests for journal-first ordering

Reorder mock queue to match new flow (settings before update), update
failure test to expect 500 instead of silent success, add try-catch
with proper error response in route handler.

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

* feat: add reverse charge VAT (ruta 20-32) and improve mobile UX across dashboard

Add full reverse charge (omvänd skattskyldighet) support to the VAT declaration:
- Map accounts 2614/2624/2634 to ruta 30/31/32 for self-assessed output VAT
- Calculate purchase bases (ruta 20-24) from supplier invoices by supplier type
- Include ruta 30-32 in ruta 49 formula and totalOutputVat summary
- Display reverse charge section in reports UI and composition chart
- Add comprehensive test coverage for all reverse charge scenarios

Improve mobile UX across the app:
- Convert nav drawer to bottom sheet with drag handle and safe area padding
- Add mobile card layout for PaymentBookingDialog journal lines
- Replace settings tab pills with dropdown selector on mobile
- Make wizard step indicators responsive (collapsed on mobile)
- Ensure all dialog footers stack buttons full-width on mobile
- Add 44px minimum touch targets throughout
- Make onboarding buttons full-width on mobile

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

* fix: address Greptile review — indentation, query efficiency, tab dedup

- Fix misleading try-block indentation in mark-paid route
- Filter reversed entries at DB level (.eq('status', 'posted')) instead
  of fetching then discarding in memory
- Extract shared settingsTabs array so mobile Select and desktop
  TabsList stay in sync automatically

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

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:42:57 +01:00
Jakob Wennberg a25d10a528 Initial copy from influencer-biz 2026-02-13 14:00:46 +01:00