Use text-search approach for rate conditions (breakfast/cancel/payment)
Original scrapy approach: extract <li> condition lines from each rate plan row and text-search for known keywords. No match = null (unknown), not assumed false. Adds breakfast_text, cancel_text, payment_text columns to booking_com_rates. Booleans now nullable (null = not mentioned, true/false = explicit signal). JS extraction searches all <li> items in the row (falls back to newline-split innerText if none). Breakfast: 'breakfast' keyword. Cancel: 'free cancellation', 'non-refundable', 'total cost to cancel', 'fully chargeable'. Payment: 'no prepayment', 'pay at the property', 'pay online'. data-fltrs used as fallback. API snapshot endpoint now returns breakfast/cancel/payment text strings. Old boolean-only rows degrade gracefully to derived labels. Modal plan rows replace the fixed meal|cancel|price column layout with a single stacked conditions cell: 0-3 lines depending on what the page actually shows. Breakfast green when 'included', cancel green when 'Free cancellation…'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
69ecf1012e
commit
38b0c36923
6 changed files with 132 additions and 46 deletions
|
|
@ -1276,7 +1276,7 @@ const MonthSelector: React.FC<{
|
|||
interface RateHistoryPoint { t: string | null; rate: number }
|
||||
interface RateHistorySeries { room_type: string; points: RateHistoryPoint[] }
|
||||
interface RateHistoryModal { hotelId: number; hotelName: string; stayDate: string }
|
||||
interface RatePlan { meal: string; cancel: string; price: number; max_persons: number | null }
|
||||
interface RatePlan { breakfast: string | null; cancel: string | null; payment: string | null; price: number; max_persons: number | null }
|
||||
interface RoomSnapshot { room_type: string; rooms_left: number | null; availability_status: string; plans: RatePlan[] }
|
||||
interface RateSnapshot { stay_date: string; legacy: boolean; rooms: RoomSnapshot[] }
|
||||
|
||||
|
|
@ -1350,11 +1350,25 @@ const RateHistoryModalComponent: React.FC<{ modal: RateHistoryModal; onClose: ()
|
|||
<tbody>
|
||||
{room.plans.map((plan, pi) => (
|
||||
<tr key={pi} style={{ borderTop: '1px solid var(--border)' }}>
|
||||
<td style={{ padding: '6px 12px', color: 'var(--text-mid)' }}>{plan.meal}</td>
|
||||
<td style={{ padding: '6px 12px', color: plan.cancel.startsWith('Free') ? '#16a34a' : 'var(--text-mid)' }}>
|
||||
{plan.cancel}
|
||||
<td style={{ padding: '6px 12px' }}>
|
||||
{plan.breakfast && (
|
||||
<div style={{ color: plan.breakfast.toLowerCase().includes('included') ? '#16a34a' : 'var(--text-mid)' }}>
|
||||
{plan.breakfast}
|
||||
</div>
|
||||
)}
|
||||
{plan.cancel && (
|
||||
<div style={{ color: plan.cancel.toLowerCase().startsWith('free') ? '#16a34a' : 'var(--text-mid)' }}>
|
||||
{plan.cancel}
|
||||
</div>
|
||||
)}
|
||||
{plan.payment && (
|
||||
<div style={{ color: 'var(--text-mid)' }}>{plan.payment}</div>
|
||||
)}
|
||||
{!plan.breakfast && !plan.cancel && !plan.payment && (
|
||||
<span style={{ color: 'var(--text-light)', fontSize: 11 }}>—</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={{ padding: '6px 12px', textAlign: 'right', fontWeight: 600, color: 'var(--text-dark)' }}>
|
||||
<td style={{ padding: '6px 12px', textAlign: 'right', fontWeight: 600, color: 'var(--text-dark)', whiteSpace: 'nowrap' }}>
|
||||
£{plan.price.toLocaleString()}
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue