diff --git a/src/CONST.ts b/src/CONST.ts index 84b393a1f5ae..9e137d711de3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2079,6 +2079,7 @@ const CONST = { ARE_REPORT_FIELDS_ENABLED: 'areReportFieldsEnabled', ARE_CONNECTIONS_ENABLED: 'areConnectionsEnabled', ARE_EXPENSIFY_CARDS_ENABLED: 'areExpensifyCardsEnabled', + ARE_INVOICES_ENABLED: 'areInvoicesEnabled', ARE_TAXES_ENABLED: 'tax', }, DEFAULT_CATEGORIES: [ @@ -2321,6 +2322,7 @@ const CONST = { CARD_SECURITY_CODE: /^[0-9]{3,4}$/, CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/, ROOM_NAME: /^#[\p{Ll}0-9-]{1,100}$/u, + DOMAIN_BASE: '^(?:https?:\\/\\/)?(?:www\\.)?([^\\/]+)', // eslint-disable-next-line max-len, no-misleading-character-class EMOJI: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 45e958627058..fd1e19acf7f3 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -587,6 +587,10 @@ const ONYXKEYS = { WORKSPACE_TAX_NAME_FORM_DRAFT: 'workspaceTaxNameFormDraft', WORKSPACE_TAX_VALUE_FORM: 'workspaceTaxValueForm', WORKSPACE_TAX_VALUE_FORM_DRAFT: 'workspaceTaxValueFormDraft', + WORKSPACE_INVOICES_COMPANY_NAME_FORM: 'workspaceInvoicesCompanyNameForm', + WORKSPACE_INVOICES_COMPANY_NAME_FORM_DRAFT: 'workspaceInvoicesCompanyNameFormDraft', + WORKSPACE_INVOICES_COMPANY_WEBSITE_FORM: 'workspaceInvoicesCompanyWebsiteForm', + WORKSPACE_INVOICES_COMPANY_WEBSITE_FORM_DRAFT: 'workspaceInvoicesCompanyWebsiteFormDraft', NEW_CHAT_NAME_FORM: 'newChatNameForm', NEW_CHAT_NAME_FORM_DRAFT: 'newChatNameFormDraft', SUBSCRIPTION_SIZE_FORM: 'subscriptionSizeForm', @@ -676,6 +680,8 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.WORKSPACE_TAX_NAME_FORM]: FormTypes.WorkspaceTaxNameForm; [ONYXKEYS.FORMS.WORKSPACE_TAX_CODE_FORM]: FormTypes.WorkspaceTaxCodeForm; [ONYXKEYS.FORMS.WORKSPACE_TAX_VALUE_FORM]: FormTypes.WorkspaceTaxValueForm; + [ONYXKEYS.FORMS.WORKSPACE_INVOICES_COMPANY_NAME_FORM]: FormTypes.WorkspaceInvoicesCompanyNameForm; + [ONYXKEYS.FORMS.WORKSPACE_INVOICES_COMPANY_WEBSITE_FORM]: FormTypes.WorkspaceInvoicesCompanyWebsiteForm; [ONYXKEYS.FORMS.NEW_CHAT_NAME_FORM]: FormTypes.NewChatNameForm; [ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM]: FormTypes.SubscriptionSizeForm; [ONYXKEYS.FORMS.ISSUE_NEW_EXPENSIFY_CARD_FORM]: FormTypes.IssueNewExpensifyCardForm; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index f6bdaecdf339..d525cc0ee790 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -680,6 +680,14 @@ const ROUTES = { route: 'settings/workspaces/:policyID/invoices', getRoute: (policyID: string) => `settings/workspaces/${policyID}/invoices` as const, }, + WORKSPACE_INVOICES_COMPANY_NAME: { + route: 'settings/workspaces/:policyID/invoices/company-name', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/invoices/company-name` as const, + }, + WORKSPACE_INVOICES_COMPANY_WEBSITE: { + route: 'settings/workspaces/:policyID/invoices/company-website', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/invoices/company-website` as const, + }, WORKSPACE_TRAVEL: { route: 'settings/workspaces/:policyID/travel', getRoute: (policyID: string) => `settings/workspaces/${policyID}/travel` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 0da8b088f5ec..e32dfca65dec 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -373,6 +373,8 @@ const SCREENS = { EXPENSIFY_CARD_SETTINGS_FREQUENCY: 'Workspace_ExpensifyCard_Settings_Frequency', BILLS: 'Workspace_Bills', INVOICES: 'Workspace_Invoices', + INVOICES_COMPANY_NAME: 'Workspace_Invoices_Company_Name', + INVOICES_COMPANY_WEBSITE: 'Workspace_Invoices_Company_Website', TRAVEL: 'Workspace_Travel', MEMBERS: 'Workspace_Members', INVITE: 'Workspace_Invite', diff --git a/src/languages/en.ts b/src/languages/en.ts index 2332e7d76cb6..51a6747a231b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3319,6 +3319,10 @@ export default { viewUnpaidInvoices: 'View unpaid invoices', sendInvoice: 'Send invoice', sendFrom: 'Send from', + invoicingDetails: 'Invoicing details', + invoicingDetailsDescription: 'This info will appear on your invoices.', + companyName: 'Company name', + companyWebsite: 'Company website', paymentMethods: { personal: 'Personal', business: 'Business', diff --git a/src/languages/es.ts b/src/languages/es.ts index 271ff43a95a9..bff465980d35 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3370,6 +3370,10 @@ export default { viewUnpaidInvoices: 'Ver facturas emitidas pendientes', sendInvoice: 'Enviar factura', sendFrom: 'Enviar desde', + invoicingDetails: 'Detalles de facturación', + invoicingDetailsDescription: 'Esta información aparecerá en tus facturas.', + companyName: 'Nombre de la empresa', + companyWebsite: 'Sitio web de la empresa', paymentMethods: { personal: 'Personal', business: 'Empresas', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 2cdc6bff4e08..1d6af7221da9 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -419,6 +419,8 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/taxes/ValuePage').default, [SCREENS.WORKSPACE.TAX_CREATE]: () => require('../../../../pages/workspace/taxes/WorkspaceCreateTaxPage').default, [SCREENS.WORKSPACE.TAX_CODE]: () => require('../../../../pages/workspace/taxes/WorkspaceTaxCodePage').default, + [SCREENS.WORKSPACE.INVOICES_COMPANY_NAME]: () => require('../../../../pages/workspace/invoices/WorkspaceInvoicingDetailsName').default, + [SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE]: () => require('../../../../pages/workspace/invoices/WorkspaceInvoicingDetailsWebsite').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: () => require('../../../../pages/workspace/expensifyCard/issueNew/IssueNewCardPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceCardSettingsPage').default, [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_ACCOUNT]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceSettlementAccountPage').default, diff --git a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts index c27ccaab5176..942a23068979 100755 --- a/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts +++ b/src/libs/Navigation/linkingConfig/FULL_SCREEN_TO_RHP_MAPPING.ts @@ -159,6 +159,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial> = { SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_VALUE, SCREENS.WORKSPACE.REPORT_FIELDS_EDIT_INITIAL_VALUE, ], + [SCREENS.WORKSPACE.INVOICES]: [SCREENS.WORKSPACE.INVOICES_COMPANY_NAME, SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE], [SCREENS.WORKSPACE.EXPENSIFY_CARD]: [ SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW, SCREENS.WORKSPACE.EXPENSIFY_CARD_BANK_ACCOUNT, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 204a4b559b03..f4e766517a0a 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -475,6 +475,12 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.SHARE]: { path: ROUTES.WORKSPACE_PROFILE_SHARE.route, }, + [SCREENS.WORKSPACE.INVOICES_COMPANY_NAME]: { + path: ROUTES.WORKSPACE_INVOICES_COMPANY_NAME.route, + }, + [SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE]: { + path: ROUTES.WORKSPACE_INVOICES_COMPANY_WEBSITE.route, + }, [SCREENS.WORKSPACE.EXPENSIFY_CARD_LIMIT]: { path: ROUTES.WORKSPACE_EXPENSIFY_CARD_LIMIT.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index a43eab452463..25a12c47eadd 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -665,6 +665,12 @@ type SettingsNavigatorParamList = { policyID: string; taxID: string; }; + [SCREENS.WORKSPACE.INVOICES_COMPANY_NAME]: { + policyID: string; + }; + [SCREENS.WORKSPACE.INVOICES_COMPANY_WEBSITE]: { + policyID: string; + }; [SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: { policyID: string; }; diff --git a/src/libs/Url.ts b/src/libs/Url.ts index 970e6b3ed195..ef595c484bae 100644 --- a/src/libs/Url.ts +++ b/src/libs/Url.ts @@ -1,4 +1,5 @@ import 'react-native-url-polyfill/auto'; +import CONST from '@src/CONST'; import type {Route} from '@src/ROUTES'; /** @@ -70,4 +71,9 @@ function hasURL(text: string) { return urlPattern.test(text); } -export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL, appendParam, hasURL, addLeadingForwardSlash}; +function extractUrlDomain(url: string): string | undefined { + const match = String(url).match(CONST.REGEX.DOMAIN_BASE); + return match?.[1]; +} + +export {addTrailingForwardSlash, hasSameExpensifyOrigin, getPathFromURL, appendParam, hasURL, addLeadingForwardSlash, extractUrlDomain}; diff --git a/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx b/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx index 53d42b42e908..d53940a4cfcb 100644 --- a/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx +++ b/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx @@ -13,6 +13,7 @@ import usePolicy from '@hooks/usePolicy'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import playSound, {SOUNDS} from '@libs/Sound'; +import * as Url from '@libs/Url'; import * as ValidationUtils from '@libs/ValidationUtils'; import Navigation from '@navigation/Navigation'; import * as IOU from '@userActions/IOU'; @@ -43,13 +44,6 @@ function IOURequestStepCompanyInfo({route, report, transaction}: IOURequestStepC const formattedAmount = CurrencyUtils.convertToDisplayString(Math.abs(transaction?.amount ?? 0), transaction?.currency); - const extractUrlDomain = (url: string): string | undefined => { - const DOMAIN_BASE_REGEX = '^(?:https?:\\/\\/)?(?:www\\.)?([^\\/]+)'; - const match = String(url).match(DOMAIN_BASE_REGEX); - - return match?.[1]; - }; - const validate = useCallback( (values: FormOnyxValues): FormInputErrors => { const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_NAME, INPUT_IDS.COMPANY_WEBSITE]); @@ -58,7 +52,7 @@ function IOURequestStepCompanyInfo({route, report, transaction}: IOURequestStepC if (!ValidationUtils.isValidWebsite(values.companyWebsite)) { errors.companyWebsite = translate('bankAccount.error.website'); } else { - const domain = extractUrlDomain(values.companyWebsite); + const domain = Url.extractUrlDomain(values.companyWebsite); if (!domain || !Str.isValidDomainName(domain)) { errors.companyWebsite = translate('iou.invalidDomainError'); diff --git a/src/pages/workspace/invoices/WorkspaceInvoicingDetailsName.tsx b/src/pages/workspace/invoices/WorkspaceInvoicingDetailsName.tsx new file mode 100644 index 000000000000..fff7c592baaa --- /dev/null +++ b/src/pages/workspace/invoices/WorkspaceInvoicingDetailsName.tsx @@ -0,0 +1,79 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TextInput from '@components/TextInput'; +import useAutoFocusInput from '@hooks/useAutoFocusInput'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as ValidationUtils from '@libs/ValidationUtils'; +import Navigation from '@navigation/Navigation'; +import type {SettingsNavigatorParamList} from '@navigation/types'; +import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; +import INPUT_IDS from '@src/types/form/WorkspaceInvoicesCompanyNameForm'; + +type WorkspaceInvoicingDetailsNameProps = StackScreenProps; + +function WorkspaceInvoicingDetailsName({route}: WorkspaceInvoicingDetailsNameProps) { + const {policyID} = route.params; + + const {translate} = useLocalize(); + const {inputCallbackRef} = useAutoFocusInput(); + const styles = useThemeStyles(); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const submit = (values: FormOnyxValues) => { + // TODO: implement UpdateInvoiceCompanyName API call when it's supported + Navigation.goBack(); + }; + + const validate = (values: FormOnyxValues): FormInputErrors => + ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_NAME]); + + return ( + + + + + + + + + ); +} + +WorkspaceInvoicingDetailsName.displayName = 'WorkspaceInvoicingDetailsName'; + +export default WorkspaceInvoicingDetailsName; diff --git a/src/pages/workspace/invoices/WorkspaceInvoicingDetailsSection.tsx b/src/pages/workspace/invoices/WorkspaceInvoicingDetailsSection.tsx new file mode 100644 index 000000000000..c734e4b6d517 --- /dev/null +++ b/src/pages/workspace/invoices/WorkspaceInvoicingDetailsSection.tsx @@ -0,0 +1,57 @@ +import React, {useMemo} from 'react'; +import {useOnyx} from 'react-native-onyx'; +import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; +import Section from '@components/Section'; +import useLocalize from '@hooks/useLocalize'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@navigation/Navigation'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; + +type WorkspaceInvoicingDetailsSectionProps = { + /** The current policy ID */ + policyID: string; +}; + +function WorkspaceInvoicingDetailsSection({policyID}: WorkspaceInvoicingDetailsSectionProps) { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const {shouldUseNarrowLayout} = useResponsiveLayout(); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + + const horizontalPadding = useMemo(() => (shouldUseNarrowLayout ? styles.ph5 : styles.ph8), [shouldUseNarrowLayout, styles]); + + return ( +
+ Navigation.navigate(ROUTES.WORKSPACE_INVOICES_COMPANY_NAME.getRoute(policyID))} + style={horizontalPadding} + /> + Navigation.navigate(ROUTES.WORKSPACE_INVOICES_COMPANY_WEBSITE.getRoute(policyID))} + style={horizontalPadding} + /> +
+ ); +} + +WorkspaceInvoicingDetailsSection.displayName = 'WorkspaceInvoicingDetailsSection'; + +export default WorkspaceInvoicingDetailsSection; diff --git a/src/pages/workspace/invoices/WorkspaceInvoicingDetailsWebsite.tsx b/src/pages/workspace/invoices/WorkspaceInvoicingDetailsWebsite.tsx new file mode 100644 index 000000000000..5a58e8935db2 --- /dev/null +++ b/src/pages/workspace/invoices/WorkspaceInvoicingDetailsWebsite.tsx @@ -0,0 +1,101 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import {Str} from 'expensify-common'; +import React from 'react'; +import {useOnyx} from 'react-native-onyx'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TextInput from '@components/TextInput'; +import useAutoFocusInput from '@hooks/useAutoFocusInput'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Url from '@libs/Url'; +import * as ValidationUtils from '@libs/ValidationUtils'; +import Navigation from '@navigation/Navigation'; +import type {SettingsNavigatorParamList} from '@navigation/types'; +import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; +import INPUT_IDS from '@src/types/form/WorkspaceInvoicesCompanyWebsiteForm'; + +type WorkspaceInvoicingDetailsWebsiteProps = StackScreenProps; + +function WorkspaceInvoicingDetailsWebsite({route}: WorkspaceInvoicingDetailsWebsiteProps) { + const {policyID} = route.params; + + const {translate} = useLocalize(); + const {inputCallbackRef} = useAutoFocusInput(); + const styles = useThemeStyles(); + const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const submit = (values: FormOnyxValues) => { + // TODO: implement UpdateInvoiceCompanyWebsite API call when it's supported + Navigation.goBack(); + }; + + const validate = ( + values: FormOnyxValues, + ): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, [INPUT_IDS.COMPANY_WEBSITE]); + + if (values.companyWebsite) { + if (!ValidationUtils.isValidWebsite(values.companyWebsite)) { + errors.companyWebsite = translate('bankAccount.error.website'); + } else { + const domain = Url.extractUrlDomain(values.companyWebsite); + + if (!domain || !Str.isValidDomainName(domain)) { + errors.companyWebsite = translate('iou.invalidDomainError'); + } else if (ValidationUtils.isPublicDomain(domain)) { + errors.companyWebsite = translate('iou.publicDomainError'); + } + } + } + + return errors; + }; + + return ( + + + + + + + + + ); +} + +WorkspaceInvoicingDetailsWebsite.displayName = 'WorkspaceInvoicingDetailsWebsite'; + +export default WorkspaceInvoicingDetailsWebsite; diff --git a/src/types/form/WorkspaceInvoicesCompanyNameForm.ts b/src/types/form/WorkspaceInvoicesCompanyNameForm.ts new file mode 100644 index 000000000000..d3e6dd606cd5 --- /dev/null +++ b/src/types/form/WorkspaceInvoicesCompanyNameForm.ts @@ -0,0 +1,18 @@ +import type {ValueOf} from 'type-fest'; +import type Form from './Form'; + +const INPUT_IDS = { + COMPANY_NAME: 'companyName', +} as const; + +type InputID = ValueOf; + +type WorkspaceInvoicesCompanyNameForm = Form< + InputID, + { + [INPUT_IDS.COMPANY_NAME]: string; + } +>; + +export type {WorkspaceInvoicesCompanyNameForm}; +export default INPUT_IDS; diff --git a/src/types/form/WorkspaceInvoicesCompanyWebsiteForm.ts b/src/types/form/WorkspaceInvoicesCompanyWebsiteForm.ts new file mode 100644 index 000000000000..3f3bba19d96e --- /dev/null +++ b/src/types/form/WorkspaceInvoicesCompanyWebsiteForm.ts @@ -0,0 +1,18 @@ +import type {ValueOf} from 'type-fest'; +import type Form from './Form'; + +const INPUT_IDS = { + COMPANY_WEBSITE: 'companyWebsite', +} as const; + +type InputID = ValueOf; + +type WorkspaceInvoicesCompanyWebsiteForm = Form< + InputID, + { + [INPUT_IDS.COMPANY_WEBSITE]: string; + } +>; + +export type {WorkspaceInvoicesCompanyWebsiteForm}; +export default INPUT_IDS; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index 60c068b2bea1..00e23bad68f3 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -50,6 +50,8 @@ export type {WorkspaceTaxNameForm} from './WorkspaceTaxNameForm'; export type {WorkspaceTaxValueForm} from './WorkspaceTaxValueForm'; export type {WorkspaceTaxCustomName} from './WorkspaceTaxCustomName'; export type {WorkspaceTaxCodeForm} from './WorkspaceTaxCodeForm'; +export type {WorkspaceInvoicesCompanyNameForm} from './WorkspaceInvoicesCompanyNameForm'; +export type {WorkspaceInvoicesCompanyWebsiteForm} from './WorkspaceInvoicesCompanyWebsiteForm'; export type {PolicyCreateDistanceRateForm} from './PolicyCreateDistanceRateForm'; export type {PolicyDistanceRateTaxReclaimableOnEditForm} from './PolicyDistanceRateTaxReclaimableOnEditForm'; export type {PolicyDistanceRateEditForm} from './PolicyDistanceRateEditForm';