Skip to content

Commit

Permalink
Add Edit customer information page
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenlago99 committed Oct 8, 2024
1 parent 99fa5c1 commit 2eb6724
Show file tree
Hide file tree
Showing 10 changed files with 481 additions and 234 deletions.
4 changes: 3 additions & 1 deletion src/components/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ import { Icon } from './designSystem'
import { TextInput } from './form'

interface SearchInputProps {
className?: string
onChange: ReturnType<UseDebouncedSearch>['debouncedSearch']
placeholder?: string
}

export const SearchInput = ({ onChange, placeholder }: SearchInputProps) => {
export const SearchInput = ({ className, onChange, placeholder }: SearchInputProps) => {
const [localValue, setLocalValue] = useState<string>('')

return (
<TextInputForSearch
className={className}
placeholder={placeholder}
value={localValue}
onChange={(value) => {
Expand Down
32 changes: 17 additions & 15 deletions src/components/customerPortal/PortalCustomerInfos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import { gql } from '@apollo/client'
import { memo } from 'react'
import styled from 'styled-components'

import SectionContainer from '~/components/customerPortal/common/SectionContainer'
import SectionTitle from '~/components/customerPortal/common/SectionTitle'
import { Skeleton, Typography } from '~/components/designSystem'
import { CountryCodes } from '~/core/constants/countryCodes'
import { useGetPortalCustomerInfosQuery } from '~/generated/graphql'
import { useInternationalization } from '~/hooks/core/useInternationalization'
import { NAV_HEIGHT, theme } from '~/styles'

gql`
Expand All @@ -27,16 +30,22 @@ gql`
`

interface PortalCustomerInfosProps {
translate: Function
viewEditInformation: () => void
}

export const PortalCustomerInfos = memo(({ translate }: PortalCustomerInfosProps) => {
const PortalCustomerInfos = ({ viewEditInformation }: PortalCustomerInfosProps) => {
const { translate } = useInternationalization()

const { data, loading } = useGetPortalCustomerInfosQuery()
const customerPortalUser = data?.customerPortalUser

return (
<section>
<Title variant="subhead">{translate('text_6419c64eace749372fc72b07')}</Title>
<SectionContainer>
<SectionTitle
title={translate('text_6419c64eace749372fc72b07')}
className="justify-between"
action={{ title: translate('TODO: Edit information'), onClick: viewEditInformation }}
/>
<InfosContainer>
{loading ? (
<InfoSkeletonContainer>
Expand Down Expand Up @@ -152,11 +161,11 @@ export const PortalCustomerInfos = memo(({ translate }: PortalCustomerInfosProps
</>
)}
</InfosContainer>
</section>
</SectionContainer>
)
})
}

PortalCustomerInfos.displayName = 'PortalCustomerInfos'
export default PortalCustomerInfos

const InfoSkeletonContainer = styled.div`
display: flex;
Expand All @@ -171,14 +180,6 @@ const InfoSkeletonLine = styled.div`
}
`

const Title = styled(Typography)`
display: flex;
align-items: center;
height: 40px;
box-shadow: ${theme.shadows[7]};
margin-bottom: ${theme.spacing(6)};
`

const InfosContainer = styled.section`
display: flex;
column-gap: ${theme.spacing(8)};
Expand All @@ -194,6 +195,7 @@ const InfosContainer = styled.section`

const InfoLine = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
margin-bottom: ${theme.spacing(2)};
Expand Down
144 changes: 128 additions & 16 deletions src/components/customerPortal/PortalInvoicesList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { gql } from '@apollo/client'
import { Stack } from '@mui/material'
import { DateTime } from 'luxon'
import { useEffect } from 'react'
import styled, { css } from 'styled-components'

import SectionContainer from '~/components/customerPortal/common/SectionContainer'
import SectionTitle from '~/components/customerPortal/common/SectionTitle'
import {
Button,
InfiniteScroll,
Expand All @@ -12,6 +16,7 @@ import {
Tooltip,
Typography,
} from '~/components/designSystem'
import { OverviewCard } from '~/components/OverviewCard'
import { SearchInput } from '~/components/SearchInput'
import { addToast } from '~/core/apolloClient'
import { intlFormatNumber } from '~/core/formats/intlFormatNumber'
Expand All @@ -26,6 +31,9 @@ import {
PortalInvoiceListItemFragmentDoc,
useCustomerPortalInvoicesLazyQuery,
useDownloadCustomerPortalInvoiceMutation,
useGetCustomerPortalInvoicesCollectionLazyQuery,
useGetCustomerPortalOverdueBalancesLazyQuery,
useGetCustomerPortalUserCurrencyQuery,
} from '~/generated/graphql'
import { useDebouncedSearch } from '~/hooks/useDebouncedSearch'
import { NAV_HEIGHT, theme } from '~/styles'
Expand Down Expand Up @@ -68,11 +76,43 @@ gql`
}
}
query getCustomerPortalInvoicesCollection($expireCache: Boolean) {
customerPortalInvoiceCollections(expireCache: $expireCache) {
collection {
amountCents
invoicesCount
currency
}
}
}
query getCustomerPortalOverdueBalances($expireCache: Boolean) {
customerPortalOverdueBalances(expireCache: $expireCache) {
collection {
amountCents
currency
lagoInvoiceIds
}
}
}
query getCustomerPortalUserCurrency {
customerPortalUser {
currency
}
}
${PortalInvoiceListItemFragmentDoc}
${InvoiceForFinalizeInvoiceFragmentDoc}
${InvoiceForUpdateInvoicePaymentStatusFragmentDoc}
`

interface CalculatedData {
amount: number
count: number
currency?: CurrencyEnum
}

const mapStatusConfig = ({
paymentStatus,
paymentOverdue,
Expand Down Expand Up @@ -114,6 +154,47 @@ const PortalInvoicesList = ({ translate, documentLocale }: PortalCustomerInvoice
},
})

const { data: userCurrencyData } = useGetCustomerPortalUserCurrencyQuery()
const [getOverdueBalance, { data: overdueData, loading: overdueLoading }] =
useGetCustomerPortalOverdueBalancesLazyQuery()
const [getInvoicesCollection, { data: invoicesData, loading: invoicesLoading }] =
useGetCustomerPortalInvoicesCollectionLazyQuery()

useEffect(() => {
getOverdueBalance()
getInvoicesCollection()

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

const customerCurrency = userCurrencyData?.customerPortalUser?.currency ?? CurrencyEnum.Usd

const overdue = (
overdueData?.customerPortalOverdueBalances?.collection || []
).reduce<CalculatedData>(
(acc, item) => {
return {
amount: acc.amount + deserializeAmount(item.amountCents, item.currency),
count: acc.count + item.lagoInvoiceIds.length,
currency: item.currency,
}
},
{ amount: 0, count: 0, currency: customerCurrency },
)

const invoices = (
invoicesData?.customerPortalInvoiceCollections?.collection || []
).reduce<CalculatedData>(
(acc, item) => {
return {
amount: acc.amount + deserializeAmount(item.amountCents, item.currency ?? customerCurrency),
count: acc.count + Number(item.invoicesCount),
currency: item.currency ?? acc.currency,
}
},
{ amount: 0, count: 0, currency: customerCurrency },
)

const [downloadInvoice] = useDownloadCustomerPortalInvoiceMutation({
onCompleted(localData) {
const fileUrl = localData?.downloadCustomerPortalInvoice?.fileUrl
Expand Down Expand Up @@ -145,21 +226,52 @@ const PortalInvoicesList = ({ translate, documentLocale }: PortalCustomerInvoice
const hasNoInvoices = !loading && !error && !metadata?.totalCount && !hasSearchTerm

return (
<section>
<PageHeader $isEmpty={hasNoInvoices}>
<Typography variant="subhead" color="grey700">
{translate('text_6419c64eace749372fc72b37')}
</Typography>

{!hasNoInvoices && (
<HeaderRigthBlock>
<SearchInput
onChange={debouncedSearch}
placeholder={translate('text_6419c64eace749372fc72b33')}
/>
</HeaderRigthBlock>
)}
</PageHeader>
<SectionContainer>
<SectionTitle title={translate('text_6419c64eace749372fc72b37')} />

<Stack gap={4}>
<Stack flexDirection="row" gap={4}>
<OverviewCard
isLoading={invoicesLoading}
title={translate('text_6670a7222702d70114cc7957')}
content={intlFormatNumber(invoices.amount, {
currency: invoices.currency,
locale: documentLocale,
currencyDisplay: 'narrowSymbol',
})}
caption={translate(
'text_6670a7222702d70114cc795c',
{ count: invoices.count },
invoices.count,
)}
/>
<OverviewCard
isLoading={overdueLoading}
title={translate('text_6670a7222702d70114cc795a')}
tooltipContent={translate('text_6670a757999f8a007789bb5d')}
content={intlFormatNumber(overdue.amount, {
currency: overdue.currency,
locale: documentLocale,
currencyDisplay: 'narrowSymbol',
})}
caption={translate(
'text_6670a7222702d70114cc795c',
{ count: overdue.count },
overdue.count,
)}
isAccentContent={overdue.count > 0}
/>
</Stack>
</Stack>

{!hasNoInvoices && (
<SearchInput
className="my-8 w-full max-w-full"
onChange={debouncedSearch}
placeholder={translate('text_6419c64eace749372fc72b33')}
/>
)}

{hasNoInvoices ? (
<Typography>{translate('text_6419c64eace749372fc72b3b')}</Typography>
) : (
Expand Down Expand Up @@ -273,7 +385,7 @@ const PortalInvoicesList = ({ translate, documentLocale }: PortalCustomerInvoice
/>
</InfiniteScroll>
)}
</section>
</SectionContainer>
)
}

Expand Down
Loading

0 comments on commit 2eb6724

Please sign in to comment.