[EPAC-965]: Bill page amendments panel#804
Merged
riddim-developer-bot[bot] merged 2 commits intoJun 14, 2026
Merged
Conversation
added 2 commits
June 14, 2026 04:30
Adds an "Amendments" panel to the iOS bill page showing amendments tabled
against a bill, with mover name, stage, status badge (passed/defeated/
withdrawn), and a tap-to-expand row revealing the verbatim amendment text.
Backend integration uses the existing GET /api/v1/bills/{id} bill-depth
endpoint, which already carries the embedded amendments array. The iOS layer
decodes only the typed JSON shape — LEGISinfo and committee-minute parsing
remain backend responsibilities.
Hides the panel when the backend has no amendments record for a bill, and
renders an empty-state row when the bill is tracked but no amendments have
been tabled yet.
Includes Clean Architecture port + use case + adapter split, EN/FR
localization, unit tests for the use case and repository, and snapshot tests
for passed / defeated / withdrawn / multiple-by-same-MP / empty states.
Updates the use-case catalog with the new LoadBillAmendments entry and the
new BillAmendmentsRepository port.
Records reference PNGs for the five new BillAmendmentsPanel snapshot tests (passed, defeated, withdrawn, multipleBySameMP, empty) in light, dark, and accessibility-large variants.
riddim-developer-bot
Bot
deleted the
symphony/epac-965-bill-page-amendments-tracker
branch
June 14, 2026 08:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an Amendments panel to the iOS bill page showing amendments tabled against a bill (number, mover, stage, status, optional clause descriptor), with a tap-to-expand row revealing the verbatim amendment text and the parl.ca source link.
Linear: EPAC-965
Project: Bills, Votes & Committees — depth across the legislative cycle
The ticket scope is iOS only — the backend already ships amendments via the bill-depth endpoint.
Architecture
Clean Architecture split:
ios/epac/Domain/Entities/BillAmendment.swift—BillAmendment+BillAmendmentStatus(passed/defeated/withdrawn/unknown).ios/epac/Domain/Ports/BillAmendmentsRepository.swift— returns[BillAmendment]?:nil⇒ hide panel,[]⇒ empty state, non-empty ⇒ list.ios/epac/Application/LoadBillAmendments.swift—LoadBillAmendments.execute(billID:).ios/epac/Data/Repositories/BackendBillAmendmentsRepository.swift— callsGET /api/v1/bills/{id}, decodes the bill-depth JSON, extracts theamendmentsarray.ios/epac/Views/Bills/BillAmendmentsPanel.swift—BillAmendmentsPanel(Section with rows and an optional empty-state row) + collapsed/expandedBillAmendmentRow(DisclosureGroup).ios/epac/Views/Bills/BillDetailView.swift— autoloads the panel below the existing committee-stage panel.The use case never imports LEGISinfo or parl.ca wire formats — the backend JSON contract is the boundary. Catalog updated for the new use case and port.
Backend contract (consumed, not added)
Endpoint:
GET /api/v1/bills/{id}(existinggetBillDepthoperation). Status 204/404 ⇒ no record. Status 200 ⇒ bill JSON; the iOS adapter pullsbill.amendmentsand maps each item to the domain entity.The adapter only reads these fields per amendment (others are tolerated/ignored):
id,number,title,status,stage,sponsor_name,proposed_on,text,source_url.Deviations from the literal ticket text
The ticket described a dedicated
GET /bills/<legisinfo_id>/amendmentsendpoint with a richer schema (mover_member_id,clause_reference). The deployed backend exposes amendments through the existing bill-depth endpoint with a simpler schema:sponsor_name(string, not a member ID) and no separateclause_reference. Implications:mover_member_idand an iOS update can then link the name. Out of scope for this iOS-only ticket.clause_referencefield. The view showsamendment.titlewhen present (e.g. "Clause 5 — replace subsection (2)"), which is what the backend example payloads carry today.The boundary rule — verbatim amendment text, no paraphrasing — is preserved end-to-end: the entity carries the raw
textfield, the use case does not transform it, and the view renders it viaText(amendment.text).textSelection(.enabled)inside the expanded row.Localization
EN and FR strings added under the
billAmendments.*namespace inios/epac/{en,fr}.lproj/Localizable.strings.Tests
Unit tests (9 tests, all passing locally):
epacTests/Application/LoadBillAmendmentsTests— use case delegates to repository, surfaces nil / empty / populated / error.epacTests/BillAmendmentsRepositoryTests— JSON decoding, 200 with multiple statuses, 200 with no amendments, 204, 404, 5xx (usesURLProtocolmock; no real network).Snapshot tests (5 panel states × 3 modes — light, dark, accessibility-large — 15 PNGs):
testBillAmendmentsPanel_passedtestBillAmendmentsPanel_defeatedtestBillAmendmentsPanel_withdrawntestBillAmendmentsPanel_multipleBySameMPtestBillAmendmentsPanel_emptyTest plan
pr-buildpasses (unit + snapshot tests on iOS Simulator).Release-Note:Bill page now shows an Amendments panel with each tabled amendment's number, mover, stage, status (Passed / Defeated / Withdrawn), and tap-to-expand verbatim text.