Skip to content

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.php to 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.php with 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.php action:
    • Accept: BudgetPlan model, optional ?Quarter $overrideQuarter
    • Logic: Implement quarter selection priority (URL param → current → package commencement → plan commencement)
    • Return: Quarter model
    • Reference: Mirror logic from BudgetPlanController::show() lines 161-184
    • Add comprehensive docblock explaining quarter selection priority

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.php action:

    • Accept: Package model
    • Logic:
      1. Get latest BudgetPlan for package (use Package::with('budgetPlans'))
      2. If no plan, return null
      3. Call GetCurrentQuarterForBudgetPlan for the plan
      4. Extract FundingStreamData for determined quarter
      5. Format quarter display string (e.g., “Q3 2025” or “July - September 2025”)
      6. Return PackageFundingSummaryData instance
    • Error handling: Gracefully handle missing funding data
    • Add detailed docblock with examples

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

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.php in getTabData() 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.

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.vue component:
    • Props:
      • fundingStreams?: FundingStreamData[] - Array of funding stream data
      • quarterDisplay?: 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-3 for 2-column layout
      • Responsive: md:grid-cols-2 (2 cols on desktop) with fallback to grid-cols-1 on mobile
      • Gap spacing: gap-3 or gap-4 for consistent spacing
    • 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

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.vue component
      • 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

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

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.vue to handle empty state:
    • Conditional render:
      • If fundingStreams is empty or falsy: Show empty state div
      • Else: Show badge collection
    • 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”

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 --dirty on all modified/new PHP files
    • Run npm run lint or prettier --write on 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

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

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

PhaseTasksEstimated EffortNotes
Phase 121-2 hoursResearch only, no code changes
Phase 254-6 hoursBackend foundation, can parallelize T002-T007
Phase 376-8 hoursFrontend component, most parallelizable
Phase 443-4 hoursTesting, mostly parallelizable
Phase 532-3 hoursEmpty state, quick iteration
Phase 621-2 hoursFinal polish and verification
Total2317-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

  1. Review & Approve Tasks

    • Review task breakdown for clarity and completeness
    • Confirm effort estimates align with team capacity
    • Identify any missing dependencies
  2. 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
  3. Sync to Jira (if needed)

    /trilogy.jira-sync

    Creates Jira stories and sub-tasks linked to epic TP-2501

  4. Begin Implementation

    • Start with T001-T002 (research)
    • Create branches per phase or user story
    • Use task IDs in commit messages for traceability
  5. Track Progress

    • Update task checkboxes as work completes
    • Use [TaskID] in commit messages
    • Regular syncs to track blockers

References