diff --git a/src/components/Contractor/Payments/Detail/Detail.stories.tsx b/src/components/Contractor/Payments/Detail/Detail.stories.tsx
new file mode 100644
index 00000000..bd2c26e0
--- /dev/null
+++ b/src/components/Contractor/Payments/Detail/Detail.stories.tsx
@@ -0,0 +1,64 @@
+import type { StoryDefault, Story } from '@ladle/react'
+import { action } from '@ladle/react'
+import { DetailPresentation } from './DetailPresentation'
+
+export default {
+ title: 'Domain/Contractor/Payments',
+} satisfies StoryDefault
+
+export const PaymentDetailDefault: Story = () => {
+ const mockPayments = [
+ {
+ id: '1',
+ name: 'Fitzgerald, Ella',
+ hours: 10.0,
+ wage: 0,
+ bonus: 0,
+ reimbursement: 0,
+ paymentMethod: 'Direct Deposit',
+ total: 180,
+ },
+ {
+ id: '2',
+ name: 'Armstrong, Louis',
+ hours: 0,
+ wage: 1000,
+ bonus: 0,
+ reimbursement: 0,
+ paymentMethod: 'Direct Deposit',
+ total: 1000,
+ },
+ ]
+
+ return (
+
+ )
+}
+
+PaymentDetailDefault.meta = {
+ description:
+ 'Payment Statement Detail showing detailed payment breakdown for a specific date with all contractors and payment components',
+}
+
+export const PaymentDetailEmpty: Story = () => {
+ return (
+
+ )
+}
+
+PaymentDetailEmpty.meta = {
+ description:
+ 'Payment Statement Detail with no payments on the selected date - displays empty state',
+}
diff --git a/src/components/Contractor/Payments/Detail/DetailPresentation.tsx b/src/components/Contractor/Payments/Detail/DetailPresentation.tsx
new file mode 100644
index 00000000..8864f924
--- /dev/null
+++ b/src/components/Contractor/Payments/Detail/DetailPresentation.tsx
@@ -0,0 +1,136 @@
+import { useTranslation } from 'react-i18next'
+import { DataView, Flex, EmptyData, ActionsLayout } from '@/components/Common'
+import { useComponentContext } from '@/contexts/ComponentAdapter/useComponentContext'
+import { HamburgerMenu } from '@/components/Common/HamburgerMenu'
+import { useI18n } from '@/i18n'
+import { formatNumberAsCurrency } from '@/helpers/formattedStrings'
+import { useLocale } from '@/contexts/LocaleProvider/useLocale'
+import { formatHoursDisplay } from '@/components/Payroll/helpers'
+
+interface PaymentData {
+ id: string
+ name: string
+ hours: number
+ wage: number
+ bonus: number
+ reimbursement: number
+ paymentMethod: string
+ total: number
+}
+
+interface ContractorPaymentDetailPresentationProps {
+ date: string
+ payments: PaymentData[]
+ onBack: () => void
+ onViewPayment: (paymentId: string) => void
+ onCancelPayment: (paymentId: string) => void
+}
+
+export const DetailPresentation = ({
+ date,
+ payments,
+ onBack,
+ onViewPayment,
+ onCancelPayment,
+}: ContractorPaymentDetailPresentationProps) => {
+ const { Button, Text, Heading } = useComponentContext()
+ useI18n('ContractorPayment.ContractorPaymentDetail')
+ const { t } = useTranslation('ContractorPayment.ContractorPaymentDetail')
+ const { locale } = useLocale()
+
+ return (
+
+ {t('title')}
+
+
+ {t('paymentsOnDateTitle', { date })}
+
+ {payments.length === 0 ? (
+
+
+
+
+
+ ) : (
+ <>
+ (
+
+ ),
+ },
+ {
+ title: t('tableHeaders.hours'),
+ render: ({ hours }) => {formatHoursDisplay(hours)},
+ },
+ {
+ title: t('tableHeaders.wage'),
+ render: ({ wage }) => {formatNumberAsCurrency(wage, locale)},
+ },
+ {
+ title: t('tableHeaders.bonus'),
+ render: ({ bonus }) => {formatNumberAsCurrency(bonus, locale)},
+ },
+ {
+ title: t('tableHeaders.reimbursement'),
+ render: ({ reimbursement }) => (
+ {formatNumberAsCurrency(reimbursement, locale)}
+ ),
+ },
+ {
+ title: t('tableHeaders.paymentMethod'),
+ render: ({ paymentMethod }) => {paymentMethod},
+ },
+ {
+ title: t('tableHeaders.total'),
+ render: ({ total }) => {formatNumberAsCurrency(total, locale)},
+ },
+ {
+ title: t('tableHeaders.action'),
+ render: ({ id, name }) => (
+ {
+ onViewPayment(id)
+ },
+ },
+ {
+ label: t('actions.cancel'),
+ onClick: () => {
+ onCancelPayment(id)
+ },
+ },
+ ]}
+ triggerLabel={t('tableHeaders.action')}
+ />
+ ),
+ },
+ ]}
+ data={payments}
+ label={t('title')}
+ />
+
+
+
+
+ >
+ )}
+
+
+ )
+}
diff --git a/src/components/Contractor/Payments/types.ts b/src/components/Contractor/Payments/types.ts
new file mode 100644
index 00000000..0001212a
--- /dev/null
+++ b/src/components/Contractor/Payments/types.ts
@@ -0,0 +1,7 @@
+import type { ContractorPaymentGroup } from '@gusto/embedded-api/models/components/contractorpaymentgroup'
+import type { ContractorPaymentForGroup } from '@gusto/embedded-api/models/components/contractorpaymentforgroup'
+import type { ContractorPaymentGroupTotals } from '@gusto/embedded-api/models/components/contractorpaymentgroup'
+
+export type { ContractorPaymentGroup, ContractorPaymentForGroup, ContractorPaymentGroupTotals }
+
+export type ContractorPaymentGroupMinimal = Omit
diff --git a/src/i18n/en/ContractorPayment.ContractorPaymentDetail.json b/src/i18n/en/ContractorPayment.ContractorPaymentDetail.json
new file mode 100644
index 00000000..3fd4dd9e
--- /dev/null
+++ b/src/i18n/en/ContractorPayment.ContractorPaymentDetail.json
@@ -0,0 +1,27 @@
+{
+ "title": "Contractor payment history",
+ "paymentsOnDateTitle": "Payments done on {{date}}",
+ "noPaymentsFound": "No payments found",
+ "noPaymentsDescription": "No payments were found for this date",
+ "tableHeaders": {
+ "contractor": "Contractor",
+ "hours": "Hours",
+ "wage": "Wage",
+ "bonus": "Bonus",
+ "reimbursement": "Reimbursement",
+ "paymentMethod": "Payment method",
+ "total": "Total",
+ "action": "Action"
+ },
+ "actions": {
+ "view": "View",
+ "cancel": "Cancel"
+ },
+ "cancelConfirmation": "Canceling a contractor payment cannot be undone. A new payment will have to be created if you want to pay this contractor. Are you sure?",
+ "backButton": "Back",
+ "paymentMethods": {
+ "directDeposit": "Direct Deposit",
+ "check": "Check",
+ "historicalPayment": "Historical Payment"
+ }
+}
diff --git a/src/types/i18next.d.ts b/src/types/i18next.d.ts
index 71b78285..8fe6737c 100644
--- a/src/types/i18next.d.ts
+++ b/src/types/i18next.d.ts
@@ -513,6 +513,33 @@ export interface ContractorSubmit{
"successMessage":string;
};
};
+export interface ContractorPaymentContractorPaymentDetail{
+"title":string;
+"paymentsOnDateTitle":string;
+"noPaymentsFound":string;
+"noPaymentsDescription":string;
+"tableHeaders":{
+"contractor":string;
+"hours":string;
+"wage":string;
+"bonus":string;
+"reimbursement":string;
+"paymentMethod":string;
+"total":string;
+"action":string;
+};
+"actions":{
+"view":string;
+"cancel":string;
+};
+"cancelConfirmation":string;
+"backButton":string;
+"paymentMethods":{
+"directDeposit":string;
+"check":string;
+"historicalPayment":string;
+};
+};
export interface EmployeeBankAccount{
"accountNumberLabel":string;
"accountTypeChecking":string;
@@ -1608,6 +1635,6 @@ export interface common{
interface CustomTypeOptions {
defaultNS: 'common';
- resources: { 'Company.AddBank': CompanyAddBank, 'Company.Addresses': CompanyAddresses, 'Company.AssignSignatory': CompanyAssignSignatory, 'Company.BankAccount': CompanyBankAccount, 'Company.DocumentList': CompanyDocumentList, 'Company.FederalTaxes': CompanyFederalTaxes, 'Company.Industry': CompanyIndustry, 'Company.Locations': CompanyLocations, 'Company.OnboardingOverview': CompanyOnboardingOverview, 'Company.PaySchedule': CompanyPaySchedule, 'Company.SignatureForm': CompanySignatureForm, 'Company.StateTaxes': CompanyStateTaxes, 'Contractor.Address': ContractorAddress, 'Contractor.ContractorList': ContractorContractorList, 'Contractor.NewHireReport': ContractorNewHireReport, 'Contractor.PaymentMethod': ContractorPaymentMethod, 'Contractor.Profile': ContractorProfile, 'Contractor.Submit': ContractorSubmit, 'Employee.BankAccount': EmployeeBankAccount, 'Employee.Compensation': EmployeeCompensation, 'Employee.Deductions': EmployeeDeductions, 'Employee.DocumentSigner': EmployeeDocumentSigner, 'Employee.EmployeeList': EmployeeEmployeeList, 'Employee.FederalTaxes': EmployeeFederalTaxes, 'Employee.HomeAddress': EmployeeHomeAddress, 'Employee.Landing': EmployeeLanding, 'Employee.OnboardingSummary': EmployeeOnboardingSummary, 'Employee.PaySchedules': EmployeePaySchedules, 'Employee.PaymentMethod': EmployeePaymentMethod, 'Employee.Profile': EmployeeProfile, 'Employee.SplitPaycheck': EmployeeSplitPaycheck, 'Employee.StateTaxes': EmployeeStateTaxes, 'Employee.Taxes': EmployeeTaxes, 'Payroll.PayrollBlocker': PayrollPayrollBlocker, 'Payroll.PayrollConfiguration': PayrollPayrollConfiguration, 'Payroll.PayrollEditEmployee': PayrollPayrollEditEmployee, 'Payroll.PayrollFlow': PayrollPayrollFlow, 'Payroll.PayrollHistory': PayrollPayrollHistory, 'Payroll.PayrollLanding': PayrollPayrollLanding, 'Payroll.PayrollList': PayrollPayrollList, 'Payroll.PayrollOverview': PayrollPayrollOverview, 'Payroll.PayrollReceipts': PayrollPayrollReceipts, 'Payroll.PayrollSchedule': PayrollPayrollSchedule, 'common': common, }
+ resources: { 'Company.AddBank': CompanyAddBank, 'Company.Addresses': CompanyAddresses, 'Company.AssignSignatory': CompanyAssignSignatory, 'Company.BankAccount': CompanyBankAccount, 'Company.DocumentList': CompanyDocumentList, 'Company.FederalTaxes': CompanyFederalTaxes, 'Company.Industry': CompanyIndustry, 'Company.Locations': CompanyLocations, 'Company.OnboardingOverview': CompanyOnboardingOverview, 'Company.PaySchedule': CompanyPaySchedule, 'Company.SignatureForm': CompanySignatureForm, 'Company.StateTaxes': CompanyStateTaxes, 'Contractor.Address': ContractorAddress, 'Contractor.ContractorList': ContractorContractorList, 'Contractor.NewHireReport': ContractorNewHireReport, 'Contractor.PaymentMethod': ContractorPaymentMethod, 'Contractor.Profile': ContractorProfile, 'Contractor.Submit': ContractorSubmit, 'ContractorPayment.ContractorPaymentDetail': ContractorPaymentContractorPaymentDetail, 'Employee.BankAccount': EmployeeBankAccount, 'Employee.Compensation': EmployeeCompensation, 'Employee.Deductions': EmployeeDeductions, 'Employee.DocumentSigner': EmployeeDocumentSigner, 'Employee.EmployeeList': EmployeeEmployeeList, 'Employee.FederalTaxes': EmployeeFederalTaxes, 'Employee.HomeAddress': EmployeeHomeAddress, 'Employee.Landing': EmployeeLanding, 'Employee.OnboardingSummary': EmployeeOnboardingSummary, 'Employee.PaySchedules': EmployeePaySchedules, 'Employee.PaymentMethod': EmployeePaymentMethod, 'Employee.Profile': EmployeeProfile, 'Employee.SplitPaycheck': EmployeeSplitPaycheck, 'Employee.StateTaxes': EmployeeStateTaxes, 'Employee.Taxes': EmployeeTaxes, 'Payroll.PayrollBlocker': PayrollPayrollBlocker, 'Payroll.PayrollConfiguration': PayrollPayrollConfiguration, 'Payroll.PayrollEditEmployee': PayrollPayrollEditEmployee, 'Payroll.PayrollFlow': PayrollPayrollFlow, 'Payroll.PayrollHistory': PayrollPayrollHistory, 'Payroll.PayrollLanding': PayrollPayrollLanding, 'Payroll.PayrollList': PayrollPayrollList, 'Payroll.PayrollOverview': PayrollPayrollOverview, 'Payroll.PayrollReceipts': PayrollPayrollReceipts, 'Payroll.PayrollSchedule': PayrollPayrollSchedule, 'common': common, }
};
}
\ No newline at end of file