tasks
Tasks: Funding Stream Balance in Package Sidebar
Feature Code: FRB (Funding Remaining Balance) Epic: TP-2501 (Budget Reloaded) Spec: spec.md Plan: plan.md Created: 2025-12-09 Status: Ready for Implementation
Overview
This tasks list breaks down the implementation of the FRB feature into 23 actionable tasks organized by phase and user story. Each task is sized for independent implementation by an LLM or developer.
Task Organization:
- Phase 1: Research & Setup (2 tasks)
- Phase 2: Backend Foundation (5 tasks)
- Phase 3: User Story 1 - Quick Funding Check (7 tasks)
- Phase 4: User Story 2 - Monitor Funding Changes (4 tasks)
- Phase 5: User Story 3 - Empty State (3 tasks)
- Phase 6: Polish & Testing (2 tasks)
Total Tasks: 23 Estimated Effort: 2-3 weeks (4-6 developer days with parallel execution) Test Coverage: All user stories have independent acceptance criteria
Phase 1: Research & Setup
Research & Investigation
- T001 Review
domain/Budget/Data/FundingStreamData.phpto confirm all required properties (availableAmount,externalId,colour,name) exist and are accessible - T002 [P] Review existing quarter determination logic in
domain/Budget/Http/Controllers/BudgetPlanController.php(lines 158-184) and identify best approach for code reuse (new service vs. direct call)
Success Criteria:
- Confirmed FundingStreamData has all needed properties
- Decision documented on quarter logic reuse approach
Phase 2: Backend Foundation
Data Transfer Objects (DTOs)
- T003 Create
domain/Budget/Data/PackageFundingSummaryData.phpwith properties:currentQuarterDisplay: ?string(e.g., “Q3 2025”)fundingStreams: Collection(of FundingStreamData)- Add factory method
fromBudgetPlan(?BudgetPlan)that returns null if no plan - Add appropriate type hints and docblocks
Success Criteria:
- DTO creates successfully with valid data
- Returns null when BudgetPlan is null
- Serializes correctly to JSON for Inertia response
Services & Actions
- T004 [P] Create
domain/Budget/Actions/GetCurrentQuarterForBudgetPlan.phpaction:- Accept:
BudgetPlanmodel, optional?Quarter $overrideQuarter - Logic: Implement quarter selection priority (URL param → current → package commencement → plan commencement)
- Return:
Quartermodel - Reference: Mirror logic from
BudgetPlanController::show()lines 161-184 - Add comprehensive docblock explaining quarter selection priority
- Accept:
Success Criteria:
-
Returns current quarter when available
-
Falls back to package commencement quarter
-
Handles all edge cases documented in plan.md
-
T005 [P] Create
domain/Budget/Actions/GetPackageFundingSummary.phpaction:- Accept:
Packagemodel - Logic:
- Get latest BudgetPlan for package (use
Package::with('budgetPlans')) - If no plan, return null
- Call GetCurrentQuarterForBudgetPlan for the plan
- Extract FundingStreamData for determined quarter
- Format quarter display string (e.g., “Q3 2025” or “July - September 2025”)
- Return PackageFundingSummaryData instance
- Get latest BudgetPlan for package (use
- Error handling: Gracefully handle missing funding data
- Add detailed docblock with examples
- Accept:
Success Criteria:
- Returns PackageFundingSummaryData when plan exists
- Returns null when no plan exists
- FundingStreamData matches Service Plan view exactly
Data Transfer Object Integration
- T006 Update
domain/Package/Data/PackageViewData.php:- Add property:
public ?PackageFundingSummaryData $fundingSummary = null; - Ensure property is included in DTO’s data casting/serialization
- Update class docblock to document new property
- Add property:
Success Criteria:
- Property serializes in Inertia response
- Can be accessed in Vue as
viewLayoutData.funding_summary - Maintains backward compatibility (optional property)
Service Layer Integration
- T007 [P] Update
domain/Package/Services/PackageService.phpingetTabData()method:- After fetching package data, call:
$packageViewData->fundingSummary = GetPackageFundingSummary::run($package); - Ensure this is called for ALL package view routes
- Add inline comment explaining why funding is populated here
- Test that funding data is populated for Overview, Care Circle, Service Plan, etc.
- After fetching package data, call:
Success Criteria:
- Funding summary populated in all package view contexts
- No additional database queries added
- Data available in viewLayoutData on all tabs
Phase 3: User Story 1 - Quick Funding Check During Service Planning
User Story Goal: Care coordinators see available funding for each stream in the package sidebar and immediately assess funding constraints while planning services without switching to the Service Plan tab
Test Criteria:
- Funding balances visible on every package tab (Overview, Care Circle, Needs, Risks, Service Plan, Notes, Bills, Statements, Claim History, Transactions, Contributions)
- Data matches Service Plan view’s funding information within same session
- Badges display in correct format: “[StreamCode] $[Amount]”
- Section displays below Recipient Information section
Vue Components
- T008 [US1] Create
resources/js/Components/Package/Sidebar/FundingStreamBalanceSidebar.vuecomponent:- Props:
fundingStreams?: FundingStreamData[]- Array of funding stream dataquarterDisplay?: string- Quarter info for tooltip (e.g., “Q3 2025”)
- Template structure:
- Section heading: “This Quarter’s Funding”
- Conditional render: If no fundingStreams, render empty state (handled in US3)
- If fundingStreams: Loop and render badges in 2-column grid
- Grid Layout:
- Use
grid grid-cols-2 gap-3for 2-column layout - Responsive:
md:grid-cols-2(2 cols on desktop) with fallback togrid-cols-1on mobile - Gap spacing:
gap-3orgap-4for consistent spacing
- Use
- Styling:
- Tailwind grid utilities for 2-column horizontal layout
- Support dark mode (inherit from parent sidebar)
- Accessibility:
- Use semantic HTML (section, div)
- aria-label for section
- Add docstring explaining component purpose
- Props:
Success Criteria:
-
Component renders 2-column grid layout (2 badges per row)
-
Grid wraps to 1 column on mobile screens
-
Each stream has accessible description/tooltip
-
Dark mode support verified
-
Responsive layout works on all screen sizes
-
T009 [P] [US1] Create individual badge rendering logic in
FundingStreamBalanceSidebar.vue:- For each funding stream in fundingStreams:
- Import and render existing
FundingStreamBadge.vuecomponent - Pass props:
externalId,colour - Add wrapper with:
- Badge display format: “[StreamCode] $[Amount]” (e.g., “ON $25,000”)
- Currency formatted to 2 decimal places using existing app formatter
- Tooltip content on hover showing:
- Full funding stream name (e.g., “Home support ongoing”)
- Quarter info (e.g., “Q3 2025: July - September 2025”)
- Additional context if needed
- Accessible title attribute with full description: “StreamName - Q3 2025 - $25,000”
- Style badge container to match design version B mockup
- Import and render existing
- For each funding stream in fundingStreams:
Success Criteria:
-
Each funding stream displays as colored badge with code + amount only (minimal display)
-
Tooltip shows full name + quarter range on hover
-
Amount properly formatted to 2 decimal places
-
Colors match FundingStreamBadge styling
-
Badge fits 2-column grid layout
-
T010 [P] [US1] Update
resources/js/Components/Package/Sidebar/PackageSidebar.vue:- Add import:
import FundingStreamBalanceSidebar from './FundingStreamBalanceSidebar.vue' - Add component to template:
- Position: After Recipient Information section
- Conditional render:
v-if="viewLayoutData.funding_summary?.fundingStreams" - Props:
:fundingStreams="viewLayoutData.funding_summary?.fundingStreams" :quarterDisplay="viewLayoutData.funding_summary?.quarterDisplay"
- Verify component displays on all package tabs
- Add comment explaining conditional render
- Add import:
Success Criteria:
- FundingStreamBalanceSidebar renders below Recipient Information
- Only renders when funding_summary data exists
- Data passed correctly to child component
- Works on all package tabs
Testing - User Story 1
- T011 [P] [US1] Create unit test file
tests/Unit/Budget/GetPackageFundingSummaryTest.php:- Test: Package with no budget plan returns null
- Test: Package with budget plan returns PackageFundingSummaryData with correct streams
- Test: Single funding stream displays correctly
- Test: Multiple funding streams (2-5) all included
- Test: Zero balance streams included
- Test: Negative balance streams included
- Test: Quarter display formatted correctly
Success Criteria:
-
All 7 test cases pass
-
Coverage >90% of GetPackageFundingSummary action
-
Edge cases validated
-
T012 [P] [US1] Create feature test file
tests/Feature/Package/PackageFundingSidebarTest.php:- Test: GET /packages/{package}/overview returns funding_summary in viewLayoutData
- Test: Funding amounts match Service Plan view exactly
- Test: Funding visible on Overview, Care Circle, Service Plan tabs
- Test: Coordinator can access funding data (authorization check)
- Test: Zero balances render without errors
Success Criteria:
-
All tab views return funding data in response
-
Funding matches Service Plan calculation
-
Authorization works correctly
-
No errors on edge cases
-
T013 [P] [US1] Create Vue component snapshot test for
FundingStreamBalanceSidebar.vue:- Snapshot: Component with 2 funding streams (ON, CM)
- Snapshot: Component with 1 funding stream (ON only)
- Snapshot: Component with many streams (8+)
- Verify: Vertical layout, spacing, badge format
- Verify: Tooltips and accessibility attributes present
Success Criteria:
-
Snapshot tests match expected layout
-
All accessibility attributes present
-
Mobile responsive verified
-
T014 [US1] Manual verification test - Create test script or manual checklist:
- Navigate to /packages/{package-id}/overview
- Verify funding section displays below Recipient Information
- Click on badge tooltip → full stream name displays
- Navigate to /packages/{package-id}/care-circle → funding still visible
- Navigate to /packages/{package-id}/service-plan → funding still visible
- Zoom to 200% → layout responsive, no overflow
- Open browser DevTools → no console errors
Success Criteria:
- All manual verification steps pass
- No visual regressions
- Responsive layout works
Phase 4: User Story 2 - Monitor Funding Changes After Budget Updates
User Story Goal: Care coordinators see funding balances update in the sidebar after modifying a budget, verifying funding allocations immediately without page refresh
Test Criteria:
- Funding balances reflect current active budget plan state
- Updates appear without page reload when navigating between tabs
- Balances match Service Plan view at all times
- If multiple budget plans exist, only current active plan’s data shows
Backend Updates for Dynamic Changes
- T015 [US2] Verify Inertia re-render behavior:
- Confirm that navigating between tabs triggers Inertia data refresh
- Confirm GetPackageFundingSummary is called on each tab navigation
- Verify funding data is NOT stale when switching tabs
- Add comment to GetPackageFundingSummary explaining when it’s called
- Document in plan.md that updates rely on Inertia re-renders (no polling needed)
Success Criteria:
- Tab navigation triggers fresh funding data fetch
- No stale data on concurrent tabs
- Behavior matches Service Plan tab update behavior
Testing - User Story 2
- T016 [P] [US2] Create feature test for funding updates:
- Setup: Create package with budget plan (ON: $100,000)
- Step 1: GET /packages/{package}/overview → assert funding shows $100,000
- Step 2: Programmatically update budget (reduce ON funding to $75,000)
- Step 3: GET /packages/{package}/care-circle → assert funding shows updated $75,000
- Step 4: Verify funding matches Service Plan view after update
- Test: Multiple updates in sequence
Success Criteria:
-
Funding updates reflected on tab navigation
-
No manual refresh required
-
Data consistency across tabs verified
-
T017 [P] [US2] Create browser/Vue lifecycle test (if using Vitest):
- Test: Component re-renders when fundingStreams prop changes
- Test: Tooltip content updates when stream name changes
- Test: Amount formatting updates when balance changes
- Test: No memory leaks or unnecessary re-renders
Success Criteria:
-
Component lifecycle handled correctly
-
No performance issues detected
-
Re-renders only when needed
-
T018 [P] [US2] Create performance test:
- Measure time to render FundingStreamBalanceSidebar with 1, 3, 8+ streams
- Verify page load time with funding data <500ms additional latency
- Verify no N+1 queries when loading funding data
- Profile Inertia re-render performance on tab change
Success Criteria:
- Component renders in <50ms (Vue standard)
- Page load <500ms (no regression)
- Single query for funding data (no N+1)
Phase 5: User Story 3 - Empty State When No Budget Plan Exists
User Story Goal: Care coordinators see clear indication when a package has no active funding, understanding if budget setup is required before service planning
Test Criteria:
- When package has no budget plan, funding section displays graceful empty state
- Section displays “No Funding Streams” message with subtle styling
- Sidebar displays other package metadata normally
- When budget is created, funding section appears automatically on next view
Empty State Component
- T019 [US3] Update
resources/js/Components/Package/Sidebar/FundingStreamBalanceSidebar.vueto handle empty state:- Conditional render:
- If
fundingStreamsis empty or falsy: Show empty state div - Else: Show badge collection
- If
- Empty state styling:
- Centered text: “No Funding Streams”
- Color: Muted gray (#6B7280 or similar, dark mode adjusted)
- Padding: Same as badge section for consistent spacing
- Font size: Slightly smaller than normal text (text-sm)
- Opacity: Subtle (opacity-70 or similar)
- Ensure section is still visible (not hidden) to indicate feature exists
- Add aria-label for accessibility: “No funding streams available”
- Conditional render:
Success Criteria:
- Empty state displays when fundingStreams is empty
- Styling is professional and non-error appearance
- Section container visible (not hidden)
- Accessible to screen readers
Testing - User Story 3
- T020 [P] [US3] Create feature test for empty state:
- Setup: Create package WITHOUT budget plan
- Test: GET /packages/{new-package}/overview → returns funding_summary as null or empty
- Verify: PackageSidebar component renders without errors
- Verify: FundingStreamBalanceSidebar shows empty state message
- Test: Later create budget → funding section appears on next view
Success Criteria:
-
Null/empty funding_summary handled gracefully
-
Component renders without JavaScript errors
-
Empty state message visible
-
Funding appears after budget creation
-
T021 [P] [US3] Create snapshot test for empty state:
- Snapshot: FundingStreamBalanceSidebar with no fundingStreams
- Verify: Empty state message present
- Verify: Section still renders (not hidden)
- Verify: Styling matches other empty states in app
Success Criteria:
-
Empty state snapshot matches design
-
Consistent with app’s empty state patterns
-
T022 [US3] Manual verification - Empty state appearance:
- Create new package (no budget plan)
- Navigate to /packages/{new-package}/overview
- Verify “No Funding Streams” message displays
- Verify message is centered and subtle (not error-like)
- Verify other sidebar sections display normally
- Create budget plan for package
- Refresh page → funding section now displays with streams
Success Criteria:
- Empty state appears as designed
- User understands feature exists but no budget
- Funding appears after budget creation
Phase 6: Polish & Testing
Code Quality
- T023 [P] Code formatting, linting, and final cleanup:
- Run
vendor/bin/pint --dirtyon all modified/new PHP files - Run
npm run lintorprettier --writeon all Vue/TypeScript files - Fix any ESLint violations
- Remove any console.log or debug statements
- Verify all imports are used (no unused imports)
- Add/update docblocks on all public methods
- Verify no commented-out code remains
- Run
Success Criteria:
-
All files pass linting
-
No code style violations
-
Clean, production-ready code
-
T024 [P] Final test suite execution and coverage:
- Run
php artisan test tests/Unit/Budget/→ All pass - Run
php artisan test tests/Feature/Package/PackageFundingSidebarTest.php→ All pass - Run full
php artisan test→ No regressions - Verify test coverage >80% for new code
- Generate coverage report if available
- Document any skipped or pending tests
- Run
Success Criteria:
- All tests pass
- No regressions in existing tests
- Coverage >80%
- Ready for merge/deployment
Dependency Graph
graph TD T001[T001: Research FundingStreamData] --> T002[T002: Research Quarter Logic] T002 --> T003[T003: Create PackageFundingSummaryData] T003 --> T004[T004: Create GetCurrentQuarterForBudgetPlan] T004 --> T005[T005: Create GetPackageFundingSummary] T005 --> T006[T006: Update PackageViewData] T006 --> T007[T007: Update PackageService]
T007 --> T008[T008: Create FundingStreamBalanceSidebar.vue] T007 --> T009[T009: Badge Rendering Logic] T009 --> T010[T010: Update PackageSidebar.vue]
T005 --> T011[T011: Unit Tests] T010 --> T012[T012: Feature Tests] T008 --> T013[T013: Vue Snapshot Tests] T013 --> T014[T014: Manual Verification]
T007 --> T015[T015: Verify Inertia Re-render] T015 --> T016[T016: Funding Update Tests] T016 --> T017[T017: Vue Lifecycle Tests] T017 --> T018[T018: Performance Tests]
T010 --> T019[T019: Empty State Component] T019 --> T020[T020: Empty State Feature Tests] T020 --> T021[T021: Empty State Snapshots] T021 --> T022[T022: Manual Empty State Verification]
T018 --> T023[T023: Code Formatting & Linting] T022 --> T023 T023 --> T024[T024: Final Test Execution]Parallel Execution Opportunities
Phase 2 (Backend Foundation):
- T002 (Research) can run in parallel with T001
- T004 (Quarter Action) can run in parallel with T003 (DTO)
- T005 (Summary Action) depends on T003 & T004, can start once both complete
- T006 (DTO Integration) can run in parallel with T005
- T007 (Service Integration) depends on T006, starts after T006 complete
Phase 3 (User Story 1):
- T008, T009, T011, T012, T013 can run in parallel once Phase 2 complete
- T010 depends on T009 (component logic)
- T014 is manual verification, runs after all automated tests pass
Phase 4 (User Story 2):
- T016, T017, T018 can run in parallel
- All depend on Phase 3 completion
Phase 5 (User Story 3):
- T020, T021, T022 can run in parallel
- All depend on T019 completion
Phase 6 (Polish):
- T023 can run in parallel with Phase 5
- T024 runs after T023 complete
Estimated Parallel Speedup: ~40% reduction in total time through parallel execution
Task Estimates & Effort
| Phase | Tasks | Estimated Effort | Notes |
|---|---|---|---|
| Phase 1 | 2 | 1-2 hours | Research only, no code changes |
| Phase 2 | 5 | 4-6 hours | Backend foundation, can parallelize T002-T007 |
| Phase 3 | 7 | 6-8 hours | Frontend component, most parallelizable |
| Phase 4 | 4 | 3-4 hours | Testing, mostly parallelizable |
| Phase 5 | 3 | 2-3 hours | Empty state, quick iteration |
| Phase 6 | 2 | 1-2 hours | Final polish and verification |
| Total | 23 | 17-25 hours | ~2-3 weeks (1 developer or 1 week with parallel) |
Suggested MVP Scope
Minimum Viable Product (Phase 1-3):
For a quick MVP release, implement:
- ✅ T001-T007 (Backend foundation)
- ✅ T008-T014 (User Story 1 - Quick Funding Check)
- ⏭️ Skip T015-T022 (User Story 2 & 3 can follow in Phase 2)
- ✅ T023-T024 (Code quality)
MVP Effort: ~10-12 hours (1-2 days) MVP Coverage: Core feature (funding visibility on sidebar) MVP Gaps: Dynamic updates after budget changes, elegant empty state (can ship as future improvements)
Success Metrics for Each User Story
User Story 1 Success
- ✅ Funding visible on all 11 package tabs
- ✅ Data matches Service Plan view exactly
- ✅ Component renders without errors
- ✅ All tests pass
- ✅ Manual verification checklist complete
User Story 2 Success
- ✅ Funding updates when navigating between tabs after budget change
- ✅ No stale data shown
- ✅ Performance <500ms page load
- ✅ Update tests pass
User Story 3 Success
- ✅ Empty state displays when no budget plan
- ✅ Message is professional (not error-like)
- ✅ Funding appears after budget creation
- ✅ Empty state tests pass
Next Steps
-
Review & Approve Tasks
- Review task breakdown for clarity and completeness
- Confirm effort estimates align with team capacity
- Identify any missing dependencies
-
Assign Tasks to Team
- Assign Phase 1 (Research) to one developer
- Assign Phase 2 (Backend) to one developer (parallel with next)
- Assign Phase 3 (Frontend) to one or two developers (parallelizable)
- Coordinate Phase 4-6 based on Phase 3 completion
-
Sync to Jira (if needed)
/trilogy.jira-syncCreates Jira stories and sub-tasks linked to epic TP-2501
-
Begin Implementation
- Start with T001-T002 (research)
- Create branches per phase or user story
- Use task IDs in commit messages for traceability
-
Track Progress
- Update task checkboxes as work completes
- Use
[TaskID]in commit messages - Regular syncs to track blockers
References
- Specification: spec.md
- Implementation Plan: plan.md
- Quality Checklist: checklists/spec-quality.md
- Epic: TP-2501 (Budget Reloaded)
- Initiative: TP-1869 (Budgets and Services)