diff --git a/README.md b/README.md index 7892073..02c515a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Personal Travel Log -A lightweight personal travel dashboard for GitHub Pages with itinerary, budget, notes, PWA support and automated Google Flights price tracking. +A lightweight personal travel dashboard for GitHub Pages with itinerary, budget, notes, PWA support with itinerary, booking status, flight operations, budget, notes and optional on-demand price checks. ## Features @@ -9,7 +9,7 @@ A lightweight personal travel dashboard for GitHub Pages with itinerary, budget, - Checklist, budget and notes saved in `localStorage` - Export/import local travel data - Light/dark mode and PWA/offline support -- **Google Flights price snapshots through SerpApi + GitHub Actions** +- **On-demand Google Flights price snapshots through SerpApi + GitHub Actions** - Fare-specific baggage details from Google Flights search and Booking Options - Direct-flight priority, stops/airline filters, price history and price alerts - SerpApi credit/usage snapshot written automatically to this README @@ -153,15 +153,9 @@ data/api-usage.json and commits refreshed snapshots back to `main`. -### Automatic refresh +### Price refresh mode -The default schedule is: - -```text -07:17 Asia/Ho_Chi_Minh -``` - -At 2 main search requests per refresh, a 30-day month is roughly **60 Google Flights search requests**, plus manual checks. Booking Options can add up to **240 requests/month** at the default 8 requests/day if it is enabled every day. Actual provider usage is shown in the live SerpApi usage table above and resets when SerpApi starts the next billing cycle. +Automatic flight and hotel price schedules are currently **paused because the trip has been booked**. Both workflows retain `workflow_dispatch`, so price snapshots can still be refreshed manually when needed. Flight-status tracking remains active independently. ### Price dashboard diff --git a/app.css b/app.css index 51dd249..515542c 100644 --- a/app.css +++ b/app.css @@ -10,3 +10,11 @@ @media(max-width:520px){ .timeline-item:not(:last-child)::after{left:55px} } + +/* Post-booking trip mode */ +.booking-summary{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px} +.booking-chip{display:inline-flex;align-items:center;min-height:30px;padding:6px 10px;border:1px solid var(--line);border-radius:999px;font-size:12px;font-weight:750;background:var(--surface)} +.booking-chip.success{border-color:rgba(34,197,94,.25);background:rgba(34,197,94,.09)} +.booking-chip.muted{color:var(--muted)} +.booking-dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:#22c55e;box-shadow:0 0 0 4px rgba(34,197,94,.12);margin-right:6px} +@media(max-width:640px){.booking-summary{gap:6px}.booking-chip{font-size:11px;padding:5px 8px}.hero-actions{display:grid;grid-template-columns:1fr 1fr}.hero-actions .btn:first-child{grid-column:1/-1}} diff --git a/dashboard.css b/dashboard.css index 517bc3f..f7df509 100644 --- a/dashboard.css +++ b/dashboard.css @@ -153,3 +153,49 @@ body:has(#itinerary) .notes-actions{margin-top:11px} body:has(#itinerary) .checklist,body:has(#itinerary) .budget{padding-left:14px;padding-right:14px} body:has(#itinerary) .notes-wrap{padding:14px} } + + +/* Post-booking dashboard */ +body:has(#itinerary) .booking-summary{display:flex;flex-wrap:wrap;gap:7px;margin-top:13px} +body:has(#itinerary) .booking-chip{display:inline-flex;align-items:center;min-height:26px;padding:0 9px;border:1px solid rgba(255,255,255,.18);border-radius:999px;background:rgba(255,255,255,.1);color:#fff;font-size:10.5px;font-weight:700} +body:has(#itinerary) .booking-chip.success{background:rgba(34,197,94,.16)} +body:has(#itinerary) .booking-dot{width:6px;height:6px;margin-right:6px;border-radius:50%;background:#4ade80;box-shadow:0 0 0 3px rgba(74,222,128,.15)} +body:has(#itinerary) .booking-center{grid-column:1/-1;min-width:0} +body:has(#itinerary) .booking-center-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:11px;padding:16px 20px 0} +body:has(#itinerary) .booking-panel{min-width:0;padding:14px;border:1px solid var(--dashboard-border);border-radius:12px;background:var(--surface);display:flex;flex-direction:column;justify-content:space-between;gap:12px} +body:has(#itinerary) .booking-panel-head{display:flex;align-items:flex-start;gap:9px;min-width:0} +body:has(#itinerary) .booking-panel-head>span{font-size:18px;line-height:1.3} +body:has(#itinerary) .booking-panel-head>div{display:grid;gap:3px;min-width:0} +body:has(#itinerary) .booking-panel-head b{font-size:12px} +body:has(#itinerary) .booking-panel-head small{color:var(--muted);font-size:10.5px;line-height:1.45;overflow-wrap:anywhere} +body:has(#itinerary) .booking-panel-actions{display:flex;align-items:center;flex-wrap:wrap;gap:7px} +body:has(#itinerary) .booking-panel .booking-chip{border-color:var(--line);background:var(--surface-2);color:var(--muted)} +body:has(#itinerary) .booking-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:12px 20px 0} +body:has(#itinerary) .booking-fields label{display:grid;min-width:0;gap:5px;color:var(--muted);font-size:10.5px;font-weight:750} +body:has(#itinerary) .booking-fields input{width:100%;min-width:0;height:36px;box-sizing:border-box;padding:0 10px;border:1px solid var(--line);border-radius:9px;background:var(--surface);color:var(--text);font:inherit;outline:none} +body:has(#itinerary) .booking-fields input:focus{border-color:#8eb0f6;box-shadow:0 0 0 3px var(--primary-soft)} +body:has(#itinerary) .booking-save{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 20px 18px;color:var(--muted);font-size:10.5px} + +@media(max-width:820px){ + body:has(#itinerary) .trip-hero{display:block;min-height:0} + body:has(#itinerary) .hero-copy{padding-right:24px} + body:has(#itinerary) .hero-copy h1, + body:has(#itinerary) .hero-route, + body:has(#itinerary) .hero-meta{max-width:none} + body:has(#itinerary) .countdown{position:relative;right:auto;top:auto;width:auto;min-height:0;height:auto;margin:0 24px 24px;padding:12px 14px;display:flex;align-items:baseline;justify-content:center;gap:7px} + body:has(#itinerary) .countdown strong{margin:0;font-size:28px} + body:has(#itinerary) .countdown b{display:block;margin:0 0 0 auto} + body:has(#itinerary) .booking-center-grid{grid-template-columns:1fr} +} + +@media(max-width:520px){ + body:has(#itinerary) .hero-copy{padding:20px 16px 16px} + body:has(#itinerary) .hero-actions{display:grid;grid-template-columns:1fr 1fr} + body:has(#itinerary) .hero-actions .btn{width:100%;box-sizing:border-box;white-space:normal;text-align:center;justify-content:center} + body:has(#itinerary) .countdown{margin:0 16px 16px;justify-content:flex-start;flex-wrap:wrap} + body:has(#itinerary) .countdown b{width:100%;margin:0;font-size:9.5px} + body:has(#itinerary) .booking-center-grid{padding:12px 14px 0} + body:has(#itinerary) .booking-fields{grid-template-columns:1fr;padding:10px 14px 0} + body:has(#itinerary) .booking-save{align-items:stretch;flex-direction:column;padding:10px 14px 14px} + body:has(#itinerary) .booking-save .btn{width:100%;justify-content:center} +} diff --git a/index.html b/index.html index ddb4075..5e28dce 100644 --- a/index.html +++ b/index.html @@ -22,9 +22,10 @@