Files
PocketVeto/frontend/lib/types.ts
Jack Levy 0de8c83987 feat: weekly digest + local-time quiet hours
Weekly Digest (send_weekly_digest Celery task):
- Runs every Monday 8:30 AM UTC via beat schedule
- Queries all followed bills updated in the past 7 days per user
- Sends low-priority ntfy push (Priority: low, Tags: newspaper,calendar)
- Creates a NotificationEvent (weekly_digest type) for RSS feed visibility
- Admin can trigger immediately via POST /api/admin/trigger-weekly-digest
- Manual Controls panel now includes "Send Weekly Digest" button

Local-time quiet hours:
- Browser auto-detects IANA timezone via Intl.DateTimeFormat().resolvedOptions().timeZone
- Timezone saved to notification_prefs alongside quiet_hours_start/end on Save
- Dispatcher converts UTC → user's local time (zoneinfo stdlib) before hour comparison
- Falls back to UTC if timezone absent or unrecognised
- Quiet hours UI: 12-hour AM/PM selectors, shows detected timezone as hint
- Clearing quiet hours also clears stored timezone

Co-Authored-By: Jack Levy
2026-03-01 22:04:54 -05:00

190 lines
4.0 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;
label?: "cited_fact" | "inference";
}
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;
has_document?: boolean;
}
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;
timezone: string | null; // IANA name, e.g. "America/New_York"
}
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;
}