rates/frontend/src/types.ts
jtricerolph 74ae94671b Wire up direct-rates column; remove dormant pause-on-block flow
Direct-rates sub-row in Market View was dead: the frontend filters
competitors on direct_hotel_id but /matrix and /hotels never returned it.
Add direct_hotel_id to both queries (+ HotelResponse), and only render the
"Direct" sub-row when a hotel actually has a non-null direct rate (was
rendering all-dashes on an empty {} object).

Remove the pause-on-block flow entirely — dormant since rotate-on-block
replaced it (nothing set booking_scraper_paused=true after set_scraper_paused
was dropped): is_scraper_paused, /config/unpause, the /scrape paused guard,
ScraperStatusResponse.paused/pause_until, and the frontend Paused badge +
Unpause button. Trim now-unused datetime import.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 06:01:56 +00:00

112 lines
2.4 KiB
TypeScript

export interface User {
email: string
name: string
is_admin: boolean
caps: string[]
}
export function can(user: User | null, cap: string): boolean {
if (!user) return false
return user.is_admin || user.caps.includes(cap)
}
export interface Hotel {
id: number
name: string
tier: 'own' | 'competitor' | 'market'
star_rating: number | null
review_score: number | null
booking_com_url: string | null
booking_com_id: string | null
display_order: number
notes: string | null
is_active: boolean
scraped_dates?: number
last_scraped?: string | null
}
export interface RateMatrixEntry {
hotel_id: number
hotel_name: string
tier: string
rate_date: string
rate_gross: number | null
availability_status: string
rooms_left: number | null
scraped_at: string | null
}
export interface ScraperStatus {
enabled: boolean
backend: string
daily_time: string
last_batch: {
batch_id: string
started_at: string
status: string
rates_scraped: number
dates_completed: number
} | null
}
export interface BookabilityCategory {
category_id: string
category_name: string
room_count: number
display_order: number
dates: BookabilityDate[]
}
export interface BookabilityDate {
date: string
gross_rate: number | null
tariffs: TariffSummary[]
occupancy_pct: number | null
available_rooms: number | null
is_bookable: boolean
}
export interface TariffSummary {
tariff_name: string
rate: number | null
min_stay: number | null
advance_max: number | null
is_available: boolean
}
export interface AdvancePurchaseCurvePoint {
lead_bucket: string
avg_rate: number
sample_count: number
}
export interface DowAnalysisPoint {
dow: number
dow_label: string
avg_rate: number
date_count: number
}
export interface StrategySummary {
advance_discount_pct: number | null
weekend_premium_pct: number | null
avg_sold_out_rate_pct: number | null
strategy_label: string
}
export interface HotelAnalysis {
hotel: Hotel
date_range: { from: string; to: string }
advance_purchase_curve: AdvancePurchaseCurvePoint[]
dow_analysis: DowAnalysisPoint[]
sold_out_pattern: Array<{ dow: number; dow_label: string; total_dates: number; sold_out_dates: number }>
strategy_summary: StrategySummary
}
export interface RateTimelinePoint {
scraped_at: string
rate_gross: number | null
availability_status: string
rooms_left: number | null
days_out: number
}