Skip to content

[Phase 2] feat(ui): dashboard — fee alerts panel #88

@Tinna23

Description

@Tinna23

Overview

Add a dedicated /dashboard/alerts route with a UI for creating, viewing, and deleting fee alert rules. Also add an in-app firing indicator that appears on the dashboard when an alert is currently active.

Route

/dashboard/alerts — alert management page

Acceptance Criteria

Route & Page

  • src/app/dashboard/alerts/page.tsx
  • Add alert API functions to src/lib/api.ts:
    • fetchAlerts(): Promise<Alert[]>
    • createAlert(rule: CreateAlertInput): Promise<Alert>
    • deleteAlert(id: string): Promise<void>
    • fetchFiringAlerts(): Promise<FiringAlert[]>
  • Add Alert, CreateAlertInput, FiringAlert types to src/lib/types.ts

Create Alert Form

  • Metric selector: avg_fee | base_fee | max_fee
  • Condition selector: ABOVE | BELOW
  • Threshold input: number in stroops
  • Email input: optional, validated as a proper email format if provided
  • Submit button: CREATE ALERT
  • Inline validation — prevent submission if threshold is empty or email is invalid
  • Success state after creation — form resets, new alert appears in list

Active Alerts List

  • Lists all active alert rules
  • Each row: metric, condition, threshold, email (masked if present), firing badge if currently triggered
  • Delete button per row with a confirmation step
  • Empty state: "No alerts configured" with a prompt to create one

In-App Firing Indicator

  • On the main /dashboard page, poll GET /api/alerts/status every 10s alongside existing polls
  • If any alerts are firing: show a dismissible banner at the top of the dashboard
    • e.g. ⚡ ALERT: avg_fee is ABOVE 500 stroops — current value: 620 stroops
    • Banner colour: red background, white text
  • If multiple alerts firing: show the count with an expand option

Navigation

  • Add ALERTS link to the dashboard nav/sidebar with a red dot badge when alerts are firing

Type Shapes

export interface Alert {
  id: string;
  condition: 'ABOVE' | 'BELOW';
  threshold: number;
  metric: 'avg_fee' | 'base_fee' | 'max_fee';
  email?: string;
  active: boolean;
  triggered: boolean;
  created_at: string;
}

export interface CreateAlertInput {
  condition: 'ABOVE' | 'BELOW';
  threshold: number;
  metric: 'avg_fee' | 'base_fee' | 'max_fee';
  email?: string;
}

export interface FiringAlert extends Alert {
  current_value: number;
}

Notes

  • In-app alerts are the minimum delivery — email is handled entirely by the backend
  • Related backend issues: schema/CRUD issue and checker/email issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    frontendFrontend / UI work

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions