Skip to content

feat: add hour_of_day_range, swell_height, and wind_direction notification filters#8

Open
jsauca wants to merge 2 commits into
BaptisteLac:mainfrom
jsauca:feat/notification-filters-wave-wind
Open

feat: add hour_of_day_range, swell_height, and wind_direction notification filters#8
jsauca wants to merge 2 commits into
BaptisteLac:mainfrom
jsauca:feat/notification-filters-wave-wind

Conversation

@jsauca

@jsauca jsauca commented May 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Three new rule types for the /moi/notifications filter, building on the existing cloud_cover / tide_phase / etc. patterns:

  • hour_of_day_range — restrict alerts to a daily window (e.g. 10h–14h). Stored as start-end (0–23, inclusive).
  • swell_height — numeric meters with operator (≤/≥/</>). Fetched from the Open-Meteo marine API. Uses Biscarrosse-Plage coords (44.43, -1.25) as an open-Atlantic proxy — the Arcachon zone gets snapped to a sheltered bay grid cell, while Biscarrosse gives a representative reading for boats heading out the Cap Ferret pass.
  • wind_direction — multi-select of 8 cardinal sectors (N / NE / E / SE / S / SO / O / NO). Stored as comma-separated codes; the engine buckets the actual wind degrees into the nearest 45° sector and checks set membership.

Touch points

  • 2 migrations extending the notification_rules.type CHECK constraint
  • Both rule engines (src/lib/notifications/rule-engine.ts + supabase/functions/_shared/scoring.ts) — added types, degreesToCardinal8 helper, evaluation branches, extended ComputedConditions and buildHourlyConditions signature
  • Both edge functions (notify-morning, notify-evening) — added wind_direction_10m to the existing forecast call (free) + new marine fetch with graceful fallback if the marine API fails
  • UI (NotificationsClient.tsx) — new labels, swell numeric input with m suffix, wind direction 4-col chip multi-select, validation, ruleLabel display
  • 33 new test cases in rule-engine.test.ts covering both new rule types + the helper

Test plan

  • npm test -- rule-engine → 42/42 pass
  • npx tsc --noEmit → clean
  • Apply migrations: supabase db push (or via dashboard)
  • Deploy edge functions: supabase functions deploy notify-morning notify-evening
  • Manual smoke test at /moi/notifications:
    • Add Houle ≤ 1.0 m rule — appears with correct label
    • Add Direction du vent — N, NO rule — multi-select chips toggle, label reads "Vent venant de N, NO"
    • Add Plage horaire 10h–14h rule — boundaries inclusive
    • Try wind_direction with no sector selected — error shown, no insert

🤖 Generated with Claude Code

jsauca and others added 2 commits May 5, 2026 17:01
New filter type lets users restrict alerts to a specific hour-of-day
window (e.g. only between 10h and 14h). To make the window meaningful,
the rule engine now scans all 24 hours of each day and reports matching
hours instead of evaluating once against daily averages.

- Migration extends the notification_rules type CHECK with
  'hour_of_day_range' (value stored as "<start>-<end>", inclusive,
  Paris-local hours 0-23, no wrap-around).
- Rule engine adds an `hour` field to ComputedConditions and a new
  evaluateRulesAcrossDay() that returns matched + matchingHours.
  Mirrored in both src/lib/notifications/rule-engine.ts (client) and
  supabase/functions/_shared/scoring.ts (edge).
- buildHourlyConditions() produces 24 per-hour snapshots reusing the
  existing computeTidePhase. Wind/cloud are per-hour; species scores,
  global score, coefficient and pressure trend stay day-level and are
  broadcast across the snapshots.
- notify-morning and notify-evening switch from daily evaluation to
  the hourly scan. Push body now reports the matching window via a
  formatWindow helper that collapses contiguous hours.
- UI: new "Plage horaire" type with two number inputs (0-23), saved
  as "<start>-<end>"; ruleLabel renders e.g. "Plage horaire 10h–15h".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two new rule types for the notification filter:
- swell_height (numeric, meters) — fetched from Open-Meteo marine API
  using Biscarrosse-Plage as an open-Atlantic proxy, since the Arcachon
  zone coords get snapped to a sheltered bay grid cell
- wind_direction — multi-select of 8 cardinal sectors (N/NE/E/SE/S/SO/O/NO),
  stored as comma-separated codes; the engine buckets the actual wind
  degrees into the nearest 45° sector

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented May 5, 2026

Copy link
Copy Markdown

@jsauca is attempting to deploy a commit to the baptistelac's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant