Commit graph

29 commits

Author SHA1 Message Date
b9fdd97330 Add PWA manifest support
Icons already existed in public/icons/ but nothing wired them up —
no manifest, no service worker, not installable.
2026-07-29 17:28:35 +00:00
4137813fc7 Use central Anthropic key for AI insights; add update-check banner
AI insights now fetches the Claude API key from the central settings
service instead of storing its own encrypted copy, so wages and other
apps can share the same key. Also wires up the update-available banner
using the existing version-check hook pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 20:43:03 +00:00
2a7ee1d6b8 Expand AI insight: fix broken competitor query, add continuity, 30-day horizon, holidays
- Fix gather_competitor_data() tier filter: it queried tier IN ('primary','secondary'),
  values that never exist (real values are 'own'/'competitor'/'market'), so the
  cheapest-competitor comparison has always silently returned nothing.
- Feed the previous insight back into the prompt so the model can note what's
  changed/resolved instead of repeating itself.
- Extend forecast horizon from 14 to 30 days; add a per-day revenue table
  alongside the existing occupancy table.
- Annotate the occupancy table with UK (England) bank holidays.
- Add a same-channel market-movement section (B.com vs B.com, rack vs rack)
  diffing rates against the last insight's snapshot, threshold £3.
- Add a parsed headline field + insight history list on the Dashboard,
  collapsed to headline/age and expandable to full content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 18:03:31 +00:00
2f5349bd1c Fix session-expiry redirect breaking standalone PWA out of its shell
Same fix as kitchen/kds: AuthGate unconditionally hard-navigated
window.top to the central /login on session expiry, even when not
embedded in the portal iframe — dropping an installed/directly-opened
forecasting session into the portal's framed browser view instead of
staying in its own window.

Now only bounces to central login when actually embedded (passing
?from= so it returns here afterwards); standalone or directly-opened
tabs get an in-app login form and never navigate away. Also wired up
the inactivity auto-logout timer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 17:07:15 +00:00
7007eb7020 Fix API keys list not showing — unwrap .keys from response
Backend returns { keys: [...] } but frontend was treating the whole
object as the array, so apiKeys.length was always falsy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-23 11:29:35 +00:00
d47e6dff40 Add name, email and sign out button to sidebar footer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-22 11:10:09 +00:00
71a385e670 Remove responsive breakpoint — sidebar always visible (desktop-forced via CSS)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 08:54:51 +00:00
f26141f258 Force desktop viewport (width=1280) — info-heavy display not suited to responsive layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-20 23:15:55 +00:00
785e804414 Remove PWA nginx location blocks from forecasting
Stale manifest/sw/registerSW location blocks left after PWA plugin removal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-14 08:45:33 +00:00
ba3351a8a3 Remove vite-plugin-pwa from forecasting frontend
registerSW.js was 404ing in the browser — the PWA plugin was a leftover
from the original port and this is an internal hotel app with no PWA requirement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-14 08:39:39 +00:00
5fbf155f62 Add weather sync job, API endpoints and settings UI
Fetches daily ERA5 weather from Open-Meteo (no API key).
Configurable location, timezone and sync time via Settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 21:10:03 +00:00
7dfaa5a9fb Add bare /health location to nginx for management monitor compatibility
The management monitor checks http://{host}:{port}/health (no slug prefix).
Adds a location = /health alias alongside the existing /forecasting/health
so both the slug URL (browser/NPM) and the bare path (monitor) work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 17:07:24 +00:00
1aa52c563e Add Resos connection status card to Settings — read-only, sourced from central Settings
Replaces the removed API key form with a status card showing whether the
Resos key is configured in the central Settings app, plus a Test Connection
button. Adds back the GET /settings/resos and POST /settings/resos/test
endpoints (now reading from central_settings rather than system_config).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 15:02:42 +00:00
3650c92175 Move Resos API key to central Settings service; add sidebar scrollbar styling
Removes the standalone resos_api_key from the forecasting app's own
system_config table. All credential fetches now go through
central_settings.get_resos_credentials() / get_resos_credentials_sync()
which pull from the Settings app (LXC 116) via the internal integration
endpoint — the same pattern already used for NewBook. The Resos API
Config section is removed from the forecasting Settings page; users
manage the key in the central Settings app instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 14:35:35 +00:00
9057d764fa Configurable inactivity timeout — disabled automatically in PWA/standalone mode 2026-07-13 12:29:01 +00:00
e4152b183b Add shared device inactivity timeout to AuthGate 2026-07-13 11:53:05 +00:00
dde41bc5d1 Escape HTML entities before rendering AI insight content
The renderContent() function used dangerouslySetInnerHTML without
first sanitizing the AI-generated text, allowing any HTML in the
model response to execute in the browser. Added escHtml() helper
and applied it before the bold-substitution regex.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 09:25:02 +00:00
fce9048902 Replace letter icons with Lucide PWA icons 2026-07-11 20:30:11 +00:00
1ee3f7919f Make forecasting installable as a PWA
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:27:00 +00:00
084555efdb Fix mid-session 401 redirecting iframe to wrong URL, causing portal EmbeddedFallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 11:43:58 +00:00
f3e02c3867 Fix expired session showing EmbeddedFallback in portal iframe
When the JWT expired, AuthGate redirected window.location to /auth/login
which loaded inside the portal iframe. The portal detected window.self !==
window.top and showed the EmbeddedFallback ("This app isn't available yet")
instead of the login page.

Redirect window.top instead so the portal itself navigates to /login.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-09 20:19:36 +00:00
76ed477c3a Remove bookability and competitor rates — moved to Rate Monitor app
Deletes bookability.py, competitor_rates.py, Bookability.tsx,
CompetitorRates.tsx. Removes their imports, router mounts, and nav items.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:14:26 +00:00
1612468122 Bookability: run date refresh synchronously, update timestamp immediately
Backend now awaits the refresh in a thread executor instead of queuing a
background task, so the response returns only after data is written. Frontend
drops the 3s setTimeout and invalidates the cache immediately on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 10:08:20 +00:00
7223ae9c30 Bookability: show last-updated timestamp per date column
Backend adds valid_from to DateRateInfo and computes date_last_updated dict
(max valid_from across categories per date). Frontend renders it as a small
timestamp below the date in each column header — time only if today, date+time
if older. Full ISO string in title tooltip.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 10:03:17 +00:00
9e6801482f Fix Forecasts nav: useParams key was forecastId but route param is :page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:48:14 +00:00
7c8ea1af15 Add favicon.svg for forecasting app
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:22:13 +00:00
aeb99650bd NewBook credentials from central Settings service
Stack-wide NewBook config lives in the Settings app (LXC 116) and is
fetched live via SETTINGS_URL/SETTINGS_SECRET — same pattern as cashup,
room-planner and maintenance. App-local system_config credentials remain
as a fallback for standalone/dev use. The app's Settings → Newbook page
no longer edits credentials; it points to the central app and keeps
Test Connection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 19:36:41 +00:00
851747b561 fix: pin top-bar/page-content grid rows at mobile widths
page-content kept grid-row 1/-1 from the desktop rule, so the
top-bar auto-placed into an implicit row below the content —
the nav menu rendered at the bottom of the page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 19:17:01 +00:00
75d2c1fa9d Forecasting app: hybrid port to HNF stack
Python FastAPI ML backend kept intact; auth replaced with central hnf_session cookie verification. Frontend rebuilt on React 18 + TS + Vite with stack design system, Plotly charts retained. Shared Postgres via DATABASE_URL; schema applied on startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 18:49:34 +00:00