From 0ab037a0df6fbc799e2a2a1c2ae66f1ee79c4c1c Mon Sep 17 00:00:00 2001 From: Kelly Phan Date: Tue, 26 Nov 2024 16:56:13 +0100 Subject: [PATCH] feat: create preview invoice drawer --- .../invoices/PreviewCustomSectionDrawer.tsx | 108 ++++++++++++++++++ src/generated/graphql.tsx | 46 ++++++++ .../settings/Invoices/CreateCustomSection.tsx | 18 +++ translations/base.json | 6 +- 4 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 src/components/settings/invoices/PreviewCustomSectionDrawer.tsx diff --git a/src/components/settings/invoices/PreviewCustomSectionDrawer.tsx b/src/components/settings/invoices/PreviewCustomSectionDrawer.tsx new file mode 100644 index 000000000..f419d60a7 --- /dev/null +++ b/src/components/settings/invoices/PreviewCustomSectionDrawer.tsx @@ -0,0 +1,108 @@ +import { gql } from '@apollo/client' +import { forwardRef, useImperativeHandle, useRef, useState } from 'react' + +import { Button, Drawer, DrawerRef, Typography } from '~/components/designSystem' +import { + CreateInvoiceCustomSectionInput, + useGetOrganizationCustomFooterForInvoiceLazyQuery, +} from '~/generated/graphql' +import { useInternationalization } from '~/hooks/core/useInternationalization' +import Logo from '~/public/images/logo/lago-logo-grey.svg' + +gql` + query GetOrganizationCustomFooterForInvoice { + organization { + billingConfiguration { + invoiceFooter + } + } + } +` + +type TPreviewCustomSectionDrawerProps = Pick< + CreateInvoiceCustomSectionInput, + 'displayName' | 'details' +> + +export interface PreviewCustomSectionDrawerRef { + openDrawer: (params: TPreviewCustomSectionDrawerProps) => void + closeDrawer: () => void +} + +export const PreviewCustomSectionDrawer = forwardRef( + (_props, ref) => { + const { translate } = useInternationalization() + const drawerRef = useRef(null) + const [localData, setLocalData] = useState< + TPreviewCustomSectionDrawerProps & { + invoiceFooter?: string + } + >() + + const [getOrganizationCustomFooter] = useGetOrganizationCustomFooterForInvoiceLazyQuery() + + useImperativeHandle(ref, () => ({ + openDrawer: async (args) => { + const { data } = await getOrganizationCustomFooter() + + setLocalData({ + ...args, + invoiceFooter: data?.organization?.billingConfiguration?.invoiceFooter ?? undefined, + }) + + drawerRef.current?.openDrawer() + }, + closeDrawer: () => drawerRef.current?.closeDrawer(), + })) + + const hasLocalData = localData?.displayName || localData?.details + + return ( + ( +
+ +
+ )} + title={ +
+ + {translate('text_17326350108761jc0z8eusa8')} + +
+ } + > +
+
+ {hasLocalData && ( +
+ {localData?.displayName && ( + + {localData.displayName} + + )} + {localData?.details && ( + {localData.details} + )} +
+ )} + + + {localData?.invoiceFooter} + +
+ + {translate('text_6419c64eace749372fc72b03')} + + +
+
+
+
+ ) + }, +) + +PreviewCustomSectionDrawer.displayName = 'PreviewCustomSectionDrawer' diff --git a/src/generated/graphql.tsx b/src/generated/graphql.tsx index 92647ed1e..7e870a63e 100644 --- a/src/generated/graphql.tsx +++ b/src/generated/graphql.tsx @@ -7890,6 +7890,11 @@ export type UpdateOrganizationInvoiceTemplateMutationVariables = Exact<{ export type UpdateOrganizationInvoiceTemplateMutation = { __typename?: 'Mutation', updateOrganization?: { __typename?: 'CurrentOrganization', id: string, billingConfiguration?: { __typename?: 'OrganizationBillingConfiguration', id: string, invoiceFooter?: string | null } | null } | null }; +export type GetOrganizationCustomFooterForInvoiceQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetOrganizationCustomFooterForInvoiceQuery = { __typename?: 'Query', organization?: { __typename?: 'CurrentOrganization', billingConfiguration?: { __typename?: 'OrganizationBillingConfiguration', invoiceFooter?: string | null } | null } | null }; + export type CreateInviteMutationVariables = Exact<{ input: CreateInviteInput; }>; @@ -18864,6 +18869,47 @@ export function useUpdateOrganizationInvoiceTemplateMutation(baseOptions?: Apoll export type UpdateOrganizationInvoiceTemplateMutationHookResult = ReturnType; export type UpdateOrganizationInvoiceTemplateMutationResult = Apollo.MutationResult; export type UpdateOrganizationInvoiceTemplateMutationOptions = Apollo.BaseMutationOptions; +export const GetOrganizationCustomFooterForInvoiceDocument = gql` + query GetOrganizationCustomFooterForInvoice { + organization { + billingConfiguration { + invoiceFooter + } + } +} + `; + +/** + * __useGetOrganizationCustomFooterForInvoiceQuery__ + * + * To run a query within a React component, call `useGetOrganizationCustomFooterForInvoiceQuery` and pass it any options that fit your needs. + * When your component renders, `useGetOrganizationCustomFooterForInvoiceQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetOrganizationCustomFooterForInvoiceQuery({ + * variables: { + * }, + * }); + */ +export function useGetOrganizationCustomFooterForInvoiceQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetOrganizationCustomFooterForInvoiceDocument, options); + } +export function useGetOrganizationCustomFooterForInvoiceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetOrganizationCustomFooterForInvoiceDocument, options); + } +export function useGetOrganizationCustomFooterForInvoiceSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions) { + const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(GetOrganizationCustomFooterForInvoiceDocument, options); + } +export type GetOrganizationCustomFooterForInvoiceQueryHookResult = ReturnType; +export type GetOrganizationCustomFooterForInvoiceLazyQueryHookResult = ReturnType; +export type GetOrganizationCustomFooterForInvoiceSuspenseQueryHookResult = ReturnType; +export type GetOrganizationCustomFooterForInvoiceQueryResult = Apollo.QueryResult; export const CreateInviteDocument = gql` mutation createInvite($input: CreateInviteInput!) { createInvite(input: $input) { diff --git a/src/pages/settings/Invoices/CreateCustomSection.tsx b/src/pages/settings/Invoices/CreateCustomSection.tsx index 2afda4bdc..b5fa86d8b 100644 --- a/src/pages/settings/Invoices/CreateCustomSection.tsx +++ b/src/pages/settings/Invoices/CreateCustomSection.tsx @@ -9,6 +9,10 @@ import { DefaultCustomSectionDialog, DefaultCustomSectionDialogRef, } from '~/components/settings/invoices/DefaultCustomSectionDialog' +import { + PreviewCustomSectionDrawer, + PreviewCustomSectionDrawerRef, +} from '~/components/settings/invoices/PreviewCustomSectionDrawer' import { WarningDialog, WarningDialogRef } from '~/components/WarningDialog' import { INVOICE_SETTINGS_ROUTE } from '~/core/router' import { CreateInvoiceCustomSectionInput } from '~/generated/graphql' @@ -22,6 +26,7 @@ const CreateInvoiceCustomSection = () => { const warningDirtyAttributesDialogRef = useRef(null) const defaultCustomSectionDialogRef = useRef(null) + const previewCustomSectionDrawerRef = useRef(null) const { loading, isEdition, invoiceCustomSection, onSave } = useCreateEditInvoiceCustomSection() @@ -200,6 +205,18 @@ const CreateInvoiceCustomSection = () => { rows="3" multiline /> +
@@ -250,6 +267,7 @@ const CreateInvoiceCustomSection = () => { onContinue={() => navigate(INVOICE_SETTINGS_ROUTE)} /> + ) } diff --git a/translations/base.json b/translations/base.json index c65e54c88..b2d473518 100644 --- a/translations/base.json +++ b/translations/base.json @@ -639,9 +639,9 @@ "text_62e0ee200a543924c8f67759": "Looks like there are no available credits, please top up this wallet. If you already did, it can take some time to be updated.", "text_62e0ee200a543924c8f6775d": "Top up credits", "text_62e161ceb87c201025388aa2": "Edit wallet", - "text_62e161ceb87c201025388ada": "Top up credits", "text_62e161ceb87c201025388ade": "Terminate wallet", "text_62e257c032ae895bbfead62e": "Wallet successfully terminated", + "text_62e161ceb87c201025388ada": "Top up credits", "text_62e2a2f2a79d60429eff3035": "Terminated", "text_62e79671d23ae6ff149de924": "Top up credits to this customer", "text_62e79671d23ae6ff149de928": "A new invoice will be generated for each top up. The credits granted will be added to the available balance once the invoice is paid.", @@ -2753,5 +2753,7 @@ "text_1732634307286joro3vhe88v": "This change will remove these invoice custom section as the default option for the organization. All customers currently using it will be affected. These details will no longer appear on their future invoices. Are you sure you want to proceed?", "text_1733841825248s6mxx67rsw7": "Edit invoice custom section", "text_17338418252493b2rz0ks49m": "Invoice custom section successfully created", - "text_1733841825249i5g7vr4gnzo": "Invoice custom section successfully edited" + "text_1733841825249i5g7vr4gnzo": "Invoice custom section successfully edited", + "text_17326350108761jc0z8eusa8": "Invoice preview", + "text_173255335844629sa49oljif": "Preview invoice" } \ No newline at end of file