Skip to main content

Pages

Drop Frontend — Pages

All pages are in src/drop-app/src/app/ using Next.js App Router file-based routing.


Page Index

Route File Type Auth Required BottomNav
/ page.tsx Server No No
/login login/page.tsx Client No No
/register register/page.tsx Client No No
/dashboard dashboard/page.tsx Client Yes Yes
/accounts accounts/page.tsx Client Yes Yes
/transactions transactions/page.tsx Client Yes Yes
/scan scan/page.tsx Client Yes Yes
/send send/page.tsx Client Yes No
/profile profile/page.tsx Client Yes Yes
/profile/personal profile/personal/page.tsx Client Yes No
/profile/security profile/security/page.tsx Client Yes No
/profile/notifications profile/notifications/page.tsx Client Yes No
/profile/language profile/language/page.tsx Client Yes No
/notifications notifications/page.tsx Client Yes Yes
/cards cards/page.tsx Client Yes No
/complaints complaints/page.tsx Client No No
/fees fees/page.tsx Client No No
/privacy privacy/page.tsx Client No No
/terms terms/page.tsx Client No No
/withdrawal withdrawal/page.tsx Client No No

Page Details

/ — Home / Marketing Page

  • File: app/page.tsx
  • Type: Server component (no "use client")
  • Auth: None
  • Components used: DropLogoFull, DropAppIcon, Link, Image, custom icons (IconSendMoney, IconQrScan, IconVirtualCard, IconShield, IconFastTransfer, IconCorridors)
  • Data: Static arrays features (3 items) and stats (3 items) defined inline
  • Sections:
    1. Header with DropLogoFull + nav links (Tjenester, Priser, Om oss, Logg inn, Kom i gang)
    2. Hero with headline, subtext, CTA buttons, phone mockup placeholder
    3. Features grid (Send penger, Betal med QR, Virtuelt kort)
    4. Stats bar (0.5% Gebyr, <2t Leveringstid, 30+ Land)
    5. Trust section (BankID verified, Rask overføring, 30+ land)
    6. Merchant CTA section
    7. Footer with ALAI Holding AS credit

/login — Login

  • File: app/login/page.tsx
  • Type: Client component
  • Auth: None (entry point)
  • Components used: Image, Link, Button, Mail/Lock/Eye/EyeOff/ArrowRight (lucide)
  • State: email, password, showPassword, error, loading
  • Data fetching: POST /api/auth/login with { email, password }
  • Validation: Email regex ^[^\s@]+@[^\s@]+\.[^\s@]+$, required fields check
  • On success: router.push("/dashboard")
  • Social login buttons: BankID, Vipps (UI only, not functional)
  • Dev mode: Shows demo credentials [email protected] / demo1234

/register — Registration

  • File: app/register/page.tsx
  • Type: Client component
  • Auth: None
  • Components used: ArrowLeft/ArrowRight/Check/Eye/EyeOff/Phone/Mail/User/Calendar/Lock (lucide), Button
  • State: step (1-4), form fields, otp, pin, errors
  • Steps:
    1. Info — firstName, lastName, email, phone (+47 prefix), dateOfBirth, password
    2. Verify — 6-digit OTP input (MVP: any 6 digits accepted)
    3. PIN — 4-digit PIN with custom numpad UI
    4. Success — Welcome message, redirect to /dashboard
  • Validation:
    • Age >= 18 (calculated from dateOfBirth)
    • XSS protection: names reject < > " ' & ; ( ) { } [ ]
    • Password: min 8 chars, must contain letters AND numbers
    • Phone: must be 8 digits (Norwegian format)
  • Data fetching: POST /api/auth/register

/dashboard — Main Dashboard

  • File: app/dashboard/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth() with redirect)
  • Components used: DropLogo, BottomNav, ScrollArea, Bell/LogOut (lucide)
  • State: transactions, loading
  • Data fetching: GET /api/transactions?limit=10
  • Interfaces: Transaction { id, type, status, amount, currency, recipientName, createdAt }
  • Layout:
    1. Header: DropLogo + notification bell + logout + avatar initials
    2. Balance card: primary account balance, formatted NOK
    3. Action buttons: Send penger (→ /send), Skann QR (→ /scan)
    4. Recent transactions list in ScrollArea
    5. BottomNav

/accounts — Bank Accounts

  • File: app/accounts/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: BottomNav, Card, ArrowLeft/Landmark/Plus/ChevronRight (lucide)
  • Data: Reads user.bankAccounts from auth hook (no separate fetch)
  • Layout:
    1. PSD2/Open Banking info banner (blue)
    2. Account cards: bankName, masked accountNumber, balance, currency, isPrimary badge
    3. Total balance summary
    4. "Legg til bankkonto" button (BankID connection note)

/transactions — Transaction History

  • File: app/transactions/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: BottomNav, Tabs/TabsList/TabsTrigger, ArrowLeft/Clock (lucide)
  • State: transactions, filter, loading
  • Data fetching: GET /api/transactions?type={filter}&limit=50
  • Filters: Alle (all), Overforinger (remittance), QR-betalinger (qr_payment)
  • Grouping: groupByDate() function groups into: I dag, I gar, Denne uken, Eldre
  • Display: Amount with +/- prefix and color coding (green for received, red for sent)

/scan — QR Scanner

  • File: app/scan/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: BottomNav, Button, ArrowLeft/Camera/Check/X/Store (lucide)
  • State: scanState (scanning | payment | paying | success), scannedMerchant, amount, paymentResult
  • Interfaces: ScannedMerchant { id, name, category }, PaymentResult { id, status, amount, fee, merchant }
  • Flow:
    1. Scanning — Camera viewfinder UI with scan frame, "Simuler skanning" button (demo)
    2. Payment — Shows merchant info, amount input, 1% fee calculation
    3. Paying — Loading spinner
    4. Success — Confirmation with transaction details
  • Data fetching: POST /api/transactions/qr-payment with { merchantId, amount }
  • Demo merchant: "Ahmetov Kebab" (id: "merchant_001", category: "Restaurant")

/send — Send Money (Remittance)

  • File: app/send/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: Button, ArrowLeft/ArrowRight/Check/ChevronDown/Globe/User (lucide)
  • State: step (1-4), selectedRecipient, amount, recipients, rates, sending, txResult
  • Steps:
    1. Select Recipient — List from GET /api/recipients, shows name + country flag
    2. Enter Amount — NOK input, real-time conversion with exchange rate, 0.5% fee display
    3. Review — Summary of recipient, amount, rate, fee, total
    4. Success — Confirmation with reference number
  • Data fetching:
    • GET /api/recipients (on mount)
    • GET /api/rates (on mount)
    • POST /api/transactions/remittance with { recipientId, amountNOK, targetCurrency }
  • Country flags: RS (Serbia), BA (Bosnia), TR (Turkey), PK (Pakistan), PL (Poland)
  • Interface: TxResult { id, status, amount, fee, rate, recipientName, targetAmount, targetCurrency }

/profile — User Profile

  • File: app/profile/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: BottomNav, ArrowLeft/ChevronRight/LogOut/Settings/Shield/HelpCircle/Bell/CreditCard/Landmark (lucide)
  • Data: Reads user from auth hook
  • Layout:
    1. User info card with initials avatar (green bg), full name, email
    2. Menu items: Mine kontoer (→ /accounts), Varsler, Innstillinger, Sikkerhet, Hjelp og stotte
    3. Logout button with confirmation
    4. Version: "Drop v0.1.0 · ALAI Holding AS"

/withdrawal — Angrerett (Right of Withdrawal)

  • File: app/withdrawal/page.tsx
  • Type: Client component
  • Auth: No
  • Components used: ChevronLeft, RotateCcw, CheckCircle (lucide)
  • State: submitted, loading
  • Purpose: Norwegian angrerettloven compliance — 14-day right of withdrawal form
  • Layout:
    1. Info section explaining angrerett (right to cancel service agreement within 14 days)
    2. Warning banner: Angrerett does not apply to completed payment transactions, only to the service agreement itself
    3. Form with optional reason dropdown (not_needed, alternative, not_satisfied, other) and comment textarea
    4. Submit button (red) with AML retention notice (data kept for 5 years per hvitvaskingsloven)
    5. Success screen with confirmation message (14-day processing time)

/complaints — Send Complaint

  • File: app/complaints/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: MessageSquare, CheckCircle, ChevronLeft, ExternalLink (lucide)
  • State: submitted, loading, formData (category, subject, description)
  • Data fetching: POST /api/complaints with { category, subject, description }
  • Purpose: Finansavtaleloven §3-53 compliance — formal complaint submission with 15 business day response requirement
  • Layout:
    1. Info text: All complaints taken seriously, up to 15 business days processing time
    2. Form with required fields:
      • Category dropdown: transaction, fees, service, privacy, other
      • Subject text input (max 200 chars)
      • Description textarea (max 2000 chars)
    3. Submit button with POST to /api/complaints
    4. External complaint authority section: Finansklagenemnda (FinKN) contact info with link to finansklagenemnda.no
    5. Success screen: Complaint received, 15 business day review commitment

/privacy — Privacy Policy

  • File: app/privacy/page.tsx
  • Type: Client component
  • Auth: None
  • Components used: ChevronLeft, Shield (lucide)
  • Purpose: GDPR-compliant privacy policy page (Norwegian language)
  • Sections:
    1. Behandlingsansvarlig: ALAI Holding AS as data controller
    2. Hvilke opplysninger vi samler inn: Identification (name, email, phone, BankID), Financial data (bank accounts via Open Banking, transaction history), Technical data (IP, device, app version)
    3. Formaal med behandlingen: Transaction processing (PSD2/PISP), KYC/AML compliance, AML/terrorism prevention, service improvement
    4. Rettslig grunnlag: Contract (GDPR 6(1)(b)), Legal obligation (6(1)(c)) for AML/KYC, Legitimate interest (6(1)(f)) for service improvement
    5. Dine rettigheter: Innsyn (access), Retting (rectification), Sletting (erasure with 5-year AML retention), Dataportabilitet (portability)
    6. Oppbevaring: Minimum 5 years per hvitvaskingsloven, anonymization on account deletion but AML data retained
    7. Kontakt: [email protected], complaint to Datatilsynet

/terms — Terms of Service

  • File: app/terms/page.tsx
  • Type: Client component
  • Auth: None
  • Components used: ChevronLeft, FileText (lucide)
  • Purpose: Legal terms of service (Norwegian language)
  • Sections:
    1. Om tjenesten: Drop as PISP/AISP under PSD2, provided by ALAI Holding AS
    2. Krav til brukere: 18+ age, Norwegian residency with BankID, KYC required, Norwegian phone (+47)
    3. Betalingsmodell: Drop never holds customer money, pass-through model via Open Banking
    4. Gebyrer: All fees shown before transaction confirmation, see fees page for full list
    5. Ansvar: Drop responsible for correct payment execution per betalingstjenesteloven, refund rights per law, not liable for bank/recipient delays
    6. Misbruk og sperring: Right to block accounts for suspected AML/fraud, mandatory STR reporting to Økokrim/EFE
    7. Angrerett: 14-day withdrawal right per angrerettloven (does not apply to completed transactions)
    8. Tvister: Norwegian law, Oslo tingrett jurisdiction, complaint to Finansklagenemnda

/fees — Fee Overview

  • File: app/fees/page.tsx
  • Type: Client component
  • Auth: None
  • Components used: ChevronLeft, Receipt (lucide)
  • Purpose: Transparent fee disclosure page (Norwegian language)
  • Sections:
    1. Overføring til utlandet:
      • Transaction fee: 1.5% per transfer
      • Currency markup: 0.5% on mid-market rate
      • Typical total: ~2% (compare with banks at 3-7%)
    2. QR-betaling i butikk:
      • For customer: Free (no charge to payer)
      • For merchant: 0.5% (lower than card terminals)
    3. Kontotjenester:
      • Account creation: Free
      • Monthly fee: Free
      • Bank account linking (AISP): Free
    4. Viktig informasjon:
      • Fees can change with 30-day notice
      • Exchange rates updated in real-time from market
      • Always see final amount before confirming

/profile/personal — Personal Information

  • File: app/profile/personal/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: ChevronLeft, ShieldCheck (lucide), BottomNav
  • State: Reads user from auth hook
  • Layout:
    1. User avatar with initials (green gradient)
    2. Full name and email display
    3. Read-only form fields: firstName, lastName, email, phone (+47 987 65 432), dateOfBirth (15. mars 1995)
    4. BankID verification badge (green banner with ShieldCheck icon)
  • Note: All fields are disabled (cannot edit) — verified via BankID

/profile/security — Security Settings

  • File: app/profile/security/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: ChevronLeft, ChevronRight, Lock, Smartphone, Laptop (lucide), BottomNav
  • Sections:
    1. Passord: Change password button (shows "Sist endret: Aldri")
    2. To-faktor autentisering:
      • BankID verification: Active (green badge)
      • Vipps verification: Not activated (gray badge)
    3. Aktive enheter:
      • iPhone 15 Pro: Oslo, Norge — Aktiv nå (green dot indicator)
      • MacBook Pro: Oslo, Norge — I går kl. 18:45
    4. Footer: Support contact ([email protected])
  • Note: UI only, no actual functionality connected

/profile/notifications — Notification Settings

  • File: app/profile/notifications/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: ChevronLeft, Bell, Mail (lucide), BottomNav
  • State: pushEnabled, emailEnabled, settingsLoaded
  • Data fetching:
    • GET /api/settings (on mount)
    • PATCH /api/settings with { pushEnabled: boolean } or { emailEnabled: boolean } (on toggle)
  • Layout:
    1. Push-varsler toggle switch (Bell icon)
    2. E-postvarsler toggle switch (Mail icon)
  • Behavior: Toggles immediately update state and send PATCH request, revert on failure

/profile/language — Language Settings

  • File: app/profile/language/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: ChevronLeft, Check (lucide), BottomNav
  • State: selected, saving
  • Data fetching:
    • GET /api/settings (on mount)
    • PATCH /api/settings with { language: string } (on save)
  • Languages: nb (Norsk Bokmål), en (English), bs (Bosanski), sq (Shqip)
  • Layout:
    1. Language list with radio selection (green checkmark for selected)
    2. "Lagre" button (green) to save selection
  • Behavior: Selection updates local state, user must click "Lagre" to persist

/notifications — Notifications Center

  • File: app/notifications/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Components used: BottomNav, ArrowLeft, Bell, ArrowUpRight, ScanLine, Smartphone, TrendingUp (lucide)
  • State: notifications, fetching
  • Data fetching:
    • GET /api/notifications (on mount)
    • PATCH /api/notifications with { notificationIds: [ids] } (mark read, fire-and-forget)
  • Interface: Notification { id, type, title, body, read, createdAt }
  • Layout:
    1. Header with back button + "Varsler" title
    2. Empty state: Bell icon + "Ingen varsler enna" message
    3. Grouped notifications: I DAG / I GÅR / date groups
    4. Notification cards: icon based on type, title, body, timestamp, unread dot indicator
    5. BottomNav
  • Notification types: transaction_complete (green), qr_payment (yellow), security (blue), rate_update (yellow), default (gray)
  • Auto-read: Automatically marks all unread notifications as read on page load
  • Time formatting: "I dag kl. HH:MM", "I går kl. HH:MM", or "DD.MM.YYYY kl. HH:MM"

/cards — Card Management (FUTURE — feature-flagged)

Note: Cards are a FUTURE feature, gated behind feature flags (all default to false). Requires a card issuing partner before activation.

  • File: app/cards/page.tsx
  • Type: Client component
  • Auth: Yes (useAuth())
  • Feature flags: virtualCards (gate), physicalCards, cardPin, spendingLimits — all default to false
  • Components used: Button, Dialog, various lucide icons (CreditCard, Plus, ArrowLeft, Smartphone, Eye, EyeOff, Lock, X, Check, Copy, RefreshCw)
  • State: cards, selectedCard, showDetails, showOrderForm, orderForm, loading
  • Data fetching:
    • GET /api/cards (list)
    • POST /api/cards (create virtual)
    • POST /api/cards with type "physical" + address (order physical)
    • PATCH /api/cards/{id} with {status: "frozen" | "active"}
    • DELETE /api/cards/{id}
  • Card visual: Green gradient background, masked card number (•••• •••• •••• 4242), expiry, cardholder name