Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create invoice custom section #1917

Merged
merged 8 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/components/settings/invoices/DefaultCustomSectionDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { forwardRef, useImperativeHandle, useRef, useState } from 'react'

import { Button, Dialog, DialogRef } from '~/components/designSystem'
import { useInternationalization } from '~/hooks/core/useInternationalization'

type ActionType = 'setDefault' | 'removeDefault'

type TDefaultCustomSectionDialogProps = {
type: ActionType
onConfirm: () => void
onCancel: () => void
}

export interface DefaultCustomSectionDialogRef {
openDialog: (props: TDefaultCustomSectionDialogProps) => unknown
closeDialog: () => unknown
}

export const DefaultCustomSectionDialog = forwardRef<DefaultCustomSectionDialogRef, unknown>(
(_props, ref) => {
const { translate } = useInternationalization()
const dialogRef = useRef<DialogRef>(null)
const [localData, setLocalData] = useState<TDefaultCustomSectionDialogProps>()

useImperativeHandle(ref, () => ({
openDialog: (props) => {
setLocalData(props)
dialogRef.current?.openDialog()
},
closeDialog: () => {
setLocalData(undefined)
dialogRef.current?.closeDialog()
},
}))

return (
<Dialog
ref={dialogRef}
title={
localData?.type === 'setDefault'
? translate('text_1732634307286ij3e2kb6c4v')
: translate('text_1732634307286y0yb9lyb70f')
}
description={translate(
localData?.type === 'setDefault'
? 'text_17326343072869mt7lostpsa'
: 'text_1732634307286joro3vhe88v',
)}
actions={({ closeDialog }) => (
<>
<Button
variant="quaternary"
onClick={async () => {
await localData?.onCancel()
closeDialog()
}}
>
{translate('text_62728ff857d47b013204c7e4')}
</Button>

<Button
variant="primary"
onClick={async () => {
await localData?.onConfirm()
closeDialog()
}}
data-test="set-invoice-default-section"
>
{localData?.type === 'setDefault'
? translate('text_1728574726495n9jdse2hnrf')
: translate('text_1728575305796o7kwackkbj6')}
</Button>
</>
)}
data-test="set-invoice-default-section-dialog"
/>
)
},
)

DefaultCustomSectionDialog.displayName = 'DefaultCustomSectionDialog'
21 changes: 21 additions & 0 deletions src/core/router/SettingRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ const InvoiceSettings = lazyLoad(
() =>
import(/* webpackChunkName: 'invoice-settings' */ '~/pages/settings/Invoices/InvoiceSettings'),
)

const CreateInvoiceCustomSection = lazyLoad(
() =>
import(
/* webpackChunkName: 'invoice-custom-section' */ '~/pages/settings/Invoices/CreateCustomSection'
),
)

const TaxesSettings = lazyLoad(
() => import(/* webpackChunkName: 'tax-settings' */ '~/pages/settings/TaxesSettings'),
)
Expand Down Expand Up @@ -164,8 +172,14 @@ export const EMAILS_SCENARIO_CONFIG_ROUTE = `${SETTINGS_ROUTE}/emails/config/:ty
export const XERO_INTEGRATION_ROUTE = `${INTEGRATIONS_ROUTE}/xero`
export const XERO_INTEGRATION_DETAILS_ROUTE = `${INTEGRATIONS_ROUTE}/xero/:integrationId/:tab`
export const DUNNINGS_SETTINGS_ROUTE = `${SETTINGS_ROUTE}/dunnings`

/**
* Creation routes
*/
export const CREATE_DUNNING_ROUTE = `${SETTINGS_ROUTE}/dunnings/create`
export const UPDATE_DUNNING_ROUTE = `${SETTINGS_ROUTE}/dunnings/:campaignId/edit`
export const CREATE_INVOICE_CUSTOM_SECTION = `${INVOICE_SETTINGS_ROUTE}/custom-section/create`
export const EDIT_INVOICE_CUSTOM_SECTION = `${INVOICE_SETTINGS_ROUTE}/custom-section/:sectionId/edit`

export const settingRoutes: CustomRouteObject[] = [
{
Expand Down Expand Up @@ -348,4 +362,11 @@ export const settingRoutes: CustomRouteObject[] = [
element: <CreateDunning />,
permissions: ['dunningCampaignsCreate', 'dunningCampaignsView', 'dunningCampaignsUpdate'],
},
{
path: [CREATE_INVOICE_CUSTOM_SECTION, EDIT_INVOICE_CUSTOM_SECTION],
private: true,
element: <CreateInvoiceCustomSection />,
// TODO: Add permissions
permissions: ['organizationInvoicesUpdate'],
},
]
142 changes: 142 additions & 0 deletions src/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8196,6 +8196,29 @@ export type UpdateDunningCampaignMutationVariables = Exact<{

export type UpdateDunningCampaignMutation = { __typename?: 'Mutation', updateDunningCampaign?: { __typename?: 'DunningCampaign', id: string, name: string, code: string, description?: string | null, daysBetweenAttempts: number, maxAttempts: number, appliedToOrganization: boolean, thresholds: Array<{ __typename?: 'DunningCampaignThreshold', amountCents: any, currency: CurrencyEnum }> } | null };

export type InvoiceCustomSectionFormFragment = { __typename?: 'InvoiceCustomSection', name: string, code: string, description?: string | null, details?: string | null, displayName?: string | null, selected: boolean };

export type GetSingleInvoiceCustomSectionQueryVariables = Exact<{
id: Scalars['ID']['input'];
}>;


export type GetSingleInvoiceCustomSectionQuery = { __typename?: 'Query', invoiceCustomSection: { __typename?: 'InvoiceCustomSection', id: string, name: string, code: string, description?: string | null, details?: string | null, displayName?: string | null, selected: boolean } };

export type CreateInvoiceCustomSectionMutationVariables = Exact<{
input: CreateInvoiceCustomSectionInput;
}>;


export type CreateInvoiceCustomSectionMutation = { __typename?: 'Mutation', createInvoiceCustomSection?: { __typename?: 'InvoiceCustomSection', id: string, name: string, code: string, description?: string | null, details?: string | null, displayName?: string | null, selected: boolean } | null };

export type UpdateInvoiceCustomSectionMutationVariables = Exact<{
input: UpdateInvoiceCustomSectionInput;
}>;


export type UpdateInvoiceCustomSectionMutation = { __typename?: 'Mutation', updateInvoiceCustomSection?: { __typename?: 'InvoiceCustomSection', id: string, name: string, code: string, description?: string | null, details?: string | null, displayName?: string | null, selected: boolean } | null };

export type TaxFormFragment = { __typename?: 'Tax', id: string, code: string, description?: string | null, name: string, rate: number, customersCount: number };

export type TaxFormQueryShapeFragment = { __typename?: 'Tax', autoGenerated: boolean, id: string, code: string, description?: string | null, name: string, rate: number, customersCount: number };
Expand Down Expand Up @@ -10481,6 +10504,16 @@ export const DunningCampaignFormFragmentDoc = gql`
appliedToOrganization
}
`;
export const InvoiceCustomSectionFormFragmentDoc = gql`
fragment InvoiceCustomSectionForm on InvoiceCustomSection {
name
code
description
details
displayName
selected
}
`;
export const TaxFormFragmentDoc = gql`
fragment TaxForm on Tax {
id
Expand Down Expand Up @@ -20226,6 +20259,115 @@ export function useUpdateDunningCampaignMutation(baseOptions?: Apollo.MutationHo
export type UpdateDunningCampaignMutationHookResult = ReturnType<typeof useUpdateDunningCampaignMutation>;
export type UpdateDunningCampaignMutationResult = Apollo.MutationResult<UpdateDunningCampaignMutation>;
export type UpdateDunningCampaignMutationOptions = Apollo.BaseMutationOptions<UpdateDunningCampaignMutation, UpdateDunningCampaignMutationVariables>;
export const GetSingleInvoiceCustomSectionDocument = gql`
query getSingleInvoiceCustomSection($id: ID!) {
invoiceCustomSection(id: $id) {
id
...InvoiceCustomSectionForm
}
}
${InvoiceCustomSectionFormFragmentDoc}`;

/**
* __useGetSingleInvoiceCustomSectionQuery__
*
* To run a query within a React component, call `useGetSingleInvoiceCustomSectionQuery` and pass it any options that fit your needs.
* When your component renders, `useGetSingleInvoiceCustomSectionQuery` 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 } = useGetSingleInvoiceCustomSectionQuery({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useGetSingleInvoiceCustomSectionQuery(baseOptions: Apollo.QueryHookOptions<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables> & ({ variables: GetSingleInvoiceCustomSectionQueryVariables; skip?: boolean; } | { skip: boolean; }) ) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables>(GetSingleInvoiceCustomSectionDocument, options);
}
export function useGetSingleInvoiceCustomSectionLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables>(GetSingleInvoiceCustomSectionDocument, options);
}
export function useGetSingleInvoiceCustomSectionSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables>) {
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables>(GetSingleInvoiceCustomSectionDocument, options);
}
export type GetSingleInvoiceCustomSectionQueryHookResult = ReturnType<typeof useGetSingleInvoiceCustomSectionQuery>;
export type GetSingleInvoiceCustomSectionLazyQueryHookResult = ReturnType<typeof useGetSingleInvoiceCustomSectionLazyQuery>;
export type GetSingleInvoiceCustomSectionSuspenseQueryHookResult = ReturnType<typeof useGetSingleInvoiceCustomSectionSuspenseQuery>;
export type GetSingleInvoiceCustomSectionQueryResult = Apollo.QueryResult<GetSingleInvoiceCustomSectionQuery, GetSingleInvoiceCustomSectionQueryVariables>;
export const CreateInvoiceCustomSectionDocument = gql`
mutation createInvoiceCustomSection($input: CreateInvoiceCustomSectionInput!) {
createInvoiceCustomSection(input: $input) {
id
...InvoiceCustomSectionForm
}
}
${InvoiceCustomSectionFormFragmentDoc}`;
export type CreateInvoiceCustomSectionMutationFn = Apollo.MutationFunction<CreateInvoiceCustomSectionMutation, CreateInvoiceCustomSectionMutationVariables>;

/**
* __useCreateInvoiceCustomSectionMutation__
*
* To run a mutation, you first call `useCreateInvoiceCustomSectionMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useCreateInvoiceCustomSectionMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [createInvoiceCustomSectionMutation, { data, loading, error }] = useCreateInvoiceCustomSectionMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useCreateInvoiceCustomSectionMutation(baseOptions?: Apollo.MutationHookOptions<CreateInvoiceCustomSectionMutation, CreateInvoiceCustomSectionMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<CreateInvoiceCustomSectionMutation, CreateInvoiceCustomSectionMutationVariables>(CreateInvoiceCustomSectionDocument, options);
}
export type CreateInvoiceCustomSectionMutationHookResult = ReturnType<typeof useCreateInvoiceCustomSectionMutation>;
export type CreateInvoiceCustomSectionMutationResult = Apollo.MutationResult<CreateInvoiceCustomSectionMutation>;
export type CreateInvoiceCustomSectionMutationOptions = Apollo.BaseMutationOptions<CreateInvoiceCustomSectionMutation, CreateInvoiceCustomSectionMutationVariables>;
export const UpdateInvoiceCustomSectionDocument = gql`
mutation updateInvoiceCustomSection($input: UpdateInvoiceCustomSectionInput!) {
updateInvoiceCustomSection(input: $input) {
id
...InvoiceCustomSectionForm
}
}
${InvoiceCustomSectionFormFragmentDoc}`;
export type UpdateInvoiceCustomSectionMutationFn = Apollo.MutationFunction<UpdateInvoiceCustomSectionMutation, UpdateInvoiceCustomSectionMutationVariables>;

/**
* __useUpdateInvoiceCustomSectionMutation__
*
* To run a mutation, you first call `useUpdateInvoiceCustomSectionMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateInvoiceCustomSectionMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateInvoiceCustomSectionMutation, { data, loading, error }] = useUpdateInvoiceCustomSectionMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useUpdateInvoiceCustomSectionMutation(baseOptions?: Apollo.MutationHookOptions<UpdateInvoiceCustomSectionMutation, UpdateInvoiceCustomSectionMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateInvoiceCustomSectionMutation, UpdateInvoiceCustomSectionMutationVariables>(UpdateInvoiceCustomSectionDocument, options);
}
export type UpdateInvoiceCustomSectionMutationHookResult = ReturnType<typeof useUpdateInvoiceCustomSectionMutation>;
export type UpdateInvoiceCustomSectionMutationResult = Apollo.MutationResult<UpdateInvoiceCustomSectionMutation>;
export type UpdateInvoiceCustomSectionMutationOptions = Apollo.BaseMutationOptions<UpdateInvoiceCustomSectionMutation, UpdateInvoiceCustomSectionMutationVariables>;
export const GetSingleTaxDocument = gql`
query getSingleTax($id: ID!) {
tax(id: $id) {
Expand Down
Loading
Loading