Files
PocketVeto/frontend/lib/types.ts
Jack Levy 73881b2404 feat(notifications): follow modes, milestone alerts, notification enhancements
Follow Modes (neutral / pocket_veto / pocket_boost):
- Alembic migration 0013 adds follow_mode column to follows table
- FollowButton rewritten as mode-aware dropdown for bills; simple toggle for members/topics
- PATCH /api/follows/{id}/mode endpoint with validation
- Dispatcher filters pocket_veto follows (suppress new_document/new_amendment events)
- Dispatcher adds ntfy Actions header for pocket_boost follows

Change-driven (milestone) Alerts:
- New notification_utils.py with shared emit helpers and 30-min dedup
- congress_poller emits bill_updated events on milestone action text
- llm_processor replaced with shared emit util (also notifies member/topic followers)

Notification Enhancements:
- ntfy priority levels (high for bill_updated, default for others)
- Quiet hours (UTC): dispatcher holds events outside allowed window
- Digest mode (daily/weekly): send_notification_digest Celery beat task
- Notification history endpoint + Recent Alerts UI section
- Enriched following page (bill titles, member photos/details via sub-components)
- Follow mode test buttons in admin settings panel

Infrastructure:
- nginx: switch upstream blocks to set $variable proxy_pass so Docker DNS
  re-resolves upstream IPs after container rebuilds (valid=10s)
- TROUBLESHOOTING.md documenting common Docker/nginx/postgres gotchas

Authored-By: Jack Levy
2026-03-01 15:09:13 -05:00

187 lines
3.9 KiB
TypeScript

export interface MemberTerm {
congress?: number;
chamber?: string;
partyName?: string;
stateCode?: string;
stateName?: string;
startYear?: number;
endYear?: number;
district?: number;
}
export interface MemberLeadership {
type?: string;
congress?: number;
current?: boolean;
}
export interface MemberTrendScore {
score_date: string;
newsapi_count: number;
gnews_count: number;
gtrends_score: number;
composite_score: number;
}
export interface MemberNewsArticle {
id: number;
source?: string;
headline?: string;
url?: string;
published_at?: string;
relevance_score?: number;
}
export interface Member {
bioguide_id: string;
name: string;
first_name?: string;
last_name?: string;
party?: string;
state?: string;
chamber?: string;
district?: string;
photo_url?: string;
official_url?: string;
congress_url?: string;
birth_year?: string;
address?: string;
phone?: string;
terms_json?: MemberTerm[];
leadership_json?: MemberLeadership[];
sponsored_count?: number;
cosponsored_count?: number;
latest_trend?: MemberTrendScore;
}
export interface CitedPoint {
text: string;
citation: string;
quote: string;
}
export interface BriefSchema {
id: number;
brief_type?: string;
summary?: string;
key_points?: (string | CitedPoint)[];
risks?: (string | CitedPoint)[];
deadlines?: { date: string | null; description: string }[];
topic_tags?: string[];
llm_provider?: string;
llm_model?: string;
govinfo_url?: string;
created_at?: string;
}
export interface TrendScore {
score_date: string;
newsapi_count: number;
gnews_count: number;
gtrends_score: number;
composite_score: number;
}
export interface BillAction {
id: number;
action_date?: string;
action_text?: string;
action_type?: string;
chamber?: string;
}
export interface NewsArticle {
id: number;
source?: string;
headline?: string;
url?: string;
published_at?: string;
relevance_score?: number;
}
export interface Bill {
bill_id: string;
congress_number: number;
bill_type: string;
bill_number: number;
title?: string;
short_title?: string;
introduced_date?: string;
latest_action_date?: string;
latest_action_text?: string;
status?: string;
chamber?: string;
congress_url?: string;
sponsor?: Member;
latest_brief?: BriefSchema;
latest_trend?: TrendScore;
updated_at?: string;
}
export interface BillDetail extends Bill {
actions: BillAction[];
news_articles: NewsArticle[];
trend_scores: TrendScore[];
briefs: BriefSchema[];
has_document: boolean;
}
export interface PaginatedResponse<T> {
items: T[];
total: number;
page: number;
per_page: number;
pages: number;
}
export interface Follow {
id: number;
follow_type: "bill" | "member" | "topic";
follow_value: string;
follow_mode: "neutral" | "pocket_veto" | "pocket_boost";
created_at: string;
}
export interface DashboardData {
feed: Bill[];
trending: Bill[];
follows: { bills: number; members: number; topics: number };
}
export interface SettingsData {
llm_provider: string;
llm_model: string;
congress_poll_interval_minutes: number;
newsapi_enabled: boolean;
pytrends_enabled: boolean;
}
export interface NotificationSettings {
ntfy_topic_url: string;
ntfy_auth_method: string; // "none" | "token" | "basic"
ntfy_token: string;
ntfy_username: string;
ntfy_password: string;
ntfy_enabled: boolean;
rss_enabled: boolean;
rss_token: string | null;
digest_enabled: boolean;
digest_frequency: "daily" | "weekly";
quiet_hours_start: number | null;
quiet_hours_end: number | null;
}
export interface NotificationEvent {
id: number;
bill_id: string;
event_type: "new_document" | "new_amendment" | "bill_updated";
payload: {
bill_title?: string;
bill_label?: string;
brief_summary?: string;
bill_url?: string;
} | null;
dispatched_at: string | null;
created_at: string;
}