Skip to content

Commit

Permalink
feat(invoice): 📜 add invoice details preview
Browse files Browse the repository at this point in the history
  • Loading branch information
ansmonjol committed Oct 20, 2022
1 parent 4e91854 commit 65f421a
Show file tree
Hide file tree
Showing 9 changed files with 1,305 additions and 76 deletions.
31 changes: 31 additions & 0 deletions ditto/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,37 @@
"text_632d68358f1fedc68eed3ede": "{{amount}} off during {{duration}} period|{{amount}} off during {{duration}} periods",
"text_632d68358f1fedc68eed3ef9": "{{rate}} off during {{duration}} period|{{rate}} off during {{duration}} periods",
"text_633445d00315a713775f02a6": "Rate must be a value greater than 0",
"text_634687079be251fdb438338f": "Actions",
"text_634687079be251fdb4383395": "Download invoice",
"text_634687079be251fdb438339b": "Copy invoice_id",
"text_634687079be251fdb43833a7": "Succeeded",
"text_634687079be251fdb43833ad": "for {{totalAmount}}",
"text_634687079be251fdb43833b7": "Overview",
"text_634687079be251fdb43833b9": "Download invoice",
"text_634687079be251fdb43833bf": "Overview",
"text_634687079be251fdb43833cb": "Customer name",
"text_634687079be251fdb43833d7": "Legal name",
"text_634687079be251fdb43833e3": "Email",
"text_634687079be251fdb43833ef": "Address",
"text_634687079be251fdb43833fb": "Invoice number",
"text_634687079be251fdb4383407": "Issuing date",
"text_634687079be251fdb4383413": "Payment date",
"text_634d631acf4dce7b0127a39a": "{{invoiceDisplayName}} details",
"text_634d631acf4dce7b0127a3a0": "Total unit",
"text_634d631acf4dce7b0127a3a6": "Amount",
"text_634d76a690b89f2d81f95975": "Coupon",
"text_634687079be251fdb4383473": "Subtotal",
"text_634687079be251fdb43834a3": "Prepaid Credits",
"text_634687079be251fdb438347f": "Tax",
"text_634687079be251fdb43834af": "Total due",
"text_634687079be251fdb438339f": "Pending",
"text_634687079be251fdb438339d": "Failed",
"text_634812d6f16b31ce5cbf4111": "Something went wrong",
"text_634812d6f16b31ce5cbf411f": "Please refresh the page or contact us if the error persists.",
"text_634812d6f16b31ce5cbf4123": "Refresh the page",
"text_634812d6f16b31ce5cbf4126": "Something went wrong",
"text_634812d6f16b31ce5cbf4128": "Please refresh the page or contact us if the error persists.",
"text_634812d6f16b31ce5cbf412a": "Refresh the page",
"text_62c6c95fe73d08be5b86c334": "Version",
"text_63208b630aaf8df6bbfb2655": "Members",
"text_63208b630aaf8df6bbfb2657": "Members",
Expand Down
2 changes: 2 additions & 0 deletions ditto/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,7 @@ projects:
id: 633336529ca3243d15ac9df4
- name: Customer - Subscription on past - future date
id: 6335e508a4f742dfb05f54fd
- name: "\U0001F44D [Ready for dev] - Customers - Invoice detail page"
id: 634687058efb4a10996fdbdc
format: flat
variants: true
3 changes: 3 additions & 0 deletions ditto/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ module.exports = {
"project_632d6831010fafe9382b616d": {
"base": require('./👍 [Ready for dev] - Coupons - Create % and recurring coupons__base.json')
},
"project_634687058efb4a10996fdbdc": {
"base": require('./👍 [Ready for dev] - Customers - Invoice detail page__base.json')
},
"project_62c6c95d9333c1ac1be9f938": {
"base": require('./👍 [Ready for dev] - Navigation - Display app version__base.json')
},
Expand Down
165 changes: 100 additions & 65 deletions src/components/customers/CustomerInvoicesList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { gql } from '@apollo/client'
import styled from 'styled-components'
import { DateTime } from 'luxon'
import { generatePath, useNavigate } from 'react-router-dom'

import {
CustomerInvoiceListFragment,
Expand All @@ -9,10 +10,18 @@ import {
} from '~/generated/graphql'
import { Button, Popper, Status, StatusEnum, Tooltip, Typography } from '~/components/designSystem'
import { useInternationalization } from '~/hooks/core/useInternationalization'
import { HEADER_TABLE_HEIGHT, MenuPopper, NAV_HEIGHT, theme } from '~/styles'
import {
HEADER_TABLE_HEIGHT,
ItemContainer,
MenuPopper,
NAV_HEIGHT,
PopperOpener,
theme,
} from '~/styles'
import { SectionHeader, SideSection } from '~/styles/customer'
import { addToast } from '~/core/apolloClient'
import { intlFormatNumber } from '~/core/intlFormatNumber'
import { CUSTOMER_INVOICE_DETAILS_ROUTE } from '~/core/router'

gql`
fragment CustomerInvoiceList on Invoice {
Expand All @@ -33,6 +42,7 @@ gql`
`

interface CustomerInvoicesListProps {
customerId: string
invoices?: CustomerInvoiceListFragment[] | null
}

Expand All @@ -56,7 +66,8 @@ const mapStatus = (type?: InvoiceStatusTypeEnum | undefined) => {
}
}

export const CustomerInvoicesList = ({ invoices }: CustomerInvoicesListProps) => {
export const CustomerInvoicesList = ({ customerId, invoices }: CustomerInvoicesListProps) => {
let navigate = useNavigate()
const { translate } = useInternationalization()
const [downloadInvoice] = useDownloadInvoiceMutation({
onCompleted({ downloadInvoice: data }) {
Expand Down Expand Up @@ -102,72 +113,83 @@ export const CustomerInvoicesList = ({ invoices }: CustomerInvoicesListProps) =>
<PaymentCell variant="bodyHl" color="disabled" noWrap>
{translate('text_62b31e1f6a5b8b1b745ece08')}
</PaymentCell>
<ActionCell></ActionCell>
<ButtonMock />
</ListHeader>
{invoices.map(({ amountCurrency, id, issuingDate, number, totalAmountCents, status }) => {
const formattedStatus = mapStatus(status)

return (
<Item key={`invoice-${id}`}>
<IssuingDateCell noWrap>
{DateTime.fromISO(issuingDate).toFormat('LLL. dd, yyyy')}
</IssuingDateCell>
<NumberCell color="textSecondary">{number}</NumberCell>
<AmountCell color="textSecondary" align="right">
{intlFormatNumber(totalAmountCents, { currency: amountCurrency })}
</AmountCell>
<PaymentCell>
<Status type={formattedStatus.type} label={translate(formattedStatus.label)} />
</PaymentCell>
<ActionCell>
<Popper
PopperProps={{ placement: 'bottom-end' }}
opener={({ isOpen }) => (
<div>
<Tooltip
placement="top-end"
disableHoverListener={isOpen}
title={translate('text_62b31e1f6a5b8b1b745ece3c')}
>
<Button icon="dots-horizontal" variant="quaternary" />
</Tooltip>
</div>
)}
>
{({ closePopper }) => (
<MenuPopper>
<Button
startIcon="download"
variant="quaternary"
align="left"
onClick={async () => {
await downloadInvoice({
variables: { input: { id } },
})
}}
>
{translate('text_62b31e1f6a5b8b1b745ece42')}
</Button>
<Button
startIcon="duplicate"
variant="quaternary"
align="left"
onClick={() => {
navigator.clipboard.writeText(id)
addToast({
severity: 'info',
translateKey: 'text_6253f11816f710014600ba1f',
})
closePopper()
}}
>
{translate('text_62b31e1f6a5b8b1b745ece46')}
</Button>
</MenuPopper>
)}
</Popper>
</ActionCell>
</Item>
<ItemContainer key={`invoice-${id}`}>
<Item
tabIndex={0}
onClick={() =>
navigate(
generatePath(CUSTOMER_INVOICE_DETAILS_ROUTE, {
id: customerId,
invoiceId: id,
})
)
}
>
<IssuingDateCell noWrap>
{DateTime.fromISO(issuingDate).toFormat('LLL. dd, yyyy')}
</IssuingDateCell>
<NumberCell color="textSecondary">{number}</NumberCell>
<AmountCell color="textSecondary" align="right">
{intlFormatNumber(totalAmountCents, { currency: amountCurrency })}
</AmountCell>
<PaymentCell>
<Status type={formattedStatus.type} label={translate(formattedStatus.label)} />
</PaymentCell>
<ButtonMock />
</Item>
<Popper
PopperProps={{ placement: 'bottom-end' }}
opener={({ isOpen }) => (
<DotsOpener>
<Tooltip
placement="top-end"
disableHoverListener={isOpen}
title={translate('text_62b31e1f6a5b8b1b745ece3c')}
>
<Button icon="dots-horizontal" variant="quaternary" />
</Tooltip>
</DotsOpener>
)}
>
{({ closePopper }) => (
<MenuPopper>
<Button
startIcon="download"
variant="quaternary"
align="left"
onClick={async () => {
await downloadInvoice({
variables: { input: { id } },
})
}}
>
{translate('text_62b31e1f6a5b8b1b745ece42')}
</Button>
<Button
startIcon="duplicate"
variant="quaternary"
align="left"
onClick={() => {
navigator.clipboard.writeText(id)
addToast({
severity: 'info',
translateKey: 'text_6253f11816f710014600ba1f',
})
closePopper()
}}
>
{translate('text_62b31e1f6a5b8b1b745ece46')}
</Button>
</MenuPopper>
)}
</Popper>
</ItemContainer>
)
})}
</>
Expand Down Expand Up @@ -204,14 +226,22 @@ const NumberCell = styled(Typography)`

const PaymentCell = styled(Typography)`
width: 112px;
> *:not(:last-child) {
margin-right: ${theme.spacing(4)};
}
`

const AmountCell = styled(Typography)`
flex: 1;
`

const ActionCell = styled.div`
min-width: 40px;
const ButtonMock = styled.div`
width: 40px;
`

const DotsOpener = styled(PopperOpener)`
right: 0;
`

const Item = styled.div`
Expand All @@ -223,4 +253,9 @@ const Item = styled.div`
> *:not(:last-child) {
margin-right: ${theme.spacing(4)};
}
&:hover {
cursor: pointer;
background-color: ${theme.palette.grey[100]};
}
`
27 changes: 27 additions & 0 deletions src/core/router/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ const CustomerDetails = lazy(
() => import(/* webpackChunkName: 'customer-details' */ '~/pages/CustomerDetails')
)

const CustomerInvoiceDetails = lazy(
() => import(/* webpackChunkName: 'customer-details' */ '~/layouts/CustomerInvoiceDetails')
)
const InvoiceOverview = lazy(
() =>
import(/* webpackChunkName: 'invoice-overview' */ '~/pages/settings/invoices/InvoiceOverview')
)

const CouponsList = lazy(() => import(/* webpackChunkName: 'coupons-list' */ '~/pages/CouponsList'))
const CreateCoupon = lazy(
() => import(/* webpackChunkName: 'create-coupon' */ '~/pages/CreateCoupon')
Expand Down Expand Up @@ -98,6 +106,9 @@ export const UPDATE_PLAN_ROUTE = '/update/plan/:id'
export const CUSTOMERS_LIST_ROUTE = '/customers'
export const CUSTOMER_DETAILS_ROUTE = '/customer/:id'
export const CUSTOMER_DETAILS_TAB_ROUTE = `${CUSTOMER_DETAILS_ROUTE}/:tab`
export const CUSTOMER_INVOICE_DETAILS_ROUTE = `${CUSTOMER_DETAILS_ROUTE}/invoice/:invoiceId`
export const CUSTOMER_INVOICE_OVERVIEW_ROUTE = `${CUSTOMER_DETAILS_ROUTE}/invoice/:invoiceId/overview`
export const CUSTOMER_INVOICE_DETAILS_CREDIT_NOTE_ROUTE = `${CUSTOMER_DETAILS_ROUTE}/invoice/:invoiceId/credit-notes`

// Coupons routes
export const COUPONS_ROUTE = '/coupons'
Expand Down Expand Up @@ -218,6 +229,22 @@ export const routes: CustomRouteObject[] = [
private: true,
element: <CustomerDetails />,
},
{
private: true,
element: <CustomerInvoiceDetails />,
children: [
{
path: [CUSTOMER_INVOICE_DETAILS_ROUTE, CUSTOMER_INVOICE_OVERVIEW_ROUTE],
private: true,
element: <InvoiceOverview />,
},
{
path: CUSTOMER_INVOICE_DETAILS_CREDIT_NOTE_ROUTE,
private: true,
element: <div>TODO</div>,
},
],
},
{
path: COUPONS_ROUTE,
private: true,
Expand Down
Loading

0 comments on commit 65f421a

Please sign in to comment.