-
Notifications
You must be signed in to change notification settings - Fork 1
Fix PayrollListPresentation type issues after cherry-pick #586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Add PayrollLanding component with RunPayroll and PayrollHistory tabs - Fix TypeScript interface to include resource key generic - Add comprehensive unit tests focused on component orchestration - Add translation support with Payroll.PayrollLanding namespace - Fix ESLint import order in PayrollHistory.stories.tsx - Fix failing test in PayrollHistoryPresentation with waitFor - Add demo story for PayrollLanding (uses presentation components directly) - Update PayrollLanding to use proper BaseComponentInterface typing
<Flex flexDirection="column" alignItems="center" gap={24}> | ||
<div className={styles.doneIcon}>✓</div> | ||
<Text>{t('emptyState')}</Text> | ||
<Flex flexDirection="column" gap={16}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrapped this in the same flex layout I've been using in Payroll History for consistent spacing
@@ -0,0 +1,18 @@ | |||
import { I18nextProvider } from 'react-i18next' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seemed like the best way to bring app i18n context to a story that had compound i18n dictionaries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we can set this on all stories? i thought we already had that configured somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a centralized Payroll Landing component that consolidates the Payroll History and Run Payroll flows into a tabbed navigation interface. It also fixes type safety issues in the PayrollListPresentation
component where nullable date fields from the embedded API model were being passed to functions expecting non-null strings.
- Centralizes payroll flows into a new tabbed interface structure
- Resolves type errors by adding null checks before date parsing operations
- Updates component exports and entry points to use the new landing component
Reviewed Changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
File | Description |
---|---|
src/i18n/en/Payroll.PayrollList.json | Adds "title" translation for upcoming payroll section |
src/i18n/en/Payroll.PayrollLanding.json | New translation file for tab labels and accessibility text |
src/components/Payroll/index.ts | Exports the new PayrollLanding component |
src/components/Payroll/RunPayrollFlow/RunPayrollFlow.tsx | Simplifies to use PayrollLanding instead of direct RunPayroll |
src/components/Payroll/PayrollList/PayrollListPresentation.tsx | Fixes type safety with null checks for date parsing |
src/components/Payroll/PayrollLanding/PayrollLanding.tsx | New tabbed interface component for payroll flows |
src/components/Payroll/PayrollLanding/PayrollLanding.test.tsx | Comprehensive test coverage for the new component |
src/components/Payroll/PayrollLanding/PayrollLanding.stories.tsx | Storybook implementation for design system integration |
src/components/Payroll/PayrollHistory/PayrollHistoryPresentation.tsx | Minor layout alignment adjustment |
src/components/Payroll/PayrollHistory/PayrollHistory.stories.tsx | Adds I18n wrapper for proper localization |
.ladle/helpers/I18nWrapper.tsx | New helper component for storybook internationalization |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good! biggest thing is replacing RunPayroll
in PayrollLanding
with the PayrollList
component and then replacing PayrollList
in RunPayroll
with the PayrollLanding
component
@@ -0,0 +1,18 @@ | |||
import { I18nextProvider } from 'react-i18next' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we can set this on all stories? i thought we already had that configured somewhere?
const PayrollLandingStoryContent = () => { | ||
const [selectedTab, setSelectedTab] = useState('run-payroll') | ||
const { Tabs } = useComponentContext() | ||
|
||
const tabs = [ | ||
{ | ||
id: 'run-payroll', | ||
label: 'Run payroll', | ||
content: ( | ||
<PayrollListPresentation | ||
payrolls={mockPayrolls} | ||
paySchedules={mockPaySchedules} | ||
onRunPayroll={action('onRunPayroll')} | ||
/> | ||
), | ||
}, | ||
{ | ||
id: 'payroll-history', | ||
label: 'Payroll history', | ||
content: ( | ||
<PayrollHistoryPresentation | ||
payrollHistory={mockPayrollHistory} | ||
selectedTimeFilter="3months" | ||
onTimeFilterChange={action('onTimeFilterChange')} | ||
onViewSummary={action('onViewSummary')} | ||
onViewReceipt={action('onViewReceipt')} | ||
onCancelPayroll={action('onCancelPayroll')} | ||
/> | ||
), | ||
}, | ||
] | ||
|
||
return ( | ||
<Tabs | ||
tabs={tabs} | ||
selectedId={selectedTab} | ||
onSelectionChange={setSelectedTab} | ||
aria-label="Payroll navigation" | ||
/> | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this should actually be importing the PayrollLanding
component instead of recreating the tabs here?
// Mock the child components | ||
vi.mock('../RunPayrollFlow/RunPayroll', () => ({ | ||
RunPayroll: ({ | ||
companyId, | ||
onEvent, | ||
}: { | ||
companyId: string | ||
onEvent: (event: string, payload: unknown) => void | ||
}) => ( | ||
<div data-testid="run-payroll"> | ||
<h2>Run Payroll</h2> | ||
<p>Company ID: {companyId}</p> | ||
<button | ||
onClick={() => { | ||
onEvent('test-event', {}) | ||
}} | ||
> | ||
Test Event | ||
</button> | ||
</div> | ||
), | ||
})) | ||
|
||
vi.mock('../PayrollHistory/PayrollHistory', () => ({ | ||
PayrollHistory: ({ | ||
companyId, | ||
onEvent, | ||
}: { | ||
companyId: string | ||
onEvent: (event: string, payload: unknown) => void | ||
}) => ( | ||
<div data-testid="payroll-history"> | ||
<h2>Payroll History</h2> | ||
<p>Company ID: {companyId}</p> | ||
<button | ||
onClick={() => { | ||
onEvent('test-event', {}) | ||
}} | ||
> | ||
Test Event | ||
</button> | ||
</div> | ||
), | ||
})) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it preferable to mock these? i wonder if it would be more aligned with our testing approach to configure the test fixtures so they could get mocked with msw
describe('internationalization', () => { | ||
it('uses correct translation keys for tab labels', async () => { | ||
renderWithProviders(<PayrollLanding {...defaultProps} />) | ||
|
||
await waitFor(() => { | ||
expect(screen.getByTestId('run-payroll')).toBeInTheDocument() | ||
}) | ||
|
||
// Check that translated tab labels are used | ||
expect(screen.getByRole('tab', { name: 'Run payroll' })).toBeInTheDocument() | ||
expect(screen.getByRole('tab', { name: 'Payroll history' })).toBeInTheDocument() | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this kinda gets tested implicitly already with the above since we query by these to select the tabs
<RunPayroll | ||
companyId={companyId} | ||
Configuration={PayrollConfiguration} | ||
List={PayrollList} | ||
Overview={PayrollOverview} | ||
EditEmployee={PayrollEditEmployee} | ||
onEvent={onEvent} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to cause an issue where the entire payroll experience is in a single tab. We actually just want to render PayrollList
for the content here.
Then, we would update the RunPayroll component to use this PayrollLanding
component instead. This will emit events to RunPayroll which can manage transitions between the blocks
Summary
Introduces a Payroll Landing component that centralizes Payroll History and Run Payroll flows inside tabbed navigation.
Also resolves type errors in the
PayrollListPresentation
component.These errors occurred because the embedded API model now exposes nullable date fields, but
parseDateStringToLocal
expects string parameters.Changes
Screenshots