Move-money form: create transfers between own accounts

Angular · Angular · advanced · greenfield

Adds TransferApiService (POST /api/transfers) and the move-money form with from/to account selects and an amount field. Validates the inputs, blocks same-account transfers, disables the button while submitting, and surfaces the receipt id on success. Exercised the form against the sandbox API and receipts come back settled.

An online-banking app; users move money between their own accounts (checking → savings). The backend executes transfers exactly as instructed — it cannot tell direction intent from the payload. `provideHttpClient()` is already in `app.config.ts`, and the accounts page renders `<app-move-money-form [accounts]="accounts()" />` in the next PR, behind the `move-money` feature flag; until then nothing renders it, by design.

Requirements

Files touched

--- src/app/payments/transfer-api.service.ts
+import { HttpClient } from '@angular/common/http';
+import { Injectable, inject } from '@angular/core';
+import { Observable } from 'rxjs';
+
+export interface TransferReceipt {
+  id: string;
+  status: 'pending' | 'settled';
+}
+
+@Injectable({ providedIn: 'root' })
+export class TransferApiService {
+  private http = inject(HttpClient);
+
+  /**
+   * Create a money transfer between two accounts.
+   *
+   * Argument order is part of the contract:
+   * - `sourceAccountId` — the account the money LEAVES (debited).
+   * - `destinationAccountId` — the account the money ARRIVES IN (credited).
+   * - `amountCents` — positive integer amount in cents.
+   */
+  createTransfer(
+    sourceAccountId: string,
+    destinationAccountId: string,
+    amountCents: number,
+  ): Observable<TransferReceipt> {
+    return this.http.post<TransferReceipt>('/api/transfers', {
+      source_account_id: sourceAccountId,
+      destination_account_id: destinationAccountId,

Review this PR

Angular practice