dev #106

Merged
root merged 3 commits from dev into main 2026-06-04 23:59:35 +03:00
Owner
No description provided.
root added 3 commits 2026-06-04 23:59:27 +03:00
Settings → Bildirimler had grown a 6-row list (welcome / trial-ending /
referral / referral-qualified / referral-reward / win-back) that read like
an internal cron schedule rather than a user choice. Users care about
e-mail vs mobile, not which Novu trigger fires the day-3 nudge.

Replaces the per-workflow UI with two switches:

  • E-posta bildirimleri  — bundles all six marketing/lifecycle workflows
                             above, off = mute all
  • Mobil bildirim         — placeholder for the not-yet-shipped mobile
                             app push channel; the preference is stored
                             so it Just Works when push ships

Auth + payment mail remain unaffected — the server-side OPTIONAL_WORKFLOWS
filter is still the canonical opt-out gate.

API
---
Same path (`/api/email/preferences`), category-shaped payload:

  GET  → `[{category, label, description, optedOut}, …]`  (two rows)
  POST → body `{category, optedOut}`                       (toggles every
                                                            workflow in
                                                            the bundle)

UnsubscribeController is untouched — one-click List-Unsubscribe URLs in
mail still address a single workflow (we don't want clicking the welcome-
mail unsub link to also kill the trial-ending nudge a week later).

Service
-------
New `NOTIFICATION_CATEGORIES` const + `getCategoryState()` /
`setCategoryState()` on EmailPreferencesService. `mobile_push` added to
OPTIONAL_WORKFLOWS so the same row-presence guard works for it.

UI
--
NotificationsCard renders two rows (or two skeletons) — keys are stable
so the skeletons match the final layout. Category copy comes from the
API; static FALLBACK_CATEGORY_COPY avoids a flash of untitled rows
before GET resolves.

PostHog events renamed from `email_workflow_opted_in/out` to
`notifications_category_opted_in/out` since the per-workflow event was
never going to be useful.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
BMW (p5bmw) decode was weak: model was just the trim ("520i") with no
chassis/generation, body_type empty, because BMW has NO prNr segment and keeps
that data in distinct vinfoBasic labels the shared parser ignored. Live-verified
fields: "Seri"="5 G30" (chassis), "Karoseri"="Limousine" (body), "Tahrik"="RWD".

- model: fold the generation ("Seri"/"Model tanimi") into the model when present
  and not already included → "520i 5 G30" (disambiguates E60/F10/G30 for parts).
- bodyType: fall back to vinfoBasic "Karoseri" when there's no prNr K8*.
- series: read "Seri"; driveType: read "Tahrik".
Year already comes from "Üretim tarihi" (P5 year fallback). VW/Audi (prNr) and
Mercedes ("Piyasa adı", no seri/karoseri) verified unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(pl24): cleaner BMW model — append chassis only, drop redundant line token
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
94faa6cdcd
"Seri" is "{line} {chassis} [{variant}]" and the trim already implies the line
("520i"→5, "X3 sDrive20i"→X3), so append only the chassis(+variant): "520i G30",
"X3 sDrive20i G01" (was "520i 5 G30" / the redundant "X3 sDrive20i X3 G01").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
root merged commit c2d540afc7 into main 2026-06-04 23:59:35 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: root/sase.tr#106