1- import { useTranslation } from 'react-i18next'
2- import { DataView , Flex , EmptyData , ActionsLayout } from '@/components/Common'
1+ import { Trans , useTranslation } from 'react-i18next'
2+ import type { ContractorPaymentGroup } from '@gusto/embedded-api/models/components/contractorpaymentgroup'
3+ import type { Contractor } from '@gusto/embedded-api/models/components/contractor'
4+ import { getContractorDisplayName } from '../CreatePayment/helpers'
5+ import styles from './PaymentHistoryPresentation.module.scss'
6+ import { DataView , Flex , EmptyData } from '@/components/Common'
37import { useComponentContext } from '@/contexts/ComponentAdapter/useComponentContext'
48import { HamburgerMenu } from '@/components/Common/HamburgerMenu'
59import { useI18n } from '@/i18n'
6- import { formatNumberAsCurrency } from '@/helpers/formattedStrings'
7- import { useLocale } from '@/contexts/LocaleProvider/useLocale'
810import { formatHoursDisplay } from '@/components/Payroll/helpers'
9-
10- interface PaymentData {
11- id : string
12- name : string
13- wageType : string
14- paymentMethod : string
15- hours : number
16- wage : string
17- bonus : number
18- reimbursement : number
19- total : number
20- }
11+ import useNumberFormatter from '@/hooks/useNumberFormatter'
12+ import { useDateFormatter } from '@/hooks/useDateFormatter'
13+ import EyeIcon from '@/assets/icons/eye.svg?react'
14+ import CancelIcon from '@/assets/icons/slash-circle.svg?react'
2115
2216interface PaymentHistoryPresentationProps {
23- date : string
24- payments : PaymentData [ ]
25- onBack : ( ) => void
17+ paymentGroup : ContractorPaymentGroup
18+ contractors : Contractor [ ]
2619 onViewPayment : ( paymentId : string ) => void
2720 onCancelPayment : ( paymentId : string ) => void
2821}
2922
3023export const PaymentHistoryPresentation = ( {
31- date,
32- payments,
33- onBack,
24+ paymentGroup,
25+ contractors,
3426 onViewPayment,
3527 onCancelPayment,
3628} : PaymentHistoryPresentationProps ) => {
3729 const { Button, Text, Heading } = useComponentContext ( )
3830 useI18n ( 'Contractor.Payments.PaymentHistory' )
3931 const { t } = useTranslation ( 'Contractor.Payments.PaymentHistory' )
40- const { locale } = useLocale ( )
32+ const currencyFormatter = useNumberFormatter ( 'currency' )
33+ const { formatLongWithYear } = useDateFormatter ( )
34+
35+ const payments = paymentGroup . contractorPayments || [ ]
4136
4237 return (
4338 < Flex flexDirection = "column" gap = { 32 } >
4439 < Flex flexDirection = "column" gap = { 8 } >
4540 < Heading as = "h1" > { t ( 'title' ) } </ Heading >
46- < Text > { t ( 'subtitle' , { date } ) } </ Text >
41+ < Text >
42+ < Trans
43+ i18nKey = { 'subtitle' }
44+ t = { t }
45+ values = { { date : formatLongWithYear ( paymentGroup . debitDate ) } }
46+ components = { {
47+ strong : < Text weight = "bold" as = "span" /> ,
48+ } }
49+ />
50+ </ Text >
4751 </ Flex >
4852
4953 < Flex flexDirection = "column" gap = { 16 } >
5054 < Heading as = "h2" > { t ( 'paymentsSection' ) } </ Heading >
5155
5256 { payments . length === 0 ? (
53- < EmptyData title = { t ( 'noPaymentsFound' ) } description = { t ( 'noPaymentsDescription' ) } >
54- < ActionsLayout justifyContent = "center" >
55- < Button variant = "primary" onClick = { onBack } >
56- { t ( 'backButton' ) }
57- </ Button >
58- </ ActionsLayout >
59- </ EmptyData >
57+ < EmptyData title = { t ( 'noPaymentsFound' ) } description = { t ( 'noPaymentsDescription' ) } />
6058 ) : (
6159 < >
6260 < DataView
6361 columns = { [
6462 {
6563 title : t ( 'tableHeaders.contractor' ) ,
66- render : ( { name , id } ) => (
64+ render : ( { contractorUuid } ) => (
6765 < Button
6866 variant = "tertiary"
6967 onClick = { ( ) => {
70- onViewPayment ( id )
68+ onViewPayment ( contractorUuid ! )
7169 } }
7270 >
73- { name }
71+ { getContractorDisplayName (
72+ contractors . find ( contractor => contractor . uuid === contractorUuid ) ,
73+ ) }
7474 </ Button >
7575 ) ,
7676 } ,
@@ -84,7 +84,9 @@ export const PaymentHistoryPresentation = ({
8484 } ,
8585 {
8686 title : t ( 'tableHeaders.hours' ) ,
87- render : ( { hours } ) => < Text > { hours ? formatHoursDisplay ( hours ) : '–' } </ Text > ,
87+ render : ( { hours } ) => (
88+ < Text > { hours ? formatHoursDisplay ( Number ( hours ) ) : '–' } </ Text >
89+ ) ,
8890 } ,
8991 {
9092 title : t ( 'tableHeaders.wage' ) ,
@@ -93,51 +95,61 @@ export const PaymentHistoryPresentation = ({
9395 {
9496 title : t ( 'tableHeaders.bonus' ) ,
9597 render : ( { bonus } ) => (
96- < Text > { bonus ? formatNumberAsCurrency ( bonus , locale ) : '–' } </ Text >
98+ < Text > { bonus ? currencyFormatter ( Number ( bonus ) ) : '–' } </ Text >
9799 ) ,
98100 } ,
99101 {
100102 title : t ( 'tableHeaders.reimbursements' ) ,
101103 render : ( { reimbursement } ) => (
102- < Text > { formatNumberAsCurrency ( reimbursement , locale ) } </ Text >
104+ < Text > { reimbursement ? currencyFormatter ( Number ( reimbursement ) ) : '–' } </ Text >
103105 ) ,
104106 } ,
105107 {
106108 title : t ( 'tableHeaders.total' ) ,
107- render : ( { total } ) => < Text > { formatNumberAsCurrency ( total , locale ) } </ Text > ,
108- } ,
109- {
110- title : t ( 'tableHeaders.action' ) ,
111- render : ( { id, name } ) => (
112- < HamburgerMenu
113- items = { [
114- {
115- label : t ( 'actions.view' ) ,
116- onClick : ( ) => {
117- onViewPayment ( id )
118- } ,
119- } ,
120- {
121- label : t ( 'actions.cancel' ) ,
122- onClick : ( ) => {
123- onCancelPayment ( id )
124- } ,
125- } ,
126- ] }
127- triggerLabel = { t ( 'tableHeaders.action' ) }
128- />
109+ render : ( { wageTotal, reimbursement, bonus } ) => (
110+ < Text >
111+ { wageTotal
112+ ? currencyFormatter (
113+ Number ( wageTotal ) + Number ( reimbursement ) + Number ( bonus ) ,
114+ )
115+ : '–' }
116+ </ Text >
129117 ) ,
130118 } ,
131119 ] }
120+ itemMenu = { ( { contractorUuid, mayCancel } ) => {
121+ const items = [
122+ {
123+ label : t ( 'actions.view' ) ,
124+ onClick : ( ) => {
125+ onViewPayment ( contractorUuid ! )
126+ } ,
127+ icon : (
128+ < span className = { styles . icon } >
129+ < EyeIcon aria-hidden />
130+ </ span >
131+ ) ,
132+ } ,
133+ ]
134+
135+ if ( mayCancel ) {
136+ items . push ( {
137+ label : t ( 'actions.cancel' ) ,
138+ onClick : ( ) => {
139+ onCancelPayment ( contractorUuid ! )
140+ } ,
141+ icon : (
142+ < span className = { styles . icon } >
143+ < CancelIcon aria-hidden />
144+ </ span >
145+ ) ,
146+ } )
147+ }
148+ return < HamburgerMenu items = { items } triggerLabel = { t ( 'tableHeaders.action' ) } />
149+ } }
132150 data = { payments }
133151 label = { t ( 'title' ) }
134152 />
135-
136- < Flex >
137- < Button onClick = { onBack } variant = "secondary" >
138- { t ( 'backButton' ) }
139- </ Button >
140- </ Flex >
141153 </ >
142154 ) }
143155 </ Flex >
0 commit comments