Skip to content

Voter email-block status API, voters filter & branded emails - #6

Merged
Putr merged 4 commits into
masterfrom
feature/voter-bounce-status
Jun 22, 2026
Merged

Putr merged 4 commits into
masterfrom
feature/voter-bounce-status

Conversation

@Putr

@Putr Putr commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Supports the web_app voter-list/verification UX work (SiVoteApp feature/dashboard-account-home).

Changes

  • Expose voter email-block status in the API: VoterBasic/VoterFull now return email_blocked (bool) and blocked_reason (bounce/complaint/null, derived from the voter's most recent hard delivery failure via a new Voter::blockedReason() — reuses the already-loaded sentMessages, no new queries). VoterListFull.stats gains voters_blocked.
  • Status filter on the paginated voters endpoint: GET /api/voterlist/{id}/voters?filter=all|verified|unverified|bounced, so consumers can page through just the bounced/unverified voters instead of filtering one loaded page client-side.
  • created_at on SentMessageBasic so consumers can show when each message was sent (e.g. group a verification's messages by batch into a send history).
  • Branded markdown emails: the published vendor/mail theme was still stock Laravel (slate #2d3748 button, generic links). Aligned to the eGlasovanje brand (button #34b6df/text #053040, links #1b8fb8, brand neutrals) and a branded header wordmark, keeping the org personalization-logo branch. Affects all sender emails (verification, ballot invite/result, session invite, test).

All additive; no behaviour change to existing fields. PHPStan level 8 clean, full suite green (75 tests).

Putr added 4 commits June 17, 2026 13:23
The voter model already tracks email_blocked (set true on a permanent bounce or
spam complaint by the SNS webhook; cleared on successful delivery), but it was
never surfaced to API consumers, so web_app couldn't show bounced/blocked voters.

- VoterBasic + VoterFull: add email_blocked (bool) and blocked_reason
  ('bounce' | 'complaint' | null), derived from the voter's most recent hard
  delivery failure via a new Voter::blockedReason() helper (reuses the already-
  loaded sentMessages relation — no new queries).
- VoterListFull.stats: add voters_blocked count.

Verified: phpstan level 8 clean, full suite (75 passed).
GET /api/voterlist/{id}/voters now accepts ?filter=all|verified|unverified|bounced
so web_app can page through just the bounced (email_blocked) or unverified voters
instead of filtering a single loaded page client-side.

Verified: phpstan level 8 clean, voterlist tests (37 passed).
Lets consumers show when each message was sent (e.g. group a verification's
messages by batch to list every send event). Additive field.

Verified: phpstan level 8 clean, full suite.
web_sender's published mail theme was still stock Laravel — the verification
'Verify Now' button rendered dark slate (#2d3748) and links generic blue, while
web_app's emails (e.g. team invites) use the eGlasovanje brand.

- Replace vendor/mail theme CSS with web_app's branded version (button #34b6df /
  text #053040, links #1b8fb8, brand success/error, zinc neutrals). Selectors are
  identical between the two — pure color/brand alignment.
- Header fallback: the plain 'eGlasovanje' text becomes the branded wordmark
  (brand 'e' + Poppins/ink), keeping the org personalization-logo branch.

Verified by rendering emails.verification: brand color present, wordmark present,
no leftover slate.
@Putr
Putr merged commit 70ed69e into master Jun 22, 2026
1 check failed
@Putr
Putr deleted the feature/voter-bounce-status branch June 22, 2026 11:28
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