Status 2026-07-13: implemented on feature/130-report-builder (#608) — as-built notes in the #130 status section.
Parent: #130 (Report Builder — bands + bricks). Phase 1. Part of epic #506, Track A.
Scope
Bricks are defined purely in code — there is no report_blocks table and no DB registry. Each brick is a class in app/Mason/Bricks/ extending Awcodes\Mason\Brick:
getId(), getLabel(), getIcon()
allowedBands(): array of ReportBand (header, group_header, details, group_footer, footer)
configureBrickAction() — slide-over Filament form defining the brick's config schema and defaults (e.g. show_vat_id, font_size)
toHtml(array $config, array $data) / toPreviewHtml(array $config) — rendered through blade views at resources/views/mason/bricks/<brick>/{index,preview}.blade.php, with all output escaped via {{ }}
Harvest the 17 existing bricks + views from feature/145-report-builder (Header: company, client, invoice-meta, quote-meta, project · Detail: items, invoice-product, quote-product, invoice-project, quote-project, expense, tasks, customer-aging · Footer: totals, summary, notes, terms). Add two utility bricks for #95: PageBreakBrick and SpacerBrick.
Discovery/registry: ReportBricksCollection (harvested), extended with a per-band filter.
Acceptance criteria
Test scenarios (PHPUnit, #[Test], no Pest)
- Each brick renders expected HTML from a given config + data array (adapt the harvested
MasonBricksTest).
ReportBricksCollection::forBand(ReportBand::DETAILS) excludes header/footer-only bricks.
- Rendering with an unknown config key produces the same output as without it.
Status 2026-07-13: implemented on
feature/130-report-builder(#608) — as-built notes in the #130 status section.Parent: #130 (Report Builder — bands + bricks). Phase 1. Part of epic #506, Track A.
Scope
Bricks are defined purely in code — there is no
report_blockstable and no DB registry. Each brick is a class inapp/Mason/Bricks/extendingAwcodes\Mason\Brick:getId(),getLabel(),getIcon()allowedBands(): arrayofReportBand(header,group_header,details,group_footer,footer)configureBrickAction()— slide-over Filament form defining the brick's config schema and defaults (e.g.show_vat_id,font_size)toHtml(array $config, array $data)/toPreviewHtml(array $config)— rendered through blade views atresources/views/mason/bricks/<brick>/{index,preview}.blade.php, with all output escaped via{{ }}Harvest the 17 existing bricks + views from
feature/145-report-builder(Header: company, client, invoice-meta, quote-meta, project · Detail: items, invoice-product, quote-product, invoice-project, quote-project, expense, tasks, customer-aging · Footer: totals, summary, notes, terms). Add two utility bricks for #95:PageBreakBrickandSpacerBrick.Discovery/registry:
ReportBricksCollection(harvested), extended with a per-band filter.Acceptance criteria
ReportBricksCollectionwith zero DB involvement.allowedBands(); the collection can filter bricks by band.{{ }}only — no{!! !!}for user-influenced data).PageBreakBrickandSpacerBrickexist and are allowed in every band.Test scenarios (PHPUnit,
#[Test], no Pest)MasonBricksTest).ReportBricksCollection::forBand(ReportBand::DETAILS)excludes header/footer-only bricks.