Page Specifications

Per-page UI and feature specifications

Page: Accounts

Page Spec: Bank Accounts

Route

/accounts

Architecture Status

Core

Figma Reference

accounts.png

Visual Description from Figma

The bank accounts page displays all AISP-linked bank accounts via Open Banking:

NOTE: Figma shows "Kort" tab active, but this is likely a design artifact. The accounts page should activate the "Profil" tab or no tab (if accounts is accessed from dashboard link).

Background is light gray. Spacing between cards is consistent.

Page Layout

App page WITH bottom nav
├── Top Bar
│   ├── Left: Back arrow (chevron left)
│   └── Center: "Mine kontoer" heading
├── Info Card (light green bg, green shield icon)
│   ├── "Open Banking (PSD2)" heading
│   └── Explanation text (PSD2 pass-through)
├── Bank Account Cards (white rounded)
│   └── For each account:
│       ├── Bank icon (green circle) + Bank name + Badge (if primary) + Account number
│       └── Balance amount (right-aligned)
├── Total Balance Card (white rounded)
│   ├── "Samlet saldo" label (left)
│   └── Total amount in green (right)
├── Add Account Button (white rounded)
│   └── "+ Koble til ny bankkonto"
└── Bottom Nav (Profil active or none)

Components

Top Bar

<div className="flex items-center px-6 pt-6">
  <button onClick={router.back} className="rounded-lg p-2 hover:bg-white/80">
    <ChevronLeft className="h-5 w-5 text-[#1A1A1A]" />
  </button>
  <h1 className="flex-1 text-center font-[family-name:var(--font-fraunces)] text-xl font-bold text-[#1A1A1A] -ml-12">
    Mine kontoer
  </h1>
</div>

Info Card

<div className="rounded-2xl bg-[#0B6E35]/10 p-4 border border-[#0B6E35]/20">
  <div className="flex gap-3">
    <div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full bg-[#0B6E35]/20">
      <Shield className="h-5 w-5 text-[#0B6E35]" />
    </div>
    <div>
      <p className="font-semibold text-[#1A1A1A]">Open Banking (PSD2)</p>
      <p className="mt-1 text-sm text-[#6B7280]">
        Drop leser saldo fra banken din via BankID-samtykke. Vi lagrer aldri pengene dine — alt går direkte fra din bankkonto.
      </p>
    </div>
  </div>
</div>

Bank Account Card

<div className="flex items-center justify-between rounded-2xl bg-white p-4 shadow-sm">
  <div className="flex items-center gap-3">
    <div className="flex h-12 w-12 items-center justify-center rounded-full bg-[#0B6E35]/10">
      <Landmark className="h-6 w-6 text-[#0B6E35]" />
    </div>
    <div>
      <div className="flex items-center gap-2">
        <p className="text-base font-bold text-[#1A1A1A]">{bankName}</p>
        {isPrimary && (
          <span className="rounded-full bg-[#0B6E35]/10 px-2 py-0.5 text-xs font-medium text-[#0B6E35]">
            Primær
          </span>
        )}
      </div>
      <p className="text-sm text-[#6B7280]">{accountNumber}</p>
    </div>
  </div>
  <p className="text-lg font-bold text-[#1A1A1A]">{formattedBalance} NOK</p>
</div>

Total Balance Card

<div className="flex items-center justify-between rounded-2xl bg-white p-4 shadow-sm">
  <p className="text-sm text-[#6B7280]">Samlet saldo</p>
  <p className="text-xl font-bold text-[#0B6E35]">{formattedTotal} NOK</p>
</div>

Add Account Button

<button className="flex h-14 w-full items-center justify-center gap-2 rounded-2xl bg-white text-base font-medium text-[#1A1A1A] shadow-sm transition-colors hover:bg-[#F9FAFB]">
  <Plus className="h-5 w-5" />
  Koble til ny bankkonto
</button>

Data Displayed

Data Source API
List of linked bank accounts AISP (Open Banking) GET /api/accounts
Bank name AISP account metadata
Account number AISP account metadata
Account balance AISP real-time balance read
Primary account flag User preference stored in DB
Total balance Calculated sum of all accounts Client-side calculation

User Interactions

Element Action Result
Back arrow Click Navigate back to previous page (likely /dashboard)
Bank account card Click Navigate to account detail page (optional)
"+ Koble til ny bankkonto" button Click Initiate BankID flow to link new account via Open Banking
Bottom nav tabs Click Navigate to respective page

Norwegian Labels

Element Norwegian Text
Page heading Mine kontoer
Info card heading Open Banking (PSD2)
Info card text Drop leser saldo fra banken din via BankID-samtykke. Vi lagrer aldri pengene dine — alt går direkte fra din bankkonto.
Primary badge Primær
Total balance label Samlet saldo
Add account button Koble til ny bankkonto

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Info card bg #0B6E35 at 10% opacity (bg-[#0B6E35]/10)
Info card border #0B6E35 at 20% opacity (border-[#0B6E35]/20)
Primary #0B6E35
Primary hover #095C2C
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Border #E5E7EB
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Button radius rounded-2xl
Icon circle radius rounded-full
Bank icon size h-12 w-12
Shield icon size h-10 w-10

Bottom Navigation

Yes — "Kort" tab shown as active in Figma (green, filled card icon), but this is likely a design artifact. In production, either "Profil" tab should be active (if accounts is part of profile section) or no tab should be highlighted (if accessed from dashboard link).

Page: Dashboard

Page Spec: Dashboard

Route

/dashboard

Architecture Status

Core

Figma Reference

dashboard.png

Visual Description from Figma

The dashboard is the main home screen after login:

Background is light gray. Large empty space between transactions and bottom nav.

Page Layout

App page WITH bottom nav
├── Top Bar
│   ├── Left: Drop icon (small) + "drop" wordmark
│   └── Right: Bell icon, Logout icon, User avatar (initials)
├── Balance Card (white rounded)
│   ├── "Hei, {name}!" greeting
│   ├── Balance amount (large bold)
│   ├── Bank name + account number
│   ├── PSD2 explanation text
│   └── "{n} kontoer tilkoblet" link
├── Action Buttons Row
│   ├── "Send penger" (green, paper plane icon)
│   └── "Skann QR" (outlined, QR icon)
├── Recent Transactions Section
│   ├── "Siste transaksjoner" heading + "Se alle" link
│   └── Transaction cards (up to 3)
│       ├── Icon (type-based) + Name + Type subtitle
│       └── Amount + Status badge
└── Bottom Nav (Hjem active)

Components

Top Bar

<div className="flex items-center justify-between px-6 pt-6">
  <div className="flex items-center gap-2">
    <Image src="/drop-icon.png" alt="Drop" width={28} height={28} />
    <span className="font-[family-name:var(--font-fraunces)] text-lg font-bold text-[#1A1A1A]">drop</span>
  </div>
  <div className="flex items-center gap-3">
    <button className="rounded-lg p-2 hover:bg-white/80">
      <Bell className="h-5 w-5 text-[#6B7280]" />
    </button>
    <button className="rounded-lg p-2 hover:bg-white/80">
      <LogOut className="h-5 w-5 text-[#6B7280]" />
    </button>
    <div className="flex h-9 w-9 items-center justify-center rounded-full bg-[#E5E7EB] text-sm font-semibold text-[#6B7280]">
      {initials}
    </div>
  </div>
</div>

Balance Card

<div className="rounded-2xl bg-white p-6 shadow-sm">
  <p className="text-sm text-[#6B7280]">Hei, {firstName}!</p>
  <p className="mt-1 text-2xl font-bold text-[#1A1A1A]">kr {formattedBalance}</p>
  <p className="mt-1 text-xs text-[#6B7280]">{bankName} . {accountNumber}</p>
  <p className="text-xs text-[#9CA3AF]">Saldo lest fra din bankkonto via Open Banking</p>
  <div className="mt-3 flex items-center gap-1.5">
    <Landmark className="h-4 w-4 text-[#0B6E35]" />
    <Link href="/accounts" className="text-sm font-medium text-[#0B6E35] hover:underline">{accountCount} kontoer tilkoblet</Link>
  </div>
</div>

Action Buttons Row

<div className="flex gap-3">
  <Link href="/send" className="flex h-12 flex-1 items-center justify-center gap-2 rounded-xl bg-[#0B6E35] text-sm font-semibold text-white hover:bg-[#095C2C] transition-colors">
    <Send className="h-4 w-4" />
    Send penger
  </Link>
  <Link href="/scan" className="flex h-12 flex-1 items-center justify-center gap-2 rounded-xl border border-[#E5E7EB] bg-white text-sm font-medium text-[#1A1A1A] transition-colors hover:bg-[#F9FAFB]">
    <QrCode className="h-4 w-4" />
    Skann QR
  </Link>
</div>

Recent Transactions Section

<div>
  <div className="flex items-center justify-between">
    <h2 className="text-lg font-bold text-[#1A1A1A]">Siste transaksjoner</h2>
    <Link href="/transactions" className="text-sm font-medium text-[#0B6E35] hover:underline">Se alle</Link>
  </div>
  <div className="mt-3 space-y-3">
    {/* transaction cards */}
  </div>
</div>

Transaction Card

<div className="flex items-center justify-between rounded-2xl bg-white p-4 shadow-sm">
  <div className="flex items-center gap-3">
    <div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#0B6E35]/10">
      {type === 'transfer' ? <Send className="h-5 w-5 text-[#0B6E35]" /> : <QrCode className="h-5 w-5 text-[#D4A017]" />}
    </div>
    <div>
      <p className="text-sm font-semibold text-[#1A1A1A]">{counterparty}</p>
      <p className="text-xs text-[#6B7280]">{typeLabel}</p>
    </div>
  </div>
  <div className="text-right">
    <p className="text-sm font-semibold text-[#1A1A1A]">{formattedAmount} NOK</p>
    <span className={`rounded-full px-2 py-0.5 text-xs font-medium ${statusClasses}`}>{statusLabel}</span>
  </div>
</div>

Status Badges

Status Label Classes
completed fullfort bg-[#16A34A]/10 text-[#16A34A]
pending behandler bg-[#D97706]/10 text-[#D97706]
failed feilet bg-[#EF4444]/10 text-[#EF4444]

Data Displayed

Data Source API
User name JWT / user profile GET /api/account
Balance AISP (primary bank account) GET /api/account
Bank name + account number AISP linked account GET /api/account
Connected accounts count AISP GET /api/account
Last 3 transactions Transaction history GET /api/transactions?limit=3

User Interactions

Element Action Result
Bell icon Click Navigate to /notifications
Logout icon Click Clear JWT cookie, redirect to /login
User avatar Click Navigate to /profile
"2 kontoer tilkoblet" link Click Navigate to /accounts
"Send penger" button Click Navigate to /send
"Skann QR" button Click Navigate to /scan
"Se alle" link Click Navigate to /transactions
Transaction card Click Navigate to transaction detail (optional)
Bottom nav tabs Click Navigate to respective page

Norwegian Labels

Element Norwegian Text
Greeting Hei, {name}!
PSD2 note Saldo lest fra din bankkonto via Open Banking
Accounts link {n} kontoer tilkoblet
Send button Send penger
Scan button Skann QR
Transactions heading Siste transaksjoner
See all link Se alle
Transfer type Overforing
QR payment type QR-betaling
Status: completed fullfort
Status: pending behandler
Status: failed feilet

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Primary #0B6E35
Primary hover #095C2C
Accent/Gold #D4A017
Text primary #1A1A1A
Text body #374151
Text muted #6B7280
Text light #9CA3AF
Border #E5E7EB
Success #16A34A
Warning #D97706
Error #EF4444
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Button radius rounded-xl
Icon circle radius rounded-full
Avatar size h-9 w-9

Bottom Navigation

Yes — "Hjem" tab active (green, filled house icon). All other tabs inactive (gray, outline icons).

Page: Landing

Page Spec: Landing

Route

/

Architecture Status

Core

Figma Reference

NO FIGMA — design needed. Designed from architecture document + design system reference.

Visual Description (Design Direction)

No Figma screenshot exists. This is a public marketing/landing page for unauthenticated users. It should follow the design system's visual language (green primary, white cards, DM Sans body font, Fraunces for brand text) and present Drop's value proposition: simple remittance and QR payments for everyone in Norway/Scandinavia. Desktop max-width 1200px, responsive down to 375px mobile.

Page Layout

Full-width page (no bottom nav, public page)
├── Hero Section
│   ├── Drop logo (green square + $ icon + gold dot)
│   ├── "drop" wordmark (Fraunces serif bold)
│   ├── Tagline: "Enklere betalinger. Lavere gebyrer."
│   ├── Subtitle text explaining value proposition
│   ├── CTA: "Kom i gang" → /register
│   └── Secondary CTA: "Logg inn" → /login
├── Hero Section (with ambient glow background)
│   ├── Drop logo (green square + $ icon + gold dot)
│   ├── "drop" wordmark (Fraunces serif bold)
│   ├── Headline: "Enklere betalinger. Lavere gebyrer." (split, second line green)
│   ├── Subtitle text explaining value proposition
│   ├── Primary CTA: "Opprett konto — gratis" → /register
│   ├── Secondary CTA: "Logg inn" → /login
│   └── Stats card (3 columns): "0,5%" gebyr, "<2t" leveringstid, "30+" land
├── Features Section
│   ├── Heading: "Alt du trenger i en app"
│   ├── Feature card 1: Send penger (remittance icon + description)
│   ├── Feature card 2: Betal med QR (QR icon + description)
│   └── Feature card 3: Virtuelt kort (card icon + description) **NOT "Bankkontoer"**
├── Trust Section
│   ├── BankID-verifisert badge (shield icon)
│   ├── Rask overføring badge (fast transfer icon)
│   └── 30+ land badge (corridors icon)
├── Merchant CTA Section
│   ├── "Er du butikkeier?" heading
│   ├── Description: "Ta imot betalinger via QR. 1% gebyr..."
│   └── "Kom i gang" button
└── Footer
    └── "Drop — et produkt av ALAI Holding AS" copyright

Components

Hero Section

<div className="flex min-h-screen flex-col items-center justify-center bg-[#EEEEEE] px-6">
  <div className="w-full max-w-sm space-y-6 text-center">
    <Image src="/drop-icon.png" alt="Drop" width={80} height={80} />
    <h1 className="font-[family-name:var(--font-fraunces)] text-3xl font-bold text-[#1A1A1A]">drop</h1>
    <p className="text-sm italic text-[#0B6E35]">Enklere betalinger. Lavere gebyrer.</p>
    <!-- CTA buttons -->
  </div>
</div>

Feature Cards

<div className="rounded-2xl bg-white p-6 shadow-sm">
  <Icon className="h-8 w-8 text-[#0B6E35] mb-3" />
  <h3 className="text-lg font-bold text-[#1A1A1A]">Feature Title</h3>
  <p className="text-sm text-[#374151]">Description</p>
</div>

Hero Headline

<h1 className="font-[family-name:var(--font-fraunces)] text-5xl font-extrabold tracking-tight mb-4 leading-[1.08] text-[#1A1A1A]">
  Enklere betalinger.
  <br />
  <span className="text-[#0B6E35]">Lavere gebyrer.</span>
</h1>

Primary CTA Button

Secondary CTA

Stats Card

<div className="grid grid-cols-3 gap-4 rounded-2xl bg-white border border-[#E5E7EB] shadow-sm p-5">
  <div className="text-center">
    <p className="text-2xl font-bold text-[#0B6E35]">0,5%</p>
    <p className="text-xs text-[#6B7280] mt-1">Gebyr</p>
  </div>
  <!-- repeat for other stats -->
</div>

Data Displayed

User Interactions

Element Action Result
"Opprett konto — gratis" button Click Navigate to /register
"Logg inn" button Click Navigate to /login
Merchant "Kom i gang" button Click NOT IMPLEMENTED (placeholder, href="#")

Norwegian Labels

Element Norwegian Text
Brand wordmark drop
Hero headline line 1 Enklere betalinger.
Hero headline line 2 Lavere gebyrer.
Hero subtitle Send penger, betal med QR, administrer kort — alt på ett sted. Laget for alle i Skandinavia.
Primary CTA Opprett konto — gratis
Secondary CTA Logg inn
Stats label 1 Gebyr
Stats label 2 Leveringstid
Stats label 3 Land
Features heading Alt du trenger i en app
Feature 1 title Send penger
Feature 1 desc Overfør penger internasjonalt. 0,5% gebyr — billigere enn banken.
Feature 2 title Betal med QR
Feature 2 desc Skann og betal i butikken. Raskere og billigere enn kort.
Feature 3 title Virtuelt kort
Feature 3 desc Få et virtuelt kort for netthandel. Bestill fysisk kort hjem.
Trust badge 1 BankID-verifisert
Trust badge 2 Rask overføring
Trust badge 3 30+ land
Merchant CTA heading Er du butikkeier?
Merchant CTA desc Ta imot betalinger via QR. 1% gebyr — billigere enn kortterminalen.
Merchant CTA button Kom i gang
Footer copyright Drop — et produkt av ALAI Holding AS

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Primary #0B6E35
Primary hover #095C2C
Text primary #1A1A1A
Text body #374151
Text muted #6B7280
Brand font font-[family-name:var(--font-fraunces)]
Body font DM Sans (default)
Card radius rounded-2xl
Button radius rounded-xl
Button height h-12
Shadow shadow-sm

Bottom Navigation

No — this is a public page, no bottom nav.

Page: Login

Page Spec: Login

Route

/login

Architecture Status

Core

Figma Reference

login.png

Visual Description from Figma

The login page shows:

Background is light gray. The entire form is centered vertically and horizontally on the page.

Page Layout

Full-page centered (no bottom nav — auth page)
├── Logo Section (centered)
│   ├── Drop icon (64x64)
│   ├── "drop" wordmark (Fraunces serif bold)
│   └── Tagline italic green
├── Form Card (white rounded)
│   ├── E-postadresse input (mail icon)
│   ├── Passord input (lock icon + eye toggle)
│   ├── "Glemt passord?" link (right-aligned) **NOT IMPLEMENTED** (href="#")
│   └── "Logg inn" button (green, full width, arrow icon)
└── "Har du ikke konto? Opprett konto" link

Components

Logo Block

<div className="flex flex-col items-center space-y-2">
  <Image src="/drop-icon.png" alt="Drop" width={64} height={64} />
  <h1 className="font-[family-name:var(--font-fraunces)] text-3xl font-bold text-[#1A1A1A]">drop</h1>
  <p className="text-sm italic text-[#0B6E35]">Enklere betalinger. Lavere gebyrer.</p>
</div>

Form Card

<div className="rounded-2xl bg-white p-6 shadow-sm space-y-4">
  {/* form fields + buttons */}
</div>

Email Input

<div>
  <label className="mb-1.5 block text-sm font-medium text-[#1A1A1A]">E-postadresse</label>
  <div className="relative">
    <Mail className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
    <input type="email" className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-3 text-sm outline-none transition-colors focus:border-[#0B6E35] focus:ring-1 focus:ring-[#0B6E35]" placeholder="navn@eksempel.no" />
  </div>
</div>

Password Input

<div>
  <label className="mb-1.5 block text-sm font-medium text-[#1A1A1A]">Passord</label>
  <div className="relative">
    <Lock className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
    <input type={showPassword ? "text" : "password"} className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-10 text-sm outline-none transition-colors focus:border-[#0B6E35] focus:ring-1 focus:ring-[#0B6E35]" placeholder="........" />
    <button className="absolute right-3 top-1/2 -translate-y-1/2">
      <Eye className="h-4 w-4 text-[#9CA3AF]" />
    </button>
  </div>
  <div className="mt-1 text-right">
    <Link href="/forgot-password" className="text-xs font-medium text-[#0B6E35] hover:underline">Glemt passord?</Link>
  </div>
</div>

Login Button

<Button className="h-12 w-full rounded-xl bg-[#0B6E35] text-white text-sm font-semibold hover:bg-[#095C2C] transition-colors flex items-center justify-center gap-2">
  Logg inn
  <ArrowRight className="h-4 w-4" />
</Button>

Divider

<div className="flex items-center gap-3">
  <div className="h-px flex-1 bg-[#D1D5DB]" />
  <span className="text-xs font-medium tracking-wide text-[#9CA3AF]">ELLER LOGG INN MED</span>
  <div className="h-px flex-1 bg-[#D1D5DB]" />
</div>

Social Login Buttons

<div className="flex gap-3">
  <button className="flex h-12 flex-1 items-center justify-center gap-2 rounded-xl border border-[#E5E7EB] bg-white text-sm font-medium text-[#1A1A1A] transition-colors hover:bg-[#F9FAFB]">
    <Image src="/bankid-icon.png" alt="BankID" width={20} height={20} />
    BankID
  </button>
  <button className="flex h-12 flex-1 items-center justify-center gap-2 rounded-xl border border-[#E5E7EB] bg-white text-sm font-medium text-[#1A1A1A] transition-colors hover:bg-[#F9FAFB]">
    <Image src="/vipps-icon.png" alt="Vipps" width={20} height={20} />
    Vipps
  </button>
</div>
<p className="text-center text-sm text-[#6B7280]">
  Har du ikke konto? <Link href="/register" className="font-semibold text-[#0B6E35] hover:underline">Opprett konto</Link>
</p>

Error Message

<p className="text-sm text-[#EF4444] bg-[#EF4444]/10 rounded-md p-2">{error}</p>

Data Displayed

User Interactions

Element Action Result
E-postadresse input Type Captures email
Passord input Type Captures password
Eye icon Click Toggle password visibility
"Glemt passord?" link Click Navigate to forgot password flow
"Logg inn" button Click POST /api/auth/login, on success redirect to /dashboard
BankID button Click Initiate BankID auth flow (research ongoing)
Vipps button Click Initiate Vipps auth flow (research ongoing)
"Opprett konto" link Click Navigate to /register

Validation Rules

Field Rule Error Message
E-postadresse Required, valid email Ugyldig e-postadresse
Passord Required, min 1 char Passord er paakrevd
Auth failure Invalid credentials Feil e-postadresse eller passord

Norwegian Labels

Element Norwegian Text
Email label E-postadresse
Email placeholder navn@eksempel.no
Password label Passord
Forgot password link Glemt passord?
Login button Logg inn
Divider text ELLER LOGG INN MED
BankID button BankID
Vipps button Vipps
Register prompt Har du ikke konto?
Register link Opprett konto

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Input bg #F9FAFB
Primary #0B6E35
Primary hover #095C2C
Border #E5E7EB
Divider #D1D5DB
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Error #EF4444
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Input radius rounded-lg
Button radius rounded-xl
Input height h-11
Button height h-12

Bottom Navigation

No — this is an auth page, no bottom nav.

Page: Notifications

Page Spec: Notifications

Route

/notifications

Architecture Status

Core

Figma Reference

No Figma — designed from architecture

Visual Description

The notifications page displays transaction alerts, system messages, and payment confirmations:

Background is light gray (#EEEEEE). All cards are white with rounded corners (#FFFFFF, rounded-2xl). Unread notifications appear at the top.

Page Layout

App page WITH bottom nav
├── Top Bar
│   ├── Left: Back arrow (chevron left)
│   └── Center: "Varsler" heading
├── Notification List (or Empty State)
│   └── Notification cards (sorted by date, unread first)
│       ├── Unread indicator (green dot)
│       ├── Icon (type-based color)
│       ├── Title (bold if unread)
│       ├── Description (muted text)
│       └── Timestamp (relative time)
└── Bottom Nav (no active tab)

Components

Top Bar

<div className="flex items-center gap-3 px-6 pt-6">
  <Link href="/dashboard">
    <button className="rounded-lg p-2 hover:bg-white/80">
      <ArrowLeft className="h-5 w-5 text-[#6B7280]" />
    </button>
  </Link>
  <h1 className="text-xl font-bold text-[#1A1A1A]">
    Varsler
  </h1>
</div>

Notification Card (Unread)

<div
  onClick={() => markAsRead(notification.id)}
  className="relative flex items-start gap-3 rounded-2xl bg-white p-4 shadow-sm cursor-pointer hover:bg-[#F9FAFB] transition-colors"
>
  {/* Unread indicator dot */}
  <div className="absolute left-0 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full bg-[#0B6E35]" />

  {/* Icon */}
  <div className={`flex h-10 w-10 items-center justify-center rounded-full ${iconBgColor}`}>
    {getNotificationIcon(notification.type)}
  </div>

  {/* Content */}
  <div className="flex-1">
    <p className="text-sm font-bold text-[#1A1A1A]">{notification.title}</p>
    <p className="text-xs text-[#6B7280] mt-0.5">{notification.description}</p>
    <p className="text-xs text-[#9CA3AF] mt-1">{formatTimestamp(notification.created_at)}</p>
  </div>
</div>

Notification Card (Read)

<div
  className="flex items-start gap-3 rounded-2xl bg-white p-4 shadow-sm"
>
  {/* Icon */}
  <div className={`flex h-10 w-10 items-center justify-center rounded-full ${iconBgColor}`}>
    {getNotificationIcon(notification.type)}
  </div>

  {/* Content */}
  <div className="flex-1">
    <p className="text-sm font-semibold text-[#1A1A1A]">{notification.title}</p>
    <p className="text-xs text-[#6B7280] mt-0.5">{notification.description}</p>
    <p className="text-xs text-[#9CA3AF] mt-1">{formatTimestamp(notification.created_at)}</p>
  </div>
</div>

Empty State

<div className="flex flex-col items-center justify-center px-6 py-16">
  <div className="flex h-16 w-16 items-center justify-center rounded-full bg-[#E5E7EB]">
    <BellOff className="h-8 w-8 text-[#9CA3AF]" />
  </div>
  <p className="mt-4 text-lg font-bold text-[#1A1A1A]">Ingen varsler</p>
  <p className="mt-2 text-center text-sm text-[#6B7280] max-w-xs">
    Du vil motta varsler om transaksjoner og viktige meldinger her
  </p>
</div>

Notification Icon Logic

function getNotificationIcon(type: string) {
  switch (type) {
    case 'transaction_sent':
    case 'transaction_received':
      return <Send className="h-5 w-5 text-[#0B6E35]" />;
    case 'qr_payment':
      return <QrCode className="h-5 w-5 text-[#D4A017]" />;
    case 'system_message':
    case 'account_linked':
    case 'security_alert':
      return <AlertCircle className="h-5 w-5 text-[#3B82F6]" />;
    default:
      return <Bell className="h-5 w-5 text-[#6B7280]" />;
  }
}

function getIconBgColor(type: string) {
  switch (type) {
    case 'transaction_sent':
    case 'transaction_received':
      return 'bg-[#0B6E35]/10';
    case 'qr_payment':
      return 'bg-[#D4A017]/10';
    case 'system_message':
    case 'account_linked':
    case 'security_alert':
      return 'bg-[#3B82F6]/10';
    default:
      return 'bg-[#E5E7EB]';
  }
}

Timestamp Formatter

function formatTimestamp(timestamp: string): string {
  const now = new Date();
  const then = new Date(timestamp);
  const diffMs = now.getTime() - then.getTime();
  const diffMins = Math.floor(diffMs / 60000);
  const diffHours = Math.floor(diffMs / 3600000);
  const diffDays = Math.floor(diffMs / 86400000);

  if (diffMins < 1) return 'Akkurat nå';
  if (diffMins < 60) return `${diffMins} ${diffMins === 1 ? 'minutt' : 'minutter'} siden`;
  if (diffHours < 24) return `${diffHours} ${diffHours === 1 ? 'time' : 'timer'} siden`;
  if (diffDays === 1) return `I går ${then.toLocaleTimeString('nb-NO', { hour: '2-digit', minute: '2-digit' })}`;
  if (diffDays < 7) return `${diffDays} dager siden`;

  return then.toLocaleDateString('nb-NO', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' });
}

Data Displayed

Data Source API
Notification list Notifications table GET /api/notifications
Notification title Notification record From notifications table
Notification description Notification record From notifications table
Notification type Notification record transaction_sent / transaction_received / qr_payment / system_message / account_linked / security_alert
Notification read status Notification record is_read boolean
Notification timestamp Notification record created_at

User Interactions

Element Action Result
Back arrow Click Navigate back to previous page (dashboard)
Unread notification card Click Mark notification as read, update UI to show read state
Read notification card Click Optional — navigate to related resource (e.g., transaction detail)
Bottom nav tabs Click Navigate to respective page

Norwegian Labels

Element Norwegian Text
Page heading Varsler
Empty state heading Ingen varsler
Empty state description Du vil motta varsler om transaksjoner og viktige meldinger her
Timestamp: Now Akkurat nå
Timestamp: Minutes {n} minutt siden / {n} minutter siden
Timestamp: Hours {n} time siden / {n} timer siden
Timestamp: Yesterday I går {time}
Timestamp: Days {n} dager siden
Notification: Transaction sent Overføring sendt
Notification: Transaction received Penger mottatt
Notification: QR Payment QR-betaling fullført
Notification: System message Systemmelding
Notification: Account linked Bankkonto tilkoblet
Notification: Security alert Sikkerhetsvarsel

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Primary #0B6E35
Primary hover #095C2C
Accent/Gold #D4A017
Info blue #3B82F6
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Border #E5E7EB
Unread indicator #0B6E35 (green dot)
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Icon circle radius rounded-full
Hover bg #F9FAFB

Bottom Navigation

Yes — No tab active (all tabs gray, outline icons).

Page: Profile

Page Spec: Profile (Settings)

Route

/profile

Architecture Status

Core

Figma Reference

profile.png

Visual Description from Figma

The profile/settings page is the user account management screen:

Background is light gray (#EEEEEE). Spacing between cards is consistent.

Page Layout

App page WITH bottom nav
├── Top Bar
│   ├── Left: Back arrow
│   ├── Center: "Profil" heading
│   └── Right: Empty
├── User Card (white rounded, centered content)
│   ├── Avatar circle (initials, green on light green bg)
│   ├── User full name (bold)
│   └── Email address (muted)
├── Menu Card (white rounded)
│   ├── "Mine kontoer" (bank icon + chevron)
│   ├── "Varsler" (bell icon + chevron)
│   ├── "Innstillinger" (gear icon + chevron)
│   ├── "Sikkerhet" (shield icon + chevron)
│   └── "Hjelp og støtte" (question icon + chevron)
├── Logout Button Card (white rounded, red text)
│   └── "Logg ut" (logout icon)
├── Footer Text
│   └── "Drop v0.1.0 · ALAI Holding AS"
└── Bottom Nav (Profil active)

Components

Top Bar

<div className="flex items-center gap-3 px-6 pt-6">
  <Link href="/dashboard">
    <button className="rounded-lg p-2 hover:bg-white/80">
      <ArrowLeft className="h-5 w-5 text-[#6B7280]" />
    </button>
  </Link>
  <h1 className="text-xl font-bold text-[#1A1A1A]">Profil</h1>
</div>

User Card

<div className="rounded-2xl bg-white p-6 shadow-sm">
  <div className="flex items-center gap-4">
    <div className="h-14 w-14 rounded-full bg-[#0B6E35]/10 flex items-center justify-center text-xl font-bold text-[#0B6E35]">
      {user.firstName.charAt(0)}{user.lastName.charAt(0)}
    </div>
    <div>
      <p className="font-semibold text-lg text-[#1A1A1A]">{user.firstName} {user.lastName}</p>
      <p className="text-sm text-[#6B7280]">{user.email}</p>
    </div>
  </div>
</div>

Menu Card

<div className="rounded-2xl bg-white shadow-sm overflow-hidden">
  <MenuItem
    icon={<Building2 className="h-5 w-5" />}
    label="Mine kontoer"
    href="/accounts"
  />
  <Divider />
  <MenuItem
    icon={<Bell className="h-5 w-5" />}
    label="Varsler"
    href="/notifications"
  />
  <Divider />
  <MenuItem
    icon={<Settings className="h-5 w-5" />}
    label="Innstillinger"
    href="/settings"
  />
  <Divider />
  <MenuItem
    icon={<Shield className="h-5 w-5" />}
    label="Sikkerhet"
    href="/security"
  />
  <Divider />
  <MenuItem
    icon={<HelpCircle className="h-5 w-5" />}
    label="Hjelp og støtte"
    href="/support"
  />
</div>

Menu Item Component

Divider

<div className="h-px bg-[#E5E7EB] mx-5" />

Logout Button

<button
  onClick={handleLogout}
  className="w-full rounded-2xl bg-white border border-[#E5E7EB] p-4 shadow-sm hover:bg-[#FEF2F2] transition-colors"
>
  <div className="flex items-center justify-center gap-2">
    <LogOut className="h-5 w-5 text-[#EF4444]" />
    <span className="text-[15px] font-semibold text-[#EF4444]">Logg ut</span>
  </div>
</button>
<p className="text-center text-xs text-[#9CA3AF]">
  Drop v0.1.0 · ALAI Holding AS
</p>

Data Displayed

Data Source API
User full name JWT / user profile GET /api/account
User email User profile GET /api/account
User initials Derived from full name Client-side
App version Build metadata Static
Company name Static Static

User Interactions

Element Action Result
Back arrow Click Navigate back to previous page
Avatar Click Optional: navigate to profile edit page
"Mine kontoer" Click Navigate to /accounts
"Varsler" Click Navigate to /notifications
"Innstillinger" Click Navigate to /settings (app preferences)
"Sikkerhet" Click Navigate to /security (PIN, biometrics, 2FA)
"Hjelp og støtte" Click Navigate to /support (FAQs, contact)
"Logg ut" button Click Clear JWT cookie, redirect to /login
Bottom nav tabs Click Navigate to respective page

Norwegian Labels

Element Norwegian Text
Page title Profil
Bank accounts menu Mine kontoer
Notifications menu Varsler
Settings menu Innstillinger
Security menu Sikkerhet
Help menu Hjelp og støtte
Logout button Logg ut
Footer Drop v0.1.0 · ALAI Holding AS

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Avatar bg #D1E9DC (light green/mint)
Avatar text #0B6E35
Primary #0B6E35
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Border #E5E7EB
Danger #EF4444
Danger hover bg #FEF2F2
Hover bg #F9FAFB
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Avatar radius rounded-full
Avatar size h-20 w-20
Menu item padding px-5 py-4
Icon size h-5 w-5

Bottom Navigation

Yes — "Profil" tab active (green, filled person icon). All other tabs inactive (gray, outline icons).

Page: Register

Page Spec: Register

Route

/register

Architecture Status

Core

Figma Reference

onboarding.png

Implementation Status

SPEC DOCUMENTS STEP 1 ONLY. The actual implementation has 4 steps:

  1. Personal Info (documented below) — name, email, phone, DOB, password
  2. Phone Verification (NOT DOCUMENTED) — OTP input
  3. PIN Setup (NOT DOCUMENTED) — 4-digit PIN with number pad
  4. Success Screen (NOT DOCUMENTED) — welcome message + navigate to dashboard

This spec covers ONLY step 1. Steps 2-4 need separate specs or this spec needs expansion.

Visual Description from Figma

The register page (called "Opprett konto" in Figma) has step 1 of 3:

Background is light gray (#EEEEEE). All input fields have light gray backgrounds with subtle borders.

Page Layout

Full-page centered (no bottom nav — auth page)
├── Logo Section (centered)
│   ├── Drop icon (64x64)
│   ├── "drop" wordmark (Fraunces serif bold)
│   └── Tagline italic green
├── Progress Bar (3 steps)
│   ├── Step 1: filled green (active)
│   ├── Step 2: gray
│   └── Step 3: gray
├── Form Card (white rounded)
│   ├── "Opprett konto" heading
│   ├── Row: Fornavn | Etternavn (2-col)
│   ├── E-postadresse input
│   ├── Telefonnummer input (+47)
│   ├── Fodselsdato input (date picker)
│   └── Passord input (toggle visibility)
├── "Fortsett" button (full width, outside card)
└── "Har du allerede konto? Logg inn" link

Components

Logo Block

<div className="flex flex-col items-center space-y-2">
  <Image src="/drop-icon.png" alt="Drop" width={64} height={64} />
  <h1 className="font-[family-name:var(--font-fraunces)] text-3xl font-bold text-[#1A1A1A]">drop</h1>
  <p className="text-sm italic text-[#0B6E35]">Enklere betalinger. Lavere gebyrer.</p>
</div>

Progress Bar (3-step)

<div className="flex gap-2">
  <div className="h-1 flex-1 rounded-full bg-[#0B6E35]" />  {/* active */}
  <div className="h-1 flex-1 rounded-full bg-[#E5E7EB]" />  {/* inactive */}
  <div className="h-1 flex-1 rounded-full bg-[#E5E7EB]" />  {/* inactive */}
</div>

Form Card

<div className="rounded-2xl bg-white p-6 shadow-sm">
  <h2 className="mb-4 text-xl font-bold text-[#1A1A1A]">Opprett konto</h2>
  {/* form fields */}
</div>

Name Fields (2-column)

<div className="grid grid-cols-2 gap-3">
  <div>
    <label className="mb-1.5 block text-sm font-medium text-[#1A1A1A]">Fornavn</label>
    <div className="relative">
      <User className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
      <input className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-3 text-sm" placeholder="Amir" />
    </div>
  </div>
  <div>
    <label className="mb-1.5 block text-sm font-medium text-[#1A1A1A]">Etternavn</label>
    <div className="relative">
      <User className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
      <input className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-3 text-sm" placeholder="Hadzic" />
    </div>
  </div>
</div>

Standard Input (email, phone, DOB, password)

<div>
  <label className="mb-1.5 block text-sm font-medium text-[#1A1A1A]">{label}</label>
  <div className="relative">
    <Icon className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
    <input className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-3 text-sm outline-none transition-colors focus:border-[#0B6E35] focus:ring-1 focus:ring-[#0B6E35]" />
  </div>
</div>

Password Input (with eye toggle)

<div className="relative">
  <Lock className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#6B7280]" />
  <input type={showPassword ? "text" : "password"} className="h-11 w-full rounded-lg border border-[#E5E7EB] bg-[#F9FAFB] pl-10 pr-10 text-sm" placeholder="Minst 8 tegn" />
  <button className="absolute right-3 top-1/2 -translate-y-1/2">
    <Eye className="h-4 w-4 text-[#9CA3AF]" />
  </button>
</div>

Submit Button

<Button className="h-12 w-full rounded-xl bg-[#0B6E35] text-white text-sm font-semibold hover:bg-[#095C2C] transition-colors">
  Fortsett
</Button>

Error Message

<p className="text-sm text-[#EF4444] bg-[#EF4444]/10 rounded-md p-2">{error}</p>

Data Displayed

User Interactions

Element Action Result
Fornavn input Type Captures first name
Etternavn input Type Captures last name
E-postadresse input Type Captures email
Telefonnummer input Type Captures phone (+47 prefix)
Fodselsdato input Click/type Opens date picker, captures DOB
Passord input Type Captures password (min 8 chars)
Eye icon Click Toggle password visibility
"Fortsett" button Click Validate all fields, POST /api/auth/register, on success navigate to /login
"Logg inn" link Click Navigate to /login

Validation Rules

Field Rule Error Message
Fornavn Required, min 2 chars Fornavn er paakrevd
Etternavn Required, min 2 chars Etternavn er paakrevd
E-postadresse Required, valid email format Ugyldig e-postadresse
Telefonnummer Required, starts with +47, 8 digits Ugyldig telefonnummer
Fodselsdato Required, age >= 18 Du ma vaere minst 18 ar
Passord Required, min 8 chars Passordet ma vaere minst 8 tegn

Norwegian Labels

Element Norwegian Text
Page heading Opprett konto
First name label Fornavn
Last name label Etternavn
Email label E-postadresse
Email placeholder amir@eksempel.no
Phone label Telefonnummer
Phone placeholder +47
DOB label Fodselsdato
DOB placeholder mm/dd/yyyy
Password label Passord
Password placeholder Minst 8 tegn
Submit button Fortsett
Login prompt Har du allerede konto?
Login link Logg inn

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Input bg #F9FAFB
Primary #0B6E35
Primary hover #095C2C
Border #E5E7EB
Progress active #0B6E35
Progress inactive #E5E7EB
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Error #EF4444
Card radius rounded-2xl
Input radius rounded-lg
Button radius rounded-xl
Input height h-11
Button height h-12

Bottom Navigation

No — this is an auth page, no bottom nav.

Page: Scan

Page Spec: Scan QR

Route

/scan

Architecture Status

Core

Figma Reference

scan.png

Visual Description from Figma

The scan page is a full-screen dark camera-style view for QR code scanning:

Page Layout

Full-screen dark (no bottom nav — camera overlay)
├── Top Bar (over dark bg)
│   ├── Left: Back arrow (white)
│   └── Center: "Scan QR" title (white, bold)
├── Camera Viewport (dark bg, full screen)
│   └── Scanner Viewfinder (centered)
│       ├── Dashed border (gray)
│       ├── Green corner brackets (4 corners)
│       └── Green scan line (horizontal, centered)
├── Instruction Text
│   └── "Pek kameraet mot butikkens QR-kode"
└── Simulate Button (demo only)
    └── "Simuler skanning" (green, full width)

Components

Top Bar

<div className="flex items-center justify-between px-6 pt-6">
  <button onClick={() => router.back()} className="rounded-lg p-2 hover:bg-white/10">
    <ArrowLeft className="h-5 w-5 text-white" />
  </button>
  <h1 className="text-lg font-bold text-white">Scan QR</h1>
  <div className="w-9" /> {/* spacer for centering */}
</div>

Scanner Viewfinder

<div className="relative mx-auto aspect-square w-[75%] max-w-[320px]">
  {/* Dashed border */}
  <div className="absolute inset-0 rounded-2xl border-2 border-dashed border-[#6B7280]" />

  {/* Green corner brackets — top-left */}
  <div className="absolute left-0 top-0 h-10 w-10 rounded-tl-2xl border-l-4 border-t-4 border-[#0B6E35]" />
  {/* Green corner brackets — top-right */}
  <div className="absolute right-0 top-0 h-10 w-10 rounded-tr-2xl border-r-4 border-t-4 border-[#0B6E35]" />
  {/* Green corner brackets — bottom-left */}
  <div className="absolute bottom-0 left-0 h-10 w-10 rounded-bl-2xl border-b-4 border-l-4 border-[#0B6E35]" />
  {/* Green corner brackets — bottom-right */}
  <div className="absolute bottom-0 right-0 h-10 w-10 rounded-br-2xl border-b-4 border-r-4 border-[#0B6E35]" />

  {/* Scan line (centered horizontal) */}
  <div className="absolute left-4 right-4 top-1/2 h-0.5 -translate-y-1/2 bg-[#0B6E35]" />
</div>

Instruction Text

<p className="text-center text-sm text-[#9CA3AF]">
  Pek kameraet mot butikkens QR-kode
</p>

Simulate Button (Demo Only)

<button
  onClick={handleSimulateScan}
  className="mx-6 mb-8 h-12 w-[calc(100%-48px)] rounded-xl bg-[#0B6E35] text-sm font-semibold text-white transition-colors hover:bg-[#095C2C]"
>
  Simuler skanning
</button>

Data Displayed

Data Source API
None pre-loaded
On scan success QR payload (merchant ID, amount) POST /api/transactions (type: qr_payment)

User Interactions

Element Action Result
Back arrow Click Navigate back (router.back())
Camera viewfinder Scan QR code Parse QR payload → navigate to payment confirmation
"Simuler skanning" button Click Simulate QR scan with mock merchant data → navigate to payment confirmation

QR Scan Flow (Demo)

  1. User taps "Simuler skanning"
  2. App generates mock QR payload: { merchantId: "REMA1000-001", merchantName: "Rema 1000", amount: 189 }
  3. Navigate to confirmation screen (inline or modal) showing merchant name + amount
  4. User confirms → POST /api/transactions with type qr_payment, PISP initiates payment from linked bank account
  5. On success → redirect to /dashboard with success toast

QR Scan Flow (Production — Future)

  1. Camera activates, user points at merchant QR code
  2. QR library decodes payload (merchant ID, amount, reference)
  3. Same confirmation + PISP flow as above

Norwegian Labels

Element Norwegian Text
Page title Scan QR
Instruction Pek kameraet mot butikkens QR-kode
Simulate button Simuler skanning
Confirm prompt Bekreft betaling
Merchant label Butikk
Amount label Belop
Pay button Betal nå
Cancel button Avbryt
Success toast Betaling fullfort!
Error toast Betaling feilet. Prov igjen.

Design Tokens

Token Value
Page bg #1A1A1A (dark/camera)
Viewfinder border border-dashed border-[#6B7280]
Corner brackets border-[#0B6E35] (4px)
Scan line bg-[#0B6E35]
Primary #0B6E35
Primary hover #095C2C
Text white #FFFFFF
Text muted (on dark) #9CA3AF
Button radius rounded-xl
Viewfinder radius rounded-2xl
Button height h-12

Bottom Navigation

No — this is a full-screen camera overlay, no bottom nav.

Page: Send

Page Spec: Send Money

Route

/send

Architecture Status

Core

Implementation Status

SPEC DOCUMENTS STEP 1 ONLY. The actual implementation has a 4-step flow:

  1. Select Recipient (documented below) — search recipients, add new
  2. Enter Amount (NOT DOCUMENTED) — amount input + exchange rate display
  3. Confirm (NOT DOCUMENTED) — review transfer details, fee breakdown
  4. Success (NOT DOCUMENTED) — confirmation screen + receipt

This spec covers ONLY step 1. Steps 2-4 need separate specs or this spec needs expansion.

Figma Reference

send.png

Visual Description from Figma

The Send Money page is the first step in the money transfer flow:

The page has a clean, minimal design with large touch targets and plenty of whitespace.

Page Layout

App page WITH bottom nav
├── Top Bar
│   ├── Left: Back arrow (chevron)
│   ├── Center: "Send penger" heading
│   └── Right: "1/4" step indicator
├── Content Area (light gray bg)
│   ├── Search Input
│   │   ├── Search icon (left)
│   │   └── "Søk mottakere..." placeholder
│   ├── Empty State
│   │   └── "Ingen mottakere funnet" message
│   └── Add Recipient Button
│       ├── "+" icon
│       └── "Ny mottaker" label
└── Bottom Nav (all tabs inactive)

Components

Top Bar

<div className="flex items-center justify-between px-6 pt-6 pb-4">
  <button onClick={() => router.back()} className="rounded-lg p-2 hover:bg-white/80">
    <ChevronLeft className="h-6 w-6 text-[#1A1A1A]" />
  </button>
  <h1 className="font-[family-name:var(--font-fraunces)] text-xl font-bold text-[#1A1A1A]">Send penger</h1>
  <span className="text-sm text-[#6B7280]">1/4</span>
</div>

Search Input

<div className="relative">
  <Search className="absolute left-4 top-1/2 h-5 w-5 -translate-y-1/2 text-[#9CA3AF]" />
  <input
    type="text"
    placeholder="Søk mottakere..."
    className="h-14 w-full rounded-2xl border border-[#E5E7EB] bg-white pl-12 pr-4 text-[#1A1A1A] placeholder:text-[#9CA3AF] focus:border-[#0B6E35] focus:outline-none focus:ring-2 focus:ring-[#0B6E35]/20"
    value={searchQuery}
    onChange={(e) => setSearchQuery(e.target.value)}
  />
</div>

Empty State

<div className="py-12 text-center">
  <p className="text-sm text-[#6B7280]">Ingen mottakere funnet</p>
</div>

Add Recipient Button

<button
  onClick={() => router.push('/send/add-recipient')}
  className="flex h-14 w-full items-center justify-center gap-2 rounded-2xl border border-[#E5E7EB] bg-white text-sm font-medium text-[#1A1A1A] transition-colors hover:bg-[#F9FAFB]"
>
  <Plus className="h-5 w-5" />
  Ny mottaker
</button>

Recipient List (when populated)

<div className="space-y-3">
  {recipients.map((recipient) => (
    <button
      key={recipient.id}
      onClick={() => handleSelectRecipient(recipient)}
      className="flex w-full items-center justify-between rounded-2xl bg-white p-4 text-left transition-colors hover:bg-[#F9FAFB]"
    >
      <div className="flex items-center gap-3">
        <div className="flex h-10 w-10 items-center justify-center rounded-full bg-[#0B6E35]/10">
          <User className="h-5 w-5 text-[#0B6E35]" />
        </div>
        <div>
          <p className="text-sm font-semibold text-[#1A1A1A]">{recipient.name}</p>
          <p className="text-xs text-[#6B7280]">{recipient.country} • {recipient.accountNumber}</p>
        </div>
      </div>
      <ChevronRight className="h-5 w-5 text-[#9CA3AF]" />
    </button>
  ))}
</div>

Data Displayed

Data Source API
Saved recipients User's recipient list GET /api/recipients
Search results Filtered recipient list Client-side filtering
Step indicator Flow state Static (1/4)

User Interactions

Element Action Result
Back arrow Click Navigate back to previous page (dashboard)
Search input Type Filter recipient list in real-time
Add recipient button Click Navigate to /send/add-recipient (step 2)
Recipient card Click Select recipient, navigate to amount input (step 3)
Bottom nav tabs Click Navigate to respective page (exits send flow)

Norwegian Labels

Element Norwegian Text
Page title Send penger
Step indicator 1/4
Search placeholder Søk mottakere...
Empty state Ingen mottakere funnet
Add recipient button Ny mottaker

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Input bg #FFFFFF
Primary #0B6E35
Primary hover #095C2C
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Border #E5E7EB
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Button radius rounded-2xl
Input radius rounded-2xl
Avatar/Icon circle rounded-full
Icon circle bg #0B6E35]/10 (10% opacity green)

Bottom Navigation

Yes — All tabs inactive (gray, outline icons). User is in the send flow but not on a main tab page.

Flow Context

This is step 1 of 4 in the send money flow:

  1. Select Recipient (this page) — choose from saved recipients or add new
  2. Add Recipient — enter recipient details (name, country, account)
  3. Enter Amount — specify amount and currency
  4. Review & Confirm — review details, initiate PISP payment from user's bank account

Pass-through model reminder: Drop initiates payment via PISP from user's linked bank account. No money is held by Drop.

Page: Transactions

Page Spec: Transaction History

Route

/transactions

Architecture Status

Core

Figma Reference

history.png

Visual Description from Figma

The transaction history page shows a complete list of all transactions with filtering:

Background is light gray (#EEEEEE). Large empty space below transactions. All cards are white with rounded corners (#FFFFFF, rounded-2xl).

Page Layout

App page WITH bottom nav
├── Top Bar
│   ├── Left: Back arrow (chevron left)
│   └── Center: "Transaksjonshistorikk" heading
├── Filter Tabs Row (white rounded container)
│   ├── "Alle" (active, green bg)
│   ├── "Overforinger" (inactive, white bg)
│   └── "QR-betalinger" (inactive, white bg)
├── Transaction List (grouped by date)
│   ├── Date Separator: "I GAR" (uppercase, muted)
│   ├── Transaction cards (yesterday's transactions)
│   ├── Date Separator: "DENNE UKEN" (uppercase, muted)
│   └── Transaction cards (this week's transactions)
└── Bottom Nav (Kort tab active/highlighted)

Components

Top Bar

<div className="flex items-center justify-center px-6 pt-6 relative">
  <button onClick={() => router.back()} className="absolute left-6 rounded-lg p-2 hover:bg-white/80">
    <ChevronLeft className="h-6 w-6 text-[#1A1A1A]" />
  </button>
  <h1 className="font-[family-name:var(--font-fraunces)] text-xl font-bold text-[#1A1A1A]">
    Transaksjonshistorikk
  </h1>
</div>

Filter Tabs Row

<div className="flex gap-2 rounded-2xl bg-white p-1.5 shadow-sm">
  <button
    onClick={() => setFilter('all')}
    className={`flex-1 rounded-full px-4 py-2 text-sm font-semibold transition-colors ${
      filter === 'all'
        ? 'bg-[#0B6E35] text-white'
        : 'bg-white text-[#6B7280] hover:bg-[#F9FAFB]'
    }`}
  >
    Alle
  </button>
  <button
    onClick={() => setFilter('transfers')}
    className={`flex-1 rounded-full px-4 py-2 text-sm font-semibold transition-colors ${
      filter === 'transfers'
        ? 'bg-[#0B6E35] text-white'
        : 'bg-white text-[#6B7280] hover:bg-[#F9FAFB]'
    }`}
  >
    Overforinger
  </button>
  <button
    onClick={() => setFilter('qr')}
    className={`flex-1 rounded-full px-4 py-2 text-sm font-semibold transition-colors ${
      filter === 'qr'
        ? 'bg-[#0B6E35] text-white'
        : 'bg-white text-[#6B7280] hover:bg-[#F9FAFB]'
    }`}
  >
    QR-betalinger
  </button>
</div>

Date Separator

<div className="px-6 pt-4 pb-2">
  <p className="text-xs font-semibold uppercase tracking-wider text-[#9CA3AF]">
    {dateLabel}
  </p>
</div>

Transaction Card

<div className="flex items-center justify-between rounded-2xl bg-white p-4 shadow-sm">
  <div className="flex items-center gap-3">
    <div className={`flex h-10 w-10 items-center justify-center rounded-full ${
      type === 'transfer' ? 'bg-[#0B6E35]/10' : 'bg-[#D4A017]/10'
    }`}>
      {type === 'transfer'
        ? <Send className="h-5 w-5 text-[#0B6E35]" />
        : <QrCode className="h-5 w-5 text-[#D4A017]" />
      }
    </div>
    <div>
      <p className="text-sm font-semibold text-[#1A1A1A]">{counterparty}</p>
      <p className="text-xs text-[#6B7280]">{typeLabel}</p>
    </div>
  </div>
  <div className="text-right">
    <p className="text-sm font-semibold text-[#1A1A1A]">{formattedAmount} NOK</p>
    <span className={`rounded-full px-2 py-0.5 text-xs font-medium ${statusClasses}`}>
      {statusLabel}
    </span>
  </div>
</div>

Status Badges

Status Label Classes
completed fullfort bg-[#16A34A]/10 text-[#16A34A]
pending behandler bg-[#D97706]/10 text-[#D97706]
failed feilet bg-[#EF4444]/10 text-[#EF4444]

Data Displayed

Data Source API
All transactions Transaction history, filtered by selected tab GET /api/transactions?filter={all|transfers|qr}
Transaction counterparty Transaction record From transactions table
Transaction type Transaction record transfer / qr_payment
Transaction amount Transaction record Negative for outgoing
Transaction status Transaction record completed / pending / failed
Transaction date Transaction record For grouping by date separator

User Interactions

Element Action Result
Back arrow Click Navigate back to previous page (dashboard)
"Alle" tab Click Show all transactions (no filter)
"Overforinger" tab Click Filter to show only transfer transactions
"QR-betalinger" tab Click Filter to show only QR payment transactions
Transaction card Click Navigate to transaction detail page (optional)
Bottom nav tabs Click Navigate to respective page

Norwegian Labels

Element Norwegian Text
Page heading Transaksjonshistorikk
Filter: All Alle
Filter: Transfers Overforinger
Filter: QR Payments QR-betalinger
Date separator: Yesterday I GAR
Date separator: This week DENNE UKEN
Date separator: This month DENNE MANEDEN
Date separator: Earlier TIDLIGERE
Transaction type: Transfer Overforing
Transaction type: QR Payment QR-betaling
Status: completed fullfort
Status: pending behandler
Status: failed feilet

Design Tokens

Token Value
Page bg #EEEEEE
Card bg #FFFFFF
Primary #0B6E35
Primary hover #095C2C
Accent/Gold #D4A017
Text primary #1A1A1A
Text muted #6B7280
Text light #9CA3AF
Border #E5E7EB
Success #16A34A
Warning #D97706
Error #EF4444
Brand font font-[family-name:var(--font-fraunces)]
Card radius rounded-2xl
Button radius rounded-xl
Pill radius rounded-full
Icon circle radius rounded-full

Bottom Navigation

Yes — "Kort" tab appears active/highlighted (based on Figma). All other tabs inactive (gray, outline icons).