{"version":3,"file":"index.9259e697.js","sources":["../../vite/modulepreload-polyfill","../../vite/preload-helper","../../src/intl/translate.tsx","../../src/intl/hooks/useTranslate.ts","../../src/utils/toggleCss.ts","../../src/components/ContentContainer.tsx","../../src/components/Content.tsx","../../src/components/ContentPaper.tsx","../../src/utils/ApplicationStorage.ts","../../src/atoms/intl/store.ts","../../src/atoms/intl/hooks.ts","../../src/atoms/intl/changeLanguageService.ts","../../src/atoms/intl/changeLanguage.ts","../../src/common/types/localization.ts","../../src/atoms/session/store.ts","../../src/atoms/session/tenant.ts","../../src/atoms/session/hooks.ts","../../src/atoms/session/loginService.ts","../../src/atoms/session/login.ts","../../src/sections/Login/store.ts","../../src/services/queryClient.ts","../../src/atoms/session/logout.ts","../../src/utils/http.ts","../../src/utils/ServerError.ts","../../src/api/settings.ts","../../src/common/hooks/query/useFetchLocalizationSettings.ts","../../src/common/hooks/useLocalizationSettings.ts","../../src/intl/IntlProvider.tsx","../../src/intl/IntlLoadingScreen/useTexts.ts","../../src/intl/IntlLoadingScreen/IntlLoadingScreen.tsx","../../src/utils/ToastNotificationProvider.tsx","../../src/theme/palette.ts","../../src/theme/components/MuiDialogTitle.ts","../../src/theme/components/MuiFormControl.ts","../../src/theme/components/MuiIconButton.ts","../../src/theme/components/MuiLink.ts","../../src/theme/components/MuiPaper.ts","../../src/theme/components/MuiSelect.ts","../../src/theme/components/MuiTableCell.ts","../../src/theme/components/MuiTableHead.ts","../../src/theme/components/MuiTableRow.ts","../../src/theme/components/MuiTextField.ts","../../src/theme/components/MuiTypography.ts","../../src/theme/components/index.ts","../../src/theme/typography.ts","../../src/theme/index.ts","../../src/api/businessUnitSettings.ts","../../src/common/hooks/query/useFetchCustomerPortalSettings.ts","../../src/common/hooks/useThemingKey.ts","../../src/common/hooks/useCustomTheme.ts","../../src/common/components/ConfirmationDialog/useTexts.ts","../../src/common/components/ConfirmationDialog/ConfirmationDialog.tsx","../../src/common/components/ConfirmationDialog/ConfirmationDialogProvider.tsx","../../src/Root/Provider.tsx","../../src/Root/Layout.tsx","../../src/api/accountHistory.ts","../../src/common/hooks/query/useQueryAccountHistory.ts","../../src/utils/hostEnvironmentInfo.ts","../../src/atoms/UILayout.ts","../../src/common/constants.ts","../../src/components/PageWrapper.tsx","../../src/components/PageErrorState/useTexts.ts","../../src/components/PageErrorState/PageErrorState.tsx","../../src/common/hooks/useDrawerState.ts","../../src/components/cardList/CardList.tsx","../../src/components/cardList/useTexts.ts","../../src/components/cardList/ListHeader/ListHeader.tsx","../../src/components/cardList/ListBody/ListBody.tsx","../../src/components/cardList/ListFooter/ListFooter.tsx","../../src/sections/AccountHistory/useTexts.ts","../../src/common/hooks/useDebounce.ts","../../src/components/SearchBox/useTexts.ts","../../src/components/SearchBox/SearchBox.tsx","../../src/components/cardList/DebouncedSearchBox/DebouncedSearchBox.tsx","../../src/sections/AccountHistory/AccountHistoryList/store.ts","../../src/sections/AccountHistory/AccountHistoryList/hooks/useListActions.ts","../../src/api/serviceLocations.ts","../../src/common/hooks/query/useQueryServiceLocations.ts","../../src/common/types/currency.ts","../../src/components/localization/Currency.tsx","../../src/components/localization/Dates.tsx","../../src/common/utils/formatPhoneNumber.ts","../../src/common/hooks/usePhoneNumber.ts","../../src/components/localization/PhoneNumber.tsx","../../src/components/cardList/chips/DateFilterChip.tsx","../../src/components/cardList/chips/HistoryTypeFilterChip.tsx","../../src/components/cardList/chips/ServiceLocationFilterChip.tsx","../../src/components/cardList/filters/ClearFiltersButton.tsx","../../src/sections/AccountHistory/AccountHistoryList/header/Chips.tsx","../../src/sections/AccountHistory/AccountHistoryList/header/AccountHistoryListHeader.tsx","../../src/components/SideDrawer.tsx","../../src/common/utils/formatAddress.ts","../../src/components/cardList/filters/ServiceLocationFilter.tsx","../../src/sections/AccountHistory/AccountHistoryList/filters/useTexts.ts","../../src/components/DatePicker.tsx","../../src/sections/AccountHistory/AccountHistoryList/filters/StartDate.tsx","../../src/sections/AccountHistory/AccountHistoryList/filters/EndDate.tsx","../../src/common/hooks/useFeatureEnabled.ts","../../src/sections/AccountHistory/AccountHistoryList/filters/ItemType.tsx","../../src/sections/AccountHistory/AccountHistoryList/filters/FiltersDrawer.tsx","../../src/components/ComponentWithTooltip.tsx","../../src/components/cardList/DesktopListCard/useTexts.ts","../../src/components/cardList/DesktopListCard/DesktopListCard.tsx","../../src/components/cardList/CardBadge/CardBadge.tsx","../../src/components/cardList/MobileListCard/useTexts.ts","../../src/components/cardList/MobileListCard/MobileListCard.tsx","../../src/utils/openReport.ts","../../src/api/invoices.ts","../../src/common/hooks/query/useQueryInvoiceDetail.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/useTexts.ts","../../src/components/DefinitionListItem.tsx","../../src/utils/useToast.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/icons/PDF.tsx","../../src/components/OpenPDFButton.tsx","../../src/api/paymentProcessor.ts","../../src/common/hooks/query/useFetchBusinessUnitPaymentProcessor.ts","../../src/common/hooks/usePaymentsEnabled.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/listItems/AssociatedWorkOrders.tsx","../../src/common/hooks/useAddress.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/listItems/BillingLocation.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/listItems/Payments.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/listItems/PaymentStatus.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/listItems/ServiceLocation.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/listItems/ServicesPerformed.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/DetailListItems.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/drawer/DrawerContent.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/invoices/InvoiceCard.tsx","../../src/common/types/payments.ts","../../src/sections/AccountHistory/AccountHistoryList/hooks/useFormattedAccountType.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/payments/useTexts.ts","../../src/api/payments.ts","../../src/common/hooks/query/useQueryPaymentDetail.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/payments/DetailListItems.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/payments/DrawerContent.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/payments/PaymentSubtitle.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/payments/PaymentCard.tsx","../../src/common/hooks/useFormattedWorkOrderNumber/useTexts.ts","../../src/common/hooks/useFormattedWorkOrderNumber/useFormattedWorkOrderNumber.ts","../../src/common/types/services.ts","../../src/sections/AccountHistory/AccountHistoryList/cards/services/drawer/useTexts.ts","../../src/api/workOrderDetails.ts","../../src/common/hooks/query/useQueryWorkOrderDetails.ts","../../src/api/avatar.ts","../../src/common/hooks/query/useQueryAvatar.ts","../../src/common/components/ResourceDisplay/AvatarPlaceholder.tsx","../../src/common/components/ResourceDisplay/Avatar.tsx","../../src/common/components/ResourceDisplay/useTexts.ts","../../src/common/components/ResourceDisplay/ResourceDisplay.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/services/drawer/DetailListItems.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/services/drawer/DrawerContent.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/services/ServiceCard.tsx","../../src/sections/AccountHistory/AccountHistoryList/cards/AccountHistoryCard.tsx","../../src/sections/AccountHistory/AccountHistoryList/AccountHistoryList.tsx","../../src/sections/AccountHistory/LoadingSkeleton.tsx","../../src/sections/AccountHistory/AccountHistory.tsx","../../src/components/Section.tsx","../../src/components/SectionHeader.tsx","../../src/api/accounts.ts","../../src/common/hooks/query/useFetchAccountSummary.ts","../../src/sections/AccountOverview/widgets/AccountSummary/useTexts.ts","../../src/sections/AccountOverview/widgets/AccountSummary/SummaryValue.tsx","../../src/sections/AccountOverview/widgets/AccountSummary/Content.tsx","../../src/sections/AccountOverview/widgets/AccountSummary/AccountSummary.tsx","../../src/api/workOrders.ts","../../src/common/hooks/query/useQueryYourNextService.ts","../../src/sections/UpcomingServices/drawer/useTexts.ts","../../src/sections/UpcomingServices/components/ConfirmationBadge.tsx","../../src/sections/AccountOverview/widgets/YourNextService/useTexts.ts","../../src/sections/AccountOverview/widgets/common/ServiceAmount.tsx","../../src/sections/AccountOverview/widgets/common/ServicesList.tsx","../../src/sections/AccountOverview/widgets/common/ServiceLocationDetail.tsx","../../src/sections/AccountOverview/widgets/YourNextService/Content.tsx","../../src/sections/AccountOverview/widgets/YourNextService/YourNextService.tsx","../../src/sections/AccountOverview/widgets/YourLastService/useData.tsx","../../src/sections/AccountOverview/widgets/YourLastService/useTexts.ts","../../src/sections/AccountOverview/widgets/YourLastService/Content.tsx","../../src/sections/AccountOverview/widgets/YourLastService/YourLastService.tsx","../../src/sections/AccountOverview/useTexts.ts","../../src/sections/AccountOverview/AccountOverview.tsx","../../src/api/agreements.ts","../../src/common/hooks/query/useQueryAgreements.ts","../../src/sections/Agreements/LoadingSkeleton.tsx","../../src/sections/Agreements/useTexts.ts","../../src/common/types/agreements.ts","../../src/sections/Agreements/AgreementsList/filters/StatusFilter/StatusFilterChip.tsx","../../src/sections/Agreements/AgreementsList/store.ts","../../src/sections/Agreements/AgreementsList/hooks/useListActions.ts","../../src/sections/Agreements/AgreementsList/header/Chips.tsx","../../src/sections/Agreements/AgreementsList/header/AgreementsListHeader.tsx","../../src/components/form/useTexts.ts","../../src/components/form/SideDrawerForm.tsx","../../src/sections/Agreements/components/StatusBadge.tsx","../../src/common/hooks/query/useQueryAgreementDetail.ts","../../src/api/paymentAccounts.ts","../../src/common/hooks/query/useQueryPaymentAccounts.ts","../../src/common/hooks/payments.ts","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/useTexts.ts","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/AchEntry.tsx","../../src/common/utils/formatCreditCardFriendly.ts","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/CreditCardIframe.tsx","../../src/api/paymentTransactions.ts","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/useData.tsx","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/CreditCardEntry.tsx","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/DrawerContent.tsx","../../src/sections/Agreements/drawer/store.ts","../../src/sections/Agreements/drawer/AddPaymentMethod.tsx","../../src/common/types/invoiceMode.ts","../../src/common/types/contacts.ts","../../src/common/components/EmailLink.tsx","../../src/sections/Agreements/drawer/listItems/AgreementContact.tsx","../../src/sections/Agreements/drawer/listItems/AgreementLocation.tsx","../../src/sections/Agreements/drawer/useTexts.ts","../../src/sections/PaymentMethods/useTexts.ts","../../src/sections/PaymentMethods/PaymentMethodCard/PaymentAccountDetails.tsx","../../src/api/autopayments.ts","../../src/sections/Agreements/drawer/hooks/useRemoveAutoPayActions.ts","../../src/sections/Agreements/drawer/listItems/AutopayInformation.tsx","../../src/common/types/schedulingPlan.ts","../../src/common/hooks/schedulingPlan/useOrderedDaysOfWeek.ts","../../src/common/hooks/schedulingPlan/useHumanizedDaysOfWeek.ts","../../src/common/hooks/schedulingPlan/usePluralFrequencies.ts","../../src/common/hooks/schedulingPlan/useSingularFrequencies.ts","../../src/common/hooks/schedulingPlan/useHumanizedIntervalUnits.ts","../../src/common/hooks/schedulingPlan/useHumanizedSchedulingPlan.ts","../../src/sections/Agreements/drawer/listItems/Service.tsx","../../src/sections/Agreements/drawer/listItems/Services.tsx","../../src/sections/Agreements/drawer/DetailListItems.tsx","../../src/common/utils/isCardExpired.ts","../../src/components/icons/ACH.tsx","../../src/components/icons/AmericanExpress.tsx","../../src/components/icons/Discover.tsx","../../src/components/icons/Mastercard.tsx","../../src/components/icons/Visa.tsx","../../src/sections/PaymentMethods/PaymentMethodCard/CardIcon.tsx","../../src/sections/PayInvoices/drawer/useTexts.ts","../../src/sections/PayInvoices/drawer/PaymentMethodSelect.tsx","../../src/sections/Agreements/drawer/ManageAutopay.tsx","../../src/sections/Agreements/drawer/DrawerContent.tsx","../../src/sections/Agreements/AgreementsList/cards/SecondaryIcon.tsx","../../src/sections/Agreements/AgreementsList/cards/SubTitle.tsx","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/hooks/useIsAchInputValid.ts","../../src/sections/Agreements/AgreementsList/cards/hooks/useDisableSave.ts","../../src/sections/Agreements/AgreementsList/cards/hooks/useAgreementCardActions.ts","../../src/sections/Agreements/AgreementsList/cards/AgreementCard.tsx","../../src/sections/Agreements/AgreementsList/filters/StatusFilter/StatusFilter.tsx","../../src/sections/Agreements/AgreementsList/filters/FiltersDrawer.tsx","../../src/sections/Agreements/AgreementsList/AgreementsList.tsx","../../src/sections/Agreements/AgreementsPage.tsx","../../src/api/businessUnitDetails.ts","../../src/common/hooks/query/useFetchBusinessUnitDetails.ts","../../src/common/hooks/useBusinessUnitDetails.ts","../../src/utils/hooks/useTexts.ts","../../src/utils/hooks/useMobileGreeting.ts","../../src/utils/hooks/useDesktopGreeting.ts","../../src/components/appHeader/useTexts.ts","../../src/components/appHeader/AppHeaderGreeting.tsx","../../src/components/appHeader/useLogoutActions.ts","../../src/components/appHeader/Avatar.tsx","../../src/components/appHeader/AppHeaderDesktop.tsx","../../src/components/sidebar/store.ts","../../src/components/sidebar/Header.tsx","../../src/components/sidebar/List/ListItemWithChildren.tsx","../../src/components/sidebar/List/SubLists/PaymentsSubList.tsx","../../src/components/sidebar/List/SubLists/YourServicesSubList.tsx","../../src/components/sidebar/List/List.tsx","../../src/components/sidebar/List/ListItem.tsx","../../src/components/sidebar/Section.tsx","../../src/components/sidebar/useTexts.tsx","../../src/services/services/accountServices.ts","../../src/common/hooks/query/useQueryAccounts.ts","../../src/components/AccountSwitch.tsx","../../src/components/sidebar/SwitchAccount/useTexts.ts","../../src/components/sidebar/SwitchAccount/AccountSwitchList.tsx","../../src/components/sidebar/SwitchAccount/AccountSwitchAction.tsx","../../src/components/sidebar/SwitchAccount/SwitchAccountView.tsx","../../src/components/sidebar/Sidebar.tsx","../../src/common/utils/splitAddress.ts","../../src/common/hooks/useSplitAddress.ts","../../src/components/sidebar/content/FooterContent.tsx","../../src/api/logo.ts","../../src/common/hooks/query/useFetchLogoUrl.ts","../../src/common/components/LogoDisplay/useCompanyLogoExists.ts","../../src/common/components/LogoDisplay/LogoDisplay.tsx","../../src/components/sidebar/content/HeaderContent.tsx","../../src/components/sidebar/SidebarDrawer.tsx","../../src/components/appHeader/AppHeaderMobile.tsx","../../src/sections/App/AppDesktop.tsx","../../src/sections/App/AppMobile.tsx","../../src/sections/App/App.tsx","../../src/sections/Forbidden/useTexts.ts","../../src/sections/Forbidden/Forbidden.tsx","../../src/formState/utils/createEmptyFormState.ts","../../src/formState/createForm.ts","../../src/formState/utils/createFieldApi.ts","../../src/formState/utils/formContext.tsx","../../src/formState/hooks/useCreateForm.ts","../../src/formState/hooks/useForm.ts","../../src/formState/hooks/useFormApi.ts","../../src/formState/hooks/useFormMeta.ts","../../src/formState/hooks/useFormField.ts","../../src/sections/ForgotPassword/form/formFields.ts","../../src/formUI/components/SmoothScrollbar/hooks/useScrollbarOptions.ts","../../src/formUI/components/SmoothScrollbar/hooks/useInitSmoothScrollbar.ts","../../src/formUI/components/SmoothScrollbar/hooks/useOnScroll.ts","../../src/formUI/components/SmoothScrollbar/hooks/useTestActions.ts","../../src/formUI/components/SmoothScrollbar/hooks/useOnScrollTo.ts","../../src/formUI/components/SmoothScrollbar/hooks/useOnScrollIntoView.ts","../../src/formUI/components/SmoothScrollbar/hooks/useNotifyListeners.ts","../../src/formUI/components/SmoothScrollbar/hooks/useStyles.ts","../../src/formUI/components/SmoothScrollbar/SmoothScrollbar.tsx","../../src/formUI/components/Scrollbars/Scrollbars/components/FitBox.tsx","../../src/formUI/components/Scrollbars/ScrollbarsRoot/ScrollContext.tsx","../../src/formUI/components/FieldMessage.tsx","../../src/formUI/components/FieldsContainer.tsx","../../src/formUI/components/Fields/hooks/useValidateOn.ts","../../src/formUI/components/Fields/Generic/RadioGroup/RadioGroupOption.tsx","../../src/formUI/components/Fields/hooks/useDebounceText.ts","../../src/formUI/components/Fields/Generic/TextField.tsx","../../src/formUI/components/Fields/Generic/TimePicker/hooks/useStyles.ts","../../src/components/PasswordRequirements/utils.ts","../../src/sections/ForgotPassword/useTexts.ts","../../src/services/ReactQueryProvider.tsx","../../src/services/services/userService.ts","../../src/sections/ForgotPassword/useForgotPasswordActions.ts","../../src/sections/ForgotPassword/form/Footer.tsx","../../src/sections/ForgotPassword/form/Form.tsx","../../src/sections/ForgotPassword/form/FormProvider.tsx","../../src/sections/ForgotPassword/ForgotPassword.tsx","../../src/sections/Login/form/formFields.ts","../../src/sections/Login/hooks/useTexts.ts","../../src/sections/Login/hooks/useLoginActions.ts","../../src/sections/Login/form/Footer.tsx","../../src/components/Button.tsx","../../src/sections/Login/form/ForgotPasswordButton.tsx","../../src/sections/Login/form/Form.tsx","../../src/sections/Login/form/FormProvider.tsx","../../src/common/hooks/query/useQueryLoadTenant.ts","../../src/sections/Login/hooks/useCheckSubdomain.ts","../../src/sections/Login/Login.tsx","../../src/common/hooks/query/useQueryDefaultBillingLocation.ts","../../src/components/PageHeader.tsx","../../src/common/utils/staggerPagination.ts","../../src/common/hooks/query/useFetchOpenInvoices.ts","../../src/common/hooks/query/useFetchUnappliedStartingBalance.ts","../../src/sections/PayInvoices/useTexts.ts","../../src/sections/PayInvoices/store.ts","../../src/sections/PayInvoices/InvoiceCard.tsx","../../src/sections/PayInvoices/UnappliedStartingBalanceCard.tsx","../../src/sections/PayInvoices/InvoiceList.tsx","../../src/sections/PayInvoices/drawer/AddNewCreditCard.tsx","../../src/sections/PayInvoices/drawer/PaymentConfirmationAlert.tsx","../../src/sections/PayInvoices/drawer/Drawer.tsx","../../src/sections/PayInvoices/InvoiceTotal.tsx","../../src/sections/PayInvoices/PayInvoicesPage.tsx","../../src/sections/PaymentMethods/drawers/AddPaymentMethod/Drawer.tsx","../../src/common/hooks/useConfirmationDialog.ts","../../src/components/IconButtonWithTooltip.tsx","../../src/sections/PaymentMethods/PaymentMethodCard/DeleteButton.tsx","../../src/sections/PaymentMethods/PaymentMethodCard/PaymentAccountCard.tsx","../../src/sections/PaymentMethods/PaymentMethodList.tsx","../../src/sections/PaymentMethods/PaymentMethodsPage.tsx","../../src/common/hooks/query/useQueryActiveAgreements.ts","../../src/sections/ManageAutopay/LoadingSkeleton.tsx","../../src/sections/ManageAutopay/useTexts.ts","../../src/sections/ManageAutopay/ActiveAgreementsList/store.ts","../../src/sections/ManageAutopay/ActiveAgreementsList/hooks/useListActions.ts","../../src/sections/ManageAutopay/ActiveAgreementsList/header/Chips.tsx","../../src/sections/ManageAutopay/ActiveAgreementsList/header/ActiveAgreementsListHeader.tsx","../../src/sections/ManageAutopay/ActiveAgreementsList/filters/FiltersDrawer.tsx","../../src/sections/ManageAutopay/ActiveAgreementsList/ActiveAgreementsList.tsx","../../src/sections/ManageAutopay/ManageAutopayPage.tsx","../../src/sections/Profile/useTexts.ts","../../src/sections/Profile/sections/EmailAddress.tsx","../../src/sections/Profile/drawer/formFields.tsx","../../src/components/PasswordRequirements/useTexts.ts","../../src/components/PasswordRequirements/PasswordRequirements.tsx","../../src/utils/requiredValidator.ts","../../src/sections/Profile/drawer/useTexts.ts","../../src/sections/Profile/drawer/Form.tsx","../../src/sections/Profile/drawer/FormWrapper.tsx","../../src/sections/Profile/drawer/Drawer.tsx","../../src/sections/Profile/sections/Password.tsx","../../src/sections/Profile/Profile.tsx","../../src/sections/QuestionsAndComments/useTexts.ts","../../src/sections/QuestionsAndComments/store.ts","../../src/sections/QuestionsAndComments/Form/fields/CommentField.tsx","../../src/sections/QuestionsAndComments/Form/fields/ServiceLocationSelect.tsx","../../src/api/questionsAndComments.ts","../../src/sections/QuestionsAndComments/Form/FormFooter.tsx","../../src/sections/QuestionsAndComments/Form/Form.tsx","../../src/sections/QuestionsAndComments/QuestionsAndCommentsPage.tsx","../../src/sections/Register/form/formFields.ts","../../src/api/registration.ts","../../src/sections/Register/useRegisterActions.ts","../../src/sections/Register/useTexts.ts","../../src/sections/Register/form/Footer.tsx","../../src/sections/Register/form/InvalidRegistrationFooter.tsx","../../src/sections/Register/form/hooks/useCustomerPortalUserId.ts","../../src/api/customerPortalUserRegistration.ts","../../src/sections/Register/form/hooks/useFetchUserRegistration.ts","../../src/sections/Register/form/Form.tsx","../../src/sections/Register/form/FormProvider.tsx","../../src/sections/Register/Register.tsx","../../src/sections/Unknown/useTexts.ts","../../src/sections/Unknown/Unknown.tsx","../../src/sections/RequestService/store.ts","../../src/sections/RequestService/sections/AddNote/useTexts.ts","../../src/sections/RequestService/sections/AddNote/store.ts","../../src/sections/RequestService/sections/AddNote/Drawer/useTexts.ts","../../src/sections/RequestService/sections/AddNote/Drawer/Drawer.tsx","../../src/sections/RequestService/sections/AddNote/AddNote.tsx","../../src/components/ButtonWithTooltip.tsx","../../src/sections/RequestService/sections/AddServices/useTexts.ts","../../src/sections/RequestService/sections/AddServices/store.ts","../../src/sections/RequestService/sections/AddServices/Drawer/useTexts.ts","../../src/api/services.ts","../../src/sections/RequestService/sections/AddServices/useData.tsx","../../src/sections/RequestService/sections/AddServices/Drawer/ServiceCheckbox.tsx","../../src/sections/RequestService/sections/AddServices/Drawer/ServiceList.tsx","../../src/sections/RequestService/sections/AddServices/Drawer/DrawerContent.tsx","../../src/sections/RequestService/sections/AddServices/Drawer/Pagination.tsx","../../src/sections/RequestService/sections/AddServices/Drawer/Drawer.tsx","../../src/sections/RequestService/sections/AddServices/AddServices.tsx","../../src/sections/RequestService/sections/SelectLocation/store.ts","../../src/sections/RequestService/sections/SelectLocation/Drawer/useTexts.ts","../../src/sections/RequestService/sections/SelectLocation/useData.tsx","../../src/sections/RequestService/sections/SelectLocation/Drawer/LocationRadioButton.tsx","../../src/sections/RequestService/sections/SelectLocation/Drawer/LocationList.tsx","../../src/sections/RequestService/sections/SelectLocation/Drawer/DrawerContent.tsx","../../src/sections/RequestService/sections/SelectLocation/Drawer/LocationSearch.tsx","../../src/sections/RequestService/sections/SelectLocation/Drawer/Drawer.tsx","../../src/sections/RequestService/sections/SelectLocation/useTexts.ts","../../src/sections/RequestService/sections/SelectLocation/SelectLocation.tsx","../../src/sections/RequestService/sections/SetServiceDetails/store.ts","../../src/sections/RequestService/sections/YourRequest/validation.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/useTexts.ts","../../src/api/companyHolidays.ts","../../src/common/hooks/query/useFetchHolidays.ts","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/fields/ServiceDatePicker.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/fields/FrequencyMenuItemText.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/fields/Frequency.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/utils/useGetPropertyTraitsOnMount.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/fields/PropertyTraits.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/fields/Timeframe.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Form/ServiceDetailForm.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/ServiceDetailList.tsx","../../src/sections/RequestService/sections/SetServiceDetails/Drawer/Drawer.tsx","../../src/sections/RequestService/sections/SetServiceDetails/useTexts.ts","../../src/sections/RequestService/sections/SetServiceDetails/SetServiceDetails.tsx","../../src/components/PaddedDivider.tsx","../../src/sections/RequestService/sections/YourRequest/useTexts.ts","../../src/sections/RequestService/sections/YourRequest/ServiceDetails.tsx","../../src/sections/RequestService/sections/YourRequest/Service.tsx","../../src/api/opportunities.ts","../../src/sections/RequestService/sections/YourRequest/SubmitRequestButton.tsx","../../src/sections/RequestService/sections/YourRequest/YourRequest.tsx","../../src/sections/RequestService/useTexts.ts","../../src/sections/RequestService/RequestService.tsx","../../src/sections/ResetPassword/form/formFields.ts","../../src/sections/ResetPassword/useResetPasswordActions.ts","../../src/sections/ResetPassword/useTexts.ts","../../src/sections/ResetPassword/form/Footer.tsx","../../src/sections/ResetPassword/form/Form.tsx","../../src/sections/ResetPassword/form/FormProvider.tsx","../../src/sections/ResetPassword/ResetPassword.tsx","../../src/api/upcomingServices.ts","../../src/common/hooks/query/useQueryUpcomingServices.ts","../../src/sections/UpcomingServices/useTexts.ts","../../src/sections/UpcomingServices/NoUpcomingServicesSection.tsx","../../src/sections/UpcomingServices/UpcomingServicesList/store.ts","../../src/sections/UpcomingServices/UpcomingServicesList/hooks/useListActions.ts","../../src/sections/UpcomingServices/UpcomingServicesList/header/Chips.tsx","../../src/sections/UpcomingServices/UpcomingServicesList/header/UpcomingServicesListHeader.tsx","../../src/components/localization/Times.tsx","../../src/sections/UpcomingServices/drawer/ConfirmationActions.tsx","../../src/sections/UpcomingServices/drawer/DetailListItems.tsx","../../src/sections/UpcomingServices/drawer/DrawerContent.tsx","../../src/sections/UpcomingServices/UpcomingServicesList/cards/ServiceCard.tsx","../../src/sections/UpcomingServices/UpcomingServicesList/filters/useTexts.ts","../../src/sections/UpcomingServices/UpcomingServicesList/filters/FiltersDrawer.tsx","../../src/sections/UpcomingServices/UpcomingServicesList/hooks/useAccountHasNoUpcomingServices.ts","../../src/sections/UpcomingServices/UpcomingServicesList/UpcomingServicesList.tsx","../../src/sections/UpcomingServices/LoadingSkeleton.tsx","../../src/sections/UpcomingServices/UpcomingServicesPage.tsx","../../src/api/serviceRequests.ts","../../src/common/hooks/query/useQueryServiceRequests.ts","../../src/sections/YourRequests/LoadingSkeleton.tsx","../../src/sections/YourRequests/useTexts.ts","../../src/sections/YourRequests/YourRequestsList/header/YourRequestsListHeader.tsx","../../src/sections/YourRequests/components/StatusBadge.tsx","../../src/common/hooks/query/useQueryServiceRequestDetails.ts","../../src/sections/YourRequests/drawer/listItems/Issue.tsx","../../src/sections/YourRequests/drawer/useTexts.ts","../../src/sections/YourRequests/drawer/listItems/Reservation.tsx","../../src/sections/YourRequests/drawer/listItems/ServiceAddress.tsx","../../src/sections/YourRequests/drawer/listItems/ServiceContact.tsx","../../src/sections/YourRequests/drawer/DetailListItems.tsx","../../src/sections/YourRequests/drawer/DrawerContent.tsx","../../src/sections/YourRequests/YourRequestsList/store.ts","../../src/sections/YourRequests/YourRequestsList/cards/SubTitle.tsx","../../src/sections/YourRequests/YourRequestsList/cards/RequestCard.tsx","../../src/sections/YourRequests/YourRequestsList/hooks/useListActions.ts","../../src/sections/YourRequests/YourRequestsList/YourRequestsList.tsx","../../src/sections/YourRequests/YourRequestsPage.tsx","../../src/router/components/PrivateRoute.tsx","../../src/Root/Sections.tsx","../../src/Root/usePreload.tsx","../../src/Root/Root.tsx","../../src/reportWebVitals.ts","../../src/main.tsx"],"sourcesContent":["const p = function polyfill() {\n const relList = document.createElement('link').relList;\n if (relList && relList.supports && relList.supports('modulepreload')) {\n return;\n }\n for (const link of document.querySelectorAll('link[rel=\"modulepreload\"]')) {\n processPreload(link);\n }\n new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n if (mutation.type !== 'childList') {\n continue;\n }\n for (const node of mutation.addedNodes) {\n if (node.tagName === 'LINK' && node.rel === 'modulepreload')\n processPreload(node);\n }\n }\n }).observe(document, { childList: true, subtree: true });\n function getFetchOpts(script) {\n const fetchOpts = {};\n if (script.integrity)\n fetchOpts.integrity = script.integrity;\n if (script.referrerpolicy)\n fetchOpts.referrerPolicy = script.referrerpolicy;\n if (script.crossorigin === 'use-credentials')\n fetchOpts.credentials = 'include';\n else if (script.crossorigin === 'anonymous')\n fetchOpts.credentials = 'omit';\n else\n fetchOpts.credentials = 'same-origin';\n return fetchOpts;\n }\n function processPreload(link) {\n if (link.ep)\n // ep marker = processed\n return;\n link.ep = true;\n // prepopulate the load record\n const fetchOpts = getFetchOpts(link);\n fetch(link.href, fetchOpts);\n }\n};__VITE_IS_MODERN__&&p();","const scriptRel = 'modulepreload';const seen = {};const base = '/';export const __vitePreload = function preload(baseModule, deps) {\n // @ts-ignore\n if (!__VITE_IS_MODERN__ || !deps || deps.length === 0) {\n return baseModule();\n }\n return Promise.all(deps.map((dep) => {\n // @ts-ignore\n dep = `${base}${dep}`;\n // @ts-ignore\n if (dep in seen)\n return;\n // @ts-ignore\n seen[dep] = true;\n const isCss = dep.endsWith('.css');\n const cssSelector = isCss ? '[rel=\"stylesheet\"]' : '';\n // @ts-ignore check if the file is already preloaded by SSR markup\n if (document.querySelector(`link[href=\"${dep}\"]${cssSelector}`)) {\n return;\n }\n // @ts-ignore\n const link = document.createElement('link');\n // @ts-ignore\n link.rel = isCss ? 'stylesheet' : scriptRel;\n if (!isCss) {\n link.as = 'script';\n link.crossOrigin = '';\n }\n link.href = dep;\n // @ts-ignore\n document.head.appendChild(link);\n if (isCss) {\n return new Promise((res, rej) => {\n link.addEventListener('load', res);\n link.addEventListener('error', rej);\n });\n }\n })).then(() => baseModule());\n}","import type { FC } from 'react';\nimport type { WrappedComponentProps, IntlShape } from 'react-intl';\nimport type { Translate } from './types';\n\nimport { ReactElement, useEffect, memo } from 'react';\nimport { injectIntl } from 'react-intl';\n\ntype IntlAPI = IntlShape | null;\nlet intlAPI: IntlAPI = null;\n\nconst getIntlAPI = (): IntlAPI => {\n if (!intlAPI) {\n throw new Error(`Intl Manager doesn't have references to intl API`);\n }\n return intlAPI;\n};\n\ntype Props = WrappedComponentProps & { children: ReactElement | null };\n\nconst IntlManagerComp: FC = memo(\n props => {\n const { intl } = props;\n\n if (!intlAPI) {\n intlAPI = intl;\n }\n\n useEffect(() => {\n intlAPI = intl;\n }, [intl]);\n\n return props.children;\n },\n (prevProps: Props, nextProps: Props) => {\n const { intl: prevIntl } = prevProps;\n const { intl } = nextProps;\n\n return prevIntl === intl;\n },\n);\nIntlManagerComp.displayName = 'IntlManagerComp';\n\nexport const IntlManager = injectIntl(IntlManagerComp);\n\n/**\n * Expose the Intl APIs outside the components tree.\n */\nexport const translate: Translate = options => {\n return getIntlAPI()?.formatMessage(options, options.values) || '';\n};\n","import { translate } from '../translate';\n\nexport const useTranslate = () => translate;\n","// see https://github.com/lukeed/clsx/blob/master/clsx.d.ts\n\ninterface ClassArray extends Array {}\ntype ClassValue = ClassArray | Record | string | number | null | boolean | undefined;\n\nconst toVal = (mix: ClassValue) => {\n let str = '';\n let y = '';\n\n if (mix) {\n if (typeof mix === 'object') {\n if (Array.isArray(mix)) {\n for (let k = 0; k < mix.length; k++) {\n if (mix[k] && (y = toVal(mix[k]))) {\n str && (str += ' ');\n str += y;\n }\n }\n } else {\n for (const k in mix) {\n if (mix[k] && (y = toVal(k))) {\n str && (str += ' ');\n str += y;\n }\n }\n }\n } else if (typeof mix !== 'boolean' && typeof mix !== 'function') {\n str && (str += ' ');\n str += mix;\n }\n }\n\n return str;\n};\n\nexport function toggleCss(...classes: ClassValue[]): string {\n let i = 0;\n let x = '';\n let str = '';\n\n while (i < classes.length) {\n if ((x = toVal(classes[i++]))) {\n str && (str += ' ');\n str += x;\n }\n }\n return str;\n}\n","import makeStyles from '@mui/styles/makeStyles';\nimport Container, { ContainerProps } from '@mui/material/Container';\n\nimport { toggleCss } from '@/utils/toggleCss';\n\nconst useStyles = makeStyles(theme => ({\n contentContainer: {\n display: 'flex',\n width: '100%',\n height: '100%',\n flex: '0 1 auto',\n paddingTop: theme.spacing(2),\n paddingBottom: theme.spacing(2),\n paddingLeft: 0,\n paddingRight: 0,\n },\n}));\n\nexport function ContentContainer(props: ContainerProps) {\n const { className, ...other } = props;\n const classes = useStyles();\n\n return (\n \n {props.children}\n \n );\n}\n","import makeStyles from '@mui/styles/makeStyles';\nimport Container, { ContainerProps } from '@mui/material/Container';\n\nimport { toggleCss } from '@/utils/toggleCss';\n\nconst useStyles = makeStyles(() => ({\n contentContainer: {\n position: 'relative',\n height: '100%',\n width: '100%',\n },\n}));\n\nexport function Content(props: ContainerProps) {\n const { className, ...other } = props;\n const classes = useStyles();\n\n return (\n \n {props.children}\n \n );\n}\n","import makeStyles from '@mui/styles/makeStyles';\nimport Paper, { PaperProps } from '@mui/material/Paper';\n\nimport { toggleCss } from '@/utils/toggleCss';\n\nconst useStyles = makeStyles(theme => ({\n contentPaper: {\n padding: theme.spacing(2),\n display: 'flex',\n overflow: 'auto',\n flexDirection: 'column',\n },\n fullWidth: {\n width: '100%',\n },\n fullHeight: {\n height: '100%',\n },\n}));\n\ntype Props = PaperProps & {\n fullWidth?: boolean;\n fullHeight?: boolean;\n};\n\nexport function ContentPaper(props: Props) {\n const { className, fullHeight, fullWidth, ...other } = props;\n const classes = useStyles();\n\n return (\n \n {props.children}\n \n );\n}\n","export interface IStorage {\n clear(): IStorage;\n get(request: string, remove?: boolean): string | undefined;\n set(request: string, data: string): IStorage;\n remove(request: string): IStorage;\n}\n\nexport class ApplicationStorage implements IStorage {\n constructor(private useSession: boolean = false) {}\n\n private get storage(): Storage {\n return this.useSession ? sessionStorage : localStorage;\n }\n\n public get(request: string, remove: boolean = false): string | undefined {\n const res = this.storage.getItem(request);\n if (remove) {\n this.remove(request);\n }\n return res ? res : undefined;\n }\n\n public set(request: string, data: string): IStorage {\n this.storage.setItem(request, data);\n return this;\n }\n\n public remove(request: string): IStorage {\n this.storage.removeItem(request);\n return this;\n }\n\n public clear(): IStorage {\n this.storage.clear();\n return this;\n }\n}\n\nexport const setValue = (request: string, value: string, useSession: boolean = false): IStorage => {\n return new ApplicationStorage(useSession).set(request, value);\n};\n\nexport const getValue = (request: string, remove: boolean = false, useSession: boolean = false): string | undefined => {\n return new ApplicationStorage(useSession).get(request, remove);\n};\n\nexport const removeValue = (request: string, useSession: boolean = false): IStorage => {\n return new ApplicationStorage(useSession).remove(request);\n};\n\nexport const getStorage = (useSession: boolean = false): IStorage => {\n return new ApplicationStorage(useSession);\n};\n","import { proxy } from 'valtio';\n\nimport { Language } from '@/intl';\nimport * as storage from '@/utils/ApplicationStorage';\n\n// ----------------------------\n// Store state\n// ----------------------------\n\ntype IntlState = {\n language: Language;\n messages: Record | null;\n loadingLanguage: 'ready' | 'pending' | 'error';\n};\n\n// ----------------------------\n// INITIAL STATE WITH LOCAL/SESSION STORAGE SUPPORT\n\nconst getDefaultInitialState = (): IntlState => ({\n messages: null,\n language: 'en',\n loadingLanguage: 'pending',\n});\n\nlet recoveredState: IntlState | undefined;\nconst getInitialState = () => recoveredState ?? getDefaultInitialState();\n\nconst clearRecoveredState = () => {\n storage.removeValue('ww/store/intl', false);\n recoveredState = undefined;\n};\n\nconst tryToRecoverInitialState = () => {\n try {\n const stored = storage.getValue('ww/store/intl', false, false);\n\n if (stored) {\n const tmp = JSON.parse(stored) as IntlState;\n\n recoveredState = {\n messages: {},\n language: tmp.language,\n loadingLanguage: 'pending',\n };\n }\n } catch (e) {}\n};\ntryToRecoverInitialState();\n\n// ----------------------------\n// Valtio store initialization\n// ----------------------------\n\nexport const state = proxy(getInitialState());\n\n// ----------------------------\n// setter functions\n// ----------------------------\n\nexport function setLoadingLanguage(loadingLanguage: IntlState['loadingLanguage']) {\n state.loadingLanguage = loadingLanguage;\n}\n\nexport function setLanguage(language: Language, messages: IntlState['messages']) {\n state.language = language;\n state.messages = messages;\n state.loadingLanguage = 'ready';\n}\n\nexport function resetLanguage() {\n clearRecoveredState();\n Object.assign(state, getInitialState());\n}\n\n// ----------------------------\n// selector functions\n// ----------------------------\n\nexport function selectLanguage() {\n return state.language;\n}\n\nexport function selectLanguageMessages() {\n return state.messages;\n}\n\nexport function selectLanguageLoading() {\n return state.loadingLanguage;\n}\n","import { useSnapshot } from 'valtio';\nimport { state } from './store';\n\nexport function useActiveLanguage() {\n return useSnapshot(state);\n}\n\nexport function useLanguageLoading() {\n return useSnapshot(state).loadingLanguage;\n}\n","import type { Language } from '@/intl';\nimport axios from 'axios';\n\ntype Messages = Record;\n\nexport const changeLanguageService = async (language: Language, abortSignal?: AbortSignal) => {\n const source = axios.CancelToken.source();\n\n const handleOnAbort = () => source.cancel();\n abortSignal?.addEventListener('abort', handleOnAbort);\n const options = abortSignal ? { cancelToken: source.token } : undefined;\n\n try {\n // see: https://vitejs.dev/guide/assets.html#the-public-directory\n // Vite expects all dynamic import of static assets inside the public folder to start with `/`\n const folder = `/locales`;\n const fileName = `${language}.json`;\n const preventCache = `v=${Math.random()}`;\n const fileUrl = `${folder}/${fileName}?${preventCache}`;\n\n const response = await axios.get(fileUrl, options);\n\n if (response.status === 200) {\n return response.data as Messages;\n }\n\n throw new Error(`${response.status} - ${response.statusText}`);\n } catch (e) {\n throw e;\n } finally {\n abortSignal?.removeEventListener('abort', handleOnAbort);\n }\n};\n","import type { Language } from '@/intl';\n\nimport { changeLanguageService } from './changeLanguageService';\nimport { setLanguage } from './store';\n\ntype RejectError = {\n message: string;\n type: 'error-loading-locale' | 'action-cancelled';\n};\n\ntype Result = {\n language: Language;\n messages: Record;\n};\n\nlet changeLanguageController: AbortController | undefined;\nexport async function changeLanguage(language: Language): Promise {\n if (changeLanguageController) {\n changeLanguageController.abort();\n }\n changeLanguageController = new AbortController();\n const signal = changeLanguageController.signal;\n\n try {\n const messages = await changeLanguageService(language, signal);\n\n if (signal.aborted) {\n return {\n message: 'Action Cancelled',\n type: 'action-cancelled',\n };\n }\n\n changeLanguageController = undefined;\n setLanguage(language, messages);\n\n return { language, messages };\n } catch (e) {\n changeLanguageController = undefined;\n\n return {\n message: e instanceof Error ? e.message : 'unknown error',\n type: 'error-loading-locale',\n };\n }\n}\n","export enum CultureCode {\n en_AU = 'en-AU',\n en_CA = 'en-CA',\n en_GB = 'en-GB',\n en_IE = 'en-IE',\n en_NZ = 'en-NZ',\n en_US = 'en-US',\n}\n\nexport enum CultureCountry {\n Australia = 'Australia',\n Canada = 'Canada',\n England = 'England',\n Ireland = 'Ireland',\n NewZealand = 'New Zealand',\n NorthernIreland = 'Northern Ireland',\n Scotland = 'Scotland',\n UnitedStates = 'United States',\n Wales = 'Wales',\n}\n\nexport enum SystemOfMeasurement {\n Imperial = 'imperial',\n Metric = 'metric',\n}\n\nexport enum UnitOfDistance {\n Kilometer = 'kilometer',\n Mile = 'mile',\n}\n\nexport enum UnitOfDistanceAbbreviation {\n Kilometer = 'km',\n Mile = 'mi',\n}\n\nexport interface LocalizationSettings {\n culture: CultureCode;\n cultureCountry: CultureCountry;\n isInternationalTaxType: boolean;\n showCountryCode: boolean;\n systemOfMeasurement: SystemOfMeasurement;\n}\n\nexport const CultureStrings: Record = {\n [CultureCountry.Australia]: CultureCode.en_AU,\n [CultureCountry.Canada]: CultureCode.en_CA,\n [CultureCountry.England]: CultureCode.en_GB,\n [CultureCountry.Ireland]: CultureCode.en_IE,\n [CultureCountry.NewZealand]: CultureCode.en_NZ,\n [CultureCountry.NorthernIreland]: CultureCode.en_GB,\n [CultureCountry.Scotland]: CultureCode.en_GB,\n [CultureCountry.UnitedStates]: CultureCode.en_US,\n [CultureCountry.Wales]: CultureCode.en_GB,\n};\n\nexport const DefaultSystemOfMeasurement: Record = {\n [CultureCountry.Australia]: SystemOfMeasurement.Metric,\n [CultureCountry.Canada]: SystemOfMeasurement.Metric,\n [CultureCountry.England]: SystemOfMeasurement.Metric,\n [CultureCountry.Ireland]: SystemOfMeasurement.Metric,\n [CultureCountry.NewZealand]: SystemOfMeasurement.Metric,\n [CultureCountry.NorthernIreland]: SystemOfMeasurement.Metric,\n [CultureCountry.Scotland]: SystemOfMeasurement.Metric,\n [CultureCountry.UnitedStates]: SystemOfMeasurement.Imperial,\n [CultureCountry.Wales]: SystemOfMeasurement.Metric,\n};\n\nexport const defaultLocalizationSettings: LocalizationSettings = {\n culture: CultureCode.en_US,\n cultureCountry: CultureCountry.UnitedStates,\n isInternationalTaxType: false,\n showCountryCode: false,\n systemOfMeasurement: SystemOfMeasurement.Imperial,\n};\n","import { proxy, subscribe } from 'valtio';\nimport { AuthenticatedUserModel } from './loginService';\n\n// ----------------------------\n// Store state\n// ----------------------------\n\ntype Session =\n | {\n account?: string;\n authorized: false;\n tenantId?: string;\n }\n | {\n authorized: true;\n userName: string;\n token: string;\n refreshToken: string;\n user: AuthenticatedUserModel;\n tenantId?: string;\n account?: Account.AccountSelect;\n expirationInUtc: Date;\n };\n\n// ----------------------------\n// Valtio store initialization\n// ----------------------------\n\nexport const state = proxy({ authorized: false });\n\nsubscribe(state, () => {\n localStorage.setItem('state', JSON.stringify(state));\n});\n\nexport function setState(newState: Session) {\n Object.assign(state, newState);\n}\n\n// ----------------------------\n// setter functions\n// ----------------------------\n\nexport function setSession(\n token: string,\n refreshToken: string,\n user: AuthenticatedUserModel,\n expirationInUtc: string,\n userName?: string,\n) {\n state.authorized = true;\n\n if (state.authorized) {\n state.userName = userName ?? state.userName;\n state.token = token;\n state.refreshToken = refreshToken;\n state.user = user;\n state.expirationInUtc = new Date(expirationInUtc);\n }\n}\n\nexport function setAccountId(account: Account.AccountSelect) {\n if (state.authorized) {\n state.account = account;\n }\n}\n\nexport function getAccount() {\n if (state.authorized) {\n return state.account;\n }\n}\n\nexport function clearSession() {\n state.authorized = false;\n\n // @ts-expect-error\n delete state.userName;\n\n // @ts-expect-error\n delete state.token;\n\n // @ts-expect-error\n delete state.refreshToken;\n\n // @ts-expect-error\n delete state.roles;\n\n // @ts-expect-error\n delete state.user;\n\n delete state.account;\n}\n\nexport function loadState() {\n const storedStateString = localStorage.getItem('state');\n const localState = storedStateString ? JSON.parse(storedStateString) : { authorized: false };\n setState(localState);\n}\n\n// ----------------------------\n// selector functions\n// ----------------------------\n\nexport function isUserAuthorized() {\n return state.authorized;\n}\n\nexport function getToken() {\n return state.authorized ? state.token : undefined;\n}\n\nexport function isTokenValid() {\n if (state.authorized) {\n const expirationDate = state.expirationInUtc ?? new Date(new Date().toISOString());\n const date = new Date(new Date().toISOString());\n\n return expirationDate > date;\n }\n\n return true;\n}\n\nexport function getRefreshToken() {\n return state.authorized ? state.refreshToken : undefined;\n}\n\nexport function getUser() {\n return state.authorized ? state.user : undefined;\n}\n\nexport function getDisplayName() {\n return state.authorized ? `${state.user.firstName} ${state.user.lastName}` : undefined;\n}\n\nexport function getFirstName() {\n return state.authorized ? state.user.firstName : undefined;\n}\n","import { get, setTenantId, requestNewToken } from '@/utils/http';\nimport * as storage from '@/utils/ApplicationStorage';\nimport { clearSession } from './store';\n\nconst getDomain = () => {\n const url = window.location;\n const hostname = url.hostname;\n const domain = hostname.split('.')[0];\n return domain;\n};\n\ninterface TenantIdModel {\n tenantId: string;\n}\n\nconst getTenantId = async (domain: string) => {\n try {\n const response = await get(`/api/tenants?domain=${domain}`);\n return response.data.tenantId;\n } catch (e) {\n throw e;\n }\n};\n\nexport const tenantService = async () => {\n const domain = getDomain();\n const tenantId = await getTenantId(domain);\n\n setTenantId(tenantId);\n storage.setValue('tenantId', tenantId);\n\n // Refresh credentials after loading tenant but before anything else\n // Consider refactoring\n try {\n await requestNewToken();\n } catch {\n clearSession(); // Clear the session values so the user can login\n }\n\n return tenantId;\n};\n","import { useEffect, useRef } from 'react';\nimport { useSnapshot } from 'valtio';\nimport { state } from './store';\nimport { tenantService } from './tenant';\n\nexport function useIsUserAuthorized() {\n return useSnapshot(state).authorized;\n}\n\nexport function useAccountId() {\n const snapshot = useSnapshot(state);\n return snapshot.authorized ? snapshot.account?.accountId : undefined;\n}\n\nexport function useUserToken() {\n const snapshot = useSnapshot(state);\n return snapshot.authorized ? snapshot.token : undefined;\n}\n\nexport const useTenantInformation = () => {\n const loading = useRef(true);\n\n useEffect(() => {\n const fetchTenantInformation = async () => {\n loading.current = true;\n await tenantService();\n loading.current = false;\n };\n fetchTenantInformation();\n }, []);\n\n return loading.current;\n};\n","import axios from 'axios';\nimport { post } from '@/utils/http';\n\nexport interface LoginPayload {\n token: string;\n refreshToken: string;\n user: AuthenticatedUserModel;\n expirationInUtc: string;\n}\n\nexport interface AuthenticatedUserModel {\n identityUserId: string;\n contactId: string;\n firstName: string;\n lastName: string;\n email: string;\n}\n\nexport const loginService = async (userName: string, password: string, abortSignal?: AbortSignal) => {\n const source = axios.CancelToken.source();\n\n const handleOnAbort = () => source.cancel();\n abortSignal?.addEventListener('abort', handleOnAbort);\n const options = abortSignal ? { cancelToken: source.token } : undefined;\n\n try {\n const response = await post('/api/sessions', { userName, password }, options);\n if (response.status === 200 || response.status === 201) {\n return response.data;\n }\n\n throw new Error(`${response.status} - ${response.statusText}`);\n } catch (e) {\n throw e;\n } finally {\n abortSignal?.removeEventListener('abort', handleOnAbort);\n }\n};\n","import { setAuth } from '@/utils/http';\n\nimport { loginService } from './loginService';\nimport { setSession } from './store';\n\ntype RejectError = {\n message: string;\n type: 'invalid-login' | 'action-cancelled';\n};\n\nlet loginController: AbortController | undefined;\nexport async function login(userName: string, password: string): Promise {\n if (loginController) {\n loginController.abort();\n }\n loginController = new AbortController();\n const signal = loginController.signal;\n\n try {\n const loginResults = await loginService(userName, password, signal);\n\n if (signal.aborted) {\n return {\n message: 'Action Cancelled',\n type: 'action-cancelled',\n };\n }\n\n // set HTTP helper auth token\n setAuth(loginResults.token);\n\n loginController = undefined;\n setSession(\n loginResults.token,\n loginResults.refreshToken,\n loginResults.user,\n loginResults.expirationInUtc,\n userName,\n );\n\n return true;\n } catch (e) {\n loginController = undefined;\n\n return {\n message: e instanceof Error ? e.message : 'unknown error',\n type: 'invalid-login',\n };\n }\n}\n","import { proxy, useSnapshot } from 'valtio';\n\nexport interface LoginState {\n accountSelect: Account.AccountSelect[];\n error: string;\n}\n\nexport const initialState: LoginState = {\n accountSelect: [],\n error: '',\n};\n\n// Valtio store initialization\nconst state = proxy(initialState);\n\n// Setter functions\nexport function setAccountSelect(accounts: Account.AccountSelect[]) {\n state.accountSelect = accounts;\n}\n\nexport function setError(error: string) {\n state.error = error;\n}\n\nexport function resetLoginState() {\n state.accountSelect = [];\n state.error = '';\n}\n\n// Hooks\nexport function useLoginState() {\n return useSnapshot(state);\n}\n","import type { Mutation } from 'react-query/types/core/mutation';\nimport type { Query } from 'react-query/types/core/query';\n\nimport { QueryClient, QueryCache, MutationCache } from 'react-query';\n\nimport { ServerError } from '@/utils/ServerError';\n\nconst manageError = (error: ServerError) => {\n if (error.message.endsWith('401') || error.message.endsWith('403')) {\n // TODO: If the user is unauthorized should the application logout?\n }\n};\n\nconst handleQueryError = (error: unknown, _query: Query) => {\n manageError(error as ServerError);\n};\n\nconst handleMutationError = (\n error: unknown,\n _variables: unknown,\n _context: unknown,\n _mutation: Mutation,\n) => {\n manageError(error as ServerError);\n};\n\nconst queryCache = new QueryCache({ onError: handleQueryError });\n\nconst mutationCache = new MutationCache({ onError: handleMutationError });\n\n/** custom cache for react query */\nexport const queryClient = new QueryClient({\n queryCache,\n mutationCache,\n defaultOptions: {\n queries: {\n retry: 1,\n refetchOnMount: false,\n refetchOnWindowFocus: false,\n staleTime: 60000,\n },\n },\n});\n","import { clearAuth } from '@/utils/http';\nimport { resetLoginState } from '../../sections/Login/store';\nimport { queryClient } from '../../services/queryClient';\n\nimport { clearSession } from './store';\n\ntype LogoutRejectError = {\n message: string;\n type: 'unknown';\n};\n\nexport function logout(): true | LogoutRejectError {\n try {\n // clear react query cache\n queryClient.clear();\n resetLoginState();\n // clear HTTP helper auth token\n clearAuth();\n\n clearSession();\n return true;\n } catch (e) {\n return {\n message: e instanceof Error ? e.message : 'unknown error',\n type: 'unknown',\n };\n }\n}\n","import type { AxiosInstance } from 'axios';\nimport type { LoginPayload } from '@/atoms/session/loginService';\nimport { logout } from '@/atoms/session';\nimport { isTokenValid, setSession, getRefreshToken, loadState } from '@/atoms/session/store';\n\nimport axios from 'axios';\n\nexport const rootPath =\n import.meta.env.VITE_HTTP_HOST && import.meta.env.VITE_HTTP_PORT\n ? `${import.meta.env.VITE_HTTP_HOST}:${import.meta.env.VITE_HTTP_PORT}`\n : ``;\nconst extraPath = import.meta.env.VITE_HTTP_EXTRA_PATH ? `${import.meta.env.VITE_HTTP_EXTRA_PATH}/` : '';\n\n// see: https://github.com/axios/axios#request-config\nconst axiosInstance = axios.create({\n baseURL: `${rootPath}/${extraPath}`,\n withCredentials: false,\n headers: {},\n});\n\naxiosInstance.interceptors.response.use(\n function (response) {\n return response;\n },\n function (error) {\n const originalRequest = error.config;\n if (error.response.status != 401 || isTokenValid()) {\n return Promise.reject(error); // Non-auth server failures aren't retried\n }\n\n if (originalRequest.url.startsWith('/api/sessions')) {\n // Never retry sessions requests (loop)\n return Promise.reject(error);\n }\n\n if (originalRequest._skipRetry) {\n // Avoid infinite loop if refresh token is bad\n logout();\n return Promise.reject(error);\n }\n\n return new Promise(function (_resolve, reject) {\n requestNewToken()\n .then(token => {\n originalRequest._skipRetry = true;\n originalRequest.headers['Authorization'] = `Bearer ${token}`; // The defaults aren't reloaded, so this must be set manually\n _resolve(axiosInstance(originalRequest));\n })\n .catch(() => {\n logout();\n reject(error);\n });\n });\n },\n);\n\nexport const requestNewToken = async () => {\n loadState(); // Refresh local storage (the refresh token may have changed in another tab)\n const refreshToken = getRefreshToken();\n if (!refreshToken) {\n throw new Error('No refresh token available');\n }\n\n const response = await post(`/api/sessions/${refreshToken}/refresh`);\n if (response.status === 200 || response.status === 201) {\n const loginResults = response.data;\n setAuth(loginResults.token);\n setSession(loginResults.token, loginResults.refreshToken, loginResults.user, loginResults.expirationInUtc);\n return loginResults.token;\n }\n\n throw new Error(`${response.status} - ${response.statusText}`);\n};\n\n// TODO: make it configurable. It should support multiple headers.\nexport const setAuth = (token: string) => {\n // see: https://tools.ietf.org/html/rfc6750\n axiosInstance.defaults.headers.common['Authorization'] = `Bearer ${token}`;\n};\n\nexport const setTenantId = (tenantId: string) => {\n axiosInstance.defaults.headers.common['tenantId'] = tenantId;\n};\n\nexport const clearAuth = () => {\n delete axiosInstance.defaults.headers.common['Authorization'];\n};\n\nexport const http = () => axiosInstance;\n\nexport const get: AxiosInstance['get'] = (url, config) => {\n return axiosInstance.get(url, config);\n};\n\nexport const remove: AxiosInstance['delete'] = (url, config) => {\n return axiosInstance.delete(url, config);\n};\nexport const head: AxiosInstance['head'] = (url, config) => {\n return axiosInstance.head(url, config);\n};\nexport const options: AxiosInstance['options'] = (url, config) => {\n return axiosInstance.options(url, config);\n};\nexport const post: AxiosInstance['post'] = (url, data, config) => {\n return axiosInstance.post(url, data, config);\n};\nexport const put: AxiosInstance['put'] = (url, data, config) => {\n return axiosInstance.put(url, data, config);\n};\nexport const patch: AxiosInstance['patch'] = (url, data, config) => {\n return axiosInstance.patch(url, data, config);\n};\n","// see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types\n\nimport type { AxiosError } from 'axios';\nexport class ServerError extends Error {\n public readonly name = 'ServerError';\n\n constructor(public readonly message: string, public readonly errorCode: number) {\n // Pass remaining arguments (including vendor specific ones) to parent constructor\n super(message);\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ServerError);\n }\n }\n}\n\nexport const prepareServerError = (e: any): ServerError => {\n if (e instanceof ServerError) {\n return e;\n } else if (typeof e === 'object' && e.isAxiosError === true) {\n const axiosError = e as AxiosError;\n const errorCode = axiosError.code\n ? parseInt(axiosError.code)\n : axiosError.response?.status\n ? axiosError.response?.status\n : -1;\n return new ServerError(axiosError.message, errorCode);\n } else if (e instanceof Error) {\n return new ServerError(e.message, -1);\n } else {\n return new ServerError(`Unknown error`, -2);\n }\n};\n\nexport const isServerError = (entity: unknown): entity is ServerError => {\n const e = entity as ServerError;\n return !!e.message;\n};\n","import { LocalizationSettings } from '@/common/types/localization';\nimport { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = `api/Settings`;\n\nexport const getLocalizationSettings = async () => {\n try {\n const { data, status } = await get(`${baseUrl}/localization`);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to get localization settings.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { getLocalizationSettings } from '@/api/settings';\nimport { LocalizationSettings } from '@/common/types/localization';\nimport { useQuery } from 'react-query';\n\nexport const useFetchLocalizationSettings = () =>\n useQuery('LocalizationSettings', () => getLocalizationSettings(), {\n staleTime: Infinity,\n });\n","import { defaultLocalizationSettings } from '@/common/types/localization';\nimport { useMemo } from 'react';\nimport { useFetchLocalizationSettings } from './query/useFetchLocalizationSettings';\n\nexport const useLocalizationSettings = () => {\n const { data: settings } = useFetchLocalizationSettings();\n\n return useMemo(() => {\n return settings ? settings : defaultLocalizationSettings;\n }, [settings]);\n};\n","import type { ReactElement } from 'react';\n\nimport { useEffect } from 'react';\nimport { IntlProvider as ReactIntlProvider } from 'react-intl';\nimport { Box } from '@mui/material';\n\nimport { ContentContainer } from '@/components/ContentContainer';\nimport { Content } from '@/components/Content';\nimport { ContentPaper } from '@/components/ContentPaper';\n\nimport { changeLanguage, useActiveLanguage, selectLanguage } from '@/atoms/intl';\nimport { IntlManager } from '@/intl';\nimport { useLocalizationSettings } from '@/common/hooks/useLocalizationSettings';\n\ntype Props = {\n children: ReactElement;\n};\n\n/**\n * react-intl provider.\n * It loads the preferred language translations when the application mounts.\n */\nexport function IntlProvider(props: Props) {\n const { children } = props;\n\n const { messages } = useActiveLanguage();\n const { culture } = useLocalizationSettings();\n\n useEffect(() => {\n // Load initial language as soon as the provider is mounted\n const language = selectLanguage();\n changeLanguage(language);\n }, []);\n\n // shows a placeholder content until the i18n translations have been loaded\n if (!messages) {\n return (\n \n \n \n \n Loading Language Data\n \n \n \n \n );\n }\n\n // wrap the whole components' tree with react-intl provider\n return (\n \n {/* IntlManager is a workaround necessary to expose react-intl API outside the React component's tree */}\n {children}\n \n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n loading: translate({ id: `intl.loading-screen.loading` }),\n error: translate({ id: `intl.loading-screen.error` }),\n };\n }, [translate]);\n}\n","import type { ReactElement } from 'react';\n\nimport { Box } from '@mui/material';\n\nimport { ContentContainer } from '@/components/ContentContainer';\nimport { Content } from '@/components/Content';\nimport { ContentPaper } from '@/components/ContentPaper';\n\nimport { useLanguageLoading } from '@/atoms/intl';\n\nimport { useTexts } from './useTexts';\n\ntype Props = {\n children: ReactElement;\n};\n\nexport function IntlLoadingScreen(props: Props) {\n const { children } = props;\n\n const texts = useTexts();\n const loading = useLanguageLoading();\n\n switch (loading) {\n case 'pending':\n return (\n \n \n \n \n {texts.loading}\n \n \n \n \n );\n\n case 'error':\n return (\n \n \n \n \n {texts.error}\n \n \n \n \n );\n\n default:\n return children;\n }\n}\n","import { ToastContainer } from 'react-toastify';\n\n/**\n * Toast notifications root component\n */\nexport function ToastNotificationProvider() {\n return (\n \n );\n}\n","import { blue, blueGrey, green, grey, orange, red } from '@mui/material/colors';\n\nconst black = '#000000';\nconst white = '#FFFFFF';\n\nexport const palette = {\n background: {\n default: '#F4F6F8',\n paper: white,\n secondary: '#ECECEE',\n },\n badges: {\n error: '#E9C9C9',\n info: '#1257A573',\n success: '#E2F1CB',\n warning: '#FCF1CA',\n },\n black,\n custom: {\n lightGrey: '#ECECEE',\n },\n divider: grey[200],\n error: {\n contrastText: white,\n dark: red[900],\n main: red[600],\n light: red[400],\n },\n icon: blueGrey[600],\n info: {\n contrastText: white,\n dark: blue[900],\n main: blue[600],\n light: blue[400],\n },\n primary: {\n main: blue[800],\n },\n secondary: {\n contrastText: white,\n dark: grey[900],\n main: grey[600],\n light: grey[400],\n },\n success: {\n contrastText: white,\n dark: green[900],\n main: green[600],\n light: green[400],\n },\n text: {\n primary: blueGrey[900],\n secondary: blueGrey[600],\n disabled: grey[600],\n },\n warning: {\n contrastText: white,\n dark: orange[900],\n main: orange[600],\n light: orange[400],\n },\n white,\n};\n","export const MuiDialogTitle = {\n styleOverrides: {\n root: {\n fontWeight: 700,\n fontSize: '16px',\n },\n },\n};\n","export const MuiFormControl = {\n defaultProps: {\n fullWidth: true,\n size: 'small' as const,\n },\n};\n","export const MuiIconButton = {\n styleOverrides: {\n root: {\n '&:hover': {\n backgroundColor: 'rgba(0, 0, 0, 0.03)',\n },\n },\n },\n};\n","export const MuiLink = {\n styleOverrides: {\n root: {\n cursor: 'pointer',\n },\n },\n};\n","export const MuiPaper = {\n styleOverrides: {\n elevation1: {\n boxShadow: '0 0 0 1px rgba(63,63,68,0.05), 0 1px 3px 0 rgba(63,63,68,0.15)',\n },\n },\n};\n","export const MuiSelect = {\n defaultProps: {\n fullWidth: true,\n size: 'small' as const,\n variant: 'outlined' as const,\n },\n};\n","import { palette } from '../palette';\n\nexport const MuiTableCell = {\n styleOverrides: {\n root: {\n borderBottom: `1px solid ${palette.divider}`,\n },\n },\n};\n","import { grey } from '@mui/material/colors';\n\nexport const MuiTableHead = {\n styleOverrides: {\n root: {\n backgroundColor: grey[50],\n },\n },\n};\n","import { palette } from '../palette';\n\nexport const MuiTableRow = {\n styleOverrides: {\n root: {\n '&$selected': {\n backgroundColor: palette.background.default,\n },\n '&$hover': {\n '&:hover': {\n backgroundColor: palette.background.default,\n },\n },\n },\n },\n};\n","export const MuiTextField = {\n defaultProps: {\n fullWidth: true,\n size: 'small' as const,\n variant: 'outlined' as const,\n },\n};\n","export const MuiTypography = {\n styleOverrides: {\n gutterBottom: {\n marginBottom: 8,\n },\n },\n};\n","import { Components } from '@mui/material';\nimport { MuiDialogTitle } from './MuiDialogTitle';\nimport { MuiFormControl } from './MuiFormControl';\nimport { MuiIconButton } from './MuiIconButton';\nimport { MuiLink } from './MuiLink';\nimport { MuiPaper } from './MuiPaper';\nimport { MuiSelect } from './MuiSelect';\nimport { MuiTableCell } from './MuiTableCell';\nimport { MuiTableHead } from './MuiTableHead';\nimport { MuiTableRow } from './MuiTableRow';\nimport { MuiTextField } from './MuiTextField';\nimport { MuiTypography } from './MuiTypography';\n\nexport const components: Components = {\n MuiDialogTitle,\n MuiFormControl,\n MuiIconButton,\n MuiLink,\n MuiPaper,\n MuiSelect,\n MuiTableCell,\n MuiTableHead,\n MuiTableRow,\n MuiTextField,\n MuiTypography,\n};\n","import { TypographyOptions } from '@mui/material/styles/createTypography';\nimport { palette } from './palette';\n\nexport const typography: TypographyOptions = {\n h1: {\n color: palette.text.primary,\n fontWeight: 500,\n fontSize: '35px',\n letterSpacing: '-0.24px',\n lineHeight: '40px',\n },\n h2: {\n color: palette.text.primary,\n fontWeight: 500,\n fontSize: '29px',\n letterSpacing: '-0.24px',\n lineHeight: '32px',\n },\n h3: {\n color: palette.text.primary,\n fontWeight: 500,\n fontSize: '24px',\n letterSpacing: '-0.06px',\n lineHeight: '28px',\n },\n h4: {\n color: palette.text.primary,\n fontWeight: 500,\n fontSize: '20px',\n letterSpacing: '-0.06px',\n lineHeight: '24px',\n },\n h5: {\n color: palette.text.primary,\n fontWeight: 500,\n fontSize: '16px',\n letterSpacing: '-0.05px',\n lineHeight: '20px',\n },\n h6: {\n color: palette.text.primary,\n fontWeight: 500,\n fontSize: '14px',\n letterSpacing: '-0.05px',\n lineHeight: '20px',\n },\n subtitle1: {\n color: palette.text.primary,\n fontSize: '16px',\n letterSpacing: '-0.05px',\n lineHeight: '25px',\n },\n subtitle2: {\n color: palette.text.secondary,\n fontWeight: 400,\n fontSize: '14px',\n letterSpacing: '-0.05px',\n lineHeight: '21px',\n },\n body1: {\n color: palette.text.primary,\n fontSize: '14px',\n letterSpacing: '-0.05px',\n lineHeight: '21px',\n },\n body2: {\n color: palette.text.secondary,\n fontSize: '12px',\n letterSpacing: '-0.04px',\n lineHeight: '18px',\n },\n button: {\n color: palette.text.primary,\n fontSize: '14px',\n },\n caption: {\n color: palette.text.secondary,\n fontSize: '11px',\n letterSpacing: '0.33px',\n lineHeight: '13px',\n },\n overline: {\n color: palette.text.secondary,\n fontSize: '11px',\n fontWeight: 500,\n letterSpacing: '0.33px',\n lineHeight: '13px',\n textTransform: 'uppercase',\n },\n};\n","import { createTheme } from '@mui/material';\nimport { Theme } from '@mui/material/styles';\nimport { palette } from './palette';\nimport { components } from './components';\nimport { typography } from './typography';\n\ndeclare module '@mui/styles' {\n interface DefaultTheme extends Theme {}\n}\n\nexport const theme = createTheme({\n components,\n palette,\n typography,\n zIndex: {\n appBar: 1100,\n drawer: 1200,\n },\n});\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface CustomerPortalSettings extends CustomerPortalFeatures {\n businessUnitId: string;\n companyLogoImageId: string;\n defaultEmailForRequests?: boolean;\n fridayAvailability?: number;\n mondayAvailability?: number;\n saturdayAvailability?: number;\n settingsId: string;\n sundayAvailability?: number;\n themingKey: string;\n thursdayAvailability?: number;\n tuesdayAvailability?: number;\n wednesdayAvailability?: number;\n}\n\nexport interface CustomerPortalFeatures {\n enableBillingHistory?: boolean;\n enableMakePayments?: boolean;\n enableQuestionsAndComments?: boolean;\n enableRequestNewService?: boolean;\n enableServiceHistory?: boolean;\n enableUpcomingServices?: boolean;\n enableViewAgreements?: boolean;\n enableViewPaymentHistory?: boolean;\n enableCreditCardPayment?: boolean;\n enableACHPayment?: boolean;\n enableWorkOrderNumber?: boolean;\n enableScheduledDate?: boolean;\n enableScheduledTime?: boolean;\n enableServiceLocation?: boolean;\n enableIncludedServices?: boolean;\n enableTeamTechnicianInfo?: boolean;\n enablePriceOfServiceVisit?: boolean;\n enableLastServiceWorkOrderNumber?: boolean;\n enableLastServiceScheduledDate?: boolean;\n enableLastServiceScheduledTime?: boolean;\n enableLastServiceServiceLocation?: boolean;\n enableLastServiceIncludedServices?: boolean;\n enableLastServiceTeamTechnicianInfo?: boolean;\n enableLastServicePriceOfServiceVisit?: boolean;\n enableLastServiceServiceReport?: boolean;\n}\n\nconst baseUrl = '/api/CustomerPortalSettingBusinessUnit';\n\nexport const getCustomerPortalSettings = async (businessUnitId: string) => {\n try {\n const { data, status } = await get(`${baseUrl}/${businessUnitId}`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get Customer Portal settings.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { CustomerPortalSettings, getCustomerPortalSettings } from '@/api/businessUnitSettings';\nimport { useMemo } from 'react';\nimport { useQuery } from 'react-query';\n\nexport function useFetchCustomerPortalSettings(businessUnitId: string) {\n const isQueryEnabled = useMemo(() => {\n return !!businessUnitId;\n }, [businessUnitId]);\n\n return useQuery(\n ['customerPortalSettings', businessUnitId],\n () => getCustomerPortalSettings(businessUnitId),\n {\n enabled: isQueryEnabled,\n staleTime: Infinity,\n },\n );\n}\n","import { getAccount } from '@/atoms/session/store';\nimport { blue } from '@mui/material/colors';\nimport { useMemo } from 'react';\nimport { useFetchCustomerPortalSettings } from './query/useFetchCustomerPortalSettings';\n\nexport const useThemingKey = () => {\n const account = getAccount();\n const { data: settings } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n\n return useMemo(() => {\n return settings ? settings.themingKey : blue[800];\n }, [settings]);\n};\n","import { theme } from '@/theme';\nimport { createTheme } from '@mui/material';\nimport { useMemo } from 'react';\nimport { useThemingKey } from './useThemingKey';\n\nexport const useCustomTheme = () => {\n const themingKey = useThemingKey();\n\n const customTheme = useMemo(() => {\n return createTheme({\n ...theme,\n palette: {\n ...theme.palette,\n primary: {\n main: themingKey || theme.palette.primary.main,\n },\n },\n });\n }, [themingKey]);\n\n return customTheme;\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n confirmationWarning: translate({ id: 'components.confirmationDialog.confirmationWarning' }),\n defaultTitle: translate({ id: 'components.confirmationDialog.defaultTitle' }),\n no: translate({ id: 'global.no' }),\n yes: translate({ id: 'global.yes' }),\n };\n }, [translate]);\n}\n","import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from '@mui/material';\nimport { makeStyles } from '@mui/styles';\nimport { useTexts } from './useTexts';\n\nconst useStyles = makeStyles(theme => ({\n actions: {\n padding: `${theme.spacing(2)} ${theme.spacing(3)}`,\n },\n}));\n\ninterface Props {\n message: string;\n onConfirm: () => void;\n onDismiss: () => void;\n open: boolean;\n title: string;\n width?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';\n}\n\nexport function ConfirmationDialog(props: Props) {\n const { open, title, message, onConfirm, onDismiss, width } = props;\n const classes = useStyles();\n const texts = useTexts();\n\n return (\n \n {title}\n \n {message}\n \n \n \n \n \n \n );\n}\n","import { createContext, useState } from 'react';\nimport { ConfirmationDialog } from './ConfirmationDialog';\nimport { useTexts } from './useTexts';\n\nexport const ConfirmationDialogContext = createContext({} as { openDialog: (config: DialogConfig) => void });\n\nexport interface DialogConfig {\n callbackFn: (value: boolean | PromiseLike) => void;\n message: string;\n title: string;\n width?: 'lg' | 'md' | 'sm' | 'xl' | 'xs';\n}\n\ninterface Props {\n children: React.ReactNode;\n}\n\nexport function ConfirmationDialogProvider(props: Props) {\n const { children } = props;\n const [dialogOpen, setDialogOpen] = useState(false);\n const [dialogConfig, setDialogConfig] = useState();\n const texts = useTexts();\n\n const openDialog = (config: DialogConfig) => {\n setDialogOpen(true);\n setDialogConfig(config);\n };\n\n const resetDialog = () => {\n if (!dialogConfig) return;\n setDialogOpen(false);\n };\n\n const onConfirm = () => {\n if (!dialogConfig) return;\n resetDialog();\n dialogConfig.callbackFn(true);\n };\n\n const onDismiss = () => {\n if (!dialogConfig) return;\n resetDialog();\n dialogConfig.callbackFn(false);\n };\n\n return (\n \n \n {children}\n \n );\n}\n","import { ReactElement } from 'react';\n\n// Switch to HashRouter if the server doesn't support URL-rewrites\n// see: https://github.com/ReactTraining/react-router/blob/dev/docs/api-reference.md#browserrouter\nimport { BrowserRouter as Router } from 'react-router-dom';\n\nimport AdapterDateFns from '@mui/lab/AdapterDateFns';\nimport { CssBaseline } from '@mui/material';\nimport { IntlProvider } from '@/intl';\nimport { ThemeProvider } from '@mui/material/styles';\nimport { ToastNotificationProvider } from '@/utils/ToastNotificationProvider';\nimport StyledEngineProvider from '@mui/material/StyledEngineProvider';\nimport { LocalizationProvider } from '@mui/lab';\nimport { useCustomTheme } from '@/common/hooks/useCustomTheme';\nimport enAULocale from 'date-fns/locale/en-AU';\nimport enCALocale from 'date-fns/locale/en-CA';\nimport enGBLocale from 'date-fns/locale/en-GB';\nimport enNZLocale from 'date-fns/locale/en-NZ';\nimport enUSLocale from 'date-fns/locale/en-US';\nimport { CultureCode } from '@/common/types/localization';\nimport { useLocalizationSettings } from '@/common/hooks/useLocalizationSettings';\nimport { ConfirmationDialogProvider } from '@/common/components/ConfirmationDialog/ConfirmationDialogProvider';\n\ninterface Props {\n children: ReactElement;\n}\n\nconst localeMap = {\n [CultureCode.en_AU]: enAULocale,\n [CultureCode.en_CA]: enCALocale,\n [CultureCode.en_GB]: enGBLocale,\n [CultureCode.en_IE]: enGBLocale,\n [CultureCode.en_NZ]: enNZLocale,\n [CultureCode.en_US]: enUSLocale,\n};\n\n/**\n * Component responsible to instantiate and configure all required providers.\n */\nexport function Provider(props: Props) {\n const { children } = props;\n const customTheme = useCustomTheme();\n const { culture } = useLocalizationSettings();\n\n return (\n \n {/* MUI CSS reset */}\n \n\n {/* MUI theme provider, mounted with the application's custom theme */}\n \n {/* Localization provider for date and time pickers */}\n \n {/* react-router provider, enabling the URL routing */}\n \n {/* 18n provider. It starts react-intl engine */}\n \n {/* Confirmation dialog provider */}\n {children}\n \n \n \n \n\n {/* Root component configuring and rendering the toast notification root */}\n \n \n );\n}\n","import { ReactElement } from 'react';\nimport { Box } from '@mui/material';\nimport { makeStyles } from '@mui/styles';\n\ntype Props = {\n children: ReactElement;\n};\n\nconst useStyles = makeStyles(theme => ({\n root: {\n backgroundColor: theme.palette.background.default,\n },\n}));\n\nexport function Layout({ children }: Props) {\n const classes = useStyles();\n\n return (\n \n {children}\n \n );\n}\n","import { PaymentStatus } from '@/common/types/payments';\nimport { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface AccountHistoryResponse {\n total: number;\n page: number;\n take: number;\n items: AccountHistoryItemModel[];\n}\n\nexport enum HistoryItemType {\n WORK_ORDER = 'WorkOrder',\n INVOICE = 'Invoice',\n PAYMENT = 'Payment',\n}\n\nexport enum PaymentMethod {\n ACH = 'ACH',\n CASH = 'Cash',\n CHECK = 'Check',\n CREDIT_CARD = 'CreditCard',\n NONE = 'None',\n}\n\nexport enum InvoiceStatus {\n OPEN = 'Open',\n PAID = 'Paid',\n}\n\nexport interface AccountHistoryItemModel {\n itemType: HistoryItemType;\n accountId: string;\n date: Date;\n paymentId: string | null;\n paymentAmount: number | null;\n paymentAccountType: string | null;\n paymentInvoiceNums: string | null;\n paymentMethod: PaymentMethod | null;\n paymentStatus: PaymentStatus | null;\n invoiceId: string | null;\n invoiceNum: number | null;\n invoiceTotal: number | null;\n invoiceStatus: InvoiceStatus | null;\n isPartiallyRefunded: boolean | null;\n workOrderId: string | null;\n workOrderNumber: number | null;\n workOrderInvoiceNumber: number | null;\n workOrderProjectSequence: number | null;\n workOrderSubNumber: number | null;\n reference: string | null;\n}\n\nconst baseUrl = 'api/Accounts';\n\nfunction getQueryString(\n page: number,\n take: number,\n search: string,\n type: HistoryItemType | '',\n serviceLocations: string[],\n startDate: Date | null,\n endDate: Date | null,\n) {\n const params = new URLSearchParams({\n page: page.toString(),\n take: take.toString(),\n });\n\n if (!!search) {\n params.append('searchTerm', search);\n }\n if (!!type) {\n params.append('itemType', type);\n }\n if (!!serviceLocations.length) {\n serviceLocations.map(x => !!x && params.append('serviceLocation', x));\n }\n if (!!startDate) {\n const date = new Date(startDate);\n date.setUTCHours(0, 0, 0, 0);\n params.append('startDate', date.toISOString());\n }\n if (!!endDate) {\n const date = new Date(endDate);\n date.setUTCHours(23, 59, 59, 999);\n params.append('endDate', date.toISOString());\n }\n\n return params;\n}\n\nexport const getAccountHistory = async (\n accountId: string,\n page: number,\n take: number,\n search: string,\n type: HistoryItemType | '',\n serviceLocations: string[],\n startDate: Date | null,\n endDate: Date | null,\n) => {\n try {\n const queryString = getQueryString(page, take, search, type, serviceLocations, startDate, endDate);\n const { status, data } = await get(`${baseUrl}/${accountId}/history?${queryString}`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get account history.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { useQuery } from 'react-query';\nimport { AccountHistoryResponse, getAccountHistory, HistoryItemType } from '@/api/accountHistory';\n\nexport const useQueryAccountHistory = (\n accountId: string,\n page: number,\n take: number,\n search: string,\n type: HistoryItemType | '',\n serviceLocations: string[],\n startDate: Date | null,\n endDate: Date | null,\n) =>\n useQuery(\n ['accountHistory', accountId, page, take, search, type, serviceLocations, startDate, endDate],\n () => getAccountHistory(accountId, page, take, search, type, serviceLocations, startDate, endDate),\n {\n keepPreviousData: true,\n },\n );\n","// --------------------------------------------------------\n// Log helper\n// --------------------------------------------------------\n\nconst prefixStyles = [\n 'color: lightCoral',\n 'font-size: 12px',\n 'font-weight: bolder',\n 'padding-left: 10px',\n 'padding-right: 5px',\n].join(';');\n\nconst contextStyles = ['color: goldenRod', 'font-size: 12px', 'font-weight: bolder', 'padding-right: 10px'].join(';');\n\nfunction log(main: string, value: string, ...args: any[]) {\n console.log(`%c[${main}] %c${value}`, prefixStyles, contextStyles, ...args);\n}\n\n// --------------------------------------------------------\n// retrieve system info\n// --------------------------------------------------------\n\nexport type EnvironmentInfo = {\n mobile: boolean;\n touchEnabled: boolean;\n width: number;\n height: number;\n pixelRatio: number;\n};\n\nexport function getHostEnvironmentInfo(): EnvironmentInfo {\n // log('NAVIGATOR', navigator.userAgent);\n const mobile = !!navigator.userAgent.match(/Mobi/gm);\n const touchEnabled = navigator.maxTouchPoints > 0;\n\n return {\n mobile,\n touchEnabled,\n width: window.screen.availWidth,\n height: window.screen.availHeight,\n pixelRatio: window.devicePixelRatio,\n };\n}\n\n// --------------------------------------------------------\n// check and subscribe to the device orientation\n// --------------------------------------------------------\n\nexport type DeviceOrientation = 'portrait' | 'landscape';\ntype OnChangeOrientationEventHandler = (orientation: DeviceOrientation) => void;\n\nexport function subscribeToDeviceOrientation(listener: OnChangeOrientationEventHandler) {\n const query = '(orientation: portrait)';\n const mq = window.matchMedia(query);\n\n const onChange = (e: MediaQueryListEvent) => {\n listener(e.matches ? 'portrait' : 'landscape');\n };\n\n mq.addEventListener('change', onChange);\n\n return () => {\n mq.removeEventListener('change', onChange);\n };\n}\n\nexport function getDeviceOrientation(): DeviceOrientation {\n const query = '(orientation: portrait)';\n const mq = window.matchMedia(query);\n\n return mq.matches ? 'portrait' : 'landscape';\n}\n\n// --------------------------------------------------------\n// utility to print system info in console\n// --------------------------------------------------------\n\nexport function printHostEnvironmentInfo() {\n log('Device orientation', getDeviceOrientation());\n\n const info = getHostEnvironmentInfo();\n log('Device Info', JSON.stringify(info, null, 2));\n}\n","import type { EnvironmentInfo, DeviceOrientation } from '@/utils/hostEnvironmentInfo';\n\nimport { proxy, useSnapshot } from 'valtio';\n\nimport {\n getHostEnvironmentInfo,\n getDeviceOrientation,\n subscribeToDeviceOrientation,\n} from '@/utils/hostEnvironmentInfo';\n\n// ----------------------------\n// Store state\n// ----------------------------\n\ntype Layout = 'mobile' | 'desktop';\ntype UILayout = {\n env: EnvironmentInfo;\n orientation: DeviceOrientation;\n layout: Layout;\n};\n\n// ----------------------------\n// Utilities\n// ----------------------------\n\nfunction determineLayout(env: EnvironmentInfo): Layout {\n // if is not mobile-ish just opt-in for desktop\n // return 'mobile';\n if (!env.mobile || !env.touchEnabled) return 'desktop';\n\n // on mobile\n const targetSideSize = env.width < env.height ? env.width : env.height;\n const sideSize = targetSideSize * env.pixelRatio;\n\n // iPhone smaller side is 1125px when you consider device pixels ratio\n // iPad smaller side is 1536px when you consider device pixels ratio\n return sideSize >= 1250 ? 'desktop' : 'mobile';\n}\n\n// ----------------------------\n// Valtio store initialization\n// ----------------------------\n\nfunction getInitialState(): UILayout {\n const env = getHostEnvironmentInfo();\n const orientation = getDeviceOrientation();\n const layout = determineLayout(env);\n\n console.log('-------');\n console.log(`Active Layout: ${layout}`);\n console.log('-------');\n\n return {\n env,\n layout,\n orientation,\n };\n}\n\nconst state = proxy(getInitialState());\n\n// ----------------------------\n// Monitor the device orientation\n// ----------------------------\n\nsubscribeToDeviceOrientation(orientation => {\n state.orientation = orientation;\n});\n\n// ----------------------------\n// selector functions\n// ----------------------------\n\nexport function getUILayout() {\n return state.layout;\n}\n\nexport function getUILayoutInfo() {\n return state.env;\n}\n\nexport function getUILayoutOrientation() {\n return state.env;\n}\n\n// ----------------------------\n// React hooks\n// ----------------------------\n\nexport function useGetUILayout() {\n return useSnapshot(state).layout;\n}\n\nexport function useGetUILayoutInfo() {\n return useSnapshot(state).env;\n}\n\nexport function useGetUILayoutOrientation() {\n return useSnapshot(state).orientation;\n}\n","export const appbarHeight = 64;\nexport const avatarSize = 36;\nexport const emptyGuid = '00000000-0000-0000-0000-000000000000';\nexport const mobileAppbarHeight = 56;\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport { appbarHeight } from '@/common/constants';\nimport { Container } from '@mui/material';\nimport Box from '@mui/material/Box';\nimport makeStyles from '@mui/styles/makeStyles';\n\ninterface Props {\n children: React.ReactNode;\n disableScroll?: boolean;\n fullWidth?: boolean;\n}\n\nconst useStyles = (props: Props) => {\n return makeStyles(theme => ({\n desktop: {\n display: 'flex',\n flexDirection: 'column',\n height: `calc(100vh - ${appbarHeight}px)`,\n width: '100%',\n overflowY: props.disableScroll ? 'hidden' : 'auto',\n padding: theme.spacing(2),\n },\n desktopContainer: {\n height: '100%',\n marginLeft: 0,\n marginRight: 'auto',\n },\n mobile: {\n height: '100%',\n overflowY: props.disableScroll ? 'hidden' : 'auto',\n padding: theme.spacing(2),\n },\n }));\n};\n\nexport function PageWrapper(props: Props) {\n const { children, fullWidth } = props;\n const layout = useGetUILayout();\n\n return layout == 'desktop' ? (\n {children}\n ) : (\n {children}\n );\n}\n\nexport function PageWrapperDesktop(props: Props) {\n const { children, fullWidth } = props;\n const classes = useStyles(props)();\n\n return (\n \n \n {children}\n \n \n );\n}\n\nexport function PageWrapperMobile(props: Props) {\n const { children } = props;\n const classes = useStyles(props)();\n\n return (\n \n {children}\n \n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n errorMessage: translate({ id: 'components.pageErrorState.errorMessage' }),\n };\n }, [translate]);\n}\n","import Alert from '@mui/material/Alert';\nimport Grid from '@mui/material/Grid';\nimport Typography from '@mui/material/Typography';\nimport { useTexts } from './useTexts';\n\nexport function PageErrorState() {\n const texts = useTexts();\n\n return (\n \n \n \n {texts.errorMessage}\n \n \n \n );\n}\n","import { useCallback, useState } from 'react';\n\nexport const useDrawerState = () => {\n const [isOpen, setIsOpen] = useState(false);\n\n const openDrawer = useCallback(() => {\n setIsOpen(true);\n }, []);\n\n const closeDrawer = useCallback(() => {\n setIsOpen(false);\n }, []);\n\n return [closeDrawer, isOpen, openDrawer] as const;\n};\n","import { Box } from '@mui/material';\n\ninterface Props {\n body: JSX.Element;\n footer: JSX.Element;\n header: JSX.Element;\n}\n\nexport function CardList(props: Props) {\n const { body, footer, header } = props;\n\n return (\n \n {header}\n {body}\n {footer}\n \n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n clearAll: translate({ id: 'sections.accountHistory.filters.clearAll' }),\n filter: translate({ id: 'sections.accountHistory.filters' }),\n invoices: translate({ id: 'sections.accountHistory.filters.invoices' }),\n onOrAfter: translate({ id: 'sections.accountHistory.filters.onOrAfter' }),\n onOrBefore: translate({ id: 'sections.accountHistory.filters.onOrBefore' }),\n payments: translate({ id: 'sections.accountHistory.filters.payments' }),\n serviceVisits: translate({ id: 'sections.accountHistory.filters.serviceVisits' }),\n showAllServiceLocations: translate({ id: 'sections.accountHistory.filters.showAllServiceLocations' }),\n };\n }, [translate]);\n}\n","import Typography from '@mui/material/Typography';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport FilterListIcon from '@mui/icons-material/FilterList';\nimport Stack from '@mui/material/Stack';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n chips?: JSX.Element;\n hideFilters?: boolean;\n openDrawer?: () => void;\n searchBox?: React.ReactNode;\n singleLineOnMobile?: boolean;\n title: string;\n}\n\nexport function ListHeader(props: Props) {\n const { chips, hideFilters, openDrawer, searchBox, singleLineOnMobile, title } = props;\n const layout = useGetUILayout();\n const texts = useTexts();\n\n return (\n \n \n {layout == 'desktop' && (\n \n \n {title}\n \n {!hideFilters && (\n <>\n {searchBox}\n \n \n )}\n \n )}\n\n {layout == 'mobile' && (\n \n \n {title}\n \n {!hideFilters && (\n \n \n {searchBox}\n \n \n \n )}\n \n )}\n\n {!!chips && chips}\n \n \n );\n}\n","import { Box, Grid, Alert } from '@mui/material';\nimport { FunctionComponent } from 'react';\n\ninterface CardProps {\n item: T;\n disabled?: boolean;\n}\n\ninterface Props {\n card: FunctionComponent>;\n items: T[];\n emptyListAlertText: string;\n disabled?: boolean;\n}\n\nexport function ListBody(props: Props) {\n const { card: Card, emptyListAlertText, items, disabled } = props;\n\n return (\n \n \n {!!items.length &&\n items.map((x, i) => (\n \n \n \n ))}\n {!items.length && {emptyListAlertText}}\n \n \n );\n}\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport Box from '@mui/material/Box';\nimport Pagination from '@mui/material/Pagination';\nimport { useCallback, useMemo } from 'react';\n\ninterface Props {\n count: number;\n page: number;\n onChange: (event: React.ChangeEvent, page: number) => void;\n}\n\nexport function ListFooter(props: Props) {\n const { count, page, onChange } = props;\n const layout = useGetUILayout();\n\n const siblingCount = useMemo(() => {\n return layout == 'mobile' ? 0 : 1;\n }, [layout]);\n\n const handlePageChange = useCallback(\n (event: React.ChangeEvent, page: number | null) => {\n if (!!page) {\n onChange(event, page);\n }\n },\n [onChange],\n );\n\n return (\n \n \n \n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n cancelled: translate({ id: 'sections.accountHistory.paymentCard.cancelled' }),\n failed: translate({ id: 'sections.accountHistory.paymentCard.failed' }),\n filters: translate({ id: 'sections.accountHistory.filters' }),\n forInvoice: translate({ id: 'sections.accountHistory.paymentCard.forInvoice' }),\n invoice: translate({ id: 'global.invoice' }),\n noHistoryAlert: translate({ id: 'sections.accountHistory.noHistoryAlert' }),\n open: translate({ id: 'sections.accountHistory.invoiceCard.open' }),\n paid: translate({ id: 'sections.accountHistory.invoiceCard.paid' }),\n payment: translate({ id: 'sections.accountHistory.paymentCard.payment' }),\n partiallyRefunded: translate({ id: 'sections.accountHistory.paymentCard.partiallyRefunded' }),\n pending: translate({ id: 'sections.accountHistory.paymentCard.pending' }),\n refunded: translate({ id: 'sections.accountHistory.paymentCard.refunded' }),\n refundedPayment: translate({ id: 'sections.accountHistory.paymentCard.refundedPayment' }),\n searchPlaceholder: translate({ id: 'sections.accountHistory.searchPlaceholder' }),\n serviceVisit: translate({ id: 'sections.accountHistory.serviceCard.serviceVisit' }),\n succeeded: translate({ id: 'sections.accountHistory.paymentCard.succeeded' }),\n title: translate({ id: 'sections.accountHistory.title' }),\n workOrder: translate({ id: 'global.workOrder' }),\n };\n }, [translate]);\n}\n","import { debounce } from 'lodash';\nimport { useState, useMemo, useEffect } from 'react';\n\nexport function useDebounce(value: T, delay: number = 500) {\n const [debounced, setDebounced] = useState(value);\n\n const update = useMemo(() => debounce((v: T) => setDebounced(v), delay), [delay]);\n\n useEffect(() => {\n update(value);\n\n return () => {\n update.cancel();\n };\n }, [update, value]);\n\n return debounced;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n search: translate({ id: 'global.search' }),\n };\n }, [translate]);\n}\n","import CloseIcon from '@mui/icons-material/Close';\nimport SearchIcon from '@mui/icons-material/Search';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport { IconButton } from '@mui/material';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onChange: (event: React.ChangeEvent) => void;\n onClear: () => void;\n placeholder?: string;\n value: string;\n}\n\nexport const SearchBox = (props: Props) => {\n const { onChange, onClear, placeholder, value } = props;\n const texts = useTexts();\n\n return (\n \n \n \n ),\n endAdornment: (\n \n \n \n \n \n ),\n }}\n onChange={onChange}\n placeholder={placeholder || texts.search}\n value={value}\n />\n );\n};\n\nSearchBox.displayName = 'SearchBox';\n","import { useDebounce } from '@/common/hooks/useDebounce';\nimport { SearchBox as CommonSearchBox } from '@/components/SearchBox/SearchBox';\nimport { useCallback, useEffect, useState } from 'react';\n\ninterface Props {\n placeholder: string;\n value: string;\n setValue: (val: string) => void;\n}\n\nexport function DebouncedSearchBox(props: Props) {\n const { placeholder, value, setValue } = props;\n const [internalValue, setInternalValue] = useState(value);\n const debouncedValue = useDebounce(internalValue, 500);\n\n const handleSearchChanged = useCallback((e: React.ChangeEvent) => {\n setInternalValue(e.target.value);\n }, []);\n\n const handleSearchCleared = useCallback(() => {\n setInternalValue('');\n }, []);\n\n useEffect(() => {\n setValue(debouncedValue);\n }, [debouncedValue, setValue]);\n\n return (\n \n );\n}\n","import { HistoryItemType } from '@/api/accountHistory';\nimport { proxy, useSnapshot } from 'valtio';\nimport { useMemo } from 'react';\n\n// Store state\nexport interface ListState {\n page: number;\n take: number;\n search: string;\n type: HistoryItemType | '';\n serviceLocations: string[];\n selected: string;\n startDate: Date | null;\n endDate: Date | null;\n}\n\nexport const initialState: ListState = {\n page: 0,\n take: 10,\n search: '',\n type: '',\n serviceLocations: [''],\n selected: '',\n startDate: null,\n endDate: null,\n};\n\n// Valtio store initialization\nexport const state = proxy(initialState);\n\n// Setter functions\nexport function setPage(page: number) {\n state.page = page;\n}\n\nexport function setTake(take: number) {\n state.take = take;\n}\n\nexport function setSearch(search: string) {\n state.search = search;\n}\n\nexport function setType(type: HistoryItemType | '') {\n state.type = type;\n}\n\nexport function clearType() {\n state.type = initialState.type;\n}\n\nexport function setServiceLocations(locations: string[]) {\n state.serviceLocations = locations;\n\n if (!state.serviceLocations.length) {\n state.serviceLocations = initialState.serviceLocations;\n }\n}\n\nexport function clearServiceLocations() {\n state.serviceLocations = initialState.serviceLocations;\n}\n\nexport function setStartDate(date: Date | null) {\n state.startDate = date;\n}\n\nexport function setEndDate(date: Date | null) {\n state.endDate = date;\n}\n\nexport function clearDates() {\n state.startDate = initialState.startDate;\n state.endDate = initialState.endDate;\n}\n\nexport function setSelectedItem(id: string) {\n state.selected = id;\n}\n\nexport function clearSelectedItem() {\n state.selected = '';\n}\n\nexport function resetFilters() {\n clearType();\n clearServiceLocations();\n clearDates();\n}\n\nexport function resetStore() {\n state.page = initialState.page;\n state.take = initialState.take;\n state.search = initialState.search;\n state.type = initialState.type;\n state.serviceLocations = initialState.serviceLocations;\n state.selected = initialState.selected;\n state.startDate = initialState.startDate;\n state.endDate = initialState.endDate;\n}\n\n//Hooks\nexport function useListState() {\n return useSnapshot(state);\n}\n\nexport function useIsListFiltered() {\n const { type, startDate, endDate, serviceLocations } = state;\n\n const isListFiltered = useMemo(() => {\n return !!type || !!startDate || !!endDate || (!!serviceLocations.length && !!serviceLocations[0]);\n }, [type, startDate, endDate, serviceLocations]);\n\n return isListFiltered;\n}\n","import { useCallback } from 'react';\nimport {\n clearDates,\n clearServiceLocations,\n clearType,\n resetFilters,\n setEndDate,\n setPage,\n setSearch,\n setTake,\n setType,\n setServiceLocations,\n setStartDate,\n} from '../store';\n\nexport function useListActions() {\n const handleClearDates = useCallback(() => {\n setPage(0);\n clearDates();\n }, []);\n\n const handleClearServiceLocations = useCallback(() => {\n setPage(0);\n clearServiceLocations();\n }, []);\n\n const handleClearType = useCallback(() => {\n setPage(0);\n clearType();\n }, []);\n\n const handleDeleteServiceLocationFilter = useCallback(\n (id: string, serviceLocations: string[]) => (_e: React.MouseEvent) => {\n setPage(0);\n setServiceLocations(serviceLocations.filter(x => x !== id));\n },\n [],\n );\n\n const handleResetFilters = useCallback(() => {\n setPage(0);\n resetFilters();\n }, []);\n\n const handleSetEndDate = useCallback((date: Date | null, _keyboardInputValue?: string | undefined) => {\n if (!date) {\n setEndDate(null);\n }\n if (date?.toString() == 'Invalid Date') {\n return;\n }\n if (!!date) {\n setPage(0);\n setEndDate(new Date(date.toDateString()));\n }\n }, []);\n\n const handleSetPage = useCallback((_e, page: number) => {\n setPage(page - 1);\n }, []);\n\n const handleSetSearch = useCallback((search: string) => {\n setPage(0);\n setSearch(search);\n }, []);\n\n const handleSetServiceLocations = useCallback((locations: string[]) => {\n setPage(0);\n setServiceLocations(locations);\n }, []);\n\n const handleSetTake = useCallback((take: number) => {\n setTake(take);\n }, []);\n\n const handleSetType = useCallback(e => {\n setPage(0);\n setType(e.target.value);\n }, []);\n\n const handleSetStartDate = useCallback((date: Date | null, _keyboardInputValue?: string | undefined) => {\n if (!date) {\n setStartDate(null);\n }\n if (date?.toString() == 'Invalid Date') {\n return;\n }\n if (!!date) {\n setPage(0);\n setStartDate(new Date(date.toDateString()));\n }\n }, []);\n\n return {\n handleClearDates,\n handleClearServiceLocations,\n handleClearType,\n handleDeleteServiceLocationFilter,\n handleResetFilters,\n handleSetEndDate,\n handleSetPage,\n handleSetSearch,\n handleSetServiceLocations,\n handleSetTake,\n handleSetType,\n handleSetStartDate,\n } as const;\n}\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface ServiceLocation {\n accountId: string;\n active: boolean;\n businessUnitId: string;\n city: string;\n country: string;\n countryCode: string;\n county: string;\n defaultBillingLocationId: string;\n defaultContactId: string;\n latitude: number;\n longitude: number;\n manualTaxRateId: string;\n name: string | null;\n number: number;\n postalCode: string;\n serviceLocationId: string;\n serviceMemo: string | null;\n state: string;\n stateAbbreviation: string;\n street1: string;\n street2: string | null;\n taxRate: number;\n taxRateDetail: string;\n timeZoneId: string;\n validationErrors: string;\n zoneId: string;\n}\n\nexport interface PropertyTrait {\n amount: number;\n name: string;\n propertyTraitId: string;\n serviceLocationId: string;\n serviceLocationPropertyTraitId: string;\n unitOfMeasure: string;\n}\n\nconst baseUrl = '/api/serviceLocations';\n\nexport const getLocations = async (accountId: string) => {\n try {\n const { data, status } = await get(`${baseUrl}?accountId=${accountId}`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get service locations.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getPropertyTraitsByService = async (serviceId: string, serviceLocationId: string) => {\n try {\n const { data, status } = await get(\n `${baseUrl}/${serviceLocationId}/ServiceLocationPropertyTraits?serviceId=${serviceId}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get property traits.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { getLocations, ServiceLocation } from '@/api/serviceLocations';\nimport { useQuery } from 'react-query';\n\nexport const useFetchServiceLocations = (accountId: string) =>\n useQuery([accountId, 'serviceLocations'], () => getLocations(accountId), {\n staleTime: Infinity,\n });\n","import { CultureCode } from './localization';\n\nexport enum CurrencyCode {\n AUD = 'AUD',\n CAD = 'CAD',\n GBP = 'GBP',\n EUR = 'EUR',\n USD = 'USD',\n NZD = 'NZD',\n}\n\nexport const DefaultCurrencyCode: Record = {\n [CultureCode.en_AU]: CurrencyCode.AUD,\n [CultureCode.en_CA]: CurrencyCode.CAD,\n [CultureCode.en_GB]: CurrencyCode.GBP,\n [CultureCode.en_IE]: CurrencyCode.EUR,\n [CultureCode.en_US]: CurrencyCode.USD,\n [CultureCode.en_NZ]: CurrencyCode.NZD,\n};\n","import { useLocalizationSettings } from '@/common/hooks/useLocalizationSettings';\nimport { DefaultCurrencyCode } from '@/common/types/currency';\nimport { FormattedNumber } from 'react-intl';\n\ninterface Props {\n value: number;\n}\n\nexport function Currency(props: Props) {\n const { value } = props;\n const { culture } = useLocalizationSettings();\n\n return (\n \n );\n}\n","import { FormattedDate, FormattedTime } from 'react-intl';\n\ninterface Props {\n value: string | number | Date | undefined;\n}\n\nexport function LongDate(props: Props) {\n const { value } = props;\n return ;\n}\n\nexport function LongDateTime(props: Props) {\n const { value } = props;\n return (\n \n );\n}\n\nexport function DateOnly(props: Props) {\n const { value } = props;\n return ;\n}\n\nexport function ShortDate(props: Props) {\n const { value } = props;\n return ;\n}\n\nexport function Time(props: Props) {\n const { value } = props;\n return ;\n}\n","export interface FormattablePhoneNumber {\n callingCode?: string;\n phone: string;\n phoneExt: string | null;\n}\n\nexport function formatPhoneNumber(l: FormattablePhoneNumber, showCountryCode: boolean) {\n if (!l || !l.phone) {\n return '';\n }\n return (\n (showCountryCode && !!l.callingCode ? `+${l.callingCode} ` : '') +\n `${l.phone}` +\n (l.phoneExt ? ` ext. ${l.phoneExt}` : '')\n );\n}\n\nexport function formatPhoneNumberTelLink(l: FormattablePhoneNumber) {\n if (!l || !l.phone) {\n return '';\n }\n return `tel:${l.callingCode || ''}${l.phone}` + (l.phoneExt ? `,${l.phoneExt}` : '');\n}\n","import { useMemo } from 'react';\nimport { formatPhoneNumber, formatPhoneNumberTelLink, FormattablePhoneNumber } from '../utils/formatPhoneNumber';\nimport { useLocalizationSettings } from './useLocalizationSettings';\n\nexport const usePhoneNumber = (p: FormattablePhoneNumber) => {\n const { showCountryCode } = useLocalizationSettings();\n\n const phoneNumber = useMemo(() => {\n return formatPhoneNumber(p, showCountryCode);\n }, [p, showCountryCode]);\n\n return phoneNumber;\n};\n\nexport const usePhoneNumberTelLink = (p: FormattablePhoneNumber) => {\n const phoneNumber = useMemo(() => {\n return formatPhoneNumberTelLink(p);\n }, [p]);\n\n return phoneNumber;\n};\n","import { usePhoneNumber, usePhoneNumberTelLink } from '@/common/hooks/usePhoneNumber';\nimport { Link } from '@mui/material';\n\ninterface Props {\n callingCode?: string;\n phone: string;\n phoneExt?: string;\n}\n\nexport function PhoneNumber(props: Props) {\n const { callingCode = '', phone, phoneExt = '' } = props;\n\n const formattedPhoneNumber = usePhoneNumber({ callingCode, phone, phoneExt });\n const telLink = usePhoneNumberTelLink({ callingCode, phone, phoneExt });\n\n return {formattedPhoneNumber};\n}\n","import { ShortDate } from '@/components/localization';\nimport Chip from '@mui/material/Chip';\nimport { useMemo } from 'react';\nimport { useTexts } from '../useTexts';\n\ntype Props = {\n startDate: Date | null;\n endDate: Date | null;\n onDelete: React.MouseEventHandler;\n};\n\nexport function DateFilterChip(props: Props) {\n const { onDelete, startDate, endDate } = props;\n const texts = useTexts();\n\n const label = useMemo(() => {\n if (!startDate) {\n return (\n \n {`${texts.onOrBefore} `}\n {!!endDate && }\n \n );\n }\n if (!endDate) {\n return (\n \n {`${texts.onOrAfter} `}\n {!!startDate && }\n \n );\n }\n if (!!startDate && !!endDate) {\n return (\n \n \n {' - '}\n \n \n );\n }\n }, [startDate, endDate, texts.onOrAfter, texts.onOrBefore]);\n\n return ;\n}\n","import { HistoryItemType } from '@/api/accountHistory';\nimport Chip from '@mui/material/Chip';\nimport { useMemo } from 'react';\nimport { useTexts } from '../useTexts';\n\ntype Props = {\n type: HistoryItemType;\n onDelete: React.MouseEventHandler;\n};\n\nexport function HistoryTypeFilterChip(props: Props) {\n const { onDelete, type } = props;\n const texts = useTexts();\n\n const label = useMemo(() => {\n switch (type) {\n case HistoryItemType.INVOICE:\n return texts.invoices;\n case HistoryItemType.WORK_ORDER:\n return texts.serviceVisits;\n case HistoryItemType.PAYMENT:\n return texts.payments;\n }\n }, [type, texts.invoices, texts.serviceVisits, texts.payments]);\n\n return ;\n}\n","import { ServiceLocation } from '@/api/serviceLocations';\nimport Chip from '@mui/material/Chip';\nimport { useMemo } from 'react';\n\ntype Props = {\n id: string;\n onDelete: React.MouseEventHandler;\n serviceLocations: ServiceLocation[];\n};\n\nexport function ServiceLocationFilterChip(props: Props) {\n const { onDelete, id, serviceLocations } = props;\n\n const label = useMemo(() => {\n const location = serviceLocations.find(x => x.serviceLocationId === id);\n\n if (!location) {\n return '';\n }\n\n return `${location.street1}${!!location.street2 ? `, ${location.street2}` : ''}`;\n }, [id, serviceLocations]);\n\n return ;\n}\n","import Button from '@mui/material/Button';\nimport Box from '@mui/material/Box';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n onClick: React.MouseEventHandler;\n}\n\nconst useStyles = makeStyles({\n button: {\n whiteSpace: 'nowrap',\n minWidth: 'max-content',\n },\n});\n\nexport function ClearFiltersButton(props: Props) {\n const { onClick } = props;\n const texts = useTexts();\n const classes = useStyles();\n\n return (\n \n \n \n );\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { DateFilterChip, HistoryTypeFilterChip, ServiceLocationFilterChip } from '@/components/cardList/chips';\nimport { ClearFiltersButton } from '@/components/cardList/filters';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { useListActions } from '../hooks';\nimport { useIsListFiltered, useListState } from '../store';\n\nexport function Chips() {\n const { startDate, endDate, type, serviceLocations } = useListState();\n const isListFiltered = useIsListFiltered();\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { handleClearDates, handleClearType, handleResetFilters, handleDeleteServiceLocationFilter } =\n useListActions();\n\n return (\n <>\n {!!locations?.length && (\n \n \n \n {!!type && }\n {(!!startDate || !!endDate) && (\n \n )}\n {!!serviceLocations.length &&\n serviceLocations.map(\n x =>\n !!x && (\n \n ),\n )}\n \n \n\n \n {isListFiltered && }\n \n \n )}\n \n );\n}\n","import { DebouncedSearchBox } from '@/components/cardList/DebouncedSearchBox';\nimport { ListHeader } from '@/components/cardList';\nimport { useTexts } from '../../useTexts';\nimport { useListState } from '../store';\nimport { useListActions } from '../hooks';\nimport { Chips } from './Chips';\n\ninterface Props {\n openDrawer: () => void;\n}\n\nexport function AccountHistoryListHeader(props: Props) {\n const { openDrawer } = props;\n const texts = useTexts();\n const { search } = useListState();\n const { handleSetSearch } = useListActions();\n\n return (\n \n }\n chips={}\n />\n );\n}\n","import * as React from 'react';\nimport CloseIcon from '@mui/icons-material/Close';\nimport { Box, Divider, Drawer, IconButton, Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useGetUILayout } from '@/atoms/UILayout';\n\ntype Props = {\n children?: React.ReactNode;\n footer?: React.ReactNode;\n footerSecondary?: React.ReactNode;\n headerSecondary?: React.ReactNode;\n isOpen: boolean;\n onClose: () => void;\n title: string;\n};\n\nexport const SideDrawer = (props: Props) => {\n const layout = useGetUILayout();\n\n const useFormStyles = makeStyles({\n container: {\n overflowY: 'auto',\n width: '100%',\n height: '100%',\n },\n drawer: {\n flexShrink: 0,\n width: layout == 'mobile' ? 350 : 550,\n maxWidth: '90%',\n },\n });\n\n const { children, footer, footerSecondary, headerSecondary, isOpen, title, onClose } = props;\n const classes = useFormStyles();\n\n return (\n \n \n \n {title}\n\n {layout == 'desktop' && (\n \n \n \n )}\n \n\n \n\n {!!headerSecondary && <>{headerSecondary}}\n\n \n {children}\n \n\n {!!footerSecondary && (\n <>\n \n {footerSecondary}\n \n )}\n\n {!!footer && (\n <>\n \n {footer}\n \n )}\n \n \n );\n};\n\nSideDrawer.displayName = 'SideDrawer';\n","export interface FormattableAddress {\n city: string;\n postalCode: string;\n stateAbbreviation: string;\n street1: string;\n street2: string | null;\n}\n\nexport function formatAddress(l: FormattableAddress | null) {\n if (!l) {\n return '';\n }\n return `${l.street1},${l.street2 ? ` ${l.street2},` : ''} ${l.city}, ${l.stateAbbreviation} ${l.postalCode}`;\n}\n","import Select from '@mui/material/Select';\nimport MenuItem from '@mui/material/MenuItem';\nimport { useCallback } from 'react';\nimport { formatAddress } from '@/common/utils/formatAddress';\nimport { ServiceLocation } from '@/api/serviceLocations';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n locations: ServiceLocation[];\n serviceLocations: string[];\n setServiceLocations: (locations: string[]) => void;\n}\n\nexport function ServiceLocationFilter(props: Props) {\n const { locations, serviceLocations, setServiceLocations } = props;\n const texts = useTexts();\n\n const handleAllClicked = useCallback(\n e => {\n setServiceLocations([e.target.dataset.value]);\n },\n [setServiceLocations],\n );\n\n const handleOptionClicked = useCallback(\n e => {\n const val = e.target.dataset.value;\n if (!serviceLocations.find(x => x === val)) {\n setServiceLocations([...serviceLocations, val].filter(x => !!x));\n } else {\n if (serviceLocations.length === 1) {\n setServiceLocations(['']);\n } else {\n setServiceLocations([...serviceLocations].filter(x => x !== val));\n }\n }\n },\n [serviceLocations, setServiceLocations],\n );\n\n return (\n \n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n clearAll: translate({ id: 'sections.accountHistory.filters.clearAll' }),\n endDateLabel: translate({ id: 'sections.accountHistory.filters.endDateLabel' }),\n invoices: translate({ id: 'sections.accountHistory.filters.invoices' }),\n payments: translate({ id: 'sections.accountHistory.filters.payments' }),\n serviceVisits: translate({ id: 'sections.accountHistory.filters.serviceVisits' }),\n showAllServiceLocations: translate({ id: 'sections.accountHistory.filters.showAllServiceLocations' }),\n showCompleteAccountHistory: translate({\n id: 'sections.accountHistory.filters.drawer.showCompleteAccountHistory',\n }),\n startDateLabel: translate({ id: 'sections.accountHistory.filters.startDateLabel' }),\n title: translate({ id: 'sections.accountHistory.filters.drawer.title' }),\n workOrder: translate({ id: 'global.workOrder' }),\n };\n }, [translate]);\n}\n","import { DatePickerProps, DesktopDatePicker, MobileDatePicker } from '@mui/lab';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport TextField, { TextFieldProps } from '@mui/material/TextField';\n\ninterface Props extends Omit, 'renderInput'> {\n renderInput?: (props: TextFieldProps) => React.ReactElement;\n}\n\nexport function DatePicker(props: Props) {\n const layout = useGetUILayout();\n\n return (\n <>\n {layout == 'desktop' ? (\n }\n />\n ) : (\n }\n />\n )}\n \n );\n}\n","import Box from '@mui/material/Box';\nimport { DatePicker } from '@/components/DatePicker';\nimport { useListState } from '../store';\nimport { useListActions } from '../hooks';\nimport { useTexts } from './useTexts';\n\nexport function StartDate() {\n const { startDate } = useListState();\n const texts = useTexts();\n const { handleSetStartDate } = useListActions();\n\n return (\n \n \n \n );\n}\n","import Box from '@mui/material/Box';\nimport { useCallback } from 'react';\nimport { DatePicker } from '@/components/DatePicker';\nimport { useListState } from '../store';\nimport { useListActions } from '../hooks';\nimport { useTexts } from './useTexts';\n\nexport function EndDate() {\n const { startDate, endDate } = useListState();\n const texts = useTexts();\n const { handleSetEndDate } = useListActions();\n\n const shouldDisableDate = useCallback(\n (date: Date | null, _keyboardInputValue?: string | undefined) => {\n if (!date) {\n return false;\n }\n\n return !!startDate && date < startDate;\n },\n [startDate],\n );\n\n return (\n \n \n \n );\n}\n","import { CustomerPortalFeatures } from '@/api/businessUnitSettings';\nimport { getAccount } from '@/atoms/session/store';\nimport { useMemo } from 'react';\nimport { useFetchCustomerPortalSettings } from './query/useFetchCustomerPortalSettings';\n\nexport const useFeatureEnabled = (feature: keyof CustomerPortalFeatures) => {\n const account = getAccount();\n const { data: settings } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n\n return useMemo(() => {\n return settings ? settings[feature] : false;\n }, [feature, settings]);\n};\n","import { HistoryItemType } from '@/api/accountHistory';\nimport Select from '@mui/material/Select';\nimport MenuItem from '@mui/material/MenuItem';\nimport { useCallback } from 'react';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { useListState } from '../store';\nimport { useListActions } from '../hooks';\nimport { useTexts } from './useTexts';\n\nexport function ItemType() {\n const texts = useTexts();\n const { type } = useListState();\n const { handleSetType } = useListActions();\n const serviceHistoryEnabled = useFeatureEnabled('enableServiceHistory');\n const paymentHistoryEnabled = useFeatureEnabled('enableViewPaymentHistory');\n const invoiceHistoryEnabled = useFeatureEnabled('enableBillingHistory');\n\n const formatMenuItemText = useCallback(\n (type: HistoryItemType) => {\n switch (type) {\n case HistoryItemType.INVOICE:\n return texts.invoices;\n case HistoryItemType.WORK_ORDER:\n return texts.serviceVisits;\n case HistoryItemType.PAYMENT:\n return texts.payments;\n }\n },\n [texts.invoices, texts.serviceVisits, texts.payments],\n );\n\n const shouldDisableOption = useCallback(\n (type: HistoryItemType) => {\n switch (type) {\n case HistoryItemType.INVOICE:\n return !invoiceHistoryEnabled;\n case HistoryItemType.WORK_ORDER:\n return !serviceHistoryEnabled;\n case HistoryItemType.PAYMENT:\n return !paymentHistoryEnabled;\n }\n },\n [invoiceHistoryEnabled, serviceHistoryEnabled, paymentHistoryEnabled],\n );\n\n return (\n \n );\n}\n","import { SideDrawer } from '@/components/SideDrawer';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { ClearFiltersButton } from '@/components/cardList/filters/ClearFiltersButton';\nimport { ServiceLocationFilter } from '@/components/cardList/filters/ServiceLocationFilter';\nimport { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { useListActions } from '../hooks';\nimport { useListState } from '../store';\nimport { useTexts } from './useTexts';\nimport { StartDate } from './StartDate';\nimport { EndDate } from './EndDate';\nimport { ItemType } from './ItemType';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function FiltersDrawer(props: Props) {\n const { onClose, open } = props;\n const texts = useTexts();\n const { handleResetFilters, handleSetServiceLocations } = useListActions();\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations } = useListState();\n\n return (\n \n \n \n {!!locations && (\n \n )}\n \n \n \n \n \n \n \n );\n}\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport { ClickAwayListener } from '@mui/material';\nimport Tooltip from '@mui/material/Tooltip';\nimport { useState } from 'react';\n\nexport interface Props {\n children?: React.ReactNode;\n showTooltip?: boolean;\n spanClassName?: string;\n tooltipText?: any;\n}\n\nexport function ComponentWithTooltip(props: Props) {\n const { children, tooltipText, showTooltip, spanClassName } = props;\n const [open, setOpen] = useState(false);\n const layout = useGetUILayout();\n\n const handleTooltipClose = () => {\n setOpen(false);\n };\n\n const handleTooltipOpen = () => {\n setOpen(true);\n };\n\n return (\n <>\n {showTooltip && (\n <>\n {layout == 'desktop' && (\n \n {children}\n \n )}\n\n {layout == 'mobile' && (\n <>\n \n
\n \n \n {children}\n \n \n
\n
\n \n )}\n \n )}\n\n {!showTooltip && <> {children} }\n \n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n view: translate({ id: 'global.view' }),\n };\n }, [translate]);\n}\n","import Paper from '@mui/material/Paper';\nimport Typography from '@mui/material/Typography';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { ComponentWithTooltip } from '@/components/ComponentWithTooltip';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n actionBtnText?: string;\n badge?: JSX.Element;\n icon: JSX.Element;\n onClick: () => void;\n secondaryIcon?: JSX.Element;\n selected: boolean;\n styleOverrides?: Partial<{\n container: Pick;\n }>;\n subTitle: React.ReactNode;\n title: React.ReactNode;\n disabled?: boolean;\n showTooltip?: boolean;\n toolTipText?: string;\n}\n\nexport const useStyles = (props: Props) =>\n makeStyles(theme => ({\n container: {\n height: '68px',\n marginBottom: theme.spacing(2),\n width: '100%',\n border: props.selected ? `1px solid ${theme.palette.primary.main}` : `1px solid transparent`,\n },\n button: {\n marginLeft: theme.spacing(2),\n },\n subTitle: {\n color: theme.palette.text.secondary,\n },\n contentWrapper: {\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n height: '100%',\n flex: '1',\n },\n content: {\n display: 'flex',\n flexDirection: 'column',\n flexGrow: 1,\n minWidth: 0,\n width: 0,\n },\n badgeContainer: {\n display: 'flex',\n flexDirection: 'row',\n },\n }));\n\nexport const DesktopListCard = (props: Props) => {\n const {\n actionBtnText,\n badge,\n icon,\n title,\n onClick,\n secondaryIcon,\n styleOverrides,\n subTitle,\n disabled,\n showTooltip,\n toolTipText,\n } = props;\n const classes = useStyles(props)();\n const texts = useTexts();\n\n return (\n \n \n {icon}\n \n \n {title}\n \n \n {subTitle}\n \n \n \n {!!secondaryIcon && {secondaryIcon}}\n {!!badge && {badge}}\n \n \n \n \n \n \n );\n};\n","import { theme } from '@/theme';\n\nimport makeStyles from '@mui/styles/makeStyles';\nimport Box from '@mui/material/Box';\n\nconst useStyles = makeStyles({\n root: {\n borderRadius: '4px',\n padding: '4px',\n display: 'inline',\n fontSize: '10px',\n fontWeight: 'bold',\n color: theme.palette.black,\n },\n error: {\n backgroundColor: theme.palette.badges.error,\n },\n info: {\n backgroundColor: theme.palette.badges.info,\n },\n success: {\n backgroundColor: theme.palette.badges.success,\n },\n warning: {\n backgroundColor: theme.palette.badges.warning,\n },\n});\n\ninterface Props {\n severity: 'error' | 'info' | 'success' | 'warning';\n text: string;\n}\n\nexport function CardBadge(props: Props) {\n const { severity, text } = props;\n const classes = useStyles();\n\n return {text};\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n view: translate({ id: 'global.view' }),\n };\n }, [translate]);\n}\n","import Paper from '@mui/material/Paper';\nimport Typography from '@mui/material/Typography';\nimport Box from '@mui/material/Box';\nimport * as React from 'react';\nimport Button from '@mui/material/Button';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { ComponentWithTooltip } from '@/components/ComponentWithTooltip';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n actionBtnText?: string;\n badge?: JSX.Element;\n icon: JSX.Element;\n onClick: () => void;\n secondaryIcon?: JSX.Element;\n selected: boolean;\n styleOverrides?: Partial<{\n container: Pick;\n }>;\n subTitle: React.ReactNode;\n title: React.ReactNode;\n disabled?: boolean;\n showTooltip?: boolean;\n toolTipText?: string;\n}\n\nconst useStyles = (props: Props) =>\n makeStyles(theme => ({\n container: {\n height: '88px',\n marginBottom: theme.spacing(2),\n width: '100%',\n border: props.selected ? `1px solid ${theme.palette.primary.main}` : `1px solid transparent`,\n },\n button: {\n marginBottom: theme.spacing(1),\n },\n subTitle: {\n color: theme.palette.text.secondary,\n },\n contentWrapper: {\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n height: '100%',\n flex: '1',\n },\n content: {\n display: 'flex',\n flexDirection: 'column',\n flexGrow: 1,\n minWidth: 0,\n width: 0,\n },\n right: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-end',\n marginLeft: theme.spacing(1),\n paddingTop: theme.spacing(2),\n paddingBottom: theme.spacing(2),\n },\n title: {\n lineHeight: '1.5em',\n maxHeight: '3em',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n '-webkit-line-clamp': 2,\n '-webkit-box-orient': 'vertical',\n },\n badgeContainer: {\n display: 'flex',\n flexDirection: 'row',\n },\n }));\n\nexport const MobileListCard = (props: Props) => {\n const {\n actionBtnText,\n badge,\n icon,\n title,\n onClick,\n secondaryIcon,\n styleOverrides,\n subTitle,\n disabled,\n showTooltip,\n toolTipText,\n } = props;\n const classes = useStyles(props)();\n const texts = useTexts();\n\n return (\n \n \n {icon}\n \n \n {title}\n \n \n {subTitle}\n \n \n \n \n \n {actionBtnText ? actionBtnText : texts.view}\n \n \n \n {!!secondaryIcon && secondaryIcon}\n {!!badge && {badge}}\n \n \n \n \n );\n};\n","import { getToken } from '@/atoms/session/store';\nimport { logout } from '@/atoms/session';\nimport { rootPath, requestNewToken } from './http';\n\nexport const openReport = async (url: string) => {\n try {\n // Get a new token to make sure the current one isn't expiring\n await requestNewToken()\n .then(() => {\n const token = getToken();\n window.open(`${rootPath}${url}?tempToken=${token}`);\n })\n .catch(() => {\n // If the access token could not be refreshed, the session is broken.\n logout();\n });\n } catch (e) {\n throw e;\n }\n};\n","import { get } from '@/utils/http';\nimport { openReport } from '@/utils/openReport';\nimport { ServerError } from '@/utils/ServerError';\nimport { PaymentRefund } from './payments';\n\nexport interface InvoiceDetailWorkOrder {\n number: number;\n services: {\n serviceName: string;\n }[];\n}\nexport interface InvoiceDetail {\n balance: number;\n billingCity: string;\n billingCountry: string;\n billingCountryCode: string;\n billingPostalCode: string;\n billingState: string;\n billingStateAbbreviation: string;\n billingStreet2: string;\n billingStreet: string;\n invoiceDate: string;\n invoiceId: string;\n invoiceNum: string;\n payments: {\n amount: number;\n paymentDate: string;\n status: number;\n refunds: PaymentRefund[];\n }[];\n serviceLocationCity: string;\n serviceLocationCountry: string;\n serviceLocationCountryCode: string;\n serviceLocationPostalCode: string;\n serviceLocationState: string;\n serviceLocationStateAbbreviation: string;\n serviceLocationStreet2: string;\n serviceLocationStreet: string;\n total: number;\n workOrders: InvoiceDetailWorkOrder[];\n}\n\nconst baseUrl = '/api/invoice';\n\nexport const getInvoiceDetails = async (invoiceId: string) => {\n try {\n const { data, status } = await get(`${baseUrl}/${invoiceId}/details`);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to get invoice details.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getInvoiceReport = async (invoiceId: string) => {\n await openReport(`${baseUrl}/${invoiceId}/report`);\n};\n","import { useQuery } from 'react-query';\nimport { getInvoiceDetails, InvoiceDetail } from '@/api/invoices';\n\nexport const useQueryInvoiceDetail = (invoiceId: string) =>\n useQuery(['invoiceDetail', invoiceId], () => getInvoiceDetails(invoiceId));\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n associatedWorkOrders: translate({ id: 'sections.accountHistory.invoiceCard.drawer.associatedWorkOrders' }),\n balance: translate({ id: 'sections.accountHistory.invoiceCard.drawer.balance' }),\n billingLocation: translate({ id: 'sections.accountHistory.invoiceCard.drawer.billingLocation' }),\n error: translate({ id: 'sections.accountHistory.invoiceCard.drawer.error' }),\n invoice: translate({ id: 'global.invoice' }),\n invoiceDate: translate({ id: 'sections.accountHistory.invoiceCard.drawer.invoiceDate' }),\n invoiceReportFailed: translate({ id: 'sections.accountHistory.invoiceCard.drawer.invoiceReportFailed' }),\n makePayment: translate({ id: 'sections.accountHistory.invoiceCard.drawer.makePayment' }),\n none: translate({ id: 'global.none' }),\n open: translate({ id: 'sections.accountHistory.invoiceCard.open' }),\n paid: translate({ id: 'sections.accountHistory.invoiceCard.drawer.paid' }),\n partiallyPaid: translate({ id: 'sections.accountHistory.invoiceCard.drawer.partiallyPaid' }),\n paymentMadeOn: translate({ id: 'sections.accountHistory.invoiceCard.drawer.paymentMadeOn' }),\n payments: translate({ id: 'sections.accountHistory.invoiceCard.drawer.payments' }),\n paymentStatus: translate({ id: 'sections.accountHistory.invoiceCard.drawer.paymentStatus' }),\n pdf: translate({ id: 'global.pdf' }),\n serviceLocation: translate({ id: 'sections.accountHistory.invoiceCard.drawer.serviceLocation' }),\n servicesPerformed: translate({ id: 'sections.accountHistory.invoiceCard.drawer.servicesPerformed' }),\n title: translate({ id: 'sections.accountHistory.invoiceCard.drawer.title' }),\n total: translate({ id: 'sections.accountHistory.invoiceCard.drawer.total' }),\n unpaid: translate({ id: 'sections.accountHistory.invoiceCard.drawer.unpaid' }),\n workOrder: translate({ id: 'global.workOrder' }),\n };\n }, [translate]);\n}\n","import { Box, Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\ninterface Props {\n primary: string;\n secondary?: string | number | JSX.Element;\n}\n\nconst useStyles = makeStyles({\n primary: {\n fontWeight: 'bold',\n },\n});\n\nexport const DefinitionListItem = (props: Props) => {\n const { primary, secondary } = props;\n const classes = useStyles();\n\n return (\n \n {primary}\n {!!secondary && {secondary}}\n \n );\n};\n","import { toast } from 'react-toastify';\n\nexport const useToast = () => toast;\n","import { SvgIcon } from '@mui/material';\nimport { useTheme } from '@mui/styles';\n\nexport function PDF(props) {\n const theme = useTheme();\n return (\n \n \n \n \n \n );\n}\n","import { LoadingButton } from '@mui/lab';\nimport { ReactNode, useCallback } from 'react';\nimport { useMutation } from 'react-query';\nimport { useToast } from '@/utils/useToast';\nimport { PDF } from '../sections/AccountHistory/AccountHistoryList/cards/icons/PDF';\n\ninterface Props {\n children: ReactNode;\n onClick: () => Promise;\n errorText: string;\n className?: string;\n}\n\nexport function OpenPDFButton(props: Props) {\n const toast = useToast();\n\n const { children, onClick, errorText, className } = props;\n\n const mutation = useMutation(onClick, {\n onError: () => {\n toast.error(errorText);\n },\n onSuccess: async () => {},\n });\n\n const handleClick = useCallback(async () => {\n mutation.mutate();\n }, [mutation]);\n\n return (\n }\n loadingPosition=\"start\"\n onClick={handleClick}\n loading={mutation.isLoading}\n className={className}\n >\n {children}\n \n );\n}\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/settings';\n\nexport enum PaymentProcessors {\n Vantiv = 'Vantiv',\n OpenEdge = 'OpenEdge',\n WorkWave = 'WorkWave',\n}\n\nexport const getBusinessUnitPaymentProcessor = async (businessUnitId: string) => {\n try {\n const { data, status } = await get(`${baseUrl}/paymentProcessor?businessUnitId=${businessUnitId}`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get payment processor information.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { getBusinessUnitPaymentProcessor } from '@/api/paymentProcessor';\nimport { useQuery } from 'react-query';\n\nexport const useFetchBusinessUnitPaymentProcessor = (businessUnitId: string) =>\n useQuery(\n ['paymentProcessor', businessUnitId],\n () => getBusinessUnitPaymentProcessor(businessUnitId),\n {\n staleTime: Infinity,\n },\n );\n","import { PaymentProcessors } from '@/api/paymentProcessor';\nimport { getAccount } from '@/atoms/session/store';\nimport { useMemo } from 'react';\nimport { useFetchBusinessUnitPaymentProcessor } from './query/useFetchBusinessUnitPaymentProcessor';\nimport { useFetchCustomerPortalSettings } from './query/useFetchCustomerPortalSettings';\n\nexport const usePaymentsEnabled = () => {\n const account = getAccount();\n const { data: settings } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n const { data: paymentProcessor } = useFetchBusinessUnitPaymentProcessor(account?.businessUnitId || '');\n const hasWWP = useMemo(() => {\n return paymentProcessor == PaymentProcessors.WorkWave;\n }, [paymentProcessor]);\n\n return useMemo(() => {\n return !!(settings?.enableMakePayments && hasWWP);\n }, [settings, hasWWP]);\n};\n","import { InvoiceDetail } from '@/api/invoices';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useMemo } from 'react';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n invoiceDetails: InvoiceDetail;\n}\n\nexport function AssociatedWorkOrders(props: Props) {\n const texts = useTexts();\n\n const {\n invoiceDetails: { workOrders },\n } = props;\n\n const associatedWorkOrders = useMemo(() => {\n if (!workOrders.length) {\n return texts.none;\n }\n const formattedNumbers = workOrders.map(workOrder => `#${workOrder.number}`);\n return formattedNumbers.join(', ');\n }, [workOrders, texts.none]);\n\n return ;\n}\n","import { ServiceLocation } from '@/api/serviceLocations';\nimport { useMemo } from 'react';\nimport { formatAddress } from '../utils/formatAddress';\n\nexport const useServiceLocationAddress = (l: ServiceLocation | null) => {\n const address = useMemo(() => {\n return formatAddress(l);\n }, [l]);\n\n return address;\n};\n\nexport const useFormattedAddress = (\n street1: string,\n street2: string,\n city: string,\n stateAbbreviation: string,\n postalCode: string,\n countryCode: string,\n) => {\n const address = useMemo(() => {\n let address = '';\n if (street1) {\n address += `${street1},`;\n }\n if (street2) {\n address += ` ${street2},`;\n }\n if (city) {\n address += ` ${city},`;\n }\n if (stateAbbreviation) {\n address += ` ${stateAbbreviation}`;\n }\n if (postalCode) {\n address += ` ${postalCode},`;\n }\n if (countryCode) {\n address += ` ${countryCode}`;\n }\n\n return address\n .split(',')\n .map(x => x.trim())\n .filter(x => !!x)\n .join(', ');\n }, [city, countryCode, postalCode, stateAbbreviation, street1, street2]);\n\n return address;\n};\n","import { InvoiceDetail } from '@/api/invoices';\nimport { useFormattedAddress } from '@/common/hooks/useAddress';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n invoiceDetails: InvoiceDetail;\n}\n\nexport function BillingLocation(props: Props) {\n const texts = useTexts();\n\n const {\n invoiceDetails: {\n billingCity,\n billingCountryCode,\n billingPostalCode,\n billingStateAbbreviation,\n billingStreet,\n billingStreet2,\n },\n } = props;\n\n const billingAddress = useFormattedAddress(\n billingStreet,\n billingStreet2,\n billingCity,\n billingStateAbbreviation,\n billingPostalCode,\n billingCountryCode,\n );\n\n return ;\n}\n","import { InvoiceDetail } from '@/api/invoices';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Currency, ShortDate } from '@/components/localization';\nimport { Typography } from '@mui/material';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n invoiceDetails: InvoiceDetail;\n}\n\nexport function Payments(props: Props) {\n const texts = useTexts();\n\n const {\n invoiceDetails: { payments },\n } = props;\n\n return (\n 0 ? (\n <>\n {payments.map((p, i) => (\n
\n
\n {`${texts.paymentMadeOn} `}\n \n
\n {p.refunds.map((r, index) => (\n \n   {} of this payment was refunded on{' '}\n .\n \n ))}\n
\n ))}\n \n ) : (\n texts.none\n )\n }\n />\n );\n}\n","import { InvoiceDetail } from '@/api/invoices';\nimport { useMemo } from 'react';\nimport { CardBadge } from '@/components/cardList/CardBadge';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n invoiceDetails: InvoiceDetail;\n}\n\nexport function PaymentStatus(props: Props) {\n const texts = useTexts();\n\n const {\n invoiceDetails: { balance, total },\n } = props;\n\n const paidStatusBadge = useMemo(() => {\n if (balance == 0) {\n return ;\n }\n\n if (balance != total) {\n return ;\n }\n\n return ;\n }, [balance, texts.paid, texts.partiallyPaid, texts.unpaid, total]);\n\n return ;\n}\n","import { InvoiceDetail } from '@/api/invoices';\nimport { useFormattedAddress } from '@/common/hooks/useAddress';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n invoiceDetails: InvoiceDetail;\n}\n\nexport function ServiceLocation(props: Props) {\n const texts = useTexts();\n\n const {\n invoiceDetails: {\n serviceLocationCity,\n serviceLocationCountryCode,\n serviceLocationPostalCode,\n serviceLocationStateAbbreviation,\n serviceLocationStreet,\n serviceLocationStreet2,\n },\n } = props;\n\n const serviceAddress = useFormattedAddress(\n serviceLocationStreet,\n serviceLocationStreet2,\n serviceLocationCity,\n serviceLocationStateAbbreviation,\n serviceLocationPostalCode,\n serviceLocationCountryCode,\n );\n\n return ;\n}\n","import { InvoiceDetail } from '@/api/invoices';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n invoiceDetails: InvoiceDetail;\n}\n\nexport function ServicesPerformed(props: Props) {\n const texts = useTexts();\n\n const {\n invoiceDetails: { workOrders },\n } = props;\n\n return (\n \n {workOrders.map((w, i) => (\n
\n {w.services.map((s, j) => (\n
\n {s.serviceName} ({texts.workOrder} #{w.number})\n
\n ))}\n
\n ))}\n \n }\n />\n );\n}\n","import { getInvoiceReport, InvoiceDetail } from '@/api/invoices';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Currency } from '@/components/localization';\nimport { LongDate } from '@/components/localization/Dates';\nimport { Box, Button, Stack } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport { useNavigate } from 'react-router';\nimport { OpenPDFButton } from '@/components/OpenPDFButton';\nimport { usePaymentsEnabled } from '@/common/hooks/usePaymentsEnabled';\nimport { useTexts } from '../useTexts';\nimport {\n AssociatedWorkOrders,\n BillingLocation,\n Payments,\n PaymentStatus,\n ServiceLocation,\n ServicesPerformed,\n} from './listItems';\n\ninterface Props {\n details: InvoiceDetail;\n}\n\nexport function DetailListItems(props: Props) {\n const texts = useTexts();\n const navigate = useNavigate();\n const paymentsEnabled = usePaymentsEnabled();\n\n const {\n details,\n details: { balance, invoiceDate, invoiceNum, total },\n } = props;\n\n const showMakePaymentButton = useMemo(() => {\n return paymentsEnabled && balance !== 0;\n }, [balance, paymentsEnabled]);\n\n const redirectToMakePayment = useCallback(() => {\n navigate('/payments/pay-invoices');\n }, [navigate]);\n\n const onInvoiceReportClick = useCallback(() => {\n return getInvoiceReport(details.invoiceId);\n }, [details.invoiceId]);\n\n return (\n \n \n\n } />\n\n \n\n \n\n \n\n \n\n } />\n\n } />\n\n \n\n \n\n {showMakePaymentButton && (\n \n \n \n )}\n \n \n {texts.invoice} #{details.invoiceNum} {texts.pdf}\n \n \n \n );\n}\n","import { useQueryInvoiceDetail } from '@/common/hooks/query/useQueryInvoiceDetail';\nimport { Alert, CircularProgress } from '@mui/material';\nimport { useTexts } from '../useTexts';\nimport { DetailListItems } from './DetailListItems';\n\ninterface Props {\n invoiceId: string;\n}\n\nexport function DrawerContent(props: Props) {\n const { invoiceId } = props;\n const texts = useTexts();\n const { data: details, status } = useQueryInvoiceDetail(invoiceId);\n\n return (\n <>\n {status == 'loading' && }\n {status == 'error' && {texts.error}}\n {status == 'success' && (\n <>\n {!details && {texts.error}}\n {details && }\n \n )}\n \n );\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faFileInvoiceDollar } from '@fortawesome/pro-regular-svg-icons';\n\nimport Box from '@mui/material/Box';\nimport { InvoiceStatus } from '@/api/accountHistory';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { SideDrawer } from '@/components/SideDrawer';\nimport { Currency, ShortDate } from '@/components/localization';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { CardBadge } from '@/components/cardList/CardBadge';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport Typography from '@mui/material/Typography';\nimport { useCallback } from 'react';\nimport { CardProps } from '../typings';\nimport { setSelectedItem, useListState } from '../../store';\nimport { DrawerContent } from './drawer/DrawerContent';\nimport { useTexts } from './useTexts';\n\nconst Title = (props: { date: Date; invoiceNumber: number | null }) => {\n const { date, invoiceNumber } = props;\n const texts = useTexts();\n\n return (\n \n \n \n {` ${texts.invoice} #${invoiceNumber}`}\n \n \n );\n};\n\nconst Badge = (props: { status: InvoiceStatus | null }) => {\n const { status } = props;\n const texts = useTexts();\n\n switch (status) {\n case InvoiceStatus.OPEN:\n return ;\n case InvoiceStatus.PAID:\n return ;\n default:\n return <>;\n }\n};\n\nexport const InvoiceCard = (props: CardProps) => {\n const { item } = props;\n const texts = useTexts();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const { selected } = useListState();\n const layout = useGetUILayout();\n\n const handleOpen = useCallback(() => {\n setSelectedItem(item.invoiceId!);\n openDrawer();\n }, [openDrawer, item.invoiceId]);\n\n const handleClose = useCallback(() => {\n setSelectedItem('');\n closeDrawer();\n }, [closeDrawer]);\n\n return (\n <>\n {layout == 'desktop' ? (\n }\n icon={}\n onClick={handleOpen}\n selected={item.invoiceId === selected}\n subTitle={}\n title={}\n />\n ) : (\n <MobileListCard\n badge={<Badge status={item.invoiceStatus} />}\n icon={<FontAwesomeIcon icon={faFileInvoiceDollar} />}\n onClick={handleOpen}\n selected={item.invoiceId === selected}\n subTitle={<Currency value={item.invoiceTotal || 0} />}\n title={<Title date={item.date} invoiceNumber={item.invoiceNum} />}\n />\n )}\n\n <SideDrawer isOpen={drawerOpen} onClose={handleClose} title={texts.title}>\n <DrawerContent invoiceId={item.invoiceId || ''} />\n </SideDrawer>\n </>\n );\n};\n","export enum PaymentAccountTypes {\n ACH = 'ACH',\n CREDIT_CARD = 'CreditCard',\n}\n\nexport enum PaymentStatus {\n CANCELLED = 'Cancelled',\n FAILED = 'Failed',\n PARTIALLY_REFUNDED = 'PartiallyRefunded',\n PENDING = 'Pending',\n REFUNDED = 'Refunded',\n SUCCEEDED = 'Succeeded',\n}\n\nexport enum HostedPaymentStatus {\n SUCCESS = 'Success',\n CANCELLED = 'Cancelled',\n}\n\nexport enum PaymentSource {\n EPAY = 3,\n MOBILE = 2,\n NONE = 0,\n OFFICE = 1,\n PORTAL = 4,\n}\n\nexport enum PaymentMethodMapping {\n ACH = 4,\n CASH = 1,\n CHECK = 2,\n CREDIT_CARD = 3,\n NONE = 0,\n}\n\nexport enum TransactionSetupMethod {\n CreditCardSale = 1,\n PaymentAccountCreate = 7,\n PaymentAccountUpdate = 8,\n}\nexport interface PaymentAccount {\n accountId: string;\n accountType: PaymentAccountTypes;\n businessUnitId: string;\n createdOn: string;\n ending: number;\n friendly: string;\n isAutoPayment: boolean;\n hasAutoPaymentInstance: boolean;\n isExpired: boolean;\n month: number;\n nameOnCard: string;\n paymentAccountId: string;\n processorPaymentAccountId: string;\n routingNumber: string;\n servicesId: string;\n year: number;\n}\n\nexport interface AddCreditCardCallback {\n account: string | null;\n accountId: string;\n approvalNumber: string | null;\n approvedAmount: number;\n cardLogo: string;\n expirationMonth: string;\n expirationYear: string;\n expressResponseCode: null;\n expressResponseMessage: string;\n hostedPaymentStatus: HostedPaymentStatus;\n hostedPaymentTransaction: string | null;\n hostedPaymentTransactionId: string;\n hostResponseCode: string;\n hostResponseMessage: string | null;\n lastFour: string;\n paymentAccountId: string;\n tenantId: string;\n transactionId: string;\n processorTransactionLogId: string;\n partnerRefId: string;\n}\n\nexport const isSuccessfulCreditCardCallback = (response: unknown): response is AddCreditCardCallback => {\n const r = response as AddCreditCardCallback;\n return r.hostedPaymentStatus == HostedPaymentStatus.SUCCESS;\n};\n\nexport const isCancelledCreditCardCallback = (response: unknown): response is AddCreditCardCallback => {\n const r = response as AddCreditCardCallback;\n return r.hostedPaymentStatus == HostedPaymentStatus.CANCELLED;\n};\n\nexport interface AddCreditCardPaymentAccountInput {\n accountId: string;\n businessUnitId: string;\n cardType: string;\n lastFour: string;\n month: string;\n processorPaymentAccountId: string;\n year: string;\n}\n\nexport interface AddCreditCardPaymentAccountResponse {\n accountId: string;\n businessUnitId: string;\n cardType: string;\n friendly: string;\n lastFour: string;\n month: string;\n nameOnCard: string;\n processorPaymentAccountId: string;\n securityCode: string;\n year: string;\n}\n\nexport interface AddAchPaymentAccountInput {\n accountId: string;\n accountNumber: string;\n businessUnitId: string;\n processorPaymentAccountId: string;\n routingNumber: string;\n}\n\nexport interface AddAchPaymentAccountResponse {\n accountId: string;\n businessUnitId: string;\n cardType: string;\n friendly: string;\n lastFour: string;\n month: string;\n nameOnCard: string;\n processorPaymentAccountId: string;\n securityCode: string;\n year: string;\n}\n\nexport interface ProcessPaymentInput {\n accountId: string;\n accountType?: string;\n agreementPaymentLinks?: string[];\n amount: number;\n businessUnitId: string;\n emailReceiptTo?: string[];\n employeeId?: string;\n friendlyValue: string;\n invoicePayments: InvoicePayment[];\n isBulkPayment?: boolean;\n nameOnCard?: string;\n partnerRefId?: string;\n paymentAccountId?: string;\n paymentDate?: Date;\n paymentId?: string;\n paymentMethod: PaymentMethodMapping;\n paymentReference?: string;\n paymentSource: PaymentSource;\n paymentStatus?: PaymentStatus;\n processorTransactionId?: string;\n startingBalancePayment?: number;\n submittedOnDateTime?: Date;\n transactionId?: string;\n transactionReferenceNumber?: string;\n workOrderId?: string;\n}\n\nexport interface InvoicePayment {\n amount: number;\n invoiceId: string;\n paymentDate: Date;\n paymentStatus?: PaymentStatus;\n}\nexport interface ChargePaymentAccountInput {\n accountId: string;\n amount: number;\n businessUnitId: string;\n employeeId: string;\n invoicePayments: InvoicePayment[];\n startingBalancePayment: number;\n paymentAccountId: string;\n paymentId?: string;\n}\n","import { PaymentMethod } from '@/api/accountHistory';\nimport { useMemo } from 'react';\n\nexport const useFormattedAccountNumber = (\n paymentAccountType: string | null,\n paymentMethod: PaymentMethod | null,\n reference: string | null,\n) => {\n const accountNumber = useMemo(() => {\n const splitAccountType = paymentAccountType?.split(' ');\n const type = splitAccountType?.length == 3 && splitAccountType[0];\n const digits = splitAccountType?.length == 3 && splitAccountType[2];\n\n if (paymentMethod != PaymentMethod.CHECK && type && digits) {\n return paymentMethod == PaymentMethod.CREDIT_CARD\n ? `${type} #**** **** **** ${digits}`\n : `${type} #*****${digits}`;\n } else if (paymentMethod == PaymentMethod.CHECK && paymentMethod && reference) {\n return `${paymentMethod} ${reference}`;\n }\n\n return null;\n }, [paymentAccountType, paymentMethod, reference]);\n\n return accountNumber;\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n amount: translate({ id: 'sections.accountHistory.paymentCard.drawer.amount' }),\n associatedInvoiceNumber: translate({\n id: 'sections.accountHistory.paymentCard.drawer.associatedInvoiceNumber',\n }),\n associatedInvoiceNumbers: translate({\n id: 'sections.accountHistory.paymentCard.drawer.associatedInvoiceNumbers',\n }),\n balance: translate({ id: 'sections.accountHistory.paymentCard.drawer.balance' }),\n error: translate({ id: 'sections.accountHistory.paymentCard.drawer.error' }),\n none: translate({ id: 'global.none' }),\n paymentDate: translate({ id: 'sections.accountHistory.paymentCard.drawer.paymentDate' }),\n paymentReceiptReportFailed: translate({\n id: 'sections.accountHistory.paymentCard.drawer.paymentReceiptReportFailed',\n }),\n paymentType: translate({ id: 'sections.accountHistory.paymentCard.drawer.paymentType' }),\n refundReceiptReportFailed: translate({\n id: 'sections.accountHistory.paymentCard.drawer.refundReceiptReportFailed',\n }),\n status: translate({ id: 'sections.accountHistory.paymentCard.drawer.status' }),\n checkNumber: translate({ id: 'sections.accountHistory.paymentCard.drawer.checkNumber' }),\n title: translate({ id: 'sections.accountHistory.paymentCard.drawer.title' }),\n viewReceipt: translate({ id: 'sections.accountHistory.paymentCard.drawer.viewReceipt' }),\n viewRefundReceipt: translate({\n id: 'sections.accountHistory.paymentCard.drawer.viewRefundReceipt',\n }),\n refundAmount: translate({ id: 'sections.accountHistory.paymentCard.drawer.refundAmount' }),\n refundDate: translate({ id: 'sections.accountHistory.paymentCard.drawer.refundDate' }),\n refundDetailsTitle: translate({ id: 'sections.accountHistory.paymentCard.drawer.refundDetailsTitle' }),\n refundPaymentType: translate({ id: 'sections.accountHistory.paymentCard.drawer.refundPaymentType' }),\n };\n }, [translate]);\n}\n","import { ChargePaymentAccountInput, PaymentStatus, ProcessPaymentInput } from '@/common/types/payments';\nimport { get, post } from '@/utils/http';\nimport { prepareServerError, ServerError } from '@/utils/ServerError';\nimport { openReport } from '@/utils/openReport';\n\nexport interface PaymentRefund {\n amount: number;\n refundMethod: string;\n refundTime: string;\n}\n\nexport interface PaymentDetail {\n paymentId: string;\n accountType: string;\n amount: number;\n associatedInvoiceNumbers: number[];\n balance: number;\n paymentDate: string;\n status: PaymentStatus;\n reference: string;\n refunds: PaymentRefund[];\n}\n\nexport interface CreditCardPaymentResult {\n payment: PaymentDetail;\n failureReason: string;\n}\n\nconst baseUrl = '/api/payments';\n\nexport const getPaymentDetails = async (paymentId: string) => {\n try {\n const { data, status } = await get<PaymentDetail>(`${baseUrl}/${paymentId}/BasicPaymentDetails`);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to get payment details.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getPaymentReceipt = async (paymentId: string) => {\n await openReport(`${baseUrl}/${paymentId}/receipt`);\n};\n\nexport const getRefundReceipt = async (paymentId: string) => {\n await openReport(`${baseUrl}/${paymentId}/refundreceipt`);\n};\n\nexport const processPayment = async (input: ProcessPaymentInput) => {\n try {\n const { data, status } = await post<PaymentDetail>(baseUrl, input);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to process payment.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const chargePaymentAccount = async (input: ChargePaymentAccountInput) => {\n try {\n const { data, status } = await post<CreditCardPaymentResult>(\n `${baseUrl}/paymentAccount/${input.paymentAccountId}`,\n input,\n );\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to make payment.`, status);\n } catch (e) {\n throw prepareServerError(e);\n }\n};\n","import { PaymentDetail, getPaymentDetails } from '@/api/payments';\nimport { useQuery } from 'react-query';\n\nexport const useQueryPaymentDetail = (paymentId: string) =>\n useQuery<PaymentDetail, Error>(['paymentDetail', paymentId], () => getPaymentDetails(paymentId));\n","import { PaymentStatus } from '@/common/types/payments';\nimport { getPaymentReceipt, getRefundReceipt, PaymentDetail } from '@/api/payments';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Currency, ShortDate } from '@/components/localization';\nimport { Grid, Stack, Typography } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { OpenPDFButton } from '@/components/OpenPDFButton';\nimport { useTexts } from './useTexts';\nimport { Badge } from './PaymentCard';\n\ninterface Props {\n details: PaymentDetail;\n}\n\nconst useStyles = makeStyles({\n downloadLink: {\n justifyContent: 'flex-start',\n },\n});\n\nexport function DetailListItems(props: Props) {\n const {\n details: {\n accountType,\n amount,\n associatedInvoiceNumbers,\n paymentDate,\n status,\n paymentId,\n reference,\n refunds,\n balance,\n },\n } = props;\n const texts = useTexts();\n\n const associatedInvoiceTitle = useMemo(() => {\n if (associatedInvoiceNumbers.length == 1) {\n return texts.associatedInvoiceNumber;\n } else {\n return texts.associatedInvoiceNumbers;\n }\n }, [associatedInvoiceNumbers, texts.associatedInvoiceNumber, texts.associatedInvoiceNumbers]);\n\n const associatedInvoiceSubTitle = useMemo(() => {\n if (!associatedInvoiceNumbers.length) {\n return texts.none;\n }\n const formattedNumbers = associatedInvoiceNumbers.map(invoiceNumber => `#${invoiceNumber}`);\n return formattedNumbers.join(', ');\n }, [associatedInvoiceNumbers, texts.none]);\n\n const onPaymentReceiptReportClick = useCallback(() => {\n return getPaymentReceipt(paymentId);\n }, [paymentId]);\n\n const onRefundReceiptReportClick = useCallback(() => {\n return getRefundReceipt(paymentId);\n }, [paymentId]);\n\n const classes = useStyles();\n\n const isRefund = status == PaymentStatus.PARTIALLY_REFUNDED || status == PaymentStatus.REFUNDED;\n const showReceipt = status == PaymentStatus.SUCCEEDED || isRefund;\n\n return (\n <Stack direction=\"column\" spacing={2}>\n <DefinitionListItem primary={associatedInvoiceTitle} secondary={associatedInvoiceSubTitle} />\n <DefinitionListItem primary={texts.paymentDate} secondary={<ShortDate value={paymentDate} />} />\n <DefinitionListItem primary={texts.amount} secondary={<Currency value={amount || 0} />} />\n <DefinitionListItem primary={texts.balance} secondary={<Currency value={balance || 0} />} />\n <DefinitionListItem primary={texts.paymentType} secondary={accountType} />\n {accountType == 'Check' && reference && (\n <DefinitionListItem primary={texts.checkNumber} secondary={reference} />\n )}\n <DefinitionListItem primary={texts.status} secondary={<Badge status={status} />} />\n\n {isRefund && <Typography variant=\"h4\">{texts.refundDetailsTitle}</Typography>}\n\n {isRefund && (\n <Grid container spacing={1}>\n <Grid item xs={4}>\n <Typography variant=\"h5\" style={{ fontWeight: 600 }}>\n {texts.refundDate}\n </Typography>\n </Grid>\n <Grid item xs={4}>\n <Typography variant=\"h5\" style={{ fontWeight: 600 }}>\n {texts.refundAmount}\n </Typography>\n </Grid>\n <Grid item xs={4}>\n <Typography variant=\"h5\" style={{ fontWeight: 600 }}>\n {texts.refundPaymentType}\n </Typography>\n </Grid>\n {refunds.map((item, index) => (\n <Grid key={index} item xs={12}>\n <Grid container spacing={1}>\n <Grid item xs={4}>\n <Typography>{<ShortDate value={item.refundTime} />}</Typography>\n </Grid>\n <Grid item xs={4}>\n <Typography>{<Currency value={item.amount} />}</Typography>\n </Grid>\n <Grid item xs={4}>\n <Typography>{item.refundMethod}</Typography>\n </Grid>\n </Grid>\n </Grid>\n ))}\n </Grid>\n )}\n\n {showReceipt && (\n <OpenPDFButton\n errorText={texts.paymentReceiptReportFailed}\n onClick={onPaymentReceiptReportClick}\n className={classes.downloadLink}\n >\n {texts.viewReceipt}\n </OpenPDFButton>\n )}\n\n {isRefund && (\n <OpenPDFButton\n errorText={texts.refundReceiptReportFailed}\n onClick={onRefundReceiptReportClick}\n className={classes.downloadLink}\n >\n {texts.viewRefundReceipt}\n </OpenPDFButton>\n )}\n </Stack>\n );\n}\n","import { useQueryPaymentDetail } from '@/common/hooks/query/useQueryPaymentDetail';\nimport { Alert, CircularProgress } from '@mui/material';\nimport { DetailListItems } from './DetailListItems';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n paymentId: string;\n}\n\nexport function DrawerContent(props: Props) {\n const { paymentId } = props;\n const texts = useTexts();\n const { data: details, status } = useQueryPaymentDetail(paymentId);\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n {status == 'success' && (\n <>\n {!details && <Alert severity=\"error\">{texts.error}</Alert>}\n {details && <DetailListItems details={details} />}\n </>\n )}\n </>\n );\n}\n","import { Currency } from '@/components/localization';\nimport { PaymentSubtitleProps } from '../typings';\n\nexport const PaymentSubtitle = (props: PaymentSubtitleProps) => {\n const { value, identifier } = props;\n\n return (\n <>\n <Currency value={value} />\n <> {identifier} </>\n </>\n );\n};\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faCreditCard } from '@fortawesome/free-regular-svg-icons';\nimport { faUniversity, faSackDollar, faMoneyCheck, faDollarSign } from '@fortawesome/pro-regular-svg-icons';\nimport { useCallback, useMemo } from 'react';\nimport { PaymentMethod } from '@/api/accountHistory';\nimport { PaymentStatus } from '@/common/types/payments';\nimport { SideDrawer } from '@/components/SideDrawer';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { ShortDate } from '@/components/localization';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { CardBadge } from '@/components/cardList/CardBadge';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport { Typography } from '@mui/material';\nimport { CardProps } from '../typings';\nimport { useTexts } from '../../../useTexts';\nimport { setSelectedItem, useListState } from '../../store';\nimport { useFormattedAccountNumber } from '../../hooks/useFormattedAccountType';\nimport { useTexts as useDrawerTexts } from './useTexts';\nimport { DrawerContent } from './DrawerContent';\nimport { PaymentSubtitle } from './PaymentSubtitle';\n\nconst Title = (props: { date: Date; invoiceNums: string | null }) => {\n const { date, invoiceNums } = props;\n const texts = useTexts();\n\n const invoiceNumsStr = useMemo(() => {\n if (!invoiceNums) return '';\n const nums = invoiceNums.split(',').map(x => x.trim());\n const joined = nums.join(', #');\n return `#${joined}`;\n }, [invoiceNums]);\n\n return (\n <Typography noWrap>\n <ShortDate value={date} />\n {` ${texts.payment}`} {!!invoiceNums && ` ${texts.forInvoice} ${invoiceNumsStr}`}\n </Typography>\n );\n};\n\nexport const Badge = (props: { status: PaymentStatus | null }) => {\n const { status } = props;\n const texts = useTexts();\n\n switch (status) {\n case PaymentStatus.PENDING:\n return <CardBadge severity=\"warning\" text={texts.pending} />;\n case PaymentStatus.SUCCEEDED:\n return <CardBadge severity=\"success\" text={texts.succeeded} />;\n case PaymentStatus.REFUNDED:\n return <CardBadge severity=\"error\" text={texts.refunded} />;\n case PaymentStatus.PARTIALLY_REFUNDED:\n return <CardBadge severity=\"error\" text={texts.partiallyRefunded} />;\n case PaymentStatus.CANCELLED:\n return <CardBadge severity=\"error\" text={texts.cancelled} />;\n case PaymentStatus.FAILED:\n return <CardBadge severity=\"error\" text={texts.failed} />;\n default:\n return <></>;\n }\n};\n\nconst Icon = (props: { type: PaymentMethod | null }) => {\n const { type } = props;\n switch (type) {\n case PaymentMethod.CASH:\n return <FontAwesomeIcon icon={faSackDollar} />;\n case PaymentMethod.CREDIT_CARD:\n return <FontAwesomeIcon icon={faCreditCard} />;\n case PaymentMethod.CHECK:\n return <FontAwesomeIcon icon={faMoneyCheck} />;\n case PaymentMethod.ACH:\n return <FontAwesomeIcon icon={faUniversity} />;\n default:\n return <FontAwesomeIcon icon={faDollarSign} />;\n }\n};\n\nexport const PaymentCard = (props: CardProps) => {\n const { item } = props;\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const texts = useDrawerTexts();\n const { selected } = useListState();\n const layout = useGetUILayout();\n\n const handleOpen = useCallback(() => {\n setSelectedItem(item.paymentId!);\n openDrawer();\n }, [openDrawer, item.paymentId]);\n\n const handleClose = useCallback(() => {\n setSelectedItem('');\n closeDrawer();\n }, [closeDrawer]);\n\n const formattedAccountType = useFormattedAccountNumber(item.paymentAccountType, item.paymentMethod, item.reference);\n\n const itemPaymentStatus = item.isPartiallyRefunded ? PaymentStatus.PARTIALLY_REFUNDED : item.paymentStatus;\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n badge={<Badge status={itemPaymentStatus} />}\n icon={<Icon type={item.paymentMethod} />}\n onClick={handleOpen}\n selected={item.paymentId === selected}\n subTitle={<PaymentSubtitle value={item.paymentAmount || 0} identifier={formattedAccountType} />}\n title={<Title date={item.date} invoiceNums={item.paymentInvoiceNums} />}\n />\n ) : (\n <MobileListCard\n badge={<Badge status={itemPaymentStatus} />}\n icon={<Icon type={item.paymentMethod} />}\n onClick={handleOpen}\n selected={item.paymentId === selected}\n subTitle={<PaymentSubtitle value={item.paymentAmount || 0} identifier={formattedAccountType} />}\n title={<Title date={item.date} invoiceNums={item.paymentInvoiceNums} />}\n />\n )}\n\n <SideDrawer isOpen={drawerOpen} onClose={handleClose} title={texts.title}>\n <DrawerContent paymentId={item.paymentId || ''} />\n </SideDrawer>\n </>\n );\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n workOrder: translate({ id: 'global.workOrder' }),\n };\n }, [translate]);\n}\n","import { useMemo } from 'react';\nimport { useTexts } from './useTexts';\n\nexport const useFormattedWorkOrderNumber = (\n number: string,\n projectSequence: number | null,\n subNumber: number | null,\n) => {\n const texts = useTexts();\n const formattedNumber = useMemo(() => {\n let str = `${texts.workOrder} #${number}`;\n\n if (!!projectSequence) {\n str += `-${projectSequence.toString().padStart(2, '0')}`;\n }\n if (!!subNumber) {\n str += `-${subNumber.toString().padStart(2, '0')}`;\n }\n\n return str;\n }, [number, projectSequence, subNumber, texts.workOrder]);\n return formattedNumber;\n};\n","export enum CustomerPortalLastServiceFields {\n EnableLastServiceWorkOrderNumber = 'enableLastServiceWorkOrderNumber',\n EnableLastServiceScheduledDate = 'enableLastServiceScheduledDate',\n EnableLastServiceScheduledTime = 'enableLastServiceScheduledTime',\n EnableLastServiceServiceLocation = 'enableLastServiceServiceLocation',\n EnableLastServiceIncludedServices = 'enableLastServiceIncludedServices',\n EnableLastServiceTeamTechnicianInfo = 'enableLastServiceTeamTechnicianInfo',\n EnableLastServicePriceOfServiceVisit = 'enableLastServicePriceOfServiceVisit',\n EnableLastServiceServiceReport = 'enableLastServiceServiceReport',\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n amount: translate({ id: 'sections.accountHistory.serviceCard.drawer.amount' }),\n dateAndTimeCompleted: translate({ id: 'sections.accountHistory.serviceCard.drawer.dateAndTimeCompleted' }),\n dateCompleted: translate({ id: 'sections.accountHistory.serviceCard.drawer.dateCompleted' }),\n error: translate({ id: 'sections.accountHistory.serviceCard.drawer.error' }),\n failedToDownloadPDF: translate({ id: 'sections.accountHistory.serviceCard.drawer.failedToDownloadPDF' }),\n pdf: translate({ id: 'global.pdf' }),\n service: translate({ id: 'sections.accountHistory.serviceCard.serviceReport' }),\n serviceLocation: translate({ id: 'sections.accountHistory.serviceCard.drawer.serviceLocation' }),\n servicesPerformed: translate({ id: 'sections.accountHistory.serviceCard.drawer.servicesPerformed' }),\n timeCompleted: translate({ id: 'sections.accountHistory.serviceCard.drawer.timeCompleted' }),\n title: translate({ id: 'sections.accountHistory.serviceCard.drawer.title' }),\n technician: translate({ id: 'sections.accountHistory.serviceCard.drawer.technician' }),\n workOrder: translate({ id: 'global.workOrder' }),\n };\n }, [translate]);\n}\n","import { get } from '@/utils/http';\nimport { openReport } from '@/utils/openReport';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface WorkOrderDetailsResource {\n resourceId: string;\n resourceType: string;\n name: string;\n color: string;\n imageId: string;\n isCustomImage: boolean;\n}\n\nexport interface WorkOrderDetailsServiceLocation {\n name?: string;\n street1: string;\n street2: string;\n city: string;\n state: string;\n stateAbbreviation: string;\n postalCode: string;\n country: string;\n countryCode: string;\n}\n\nexport interface WorkOrderDetailsService {\n name: string;\n products: string[];\n}\n\nexport enum CommitmentWindowCustomerResponse {\n CONFIRMED = 'Confirmed',\n DECLINED = 'Declined',\n UNKNOWN = 'Unknown',\n}\n\nexport enum WorkOrderStatus {\n NOT_STARTED = 'NotStarted',\n IN_PROGRESS = 'InProgress',\n COMPLETED = 'Completed',\n CANCELLED = 'Cancelled',\n}\n\nexport interface WorkOrderDetails {\n actualCompletedTime: Date | null;\n actualStartTime: Date | null;\n commitmentWindowConfirmationRequested: boolean;\n commitmentWindowCustomerResponse: CommitmentWindowCustomerResponse;\n completedByResource: WorkOrderDetailsResource;\n endOfCommitmentWindow: Date | null;\n estimatedCompletedTime: Date | null;\n estimatedStartTime: Date | null;\n startingEligibleDate: Date | null;\n endingEligibleDate: Date | null;\n number: string;\n productSubTotal: number;\n projectSequence: number | null;\n resource: WorkOrderDetailsResource | null;\n serviceLocation: WorkOrderDetailsServiceLocation;\n services: WorkOrderDetailsService[];\n serviceSubTotal: number;\n startOfCommitmentWindow: Date | null;\n status: string;\n subNumber: number | null;\n subTotal: number;\n totals: {\n discountTotal: number;\n productAfterServiceDiscount: number;\n productDiscount: number;\n productSubTotal: number;\n productTaxableSubtotal: number;\n roundedTax: number;\n serviceSubTotal: number;\n serviceTaxableSubtotal: number;\n subTotal: number;\n taxableProductAfterServiceDiscount: number;\n taxableServiceAfterServiceDiscount: number;\n };\n workOrderId: string;\n}\n\nconst baseUrl = '/api/WorkOrders';\n\nexport const getWorkOrderDetails = async (workOrderId: string) => {\n try {\n const { data, status } = await get<WorkOrderDetails>(`${baseUrl}/${workOrderId}/details`);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to get work order details.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getServiceReport = async (workOrderId: string) => {\n await openReport(`${baseUrl}/${workOrderId}/report`);\n};\n","import { WorkOrderDetails, getWorkOrderDetails } from '@/api/workOrderDetails';\nimport { useQuery } from 'react-query';\n\nexport const useQueryWorkOrderDetails = (workOrderId: string) =>\n useQuery<WorkOrderDetails, Error>(['workOrderDetails', workOrderId], () => getWorkOrderDetails(workOrderId));\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/Avatars';\n\nexport const getCustomAvatarUrl = async (imageId: string) => {\n try {\n const response = await get<string>(`${baseUrl}/${imageId}/custom`, {\n responseType: 'arraybuffer',\n });\n if (response.status === 200) {\n const blob = new Blob([response.data], { type: response.headers['content-type'] });\n return URL.createObjectURL(blob);\n }\n\n throw new ServerError(`Failed to get avatar.`, response.status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getStockAvatarUrl = async (imageId: string) => {\n try {\n const response = await get<string>(`${baseUrl}/${imageId}/stock`, {\n responseType: 'arraybuffer',\n });\n if (response.status === 200) {\n const blob = new Blob([response.data], { type: response.headers['content-type'] });\n return URL.createObjectURL(blob);\n }\n\n throw new ServerError(`Failed to get avatar.`, response.status);\n } catch (e) {\n throw e;\n }\n};\n","import { getCustomAvatarUrl, getStockAvatarUrl } from '@/api/avatar';\nimport { useQuery } from 'react-query';\n\nexport const useFetchAvatarUrl = (imageId: string, isCustom: boolean) =>\n useQuery<string, Error>(\n ['avatarUrl', imageId, isCustom],\n () => (isCustom ? getCustomAvatarUrl(imageId) : getStockAvatarUrl(imageId)),\n {\n staleTime: Infinity,\n },\n );\n","import { avatarSize } from '@/common/constants';\nimport AccountCircle from '@mui/icons-material/AccountCircle';\n\nexport function AvatarPlaceholder() {\n return <AccountCircle sx={{ fontSize: `${avatarSize}px` }} color=\"primary\" />;\n}\n","import { avatarSize } from '@/common/constants';\nimport { useFetchAvatarUrl } from '@/common/hooks/query/useQueryAvatar';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { AvatarPlaceholder } from './AvatarPlaceholder';\n\ninterface Props {\n imageId: string;\n isCustom: boolean;\n name: string;\n}\n\nconst useStyles = makeStyles({\n img: {\n borderRadius: '50%',\n height: `${avatarSize}px`,\n width: `${avatarSize}px`,\n },\n});\n\nexport function Avatar(props: Props) {\n const { imageId, isCustom, name } = props;\n const classes = useStyles();\n\n const { data, status } = useFetchAvatarUrl(imageId, isCustom);\n\n return (\n <>\n {status == 'success' ? (\n <img className={classes.img} src={data} alt={name} title={name} />\n ) : (\n <AvatarPlaceholder />\n )}\n </>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n team: translate({ id: 'global.team' }),\n technician: translate({ id: 'global.technician' }),\n };\n }, [translate]);\n}\n","import { Box, Stack, Typography } from '@mui/material';\nimport { Avatar } from './Avatar';\nimport { AvatarPlaceholder } from './AvatarPlaceholder';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n imageId: string | null;\n isCustom: boolean;\n name: string;\n}\n\nexport function ResourceDisplay(props: Props) {\n const { imageId, isCustom, name } = props;\n const texts = useTexts();\n\n return (\n <>\n <Box display=\"flex\" alignItems=\"center\">\n <Box mr={1} display=\"flex\">\n {!!imageId ? <Avatar imageId={imageId} isCustom={isCustom} name={name} /> : <AvatarPlaceholder />}\n </Box>\n <Stack>\n <Typography display=\"block\" variant=\"overline\">\n {texts.team} / {texts.technician}\n </Typography>\n <Typography display=\"block\" variant=\"h4\">\n {name}\n </Typography>\n </Stack>\n </Box>\n </>\n );\n}\n","import { DateOnly, LongDateTime, Time } from '@/components/localization/Dates';\nimport { Currency } from '@/components/localization';\nimport { useFormattedAddress } from '@/common/hooks/useAddress';\nimport { useFormattedWorkOrderNumber } from '@/common/hooks/useFormattedWorkOrderNumber';\nimport { ResourceDisplay } from '@/common/components/ResourceDisplay';\nimport { getServiceReport, WorkOrderDetails, WorkOrderDetailsService } from '@/api/workOrderDetails';\nimport Stack from '@mui/material/Stack';\nimport Box from '@mui/material/Box';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { OpenPDFButton } from '@/components/OpenPDFButton';\nimport { useCallback, useMemo } from 'react';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { CustomerPortalLastServiceFields } from '@/common/types/services';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n details: WorkOrderDetails;\n}\n\nexport function ServicesPerformedSecondary(props: { services: WorkOrderDetailsService[] }) {\n const { services } = props;\n return (\n <>\n {services.map((x, i) => (\n <span style={{ display: 'block' }} key={i}>{`${i + 1}. ${x.name}`}</span>\n ))}\n </>\n );\n}\nexport function DetailListItems(props: Props) {\n const {\n details,\n details: {\n serviceLocation: { city, countryCode, postalCode, stateAbbreviation, street1, street2 },\n },\n } = props;\n const resource = props.details.resource;\n\n const texts = useTexts();\n const formattedWorkOrderNumber = useFormattedWorkOrderNumber(\n details.number,\n details.projectSequence,\n details.subNumber,\n );\n const serviceAddress = useFormattedAddress(street1, street2, city, stateAbbreviation, postalCode, countryCode);\n\n const onServiceReportClick = useCallback(() => {\n return getServiceReport(details.workOrderId);\n }, [details.workOrderId]);\n\n const enableLastServiceWorkOrderNumber = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceWorkOrderNumber,\n );\n const enableLastServiceScheduledDate = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceScheduledDate,\n );\n const enableLastServiceScheduledTime = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceScheduledTime,\n );\n const enableLastServiceServiceLocation = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceServiceLocation,\n );\n const enableLastServiceIncludedServices = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceIncludedServices,\n );\n const enableLastServiceTeamTechnicianInfo = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceTeamTechnicianInfo,\n );\n const enableLastServicePriceOfServiceVisit = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServicePriceOfServiceVisit,\n );\n const enableLastServiceServiceReport = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceServiceReport,\n );\n\n const completedDateAndTimeOutput = useMemo(() => {\n const correctedCompletedDateTime = !!details.actualCompletedTime\n ? details.actualCompletedTime\n : (details.estimatedCompletedTime as Date);\n if (enableLastServiceScheduledDate && !enableLastServiceScheduledTime) {\n return <DateOnly value={correctedCompletedDateTime} />;\n } else if (!enableLastServiceScheduledDate && enableLastServiceScheduledTime) {\n return <Time value={correctedCompletedDateTime} />;\n } else {\n return <LongDateTime value={correctedCompletedDateTime} />;\n }\n }, [details, enableLastServiceScheduledDate, enableLastServiceScheduledTime]);\n\n const completedDateAndTimeOutputText = useMemo(() => {\n if (enableLastServiceScheduledDate && !enableLastServiceScheduledTime) {\n return texts.dateCompleted;\n } else if (!enableLastServiceScheduledDate && enableLastServiceScheduledTime) {\n return texts.timeCompleted;\n } else {\n return texts.dateAndTimeCompleted;\n }\n }, [texts, enableLastServiceScheduledDate, enableLastServiceScheduledTime]);\n\n return (\n <Stack direction=\"column\" spacing={2}>\n {enableLastServiceWorkOrderNumber && <DefinitionListItem primary={formattedWorkOrderNumber} />}\n {(!!details.actualCompletedTime || !!details.estimatedCompletedTime) &&\n (enableLastServiceScheduledDate || enableLastServiceScheduledTime) && (\n <DefinitionListItem\n primary={`${completedDateAndTimeOutputText}`}\n secondary={completedDateAndTimeOutput}\n />\n )}\n {enableLastServiceServiceLocation && (\n <DefinitionListItem primary={texts.serviceLocation} secondary={serviceAddress} />\n )}\n {enableLastServiceIncludedServices && (\n <DefinitionListItem\n primary={texts.servicesPerformed}\n secondary={<ServicesPerformedSecondary services={details.services} />}\n />\n )}\n <Box display=\"flex\" flexDirection=\"row\">\n {!!resource && enableLastServiceTeamTechnicianInfo && (\n <Box flexGrow={1} pl={0}>\n <ResourceDisplay\n imageId={resource.imageId}\n isCustom={resource.isCustomImage}\n name={resource.name}\n />\n </Box>\n )}\n\n {enableLastServicePriceOfServiceVisit && (\n <Box flexGrow={0} pr={2}>\n <DefinitionListItem primary={texts.amount} secondary={<Currency value={details.subTotal} />} />\n </Box>\n )}\n </Box>\n {enableLastServiceServiceReport && (\n <Box>\n <OpenPDFButton onClick={onServiceReportClick} errorText={texts.failedToDownloadPDF}>\n {texts.service} {texts.pdf}\n </OpenPDFButton>\n </Box>\n )}\n </Stack>\n );\n}\n","import { useQueryWorkOrderDetails } from '@/common/hooks/query/useQueryWorkOrderDetails';\nimport { Alert, CircularProgress } from '@mui/material';\nimport { DetailListItems } from './DetailListItems';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n workOrderId: string;\n}\n\nexport function DrawerContent(props: Props) {\n const { workOrderId } = props;\n const texts = useTexts();\n const { data: details, status } = useQueryWorkOrderDetails(workOrderId);\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n {status == 'success' && (\n <>\n {!details && <Alert severity=\"error\">{texts.error}</Alert>}\n {details && <DetailListItems details={details} />}\n </>\n )}\n </>\n );\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faTools } from '@fortawesome/pro-regular-svg-icons';\nimport { ShortDate } from '@/components/localization';\nimport Box from '@mui/material/Box';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { SideDrawer } from '@/components/SideDrawer';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { useFormattedWorkOrderNumber } from '@/common/hooks/useFormattedWorkOrderNumber';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport Typography from '@mui/material/Typography';\nimport { useCallback, useMemo } from 'react';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { CustomerPortalLastServiceFields } from '@/common/types/services';\nimport { useTexts } from '../../../useTexts';\nimport { CardProps } from '../typings';\nimport { setSelectedItem, useListState } from '../../store';\nimport { useTexts as useDrawerTexts } from './drawer/useTexts';\nimport { DrawerContent } from './drawer/DrawerContent';\n\nconst Title = (props: { date: Date }) => {\n const { date } = props;\n const texts = useTexts();\n\n const enableLastServiceScheduledDate = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceScheduledDate,\n );\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Typography noWrap>\n {enableLastServiceScheduledDate && <ShortDate value={date} />}\n {` ${texts.serviceVisit}`}\n </Typography>\n </Box>\n );\n};\n\nexport const ServiceCard = (props: CardProps) => {\n const { item } = props;\n const texts = useDrawerTexts();\n const { selected } = useListState();\n const layout = useGetUILayout();\n\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const formattedWorkOrderNumber = useFormattedWorkOrderNumber(\n item.workOrderNumber?.toString() || '',\n item.workOrderProjectSequence,\n item.workOrderSubNumber,\n );\n\n const handleOpen = useCallback(() => {\n setSelectedItem(item.workOrderId!);\n openDrawer();\n }, [openDrawer, item.workOrderId]);\n\n const handleClose = useCallback(() => {\n setSelectedItem('');\n closeDrawer();\n }, [closeDrawer]);\n\n const enableLastServiceWorkOrderNumber = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceWorkOrderNumber,\n );\n\n const subTitle = useMemo(() => {\n return enableLastServiceWorkOrderNumber ? formattedWorkOrderNumber : '';\n }, [enableLastServiceWorkOrderNumber, formattedWorkOrderNumber]);\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n icon={<FontAwesomeIcon icon={faTools} />}\n onClick={handleOpen}\n selected={item.workOrderId === selected}\n subTitle={subTitle}\n title={<Title date={item.date} />}\n />\n ) : (\n <MobileListCard\n icon={<FontAwesomeIcon icon={faTools} />}\n onClick={handleOpen}\n selected={item.workOrderId === selected}\n subTitle={subTitle}\n title={<Title date={item.date} />}\n />\n )}\n\n <SideDrawer isOpen={drawerOpen} onClose={handleClose} title={texts.title}>\n <DrawerContent workOrderId={item.workOrderId || ''} />\n </SideDrawer>\n </>\n );\n};\n","import { AccountHistoryItemModel, HistoryItemType } from '@/api/accountHistory';\nimport { InvoiceCard } from './invoices/InvoiceCard';\nimport { PaymentCard } from './payments/PaymentCard';\nimport { ServiceCard } from './services/ServiceCard';\n\ninterface Props {\n item: AccountHistoryItemModel;\n}\n\nexport function AccountHistoryCard(props: Props) {\n const { item } = props;\n\n switch (item.itemType) {\n case HistoryItemType.INVOICE:\n return <InvoiceCard item={item} />;\n case HistoryItemType.PAYMENT:\n return <PaymentCard item={item} />;\n case HistoryItemType.WORK_ORDER:\n return <ServiceCard item={item} />;\n }\n}\n","import { AccountHistoryItemModel } from '@/api/accountHistory';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { CardList, ListBody, ListFooter } from '@/components/cardList';\nimport { useTexts } from '../useTexts';\nimport { AccountHistoryListHeader } from './header/AccountHistoryListHeader';\nimport { useListState } from './store';\nimport { useListActions } from './hooks';\nimport { FiltersDrawer } from './filters/FiltersDrawer';\nimport { AccountHistoryCard } from './cards';\n\ninterface Props {\n items: AccountHistoryItemModel[];\n total: number;\n}\n\nexport const AccountHistoryList = (props: Props) => {\n const { items, total } = props;\n const { page, take } = useListState();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const texts = useTexts();\n const { handleSetPage } = useListActions();\n\n return (\n <>\n <CardList\n header={<AccountHistoryListHeader openDrawer={openDrawer} />}\n body={<ListBody card={AccountHistoryCard} emptyListAlertText={texts.noHistoryAlert} items={items} />}\n footer={<ListFooter count={Math.ceil(total / take)} page={page + 1} onChange={handleSetPage} />}\n />\n <FiltersDrawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n};\n","import Skeleton from '@mui/material/Skeleton';\nimport Grid from '@mui/material/Grid';\n\nexport function LoadingSkeleton() {\n return (\n <Grid container spacing={2} direction=\"column\" item sm={12} lg={8}>\n <Grid item>\n <Skeleton variant=\"text\" />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n </Grid>\n );\n}\n","import { useQueryAccountHistory } from '@/common/hooks/query/useQueryAccountHistory';\nimport { PageWrapper } from '@/components/PageWrapper';\nimport { useAccountId } from '@/atoms/session';\nimport { PageErrorState } from '@/components/PageErrorState/PageErrorState';\nimport { useEffect } from 'react';\nimport { AccountHistoryList } from './AccountHistoryList';\nimport { resetStore, useListState } from './AccountHistoryList/store';\nimport { LoadingSkeleton } from './LoadingSkeleton';\nimport { useLocation } from 'react-router';\n\nexport interface AccountHistoryState {\n isStale: boolean;\n}\n\nexport const AccountHistory = () => {\n const { page, take, search, type, serviceLocations, startDate, endDate } = useListState();\n const accountId = useAccountId();\n const query = useQueryAccountHistory(\n accountId || '',\n page,\n take,\n search,\n type,\n serviceLocations,\n startDate,\n endDate,\n );\n\n const location = useLocation();\n const state = location.state as AccountHistoryState;\n\n useEffect(() => {\n if (!!state && state.isStale) {\n query.refetch();\n }\n }, [])\n\n useEffect(() => {\n resetStore();\n }, [accountId]);\n\n return (\n <PageWrapper disableScroll>\n {query.status === 'loading' && <LoadingSkeleton />}\n {query.status === 'success' && <AccountHistoryList items={query.data.items} total={query.data.total} />}\n {query.status === 'error' && <PageErrorState />}\n </PageWrapper>\n );\n};\n\nAccountHistory.displayName = 'AccountHistory';\n","import Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport { SpacingProps } from '@mui/system';\n\ninterface Props extends SpacingProps {\n children?: React.ReactNode;\n className?: string;\n}\n\nexport const Section = (props: Props) => {\n const { children, className, ...other } = props;\n\n return (\n <Paper elevation={2}>\n <Box p={other.p ?? 2} className={className} {...other}>\n {children}\n </Box>\n </Paper>\n );\n};\n\nSection.displayName = 'Section';\n","import { Box, Typography } from '@mui/material';\n\nimport makeStyles from '@mui/styles/makeStyles';\n\nconst useStyles = makeStyles(theme => ({\n icon: {\n color: theme.palette.primary.main,\n fontSize: theme.typography.h3.fontSize,\n },\n title: {\n fontSize: '18px',\n fontWeight: 'bold',\n },\n}));\n\ninterface Props {\n icon?: JSX.Element;\n primaryAction?: JSX.Element;\n secondaryAction?: JSX.Element;\n title: string;\n}\n\nexport function SectionHeader(props: Props) {\n const { icon, primaryAction, secondaryAction, title } = props;\n const classes = useStyles();\n\n return (\n <Box pb={2} display=\"flex\" alignItems=\"center\">\n {!!icon && (\n <Box className={classes.icon} mr={1.5}>\n {icon}\n </Box>\n )}\n <Box display=\"flex\" flexGrow={1}>\n <Typography className={classes.title} variant=\"h2\">\n {title}\n </Typography>\n </Box>\n {!!primaryAction && <Box ml={2}>{primaryAction}</Box>}\n {!!secondaryAction && <Box ml={2}>{secondaryAction}</Box>}\n </Box>\n );\n}\n\nSectionHeader.displayName = 'SectionHeader';\n","import { GetOpenInvoicesResponse } from '@/common/types/invoices';\nimport { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\nimport { BillingLocation } from './billingLocations';\n\nexport interface AccountSummary {\n accountBalance: number;\n credits: number;\n openBalance: number;\n prePayments: number;\n}\n\nconst baseUrl = '/api/accounts';\n\nexport const getBalance = async (accountId: string) => {\n try {\n const { data, status } = await get<number>(`${baseUrl}/balance?accountId=${accountId}`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get account balance.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getUnappliedStartingBalance = async (accountId: string) => {\n try {\n const { data, status } = await get<number>(`${baseUrl}/${accountId}/unappliedStartingBalance`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get unapplied starting balance.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getAccountSummary = async (accountId: string) => {\n try {\n const { data, status } = await get<AccountSummary>(`${baseUrl}/balanceBreakdown?accountId=${accountId}`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get account balance breakdown.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getDefaultBillingLocation = async (accountId: string) => {\n try {\n const { data, status } = await get<BillingLocation>(`${baseUrl}/${accountId}/defaultBillingLocation`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get default billing location.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getDefaultServiceLocationId = async (accountId: string) => {\n try {\n const { data, status } = await get<string>(`${baseUrl}/${accountId}/defaultServiceLocationId`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get default service location.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getOpenInvoices = async (accountId: string, page: number, take: number, skip: number) => {\n try {\n const { data, status } = await get<GetOpenInvoicesResponse>(\n `${baseUrl}/${accountId}/invoices?page=${page}&take=${take}&skip=${skip}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get open invoices.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { AccountSummary, getAccountSummary } from '@/api/accounts';\nimport { useQuery } from 'react-query';\n\nexport const useFetchAccountSummary = (accountId: string) =>\n useQuery<AccountSummary, Error>(['account-summary', accountId], () => getAccountSummary(accountId), {\n staleTime: Infinity,\n });\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n accountBalance: translate({ id: 'sections.accountOverview.accountSummary.accountBalance' }),\n credits: translate({ id: 'sections.accountOverview.accountSummary.credits' }),\n error: translate({ id: 'sections.accountOverview.accountSummary.error' }),\n header: translate({ id: 'sections.accountOverview.accountSummary.header' }),\n makePayment: translate({ id: 'sections.accountOverview.accountSummary.makePayment' }),\n openInvoices: translate({ id: 'sections.accountOverview.accountSummary.openInvoices' }),\n prepayments: translate({ id: 'sections.accountOverview.accountSummary.prepayments' }),\n };\n }, [translate]);\n}\n","import { Box, Typography } from '@mui/material';\n\nimport makeStyles from '@mui/styles/makeStyles';\n\nconst useStyles = makeStyles({\n title: {\n fontWeight: 'bold',\n },\n});\n\ninterface Props {\n title: string;\n value: string | React.ReactNode;\n}\n\nexport const SummaryValue = (props: Props) => {\n const classes = useStyles();\n const { title, value } = props;\n\n return (\n <Box display=\"flex\" width={1}>\n <Box display=\"flex\" flexGrow={1}>\n <Typography className={classes.title}>{title}</Typography>\n </Box>\n <Box>\n <Typography>{value}</Typography>\n </Box>\n </Box>\n );\n};\n\nSummaryValue.displayName = 'SummaryValue';\n","import { Grid } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { AccountSummary } from '@/api/accounts';\nimport { Currency } from '@/components/localization';\nimport { SummaryValue } from './SummaryValue';\nimport { useTexts } from './useTexts';\n\nconst useStyles = makeStyles({\n columnContainer: {\n minInlineSize: 'fit-content',\n },\n});\n\ninterface Props {\n data: AccountSummary;\n}\n\nexport const Content = (props: Props) => {\n const { data } = props;\n const texts = useTexts();\n const classes = useStyles();\n\n return (\n <>\n <Grid container spacing={2}>\n <Grid item xs className={classes.columnContainer}>\n <Grid container direction=\"column\" spacing={2}>\n <Grid item container>\n <SummaryValue\n title={texts.accountBalance}\n value={<Currency value={data.accountBalance || 0} />}\n />\n </Grid>\n <Grid item container>\n <SummaryValue\n title={texts.openInvoices}\n value={<Currency value={data.openBalance || 0} />}\n />\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs className={classes.columnContainer}>\n <Grid container direction=\"column\" spacing={2}>\n <Grid item container>\n <SummaryValue title={texts.credits} value={<Currency value={data.credits || 0} />} />\n </Grid>\n <Grid item container>\n <SummaryValue\n title={texts.prepayments}\n value={<Currency value={data.prePayments || 0} />}\n />\n </Grid>\n </Grid>\n </Grid>\n </Grid>\n </>\n );\n};\n\nContent.displayName = 'Content';\n","import { Button, CircularProgress, Typography } from '@mui/material';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { faDollarSign } from '@fortawesome/pro-regular-svg-icons';\nimport { useNavigate } from 'react-router';\nimport { useCallback } from 'react';\nimport { useFetchAccountSummary } from '@/common/hooks/query/useFetchAccountSummary';\nimport { usePaymentsEnabled } from '@/common/hooks/usePaymentsEnabled';\nimport { useTexts } from './useTexts';\nimport { Content } from './Content';\n\ninterface Props {\n accountId: string;\n hidePrimaryAction?: boolean;\n}\n\nexport function AccountSummary(props: Props) {\n const { accountId, hidePrimaryAction = false } = props;\n const { data, status } = useFetchAccountSummary(accountId);\n const texts = useTexts();\n const paymentsEnabled = usePaymentsEnabled();\n const navigate = useNavigate();\n\n const navigateToPayInvoices = useCallback(() => {\n navigate('/payments/pay-invoices');\n }, [navigate]);\n\n return (\n <Section>\n <SectionHeader\n icon={<FontAwesomeIcon icon={faDollarSign} />}\n title={texts.header}\n primaryAction={\n paymentsEnabled && !hidePrimaryAction ? (\n <Button variant=\"contained\" color=\"primary\" onClick={navigateToPayInvoices}>\n {texts.makePayment}\n </Button>\n ) : (\n <></>\n )\n }\n />\n {status == 'error' && <Typography>{texts.error}</Typography>}\n {status == 'loading' && <CircularProgress />}\n {status == 'success' && !!data && <Content data={data} />}\n </Section>\n );\n}\n","import { get, put } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\nimport { CommitmentWindowCustomerResponse, WorkOrderStatus } from './workOrderDetails';\n\nexport interface WorkOrderWidgetService {\n serviceName: string;\n}\nexport interface WorkOrderWidgetServiceLocation {\n city: string;\n countryCode: string;\n serviceLocationName: string;\n state: string;\n street1: string;\n street2: string;\n zipCode: string;\n}\n\nexport interface WorkOrderWidgetData {\n amount: number;\n commitmentWindowConfirmationRequested: boolean;\n commitmentWindowCustomerResponse: CommitmentWindowCustomerResponse;\n datePerformed: string;\n endingEligibleDate: Date;\n estimatedTimeOfArrival: string;\n imageId: string | null;\n isCustomImage: boolean;\n resource: string;\n serviceLocation: WorkOrderWidgetServiceLocation;\n services: WorkOrderWidgetService[];\n startingEligibleDate: Date;\n workOrderId: string;\n status: WorkOrderStatus;\n}\n\nexport interface CommitmentWindowCustomerRequest {\n workOrderId: string;\n customerResponse: CommitmentWindowCustomerResponse;\n}\n\nconst baseUrl = '/api/workOrders';\n\nexport const getLastServicePerformedWidget = async (accountId: string) => {\n try {\n const { data, status } = await get<WorkOrderWidgetData | null>(\n `${baseUrl}/lastPerformedWidget?accountId=${accountId}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to fetch last service performed.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getNextScheduledWorkOrder = async (accountId: string) => {\n try {\n const { data, status } = await get<WorkOrderWidgetData | null>(\n `${baseUrl}/nextScheduledWidget?accountId=${accountId}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to fetch next scheduled service.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const setCommitmentWindowCustomerResponse = async (\n workOrderId: string,\n customerResponse: CommitmentWindowCustomerResponse,\n) => {\n try {\n const { data, status } = await put<CommitmentWindowCustomerResponse>(\n `${baseUrl}/${workOrderId}/commitmentWindowCustomerResponse?response=${customerResponse}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to update Work Order confirmation status.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { getNextScheduledWorkOrder, WorkOrderWidgetData } from '@/api/workOrders';\nimport { useQuery } from 'react-query';\n\nexport const useQueryYourNextService = (accountId: string) =>\n useQuery<WorkOrderWidgetData | null, Error>(\n ['yourNextService', accountId],\n () => getNextScheduledWorkOrder(accountId),\n {\n staleTime: Infinity,\n },\n );\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n commitmentWindow: translate({ id: 'sections.upcomingServices.serviceCard.drawer.commitmentWindow' }),\n confirmed: translate({ id: 'sections.upcomingServices.serviceCard.badge.confirmed' }),\n confirmVisit: translate({ id: 'sections.upcomingServices.serviceCard.drawer.confirmVisit' }),\n declined: translate({ id: 'sections.upcomingServices.serviceCard.badge.declined' }),\n declineVisit: translate({ id: 'sections.upcomingServices.serviceCard.drawer.declineVisit' }),\n doesNotIncludeTax: translate({ id: 'sections.upcomingServices.serviceCard.drawer.doesNotIncludeTax' }),\n eligibilityDate: translate({ id: 'sections.upcomingServices.serviceCard.drawer.eligibilityDate' }),\n error: translate({ id: 'sections.upcomingServices.serviceCard.drawer.error' }),\n failedToConfirm: translate({ id: 'sections.upcomingServices.serviceCard.drawer.failedToConfirm' }),\n failedToDecline: translate({ id: 'sections.upcomingServices.serviceCard.drawer.failedToDecline' }),\n includedServices: translate({ id: 'sections.upcomingServices.serviceCard.drawer.includedServices' }),\n needsConfirmation: translate({ id: 'sections.upcomingServices.serviceCard.badge.needsConfirmation' }),\n notYetScheduled: translate({ id: 'sections.upcomingServices.serviceCard.drawer.notYetScheduled' }),\n price: translate({ id: 'sections.upcomingServices.serviceCard.drawer.price' }),\n scheduledDate: translate({\n id: 'sections.upcomingServices.serviceCard.drawer.scheduledDate',\n }),\n scheduledDateAndTime: translate({\n id: 'sections.upcomingServices.serviceCard.drawer.scheduledDateAndTime',\n }),\n scheduledTime: translate({\n id: 'sections.upcomingServices.serviceCard.drawer.scheduledTime',\n }),\n serviceLocation: translate({ id: 'global.serviceLocation' }),\n successfullyConfirmed: translate({ id: 'global.successfullyConfirmed' }),\n successfullyDeclined: translate({ id: 'global.successfullyDeclined' }),\n title: translate({ id: 'sections.upcomingServices.serviceCard.drawer.title' }),\n };\n }, [translate]);\n}\n","import { CommitmentWindowCustomerResponse } from '@/api/workOrderDetails';\nimport { CardBadge } from '@/components/cardList/CardBadge';\nimport { useTexts } from '../drawer/useTexts';\n\ninterface Props {\n confirmationRequested: boolean;\n status: CommitmentWindowCustomerResponse;\n}\n\nexport function ConfirmationBadge(props: Props) {\n const { confirmationRequested, status } = props;\n const texts = useTexts();\n\n switch (status) {\n case CommitmentWindowCustomerResponse.CONFIRMED:\n return <CardBadge severity=\"success\" text={texts.confirmed} />;\n case CommitmentWindowCustomerResponse.DECLINED:\n return <CardBadge severity=\"error\" text={texts.declined} />;\n case CommitmentWindowCustomerResponse.UNKNOWN:\n return confirmationRequested ? <CardBadge severity=\"warning\" text={texts.needsConfirmation} /> : <></>;\n }\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n amount: translate({ id: 'sections.accountOverview.yourNextService.amount' }),\n confirmBtn: translate({ id: 'sections.accountOverview.yourNextService.confirmBtn' }),\n date: translate({ id: 'sections.accountOverview.yourNextService.date' }),\n dateAndTime: translate({ id: 'sections.accountOverview.yourNextService.dateAndTime' }),\n eligibilityDate: translate({ id: 'sections.accountOverview.yourNextService.eligibilityDate' }),\n error: translate({ id: 'sections.accountOverview.yourNextService.error' }),\n eta: translate({ id: 'global.eta' }),\n failedToConfirm: translate({ id: 'sections.upcomingServices.serviceCard.drawer.failedToConfirm' }),\n header: translate({ id: 'sections.accountOverview.yourNextService.header' }),\n noResults: translate({ id: 'sections.accountOverview.yourNextService.noResults' }),\n notScheduled: translate({ id: 'sections.accountOverview.yourNextService.notScheduled' }),\n notSet: translate({ id: 'global.notSet' }),\n serviceLocation: translate({ id: 'sections.accountOverview.yourNextService.serviceLocation' }),\n servicesToBePerformed: translate({ id: 'sections.accountOverview.yourNextService.servicesToBePerformed' }),\n successfullyConfirmed: translate({ id: 'global.successfullyConfirmed' }),\n team: translate({ id: 'global.team' }),\n technician: translate({ id: 'global.technician' }),\n time: translate({ id: 'sections.accountOverview.yourNextService.time' }),\n };\n }, [translate]);\n}\n","import { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Box, Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { Currency } from '@/components/localization';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { CustomerPortalLastServiceFields } from '@/common/types/services';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n marginLeft: theme.spacing(1),\n textAlign: 'right',\n justifyContent: 'flex-end',\n [theme.breakpoints.down('sm')]: {\n textAlign: 'left',\n justifyContent: 'flex-start',\n marginLeft: theme.spacing(0),\n marginTop: theme.spacing(2),\n },\n },\n}));\n\nconst servicesHiddenStyles = makeStyles(theme => ({\n root: {\n marginLeft: theme.spacing(0),\n marginTop: theme.spacing(0),\n [theme.breakpoints.down('sm')]: {\n textAlign: 'left',\n marginLeft: theme.spacing(0),\n marginTop: theme.spacing(2),\n },\n },\n}));\n\ninterface Props {\n amount: number;\n label: string;\n}\n\nexport const ServiceAmount = (props: Props) => {\n const defaultClass = useStyles();\n const servicesHiddenClass = servicesHiddenStyles();\n const { amount, label } = props;\n\n const enableLastServiceIncludedServices = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceIncludedServices,\n );\n\n return (\n <Box className={enableLastServiceIncludedServices ? defaultClass.root : servicesHiddenClass.root}>\n <DefinitionListItem\n primary={label}\n secondary={<Typography>{<Currency value={amount || 0} />}</Typography>}\n />\n </Box>\n );\n};\n\nServiceAmount.displayName = 'ServiceAmount';\n","import { Box, Typography } from '@mui/material';\nimport { WorkOrderWidgetService } from '@/api/workOrders';\n\ninterface Props {\n services: WorkOrderWidgetService[];\n}\n\nexport const ServicesList = (props: Props) => {\n const { services } = props;\n\n return (\n <>\n {services.length > 0 && (\n <Box>\n {services.map((service, i) => (\n <Typography key={i}>\n {i + 1}. {service.serviceName}\n </Typography>\n ))}\n </Box>\n )}\n\n {services.length == 0 && <Typography>None</Typography>}\n </>\n );\n};\n\nServicesList.displayName = 'ServicesList';\n","import { Box, Typography } from '@mui/material';\nimport { WorkOrderWidgetServiceLocation } from '@/api/workOrders';\n\ninterface Props {\n serviceLocation: WorkOrderWidgetServiceLocation;\n}\n\nexport const ServiceLocationDetail = (props: Props) => {\n const { serviceLocation } = props;\n\n return (\n <Box>\n {serviceLocation.serviceLocationName && <Typography>{serviceLocation.serviceLocationName}</Typography>}\n {serviceLocation.street1 && <Typography>{serviceLocation.street1}</Typography>}\n {serviceLocation.street2 && <Typography>{serviceLocation.street2}</Typography>}\n <Typography>\n {serviceLocation.city}, {serviceLocation.state} {serviceLocation.zipCode}, {serviceLocation.countryCode}{' '}\n </Typography>\n </Box>\n );\n};\n\nServiceLocationDetail.displayName = 'ServiceLocationDetail';\n","import { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Alert, Grid, Stack, Typography } from '@mui/material';\nimport { WorkOrderWidgetData } from '@/api/workOrders';\nimport { FormattedTime } from 'react-intl';\nimport { Currency, LongDate, ShortDate } from '@/components/localization';\nimport { ResourceDisplay } from '@/common/components/ResourceDisplay';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { useMemo } from 'react';\nimport { ServiceAmount } from '../common/ServiceAmount';\nimport { ServicesList } from '../common/ServicesList';\nimport { ServiceLocationDetail } from '../common/ServiceLocationDetail';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n data?: WorkOrderWidgetData | null;\n}\n\nexport const Content = (props: Props) => {\n const { data } = props;\n const texts = useTexts();\n\n const enableScheduledDate = useFeatureEnabled('enableScheduledDate');\n const enableScheduledTime = useFeatureEnabled('enableScheduledTime');\n const enableServiceLocation = useFeatureEnabled('enableServiceLocation');\n const enableIncludedServices = useFeatureEnabled('enableIncludedServices');\n const enableTeamTechnicianInfo = useFeatureEnabled('enableTeamTechnicianInfo');\n const enablePriceOfServiceVisit = useFeatureEnabled('enablePriceOfServiceVisit');\n\n const scheduledDateText = useMemo(() => {\n if (enableScheduledDate && enableScheduledTime === false) {\n return texts.date;\n } else if (enableScheduledDate === false && enableScheduledTime) {\n return texts.time;\n } else {\n return texts.dateAndTime;\n }\n }, [enableScheduledDate, enableScheduledTime, texts.date, texts.time, texts.dateAndTime]);\n\n return (\n <>\n {!!data && (\n <Stack direction=\"column\" spacing={2}>\n {!!data.estimatedTimeOfArrival && (enableScheduledDate || enableScheduledTime) && (\n <DefinitionListItem\n primary={scheduledDateText}\n secondary={\n (\n <Typography>\n {enableScheduledDate && (\n <>\n <LongDate value={data.estimatedTimeOfArrival} />{' '}\n {enableScheduledTime && <> - {texts.eta} </>}\n </>\n )}\n {enableScheduledTime && <FormattedTime value={data.estimatedTimeOfArrival} />}\n </Typography>\n ) || texts.notSet\n }\n />\n )}\n {!data.estimatedTimeOfArrival && (\n <>\n <DefinitionListItem\n primary={texts.eligibilityDate}\n secondary={\n (\n <Typography>\n <ShortDate value={data.startingEligibleDate} />\n {' - '}\n <ShortDate value={data.endingEligibleDate} />\n </Typography>\n ) || texts.notSet\n }\n />\n <Alert severity=\"info\">\n <Typography>{texts.notScheduled}</Typography>\n </Alert>\n </>\n )}\n\n {enableServiceLocation && (\n <DefinitionListItem\n primary={texts.serviceLocation}\n secondary={<ServiceLocationDetail serviceLocation={data.serviceLocation} />}\n />\n )}\n\n {enablePriceOfServiceVisit && enableIncludedServices === false && (\n <DefinitionListItem\n primary={texts.amount}\n secondary={<Typography>{<Currency value={data.amount || 0} />}</Typography>}\n />\n )}\n\n <Grid item container>\n {enableIncludedServices && (\n <Grid item xs={12} sm={6}>\n <DefinitionListItem\n primary={texts.servicesToBePerformed}\n secondary={<ServicesList services={data.services} />}\n />\n </Grid>\n )}\n {enablePriceOfServiceVisit && enableIncludedServices && (\n <Grid item xs={12} sm={6}>\n <ServiceAmount label={texts.amount} amount={data.amount || 0} />\n </Grid>\n )}\n </Grid>\n\n {!!data.resource && enableTeamTechnicianInfo && (\n <ResourceDisplay\n imageId={data.imageId}\n isCustom={data.isCustomImage}\n name={data.resource || texts.notSet}\n />\n )}\n </Stack>\n )}\n\n {!data && <Typography>{texts.noResults}</Typography>}\n </>\n );\n};\n\nContent.displayName = 'Content';\n","import CircularProgress from '@mui/material/CircularProgress';\nimport Typography from '@mui/material/Typography';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faClock } from '@fortawesome/free-regular-svg-icons';\nimport { useQueryYourNextService } from '@/common/hooks/query/useQueryYourNextService';\nimport { useCallback, useMemo, useState } from 'react';\nimport { useToast } from '@/utils/useToast';\nimport { setCommitmentWindowCustomerResponse } from '@/api/workOrders';\nimport { CommitmentWindowCustomerResponse, WorkOrderStatus } from '@/api/workOrderDetails';\nimport LoadingButton from '@mui/lab/LoadingButton';\nimport { queryClient } from '../../../../services/queryClient';\nimport { ConfirmationBadge } from '../../../UpcomingServices/components/ConfirmationBadge';\nimport { useTexts } from './useTexts';\nimport { Content } from './Content';\n\ninterface Props {\n accountId: string;\n}\n\nexport function YourNextService(props: Props) {\n const { accountId } = props;\n const { status, data } = useQueryYourNextService(accountId);\n const texts = useTexts();\n const toast = useToast();\n const [loading, setLoading] = useState(false);\n\n const confirmVisit = useCallback(async () => {\n try {\n setLoading(true);\n await setCommitmentWindowCustomerResponse(\n data?.workOrderId || '',\n CommitmentWindowCustomerResponse.CONFIRMED,\n );\n queryClient.invalidateQueries('yourNextService');\n queryClient.invalidateQueries('workOrderDetails');\n queryClient.invalidateQueries('upcomingServices');\n toast.success(texts.successfullyConfirmed);\n } catch {\n toast.error(texts.failedToConfirm);\n } finally {\n setLoading(false);\n }\n }, [data?.workOrderId, texts, toast]);\n\n const showBadge = useMemo(() => {\n return (\n !!data?.estimatedTimeOfArrival &&\n data?.commitmentWindowCustomerResponse !== CommitmentWindowCustomerResponse.UNKNOWN\n );\n }, [data?.commitmentWindowCustomerResponse, data?.estimatedTimeOfArrival]);\n\n const showButton = useMemo(() => {\n return (\n !!data?.estimatedTimeOfArrival &&\n data?.commitmentWindowConfirmationRequested &&\n data?.commitmentWindowCustomerResponse === CommitmentWindowCustomerResponse.UNKNOWN &&\n data?.status !== WorkOrderStatus.IN_PROGRESS\n );\n }, [\n data?.commitmentWindowConfirmationRequested,\n data?.commitmentWindowCustomerResponse,\n data?.estimatedTimeOfArrival,\n data?.status,\n ]);\n\n return (\n <Section>\n <SectionHeader\n icon={<FontAwesomeIcon icon={faClock} />}\n primaryAction={\n <>\n {showBadge && (\n <ConfirmationBadge\n status={data!.commitmentWindowCustomerResponse}\n confirmationRequested={data!.commitmentWindowConfirmationRequested}\n />\n )}\n {showButton && (\n <LoadingButton\n loading={loading}\n loadingPosition=\"start\"\n sx={{ pl: loading ? 4.5 : 2 }}\n onClick={confirmVisit}\n color=\"primary\"\n variant=\"contained\"\n disabled={data == null}\n >\n {texts.confirmBtn}\n </LoadingButton>\n )}\n </>\n }\n title={texts.header}\n />\n {status == 'error' && <Typography>{texts.error}</Typography>}\n {status == 'loading' && <CircularProgress />}\n {status == 'success' && <Content data={data} />}\n </Section>\n );\n}\n","import { useCallback, useEffect, useState } from 'react';\nimport { isServerError } from '@/utils/ServerError';\nimport { WorkOrderWidgetData, getLastServicePerformedWidget } from '@/api/workOrders';\n\ninterface ErrorData {\n error: Error;\n status: 'error';\n}\n\ninterface LoadingData {\n status: 'loading';\n}\n\ninterface SuccessData {\n payload: WorkOrderWidgetData | null;\n status: 'success';\n}\n\ntype Data = ErrorData | LoadingData | SuccessData;\n\nexport const useData = (accountId: string) => {\n const [data, setData] = useState<Data>({ status: 'loading' });\n const [isStale, setIsStale] = useState<boolean>(true);\n\n useEffect(() => {\n let mounted = true;\n\n const getSettings = async (accountId: string) => {\n try {\n setData({ status: 'loading' });\n const response = await getLastServicePerformedWidget(accountId);\n\n if (isServerError(response)) {\n throw new Error(response.message);\n }\n\n if (mounted && response != undefined) {\n setData({ status: 'success', payload: response });\n }\n } catch (e) {\n if (mounted) {\n const error = e instanceof Error ? e : new Error('unknown error');\n setData({ status: 'error', error });\n }\n } finally {\n setIsStale(false);\n }\n };\n\n if (isStale && !!accountId) {\n getSettings(accountId);\n }\n\n return () => {\n mounted = false;\n };\n }, [accountId, isStale]);\n\n const refreshData = useCallback(async () => {\n setIsStale(true);\n }, []);\n\n useEffect(() => {\n refreshData();\n }, [accountId, refreshData]);\n\n return [data, refreshData] as const;\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n amount: translate({ id: 'sections.accountOverview.yourLastService.amount' }),\n date: translate({ id: 'sections.accountOverview.yourLastService.date' }),\n dateAndTime: translate({ id: 'sections.accountOverview.yourLastService.dateAndTime' }),\n error: translate({ id: 'sections.accountOverview.yourLastService.error' }),\n header: translate({ id: 'sections.accountOverview.yourLastService.header' }),\n noResults: translate({ id: 'sections.accountOverview.yourLastService.noResults' }),\n notSet: translate({ id: 'global.notSet' }),\n serviceLocation: translate({ id: 'sections.accountOverview.yourLastService.serviceLocation' }),\n servicesPerformed: translate({ id: 'sections.accountOverview.yourLastService.servicesPerformed' }),\n team: translate({ id: 'global.team' }),\n technician: translate({ id: 'global.technician' }),\n time: translate({ id: 'sections.accountOverview.yourLastService.time' }),\n };\n }, [translate]);\n}\n","import { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Grid, Typography } from '@mui/material';\nimport { WorkOrderWidgetData } from '@/api/workOrders';\nimport { FormattedTime } from 'react-intl';\nimport { LongDate } from '@/components/localization';\nimport { ResourceDisplay } from '@/common/components/ResourceDisplay';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { CustomerPortalLastServiceFields } from '@/common/types/services';\nimport { ServiceAmount } from '../common/ServiceAmount';\nimport { ServicesList } from '../common/ServicesList';\nimport { ServiceLocationDetail } from '../common/ServiceLocationDetail';\nimport { useTexts } from './useTexts';\ninterface Props {\n data: WorkOrderWidgetData | null;\n}\n\nexport const Content = (props: Props) => {\n const { data } = props;\n const texts = useTexts();\n\n const enableLastServiceScheduledDate = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceScheduledDate,\n );\n const enableLastServiceScheduledTime = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceScheduledTime,\n );\n const enableLastServiceServiceLocation = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceServiceLocation,\n );\n const enableLastServiceIncludedServices = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceIncludedServices,\n );\n const enableLastServiceTeamTechnicianInfo = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServiceTeamTechnicianInfo,\n );\n const enableLastServicePriceOfServiceVisit = useFeatureEnabled(\n CustomerPortalLastServiceFields.EnableLastServicePriceOfServiceVisit,\n );\n\n return (\n <>\n {!!data && (\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n {enableLastServiceScheduledDate && enableLastServiceScheduledTime && (\n <DefinitionListItem\n primary={texts.dateAndTime}\n secondary={\n (\n <Typography>\n <LongDate value={data.datePerformed || data.estimatedTimeOfArrival} /> at{' '}\n <FormattedTime value={data.datePerformed || data.estimatedTimeOfArrival} />\n </Typography>\n ) || texts.notSet\n }\n />\n )}\n\n {enableLastServiceScheduledDate && !enableLastServiceScheduledTime && (\n <DefinitionListItem\n primary={texts.date}\n secondary={\n (\n <Typography>\n <LongDate value={data.datePerformed || data.estimatedTimeOfArrival} />\n </Typography>\n ) || texts.notSet\n }\n />\n )}\n {!enableLastServiceScheduledDate && enableLastServiceScheduledTime && (\n <DefinitionListItem\n primary={texts.time}\n secondary={\n (\n <Typography>\n <FormattedTime value={data.datePerformed || data.estimatedTimeOfArrival} />\n </Typography>\n ) || texts.notSet\n }\n />\n )}\n </Grid>\n {enableLastServiceServiceLocation && (\n <Grid item>\n <DefinitionListItem\n primary={texts.serviceLocation}\n secondary={<ServiceLocationDetail serviceLocation={data.serviceLocation} />}\n />\n </Grid>\n )}\n\n <Grid item container>\n {enableLastServiceIncludedServices && (\n <Grid item xs={12} sm={6}>\n <DefinitionListItem\n primary={texts.servicesPerformed}\n secondary={<ServicesList services={data.services} />}\n />\n </Grid>\n )}\n {enableLastServicePriceOfServiceVisit && (\n <Grid item xs={12} sm={6}>\n <ServiceAmount amount={data.amount || 0} label={texts.amount} />\n </Grid>\n )}\n </Grid>\n\n {enableLastServiceTeamTechnicianInfo && (\n <Grid item>\n <ResourceDisplay\n imageId={data.imageId}\n isCustom={data.isCustomImage}\n name={data.resource || texts.notSet}\n />\n </Grid>\n )}\n </Grid>\n )}\n\n {!data && <Typography>{texts.noResults}</Typography>}\n </>\n );\n};\n\nContent.displayName = 'Content';\n","import { CircularProgress, Typography } from '@mui/material';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { faHistory } from '@fortawesome/pro-regular-svg-icons';\nimport { useData } from './useData';\nimport { useTexts } from './useTexts';\nimport { Content } from './Content';\ninterface Props {\n accountId: string;\n}\n\nexport const YourLastService = (props: Props) => {\n const { accountId } = props;\n const [data] = useData(accountId);\n const texts = useTexts();\n\n return (\n <Section>\n <SectionHeader icon={<FontAwesomeIcon icon={faHistory} />} title={texts.header} />\n {data.status == 'error' && <Typography>{texts.error}</Typography>}\n {data.status == 'loading' && <CircularProgress />}\n {data.status == 'success' && <Content data={data.payload} />}\n </Section>\n );\n};\n\nYourLastService.displayName = 'YourLastService';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n requestServices: translate({ id: 'sections.accountOverview.requestServices' }),\n };\n }, [translate]);\n}\n","import { useCallback } from 'react';\nimport { Button, Box, Stack } from '@mui/material';\nimport { useNavigate } from 'react-router';\nimport { useAccountId } from '@/atoms/session';\nimport { PageWrapper } from '@/components/PageWrapper';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { AccountSummary } from './widgets/AccountSummary/AccountSummary';\nimport { YourNextService } from './widgets/YourNextService/YourNextService';\nimport { YourLastService } from './widgets/YourLastService/YourLastService';\nimport { useTexts } from './useTexts';\n\nexport function AccountOverview() {\n const accountId = useAccountId();\n const navigate = useNavigate();\n const texts = useTexts();\n const serviceHistoryEnabled = useFeatureEnabled('enableServiceHistory');\n const upcomingServicesEnabled = useFeatureEnabled('enableUpcomingServices');\n const requestServiceEnabled = useFeatureEnabled('enableRequestNewService');\n\n const goToRequestService = useCallback(() => {\n navigate('/your-services/request-service');\n }, [navigate]);\n\n return (\n <PageWrapper>\n <Stack direction=\"column\" spacing={2}>\n {requestServiceEnabled && (\n <Box>\n <Button color=\"primary\" variant=\"contained\" onClick={goToRequestService}>\n {texts.requestServices}\n </Button>\n </Box>\n )}\n\n {!!accountId && (\n <>\n <AccountSummary accountId={accountId} />\n\n {upcomingServicesEnabled && <YourNextService accountId={accountId} />}\n {serviceHistoryEnabled && <YourLastService accountId={accountId} />}\n </>\n )}\n </Stack>\n </PageWrapper>\n );\n}\n","import { AgreementDetails, AgreementStatus } from '@/common/types/agreements';\nimport { get } from '@/utils/http';\nimport { openReport } from '@/utils/openReport';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/Agreements';\nconst accountsBaseUrl = '/api/Accounts';\n\nexport interface AgreementsResponse {\n total: number;\n page: number;\n take: number;\n items: AgreementModel[];\n}\n\nexport interface AgreementModel {\n agreementDate: Date;\n agreementId: string;\n hasAutoPayment: boolean;\n hasExpiredPaymentMethod: boolean;\n hasValidationErrors: boolean;\n name: string;\n status: AgreementStatus;\n}\n\nfunction getQueryString(page: number, take: number, serviceLocations: string[], status: AgreementStatus | null) {\n const params = new URLSearchParams({\n page: page.toString(),\n take: take.toString(),\n });\n\n if (!!serviceLocations.length) {\n serviceLocations.map(x => !!x && params.append('serviceLocation', x));\n }\n\n if (!!status) {\n params.append('status', status);\n }\n\n return params;\n}\n\nexport const getAgreements = async (\n accountId: string,\n page: number,\n take: number,\n serviceLocations: string[],\n agreementStatus: AgreementStatus | null,\n) => {\n try {\n const queryString = getQueryString(page, take, serviceLocations, agreementStatus);\n const { status, data } = await get<AgreementsResponse>(\n `${accountsBaseUrl}/${accountId}/agreements?${queryString}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get agreements.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getAgreementDetails = async (agreementId: string) => {\n try {\n const { data, status } = await get<AgreementDetails>(`${baseUrl}/${agreementId}/Details`);\n\n if (status === 200) {\n return { ...data, agreementId: agreementId };\n }\n\n throw new ServerError(`Failed to get Agreement details.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getAgreementReport = async (agreementId: string) => {\n await openReport(`${baseUrl}/${agreementId}/report`);\n};\n","import { useQuery } from 'react-query';\nimport { AgreementsResponse, getAgreements } from '@/api/agreements';\nimport { AgreementStatus } from '@/common/types/agreements';\n\nexport const useQueryAgreements = (\n accountId: string,\n page: number,\n take: number,\n serviceLocations: string[],\n status: AgreementStatus | null,\n) =>\n useQuery<AgreementsResponse, Error>(\n ['agreements', accountId, page, take, serviceLocations, status],\n () => getAgreements(accountId, page, take, serviceLocations, status),\n {\n keepPreviousData: true,\n },\n );\n","import Skeleton from '@mui/material/Skeleton';\nimport Grid from '@mui/material/Grid';\n\nexport function LoadingSkeleton() {\n return (\n <Grid container spacing={2} direction=\"column\" item sm={12} lg={8}>\n <Grid item>\n <Skeleton variant=\"text\" />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n </Grid>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n active: translate({ id: 'sections.agreements.status.active' }),\n agreements: translate({ id: 'sections.agreements.agreements' }),\n autopayIsDisabled: translate({ id: 'sections.agreements.autopayIsDisabled' }),\n autopayIsEnabled: translate({ id: 'sections.agreements.autopayIsEnabled' }),\n autopayMethodIsExpired: translate({ id: 'sections.agreements.autopayMethodIsExpired' }),\n cancelled: translate({ id: 'sections.agreements.status.cancelled' }),\n completed: translate({ id: 'sections.agreements.status.completed' }),\n drawerTitle: translate({ id: 'sections.agreements.drawer.title' }),\n effectiveDate: translate({ id: 'sections.agreements.effectiveDate' }),\n errorAddingAch: translate({ id: 'sections.paymentMethods.drawer.errorAddingAch' }),\n failedToEnableAutopay: translate({ id: 'sections.agreements.drawer.failedToEnabledAutopay' }),\n filtersDrawerTitle: translate({ id: 'sections.agreements.filtersDrawerTitle' }),\n locationHasErrors: translate({ id: 'sections.agreements.locationHasErrors' }),\n noAgreementsAlert: translate({ id: 'sections.agreements.noAgreementsAlert' }),\n notImplementedYet: translate({ id: 'global.notImplementedYet' }),\n pageTitle: translate({ id: 'sections.agreements.pageTitle' }),\n showActiveAgreements: translate({ id: 'sections.agreements.showActiveAgreements' }),\n showAllAgreements: translate({ id: 'sections.agreements.showAllAgreements' }),\n showCancelledAgreements: translate({ id: 'sections.agreements.showCancelledAgreements' }),\n showCompletedAgreements: translate({ id: 'sections.agreements.showCompletedAgreements' }),\n successfullyAddedAch: translate({ id: 'sections.paymentMethods.drawer.successfullyAddedAch' }),\n successfullyEnabledAutopayments: translate({\n id: 'sections.agreements.drawer.successfullyEnabledAutopay',\n }),\n };\n }, [translate]);\n}\n","import { InvoiceMode } from '@/common/types/invoiceMode';\nimport { MethodOfContact } from './contacts';\nimport { Frequencies } from './schedulingPlan';\n\nexport interface AgreementContactEmail {\n email: string;\n name: string;\n}\n\nexport interface AgreementContactOther {\n contactValue: string;\n name: string;\n}\n\nexport interface AgreementContactPhone {\n callingCode: string;\n countryCode: string;\n extension: string;\n name: string;\n number: string;\n}\n\nexport interface AgreementContact {\n email: AgreementContactEmail | null;\n firstName: string;\n lastName: string;\n middleName: string;\n other: AgreementContactOther | null;\n phone: AgreementContactPhone | null;\n preferredMethodOfContact: MethodOfContact;\n}\n\nexport interface AgreementAddress {\n city: string;\n country: string;\n countryCode: string;\n county: string;\n postalCode: string;\n state: string;\n stateAbbreviation: string;\n street1: string;\n street2: string | null;\n}\n\nexport interface AgreementService {\n interval: string;\n intervalUnit: Frequencies;\n name: string;\n schedulingPlanDaysOfWeek: string;\n tolerance: string;\n}\n\nexport enum AgreementStatus {\n ACTIVE = 'Active',\n CANCELLED = 'Cancelled',\n COMPLETED = 'Completed',\n}\n\nexport enum AutoPaymentAccountType {\n CREDIT_CARD,\n ACH,\n}\nexport interface AutoPaymentAccount {\n accountId: string;\n accountType: AutoPaymentAccountType;\n businessUnitId: string;\n createdOn: Date;\n ending: string;\n expirationMonth: string;\n expirationYear: string;\n friendly: string;\n id: string;\n isExpired: boolean;\n processorPaymentAccountId: string;\n}\n\nexport interface AgreementDetails {\n agreementId: string;\n agreementServices: AgreementService[];\n autoPaymentAccounts: AutoPaymentAccount[];\n billingContact: AgreementContact;\n billingLocation: AgreementAddress;\n endDate: string | null;\n hasValidationErrors: boolean;\n invoiceMode: InvoiceMode;\n name: string;\n serviceContact: AgreementContact;\n serviceLocation: AgreementAddress;\n startDate: string | null;\n status: AgreementStatus;\n upfrontInvoicingDaysAhead: string | null;\n upfrontInvoicingTimeToCreateInvoice: string | null;\n hasAutoPaymentInstance: boolean;\n}\n","import { AgreementStatus } from '@/common/types/agreements';\nimport Chip from '@mui/material/Chip';\nimport { useMemo } from 'react';\nimport { useTexts } from '../../../useTexts';\n\ntype Props = {\n onDelete: React.MouseEventHandler;\n status: AgreementStatus;\n};\n\nexport function StatusFilterChip(props: Props) {\n const { onDelete, status } = props;\n const texts = useTexts();\n\n const label = useMemo(() => {\n switch (status) {\n case AgreementStatus.ACTIVE:\n return `${texts.active} ${texts.agreements}`;\n case AgreementStatus.CANCELLED:\n return `${texts.cancelled} ${texts.agreements}`;\n case AgreementStatus.COMPLETED:\n return `${texts.completed} ${texts.agreements}`;\n }\n }, [status, texts.active, texts.cancelled, texts.completed, texts.agreements]);\n\n return <Chip size=\"small\" color=\"primary\" variant=\"outlined\" label={label} onDelete={onDelete} />;\n}\n","import { proxy, useSnapshot } from 'valtio';\nimport { useMemo } from 'react';\nimport { AgreementStatus } from '@/common/types/agreements';\n\n// Store state\nexport interface ListState {\n page: number;\n take: number;\n selected: string;\n serviceLocations: string[];\n status: AgreementStatus | null;\n}\n\nexport const initialState: ListState = {\n page: 0,\n take: 10,\n selected: '',\n serviceLocations: [''],\n status: null,\n};\n\n// Valtio store initialization\nexport const state = proxy<ListState>(initialState);\n\n// Setter functions\nexport function setPage(page: number) {\n state.page = page;\n}\n\nexport function setTake(take: number) {\n state.take = take;\n}\n\nexport function setServiceLocations(locations: string[]) {\n state.serviceLocations = locations;\n\n if (!state.serviceLocations.length) {\n state.serviceLocations = initialState.serviceLocations;\n }\n}\n\nexport function clearServiceLocations() {\n state.serviceLocations = initialState.serviceLocations;\n}\n\nexport function setStatus(status: AgreementStatus | null) {\n state.status = status;\n}\n\nexport function clearStatus() {\n state.status = initialState.status;\n}\n\nexport function setSelectedItem(id: string) {\n state.selected = id;\n}\n\nexport function clearSelectedItem() {\n state.selected = '';\n}\n\nexport function resetFilters() {\n clearServiceLocations();\n clearStatus();\n}\n\nexport function resetStore() {\n state.page = initialState.page;\n state.selected = initialState.selected;\n state.serviceLocations = initialState.serviceLocations;\n state.status = initialState.status;\n state.take = initialState.take;\n}\n\n//Hooks\nexport function useListState() {\n return useSnapshot(state);\n}\n\nexport function useIsListFiltered() {\n const { serviceLocations, status } = state;\n\n const isListFiltered = useMemo(() => {\n return (!!serviceLocations.length && !!serviceLocations[0]) || status !== null;\n }, [serviceLocations, status]);\n\n return isListFiltered;\n}\n","import { AgreementStatus } from '@/common/types/agreements';\nimport { useCallback } from 'react';\nimport { clearServiceLocations, resetFilters, setPage, setServiceLocations, setStatus, setTake } from '../store';\n\nexport function useListActions() {\n const handleClearServiceLocations = useCallback(() => {\n setPage(0);\n clearServiceLocations();\n }, []);\n\n const handleDeleteServiceLocationFilter = useCallback(\n (id: string, serviceLocations: string[]) => (_e: React.MouseEvent<HTMLElement>) => {\n setPage(0);\n setServiceLocations(serviceLocations.filter(x => x !== id));\n },\n [],\n );\n\n const handleResetFilters = useCallback(() => {\n setPage(0);\n resetFilters();\n }, []);\n\n const handleSetPage = useCallback((_e, page: number) => {\n setPage(page - 1);\n }, []);\n\n const handleSetServiceLocations = useCallback((locations: string[]) => {\n setPage(0);\n setServiceLocations(locations);\n }, []);\n\n const handleSetTake = useCallback((take: number) => {\n setTake(take);\n }, []);\n\n const handleSetStatus = useCallback((status: AgreementStatus | null) => {\n setPage(0);\n setStatus(status);\n }, []);\n\n const handleDeleteStatus = useCallback(() => {\n setPage(0);\n setStatus(null);\n }, []);\n\n return {\n handleClearServiceLocations,\n handleDeleteServiceLocationFilter,\n handleResetFilters,\n handleSetPage,\n handleSetServiceLocations,\n handleSetTake,\n handleSetStatus,\n handleDeleteStatus,\n } as const;\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { ServiceLocationFilterChip } from '@/components/cardList/chips';\nimport { ClearFiltersButton } from '@/components/cardList/filters';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { StatusFilterChip } from '../filters/StatusFilter/StatusFilterChip';\nimport { useListActions } from '../hooks';\nimport { useIsListFiltered, useListState } from '../store';\n\nexport function Chips() {\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations, status } = useListState();\n const { handleResetFilters, handleDeleteServiceLocationFilter, handleDeleteStatus } = useListActions();\n const isListFiltered = useIsListFiltered();\n\n return (\n <>\n {!!locations?.length && (\n <Box display=\"flex\" flexDirection=\"row\" alignItems=\"center\">\n <Box flexGrow={1}>\n <Stack direction=\"row-reverse\" spacing={1} flexWrap=\"wrap\" gap={1}>\n {!!serviceLocations.length &&\n serviceLocations.map(\n x =>\n !!x && (\n <ServiceLocationFilterChip\n key={x}\n id={x}\n onDelete={handleDeleteServiceLocationFilter(x, serviceLocations)}\n serviceLocations={locations}\n />\n ),\n )}\n\n {!!status && <StatusFilterChip status={status} onDelete={handleDeleteStatus} />}\n </Stack>\n </Box>\n\n <Box ml={2} flexGrow={0}>\n {isListFiltered && <ClearFiltersButton onClick={handleResetFilters} />}\n </Box>\n </Box>\n )}\n </>\n );\n}\n","import { ListHeader } from '@/components/cardList';\nimport { useTexts } from '../../useTexts';\nimport { Chips } from './Chips';\n\ninterface Props {\n openDrawer: () => void;\n}\n\nexport function AgreementsListHeader(props: Props) {\n const { openDrawer } = props;\n const texts = useTexts();\n\n return <ListHeader title={texts.pageTitle} openDrawer={openDrawer} singleLineOnMobile chips={<Chips />} />;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n cancel: translate({ id: 'global.cancel' }),\n save: translate({ id: 'global.save' }),\n };\n }, [translate]);\n}\n","import * as React from 'react';\nimport ArrowBackIcon from '@mui/icons-material/ArrowBack';\nimport { Button, CircularProgress, IconButton, Box } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { theme } from '@/theme';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { LoadingButton } from '@mui/lab';\nimport { SideDrawer } from '../SideDrawer';\nimport { useTexts } from './useTexts';\n\ntype Props = {\n children?: React.ReactNode;\n disableSave?: boolean;\n footerSecondary?: React.ReactNode;\n headerSecondary?: React.ReactNode;\n hideFooter?: boolean;\n hidePrimary?: boolean;\n isOpen: boolean;\n isSubmitting?: boolean;\n onBackBtnClick?: () => void;\n onClose: () => void;\n onSave: () => void;\n onSecondaryAction?: () => void;\n primaryBtnLabel?: string;\n primaryBtnLoading?: boolean;\n secondaryBtnDisabled?: boolean;\n secondaryBtnLabel?: string;\n showBackBtn?: boolean;\n title: string;\n};\n\nexport function SideDrawerForm(props: Props) {\n const layout = useGetUILayout();\n const texts = useTexts();\n\n const useFormStyles = makeStyles({\n footer: {\n display: 'flex',\n justifyContent: layout == 'mobile' ? 'space-between' : 'flex-end',\n padding: theme.spacing(2),\n },\n save: {\n marginLeft: theme.spacing(1.5),\n },\n close: {\n minWidth: 'unset',\n marginLeft: 'auto',\n },\n });\n\n const {\n children,\n disableSave = false,\n footerSecondary,\n headerSecondary,\n hideFooter,\n hidePrimary = false,\n isOpen,\n isSubmitting = false,\n onBackBtnClick,\n onClose,\n onSave,\n onSecondaryAction = onClose,\n primaryBtnLabel = texts.save,\n primaryBtnLoading = false,\n secondaryBtnDisabled = false,\n secondaryBtnLabel = texts.cancel,\n showBackBtn = false,\n title,\n } = props;\n const classes = useFormStyles();\n\n return (\n <SideDrawer\n onClose={onClose}\n isOpen={isOpen}\n title={title}\n headerSecondary={headerSecondary}\n footerSecondary={footerSecondary}\n footer={\n <>\n {hideFooter ? (\n <></>\n ) : (\n <div className={classes.footer}>\n {showBackBtn && !!onBackBtnClick && (\n <Box display=\"flex\" flexGrow={1}>\n <IconButton size=\"small\" onClick={onBackBtnClick}>\n <ArrowBackIcon />\n </IconButton>\n </Box>\n )}\n\n <Box display=\"flex\" alignContent=\"center\" alignItems=\"center\">\n {isSubmitting && (\n <Box mr={1.5}>\n <CircularProgress size={25} />\n </Box>\n )}\n <Button\n data-testid=\"btn-secondary\"\n disabled={secondaryBtnDisabled}\n onClick={onSecondaryAction}\n variant=\"outlined\"\n >\n {secondaryBtnLabel}\n </Button>\n {!hidePrimary && (\n <LoadingButton\n data-testid=\"btn-primary\"\n className={classes.save}\n loading={primaryBtnLoading}\n color=\"primary\"\n variant=\"contained\"\n onClick={onSave}\n disabled={disableSave || isSubmitting}\n >\n {primaryBtnLabel}\n </LoadingButton>\n )}\n </Box>\n </div>\n )}\n </>\n }\n >\n {children}\n </SideDrawer>\n );\n}\n","import { AgreementStatus } from '@/common/types/agreements';\nimport { CardBadge } from '@/components/cardList/CardBadge';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n status: AgreementStatus;\n}\n\nexport function StatusBadge(props: Props) {\n const { status } = props;\n const texts = useTexts();\n\n switch (status) {\n case AgreementStatus.ACTIVE:\n return <CardBadge severity=\"success\" text={texts.active} />;\n case AgreementStatus.CANCELLED:\n return <CardBadge severity=\"error\" text={texts.cancelled} />;\n case AgreementStatus.COMPLETED:\n return <CardBadge severity=\"info\" text={texts.completed} />;\n default:\n return null;\n }\n}\n","import { getAgreementDetails } from '@/api/agreements';\nimport { AgreementDetails } from '@/common/types/agreements';\nimport { useQuery } from 'react-query';\n\nexport const useQueryAgreementDetails = (agreementId: string) =>\n useQuery<AgreementDetails, Error>(['agreementDetails', agreementId], () => getAgreementDetails(agreementId));\n","import {\n AddAchPaymentAccountInput,\n AddAchPaymentAccountResponse,\n AddCreditCardPaymentAccountInput,\n AddCreditCardPaymentAccountResponse,\n PaymentAccount,\n PaymentStatus,\n} from '@/common/types/payments';\nimport { get, post, remove } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface PaymentDetail {\n accountType: string;\n amount: number;\n associatedInvoiceNumbers: number[];\n paymentDate: string;\n status: PaymentStatus;\n}\n\nconst baseUrl = '/api/paymentAccounts';\n\nexport const addCreditCardPaymentAccount = async (input: AddCreditCardPaymentAccountInput) => {\n try {\n const { data, status } = await post<AddCreditCardPaymentAccountResponse[]>(`${baseUrl}/creditCard`, input);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to add credit card.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const addAchPaymentAccount = async (input: AddAchPaymentAccountInput) => {\n try {\n const { data, status } = await post<AddAchPaymentAccountResponse>(`${baseUrl}/ach`, input);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to add ACH bank account.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getPaymentAccounts = async (accountId: string) => {\n try {\n const { data, status } = await get<PaymentAccount[]>(baseUrl, {\n params: {\n accountId,\n },\n });\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to get payment accounts.`, status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const deletePaymentAccount = async (businessUnitId: string, paymentAccountId: string) => {\n try {\n const { data, status } = await remove(\n `${baseUrl}?businessUnitId=${businessUnitId}&paymentAccountId=${paymentAccountId}`,\n );\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to delete payment account.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { getPaymentAccounts } from '@/api/paymentAccounts';\nimport { PaymentAccount } from '@/common/types/payments';\nimport { useQuery } from 'react-query';\n\nexport const useQueryPaymentAccounts = (accountId: string) =>\n useQuery<PaymentAccount[], Error>(['paymentAccounts', accountId], () => getPaymentAccounts(accountId));\n","import { useTranslate } from '@/intl';\nimport { PaymentAccountTypes } from '../types/payments';\n\nexport function useHumanizedPaymentAccountTypes() {\n const translate = useTranslate();\n\n return {\n [PaymentAccountTypes.ACH]: translate({ id: 'global.ach' }),\n [PaymentAccountTypes.CREDIT_CARD]: translate({ id: 'global.creditCard' }),\n };\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n accountNumber: translate({ id: 'sections.paymentMethods.drawer.accountNumber' }),\n errorAddingAch: translate({\n id: 'sections.paymentMethods.drawer.errorAddingAch',\n }),\n errorAddingAchAccountNumber: translate({\n id: 'sections.paymentMethods.drawer.errorAddingAchAccountNumber',\n }),\n errorAddingCreditCard: translate({\n id: 'sections.paymentMethods.drawer.errorAddingCreditCard',\n }),\n errorLoadingIframe: translate({ id: 'sections.paymentMethods.drawer.errorLoadingIframe' }),\n errorMakingPayment: translate({\n id: 'sections.paymentMethods.drawer.errorMakingPayment',\n }),\n invalidAccountNumber: translate({ id: 'sections.paymentMethods.drawer.invalidAccountNumber' }),\n invalidRoutingNumber: translate({ id: 'sections.paymentMethods.drawer.invalidRoutingNumber' }),\n notImplementedYet: translate({ id: 'global.notImplementedYet' }),\n routingNumber: translate({ id: 'sections.paymentMethods.drawer.routingNumber' }),\n selectPaymentType: translate({ id: 'sections.paymentMethods.drawer.selectPaymentType' }),\n inputCreditCard: translate({ id: 'sections.paymentMethods.drawer.inputCreditCard' }),\n inputACH: translate({ id: 'sections.paymentMethods.drawer.inputACH' }),\n successfullyAddedAch: translate({\n id: 'sections.paymentMethods.drawer.successfullyAddedAch',\n }),\n successfullyAddedCreditCard: translate({\n id: 'sections.paymentMethods.drawer.successfullyAddedCreditCard',\n }),\n title: translate({ id: 'sections.paymentMethods.drawer.title' }),\n };\n }, [translate]);\n}\n","import { Stack, TextField } from '@mui/material';\nimport { useMemo } from 'react';\nimport { AchInput } from './Drawer';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n achInput: AchInput;\n setAchInput: (input: AchInput) => void;\n}\n\nexport function AchEntry(props: Props) {\n const {\n achInput: { accountNumber, routingNumber },\n setAchInput,\n } = props;\n const texts = useTexts();\n\n const isAccountNumberInvalid = useMemo(() => {\n return isNaN(Number(accountNumber));\n }, [accountNumber]);\n\n const isRoutingNumberInvalid = useMemo(() => {\n return isNaN(Number(routingNumber)) || (!!routingNumber && routingNumber.length != 9);\n }, [routingNumber]);\n\n return (\n <Stack spacing={2}>\n <TextField\n id=\"accountNumber\"\n autoComplete=\"off\"\n data-testid=\"account-number\"\n error={isAccountNumberInvalid}\n helperText={isAccountNumberInvalid && texts.invalidAccountNumber}\n inputProps={{ maxLength: 20 }}\n label={texts.accountNumber}\n onChange={e => setAchInput({ accountNumber: e.target.value, routingNumber })}\n required\n value={accountNumber}\n />\n <TextField\n id=\"routingNumber\"\n autoComplete=\"off\"\n data-testid=\"routing-number\"\n error={isRoutingNumberInvalid}\n helperText={isRoutingNumberInvalid && texts.invalidRoutingNumber}\n inputProps={{ maxLength: 9 }}\n label={texts.routingNumber}\n onChange={e => setAchInput({ accountNumber, routingNumber: e.target.value })}\n required\n value={routingNumber}\n />\n </Stack>\n );\n}\n","export interface FormattableCreditCardInfo {\n cardType: string;\n lastFourDigits: string;\n}\n\nexport function formatCreditCardFriendly(l: FormattableCreditCardInfo | null) {\n if (!l) {\n return '';\n }\n return `${l.cardType} - ${l.lastFourDigits}`;\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n AddCreditCardCallback,\n HostedPaymentStatus,\n isCancelledCreditCardCallback,\n isSuccessfulCreditCardCallback,\n TransactionSetupMethod,\n} from '@/common/types/payments';\nimport { useToast } from '@/utils/useToast';\nimport { addCreditCardPaymentAccount } from '@/api/paymentAccounts';\nimport { getAccount } from '@/atoms/session/store';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { formatCreditCardFriendly } from '@/common/utils/formatCreditCardFriendly';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onCancel: () => void;\n onSuccess: (\n _paymentAccountId: string,\n paymentStatus: HostedPaymentStatus,\n friendlyValue: string,\n transactionId: string,\n transactionReferenceNumber?: string,\n processorTransactionLogId?: string,\n partnerRefId?: string,\n ) => Promise<void>;\n transactionSetupMethod: TransactionSetupMethod;\n url: string;\n}\n\nexport function CreditCardIframe(props: Props) {\n const { onCancel, onSuccess, transactionSetupMethod, url } = props;\n const account = getAccount();\n const layout = useGetUILayout();\n const texts = useTexts();\n const toast = useToast();\n\n const [isListening, setIsListening] = useState<boolean>(false);\n\n const mounted = useRef(false);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n\n const height = useMemo(() => {\n return layout == 'desktop' ? '230px' : '530px';\n }, [layout]);\n\n const hostedPaymentsCallback = useCallback(\n async (event: MessageEvent) => {\n if (!mounted.current) return;\n\n if (typeof event.data !== 'string') {\n return;\n }\n\n const data: AddCreditCardCallback = JSON.parse(event.data);\n if (isCancelledCreditCardCallback(data)) {\n onCancel();\n }\n\n if (isSuccessfulCreditCardCallback(data) && !!account?.businessUnitId) {\n switch (transactionSetupMethod) {\n case TransactionSetupMethod.PaymentAccountCreate: {\n try {\n await addCreditCardPaymentAccount({\n accountId: data.accountId,\n businessUnitId: account.businessUnitId,\n cardType: data.cardLogo,\n lastFour: data.lastFour,\n month: data.expirationMonth.toString(),\n processorPaymentAccountId: data.paymentAccountId,\n year: data.expirationYear.toString(),\n });\n await onSuccess(\n data.paymentAccountId,\n data.hostedPaymentStatus,\n formatCreditCardFriendly({\n cardType: data.cardLogo,\n lastFourDigits: data.lastFour,\n }),\n data.transactionId,\n data.approvalNumber || undefined,\n data.partnerRefId,\n );\n break;\n } catch (e) {\n toast.error(texts.errorAddingCreditCard);\n }\n }\n case TransactionSetupMethod.CreditCardSale: {\n try {\n await onSuccess(\n data.paymentAccountId,\n data.hostedPaymentStatus,\n formatCreditCardFriendly({\n cardType: data.cardLogo,\n lastFourDigits: data.lastFour,\n }),\n data.transactionId,\n data.approvalNumber || undefined,\n data.processorTransactionLogId,\n data.partnerRefId,\n );\n } catch {\n toast.error(texts.errorMakingPayment);\n }\n break;\n }\n default: {\n return;\n }\n }\n }\n },\n [account, onCancel, onSuccess, texts, toast, transactionSetupMethod],\n );\n\n useEffect(() => {\n if (mounted.current && !isListening) {\n window.addEventListener('message', hostedPaymentsCallback, false);\n setIsListening(true);\n }\n\n return () => {\n if (!mounted.current) {\n window.removeEventListener('message', hostedPaymentsCallback);\n }\n };\n }, [hostedPaymentsCallback, isListening]);\n\n return <iframe src={url} height={height} width=\"100%\" frameBorder=\"0\"></iframe>;\n}\n","import { TransactionSetupMethod } from '@/common/types/payments';\nimport { PaymentTransactionsInput } from '@/common/types/paymentTransactions';\nimport { post } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/paymentTransactions';\n\nexport const getPaymentTransactionsIframeUrl = async (\n accountId: string,\n amount: number,\n businessUnitId: string,\n transactionSetupMethod: TransactionSetupMethod,\n) => {\n try {\n const input: PaymentTransactionsInput = {\n accountId,\n amount,\n businessUnitId,\n returnUrl: `${import.meta.env.VITE_HTTP_HOST}:${import.meta.env.VITE_HTTP_PORT}/api/paymentTransactions`,\n saveToAccount: transactionSetupMethod == TransactionSetupMethod.PaymentAccountCreate,\n transactionSetupMethod,\n };\n\n const { data, status } = await post<string>(baseUrl, input);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to get create payment transaction details.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { useCallback, useEffect, useState } from 'react';\nimport { isServerError } from '@/utils/ServerError';\nimport { getPaymentTransactionsIframeUrl } from '@/api/paymentTransactions';\nimport { TransactionSetupMethod } from '@/common/types/payments';\n\ninterface ErrorData {\n status: 'error';\n}\n\ninterface LoadingData {\n status: 'loading';\n}\n\ninterface SuccessData {\n payload: string;\n status: 'success';\n}\n\ntype Data = ErrorData | LoadingData | SuccessData;\n\nexport const useData = (\n accountId: string,\n amount: number,\n businessUnitId: string,\n transactionSetupMethod: TransactionSetupMethod,\n) => {\n const [data, setData] = useState<Data>({ status: 'loading' });\n const [isStale, setIsStale] = useState<boolean>(true);\n\n useEffect(() => {\n let mounted = true;\n\n const getSettings = async (accountId: string, businessUnitId: string) => {\n try {\n setData({ status: 'loading' });\n const response = await getPaymentTransactionsIframeUrl(\n accountId,\n amount,\n businessUnitId,\n transactionSetupMethod,\n );\n\n if (isServerError(response)) {\n throw new Error(response.message);\n }\n\n if (mounted && !!response) {\n setData({ status: 'success', payload: response });\n }\n } catch (error) {\n console.log(error);\n if (mounted) {\n setData({ status: 'error' });\n }\n } finally {\n setIsStale(false);\n }\n };\n\n if (isStale && !!accountId && !!businessUnitId) {\n getSettings(accountId, businessUnitId);\n }\n\n return () => {\n mounted = false;\n };\n }, [accountId, amount, businessUnitId, isStale, transactionSetupMethod]);\n\n const refreshData = useCallback(async () => {\n setIsStale(true);\n }, []);\n\n useEffect(() => {\n refreshData();\n }, [accountId, refreshData]);\n\n return [data, refreshData] as const;\n};\n","import { getAccount } from '@/atoms/session/store';\nimport { HostedPaymentStatus, TransactionSetupMethod } from '@/common/types/payments';\nimport { Alert, Box, CircularProgress } from '@mui/material';\nimport { CreditCardIframe } from './CreditCardIframe';\nimport { useData } from './useData';\nimport { useTexts } from './useTexts';\n\ninterface CreditCardSaleProps {\n amount: number;\n onCancel: () => void;\n onSuccess: (\n _paymentAccountId: string,\n paymentStatus: HostedPaymentStatus,\n friendlyValue: string,\n transactionId: string,\n transactionReferenceNumber?: string,\n processorTransactionLogId?: string,\n partnerRefId?: string,\n ) => Promise<void>;\n transactionSetupMethod: TransactionSetupMethod.CreditCardSale;\n}\n\ninterface PaymentAccountCreateProps {\n onCancel: () => void;\n onSuccess: (id: string) => Promise<void>;\n transactionSetupMethod: TransactionSetupMethod.PaymentAccountCreate;\n}\n\ntype Props = CreditCardSaleProps | PaymentAccountCreateProps;\n\nexport function CreditCardEntry(props: Props) {\n const { onCancel, onSuccess, transactionSetupMethod } = props;\n const account = getAccount();\n const texts = useTexts();\n\n const [data] = useData(\n account?.accountId || '',\n (props as CreditCardSaleProps).amount ?? 0,\n account?.businessUnitId || '',\n transactionSetupMethod,\n );\n\n return (\n <Box>\n {data.status == 'loading' && (\n <Box sx={{ display: 'flex', justifyContent: 'center', p: 2 }}>\n <CircularProgress />\n </Box>\n )}\n\n {data.status == 'success' && data && (\n <CreditCardIframe\n onCancel={onCancel}\n onSuccess={onSuccess}\n url={data.payload}\n transactionSetupMethod={transactionSetupMethod}\n />\n )}\n\n {data.status == 'error' && <Alert severity=\"error\">{texts.errorLoadingIframe}</Alert>}\n </Box>\n );\n}\n","import { Divider, FormControl, FormControlLabel, Radio, RadioGroup, Stack, Typography } from '@mui/material';\nimport { PaymentAccountTypes, TransactionSetupMethod } from '@/common/types/payments';\nimport { useHumanizedPaymentAccountTypes } from '@/common/hooks/payments';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { AchEntry } from './AchEntry';\nimport { CreditCardEntry } from './CreditCardEntry';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n achInput: AchInput;\n onAddCreditCardSuccess: (id: string) => Promise<void>;\n onCancelCreditCardEntry: () => void;\n paymentType: PaymentAccountTypes;\n setAchInput: (input: AchInput) => void;\n setPaymentType: (type: PaymentAccountTypes) => void;\n}\n\nexport interface AchInput {\n accountNumber: string;\n routingNumber: string;\n}\n\nexport function DrawerContent(props: Props) {\n const { achInput, onAddCreditCardSuccess, onCancelCreditCardEntry, paymentType, setAchInput, setPaymentType } =\n props;\n const texts = useTexts();\n const humanizedPaymentAccountTypes = useHumanizedPaymentAccountTypes();\n\n const handleChange = event => {\n setPaymentType(event.target.value);\n };\n\n const creditCardEnabled = useFeatureEnabled('enableCreditCardPayment');\n const achEnabled = useFeatureEnabled('enableACHPayment');\n\n if (creditCardEnabled && !achEnabled) {\n setPaymentType(PaymentAccountTypes.CREDIT_CARD);\n } else if (!creditCardEnabled && achEnabled) {\n setPaymentType(PaymentAccountTypes.ACH);\n }\n\n return (\n <Stack direction=\"column\" spacing={2} divider={creditCardEnabled && achEnabled && <Divider />}>\n <FormControl component=\"fieldset\">\n {creditCardEnabled && achEnabled && (\n <Typography gutterBottom sx={{ fontWeight: 'bold' }}>\n {texts.selectPaymentType}\n </Typography>\n )}\n {creditCardEnabled && !achEnabled && <Typography gutterBottom>{texts.inputCreditCard}</Typography>}\n {!creditCardEnabled && achEnabled && <Typography gutterBottom>{texts.inputACH}</Typography>}\n <RadioGroup value={paymentType} onChange={handleChange}>\n {creditCardEnabled && achEnabled && (\n <>\n <FormControlLabel\n control={<Radio />}\n label={humanizedPaymentAccountTypes[PaymentAccountTypes.CREDIT_CARD]}\n value={PaymentAccountTypes.CREDIT_CARD}\n />\n <FormControlLabel\n control={<Radio />}\n label={humanizedPaymentAccountTypes[PaymentAccountTypes.ACH]}\n value={PaymentAccountTypes.ACH}\n />\n </>\n )}\n </RadioGroup>\n </FormControl>\n\n {((achEnabled && creditCardEnabled && paymentType === PaymentAccountTypes.ACH) ||\n (achEnabled && !creditCardEnabled)) && <AchEntry achInput={achInput} setAchInput={setAchInput} />}\n\n {((creditCardEnabled && achEnabled && paymentType === PaymentAccountTypes.CREDIT_CARD) ||\n (creditCardEnabled && !achEnabled)) && (\n <CreditCardEntry\n onCancel={onCancelCreditCardEntry}\n onSuccess={onAddCreditCardSuccess}\n transactionSetupMethod={TransactionSetupMethod.PaymentAccountCreate}\n />\n )}\n </Stack>\n );\n}\n","import { PaymentAccount, PaymentAccountTypes } from '@/common/types/payments';\nimport { proxy, useSnapshot } from 'valtio';\nimport { AchInput } from '../../PaymentMethods/drawers/AddPaymentMethod/Drawer';\n\nexport enum WizardStep {\n Detail = 0,\n ManageAutopay = 1,\n AddPaymentMethod = 2,\n}\n\n// Store state\nexport interface WizardState {\n wizardStep: number;\n paymentAccount: PaymentAccount | null;\n paymentAccountType: PaymentAccountTypes;\n achInput: AchInput;\n}\n\nexport const initialState: WizardState = {\n wizardStep: 0,\n paymentAccount: null,\n paymentAccountType: PaymentAccountTypes.CREDIT_CARD,\n achInput: { accountNumber: '', routingNumber: '' },\n};\n\n// Valtio store initialization\nexport const state = proxy<WizardState>(initialState);\n\n// Setter functions\nexport function setPaymentAccount(account: PaymentAccount | null) {\n state.paymentAccount = account;\n}\n\nexport function setWizardStep(step: WizardStep) {\n state.wizardStep = step;\n}\nexport function setPaymentAccountType(type: PaymentAccountTypes) {\n state.paymentAccountType = type;\n}\n\nexport function setAchInput(input: AchInput) {\n state.achInput = input;\n}\n\nexport function resetStore() {\n state.wizardStep = initialState.wizardStep;\n state.paymentAccount = initialState.paymentAccount;\n state.paymentAccountType = initialState.paymentAccountType;\n state.achInput = initialState.achInput;\n}\n\n//Hooks\nexport function useAgreementDrawerState() {\n return useSnapshot(state);\n}\n","import { getAccount } from '@/atoms/session/store';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { useCallback } from 'react';\nimport { DrawerContent as AddPaymentMethodDrawerContent } from '../../PaymentMethods/drawers/AddPaymentMethod/DrawerContent';\nimport {\n setAchInput,\n setPaymentAccount,\n setPaymentAccountType,\n setWizardStep,\n useAgreementDrawerState,\n WizardStep,\n} from './store';\n\ninterface Props {\n onClose: () => void;\n}\n\nexport function AddPaymentMethod(props: Props) {\n const { onClose } = props;\n const { achInput, paymentAccountType } = useAgreementDrawerState();\n const account = getAccount();\n const { refetch } = useQueryPaymentAccounts(account?.accountId || '');\n\n const onAddCreditCardSuccess = useCallback(\n async (id: string) => {\n const response = await refetch();\n\n if (!!response.data && response.data.length) {\n const newPaymentMethod = response.data.find(p => p.processorPaymentAccountId == id);\n if (newPaymentMethod) {\n setPaymentAccount(newPaymentMethod);\n }\n }\n\n setWizardStep(WizardStep.ManageAutopay);\n },\n [refetch],\n );\n\n const onCancelCreditCardEntry = useCallback(() => {\n onClose();\n }, [onClose]);\n\n return (\n <AddPaymentMethodDrawerContent\n achInput={achInput}\n onAddCreditCardSuccess={onAddCreditCardSuccess}\n onCancelCreditCardEntry={onCancelCreditCardEntry}\n paymentType={paymentAccountType}\n setAchInput={setAchInput}\n setPaymentType={setPaymentAccountType}\n />\n );\n}\n","export enum InvoiceMode {\n NoInvoice = 'NoInvoice',\n NotSet = 'NotSet',\n OnCompletion = 'OnCompletion',\n OnDemand = 'OnDemand',\n Recurring = 'Recurring',\n}\n\nexport const humanizedInvoiceModes = {\n [InvoiceMode.NoInvoice]: 'Do Not Invoice',\n [InvoiceMode.NotSet]: 'Not Set',\n [InvoiceMode.OnCompletion]: 'On Completion',\n [InvoiceMode.OnDemand]: 'On Demand',\n [InvoiceMode.Recurring]: 'Recurring',\n};\n","export enum MethodOfContact {\n Email = 'Email',\n Phone = 'Phone',\n Other = 'Other',\n}\n","import { Link } from '@mui/material';\n\ninterface Props {\n email: string;\n}\n\nexport function EmailLink(props: Props) {\n const { email } = props;\n\n return <Link href={`mailto:${email}`}>{email}</Link>;\n}\n","import { Typography } from '@mui/material';\nimport { AgreementContact as IAgreementContact } from '@/common/types/agreements';\nimport { MethodOfContact } from '@/common/types/contacts';\nimport { PhoneNumber } from '@/components/localization/PhoneNumber';\nimport { EmailLink } from '@/common/components/EmailLink';\n\ninterface Props {\n contact: IAgreementContact;\n}\n\nexport function AgreementContact(props: Props) {\n const {\n contact: { email, firstName, lastName, other, phone, preferredMethodOfContact },\n } = props;\n\n return (\n <>\n <Typography>\n {firstName} {lastName}\n </Typography>\n\n <Typography>\n {preferredMethodOfContact == MethodOfContact.Email && !!email && <EmailLink email={email.email} />}\n\n {preferredMethodOfContact == MethodOfContact.Phone && !!phone && (\n <PhoneNumber callingCode={phone.callingCode} phone={phone.number} phoneExt={phone.extension} />\n )}\n\n {preferredMethodOfContact == MethodOfContact.Other && !!other && (\n <Typography>{other.contactValue}</Typography>\n )}\n </Typography>\n </>\n );\n}\n","import { Typography } from '@mui/material';\nimport { AgreementAddress as IAgreementAddress } from '@/common/types/agreements';\nimport { useFormattedAddress } from '@/common/hooks/useAddress';\n\ninterface Props {\n address: IAgreementAddress;\n}\n\nexport function AgreementAddress(props: Props) {\n const {\n address: { city, countryCode, postalCode, stateAbbreviation, street1, street2 },\n } = props;\n\n const address = useFormattedAddress(street1, street2 || '', city, stateAbbreviation, postalCode, countryCode);\n\n return <Typography>{address}</Typography>;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n active: translate({ id: 'sections.agreements.drawer.status.active' }),\n addNewPaymentMethod: translate({ id: 'sections.agreements.drawer.addNewPaymentMethod' }),\n agreement: translate({ id: 'global.agreement' }),\n agreementName: translate({ id: 'sections.agreements.drawer.agreementName' }),\n autopayIsDisabled: translate({ id: 'sections.agreements.drawer.autopayIsDisabled' }),\n autopayIsEnabled: translate({ id: 'sections.agreements.drawer.autopayIsEnabled' }),\n billingContact: translate({ id: 'global.billingContact' }),\n billingLocation: translate({ id: 'global.billingLocation' }),\n disableAutopay: translate({ id: 'sections.agreements.drawer.disableAutopay' }),\n cancelled: translate({ id: 'sections.agreements.drawer.status.cancelled' }),\n completed: translate({ id: 'sections.agreements.drawer.status.completed' }),\n endDate: translate({ id: 'sections.agreements.drawer.endDate' }),\n error: translate({ id: 'sections.agreements.drawer.error' }),\n errorDisablingAutopay: translate({ id: 'sections.agreements.drawer.errorDisablingAutopay' }),\n failedToDownloadPDF: translate({ id: 'sections.agreements.drawer.failedToDownloadPDF' }),\n hasAutoPayInstance: translate({ id: 'sections.payInvoices.drawer.paymentMethod.hasAutoPayInstance' }),\n invoicingType: translate({ id: 'sections.agreements.drawer.invoicingType' }),\n locationHasErrors: translate({ id: 'sections.agreements.locationHasErrors' }),\n manageAutopay: translate({ id: 'sections.agreements.drawer.manageAutopay' }),\n pdf: translate({ id: 'global.pdf' }),\n serviceContact: translate({ id: 'global.serviceContact' }),\n serviceLocation: translate({ id: 'global.serviceLocation' }),\n services: translate({ id: 'sections.agreements.drawer.services' }),\n startDate: translate({ id: 'sections.agreements.drawer.startDate' }),\n status: translate({ id: 'sections.agreements.drawer.status' }),\n successfullyDisabledAutopay: translate({ id: 'sections.agreements.drawer.successfullyDisabledAutopay' }),\n successfullyEnabledAutopay: translate({ id: 'sections.agreements.drawer.successfullyEnabledAutopay' }),\n title: translate({ id: 'sections.agreements.drawer.title' }),\n useSavedPaymentMethod: translate({ id: 'sections.payInvoices.drawer.paymentMethod.useSavedPaymentMethod' }),\n };\n }, [translate]);\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n ach: {\n deleteError: translate({ id: 'sections.paymentMethods.ach.deleteError' }),\n deleteSuccess: translate({ id: 'sections.paymentMethods.ach.deleteSuccess' }),\n },\n achName: translate({ id: 'sections.paymentMethods.ach.accountName' }),\n achPageDescription: translate({ id: 'sections.paymentMethods.pageDescriptionACH' }),\n addPaymentMethodBtn: translate({ id: 'sections.paymentMethods.addPaymentMethodBtn' }),\n card: {\n deleteError: translate({ id: 'sections.paymentMethods.card.deleteError' }),\n deleteSuccess: translate({ id: 'sections.paymentMethods.card.deleteSuccess' }),\n },\n cardHolder: translate({ id: 'sections.paymentMethods.card.cardHolder' }),\n cardName: translate({ id: 'sections.paymentMethods.card.cardName' }),\n creditCardPageDescription: translate({ id: 'sections.paymentMethods.pageDescriptionCreditCard' }),\n deleteConfirmation: {\n body: translate({ id: 'sections.paymentMethods.deleteConfirmation.body' }),\n title: translate({ id: 'sections.paymentMethods.deleteConfirmation.title' }),\n },\n deletePaymentAccountAutoPayTooltip: translate({\n id: 'sections.paymentMethods.deletePaymentAccountAutoPayTooltip',\n }),\n deletePaymentAccountAutoPayInstanceTooltip: translate({\n id: 'sections.paymentMethods.deletePaymentAccountAutoPayInstanceTooltip',\n }),\n expired: translate({ id: 'sections.paymentMethods.card.expired' }),\n expires: translate({ id: 'sections.paymentMethods.card.expires' }),\n locationHasErrors: translate({ id: 'sections.paymentMethods.locationHasErrors' }),\n moreInfo: translate({ id: 'sections.paymentMethods.moreInfo' }),\n noPaymentMethodsAlert: translate({ id: 'sections.paymentMethods.noPaymentMethodsAlert' }),\n noPaymentMethodsAlertACH: translate({ id: 'sections.paymentMethods.noPaymentMethodsAlertACH' }),\n noPaymentMethodsAlertCreditCard: translate({\n id: 'sections.paymentMethods.noPaymentMethodsAlertCreditCard',\n }),\n notImplementedYet: translate({ id: 'global.notImplementedYet' }),\n pageDescription: translate({ id: 'sections.paymentMethods.pageDescription' }),\n pageTitle: translate({ id: 'sections.paymentMethods.pageTitle' }),\n };\n }, [translate]);\n}\n","import { Box, Typography } from '@mui/material';\nimport { makeStyles } from '@mui/styles';\nimport * as React from 'react';\nimport { useMemo } from 'react';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n expMonth: string | number;\n expYear: string | number;\n friendly: string;\n isCreditCard: boolean;\n isExpired: boolean;\n isSelected?: boolean;\n styles?: Pick<React.CSSProperties, 'color'>;\n}\n\nconst useStyles = (props: Props) =>\n makeStyles(theme => ({\n subtitle: {\n color: props.isSelected ? theme.palette.white : props.styles?.color || '#9E9E9E',\n },\n title: {\n color: props.isExpired\n ? theme.palette.error.main\n : props.isSelected\n ? theme.palette.white\n : props.styles?.color || '#9E9E9E',\n fontSize: '10px',\n textTransform: 'uppercase',\n },\n }));\n\nexport function PaymentAccountDetails(props: Props) {\n const { expMonth, expYear, friendly, isCreditCard, isExpired } = props;\n const classes = useStyles(props)();\n const texts = useTexts();\n\n const friendlyName = useMemo(() => {\n return isCreditCard ? texts.cardName : texts.achName;\n }, [isCreditCard, texts]);\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Box display=\"flex\" flexGrow={1}>\n <Box>\n <Typography className={classes.title}>{friendlyName}</Typography>\n <Typography className={classes.subtitle}>{friendly}</Typography>\n </Box>\n </Box>\n\n {isCreditCard && (\n <Box display=\"flex\" justifyContent=\"flex-end\">\n <Box>\n <Typography className={classes.title}>{isExpired ? texts.expired : texts.expires}</Typography>\n <Typography align=\"right\" className={classes.subtitle}>\n {expMonth.toString().padStart(2, '0')}/{expYear}\n </Typography>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n","import { remove, post } from '@/utils/http';\n\nconst baseUrl = '/api/autoPayments';\n\nexport const enableAutopayment = async (agreementId: string, paymentAccountId: string) => {\n try {\n const { status } = await post(baseUrl, { agreementId, paymentAccountId });\n\n if (status === 200) {\n return true;\n } else {\n return false;\n }\n } catch (e) {\n throw e;\n }\n};\n\nexport const disableAutopayment = async (agreementId: string) => {\n try {\n const { status } = await remove(baseUrl, {\n headers: { 'Content-Type': 'application/json' },\n data: JSON.stringify(agreementId),\n });\n\n if (status === 200) {\n return true;\n } else {\n return false;\n }\n } catch (e) {\n throw e;\n }\n};\n","import { disableAutopayment } from '@/api/autopayments';\nimport { useCallback } from 'react';\nimport { toast } from 'react-toastify';\nimport { queryClient } from '../../../../services/queryClient';\nimport { setPaymentAccount, setWizardStep, WizardStep } from '../store';\nimport { useTexts } from '../useTexts';\n\nexport function useRemoveAutoPayActions(agreementId: string) {\n const texts = useTexts();\n\n const handleRemoveAutopay = useCallback(async () => {\n try {\n await disableAutopayment(agreementId);\n queryClient.invalidateQueries('activeAgreements');\n queryClient.invalidateQueries('agreements');\n queryClient.invalidateQueries('agreementDetails');\n queryClient.invalidateQueries('paymentAccounts');\n setPaymentAccount(null);\n setWizardStep(WizardStep.Detail);\n toast.success(texts.successfullyDisabledAutopay);\n } catch {\n toast.error(texts.errorDisablingAutopay);\n }\n }, [agreementId, texts]);\n\n return {\n handleRemoveAutopay,\n } as const;\n}\n","import Stack from '@mui/material/Stack';\nimport Button from '@mui/material/Button';\nimport { useCallback, useMemo } from 'react';\nimport AutorenewIcon from '@mui/icons-material/Autorenew';\nimport { AgreementStatus, AutoPaymentAccount, AutoPaymentAccountType } from '@/common/types/agreements';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport Box from '@mui/material/Box';\nimport { usePaymentsEnabled } from '@/common/hooks/usePaymentsEnabled';\nimport { ComponentWithTooltip } from '@/components/ComponentWithTooltip';\nimport { useTexts } from '../useTexts';\nimport { setWizardStep, WizardStep } from '../store';\nimport { PaymentAccountDetails } from '../../../PaymentMethods/PaymentMethodCard/PaymentAccountDetails';\nimport { useRemoveAutoPayActions } from '../hooks/useRemoveAutoPayActions';\n\ninterface Props {\n agreementId: string;\n autoPaymentAccounts: AutoPaymentAccount[];\n status: AgreementStatus;\n hasValidationErrors: boolean;\n}\n\nexport function AutopayInformation(props: Props) {\n const { agreementId, autoPaymentAccounts, status, hasValidationErrors } = props;\n const texts = useTexts();\n const paymentsEnabled = usePaymentsEnabled();\n const { handleRemoveAutopay } = useRemoveAutoPayActions(agreementId);\n\n const handleManageClick = useCallback(() => {\n setWizardStep(WizardStep.ManageAutopay);\n }, []);\n\n const details = useMemo(() => {\n if (!autoPaymentAccounts.length || !autoPaymentAccounts[0]) {\n return undefined;\n }\n const account = autoPaymentAccounts[0];\n\n return {\n expMonth: account.expirationMonth,\n expYear: account.expirationYear,\n friendly: account.friendly,\n isCreditCard: account.accountType == AutoPaymentAccountType.CREDIT_CARD,\n isExpired: account.isExpired,\n isSelected: false,\n styles: { color: 'inherit' },\n };\n }, [autoPaymentAccounts]);\n\n return (\n <Stack spacing={1} direction=\"column\">\n {!!autoPaymentAccounts.length && !!autoPaymentAccounts[0] ? (\n <DefinitionListItem\n primary={texts.autopayIsEnabled}\n secondary={!!details ? <PaymentAccountDetails {...details} /> : undefined}\n />\n ) : (\n <DefinitionListItem primary={texts.autopayIsDisabled} />\n )}\n {paymentsEnabled && status === AgreementStatus.ACTIVE && (\n <Box>\n <ComponentWithTooltip showTooltip={hasValidationErrors} tooltipText={texts.locationHasErrors}>\n <Button\n variant=\"outlined\"\n disabled={hasValidationErrors}\n onClick={handleManageClick}\n startIcon={<AutorenewIcon />}\n >\n {texts.manageAutopay}\n </Button>\n </ComponentWithTooltip>\n </Box>\n )}\n {paymentsEnabled && status !== AgreementStatus.ACTIVE && !!autoPaymentAccounts[0] && (\n <Box>\n <Button variant=\"outlined\" onClick={handleRemoveAutopay}>\n {texts.disableAutopay}\n </Button>\n </Box>\n )}\n </Stack>\n );\n}\n","export enum Frequencies {\n Daily = 'Daily',\n Monthly = 'Monthly',\n MultiDaysPerWeek = 'MultiDaysPerWeek',\n OnDemand = 'OnDemand',\n OneTime = 'OneTime',\n Quarterly = 'Quarterly',\n Weekly = 'Weekly',\n}\n\nexport const humanizedIntervalUnits = {\n [Frequencies.Daily]: 'Daily',\n [Frequencies.Monthly]: 'Monthly',\n [Frequencies.MultiDaysPerWeek]: 'Multiple Days Per Week',\n [Frequencies.OnDemand]: 'On Demand',\n [Frequencies.OneTime]: 'One Time',\n [Frequencies.Quarterly]: 'Quarterly',\n [Frequencies.Weekly]: 'Weekly',\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n sunday: translate({ id: 'global.daysOfWeek.sunday' }),\n monday: translate({ id: 'global.daysOfWeek.monday' }),\n tuesday: translate({ id: 'global.daysOfWeek.tuesday' }),\n wednesday: translate({ id: 'global.daysOfWeek.wednesday' }),\n thursday: translate({ id: 'global.daysOfWeek.thursday' }),\n friday: translate({ id: 'global.daysOfWeek.friday' }),\n saturday: translate({ id: 'global.daysOfWeek.saturday' }),\n };\n }, [translate]);\n}\n\nexport function useOrderedDaysOfWeek() {\n const texts = useTexts();\n\n return useMemo(() => {\n return [\n texts.sunday,\n texts.monday,\n texts.tuesday,\n texts.wednesday,\n texts.thursday,\n texts.friday,\n texts.saturday,\n ];\n }, [texts]);\n}\n","import { SchedulingPlan } from '@/api/services';\nimport { useTranslate } from '@/intl';\nimport { useMemo } from 'react';\nimport { useOrderedDaysOfWeek } from './useOrderedDaysOfWeek';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n every: translate({ id: 'global.schedulingPlans.every' }),\n noRecurrence: translate({ id: 'global.schedulingPlans.noRecurrence' }),\n to: translate({ id: 'global.schedulingPlans.to' }),\n };\n }, [translate]);\n}\n\nexport const useHumanizedDaysOfWeek = (schedulingPlan: SchedulingPlan | null): string => {\n const texts = useTexts();\n const orderedDaysOfWeek = useOrderedDaysOfWeek();\n\n if (!schedulingPlan) {\n return '';\n }\n\n const daysOfWeekBits = schedulingPlan.daysOfWeek.toString();\n const daysOfWeekBitsArray = Array.from(daysOfWeekBits).map(Number);\n const days: number[] = daysOfWeekBitsArray.map((bit, i) => (bit == 1 ? i : -1)).filter(day => day != -1);\n const daysOfWeek = days.filter(d => d >= 0 && d <= 6);\n\n const groupings = daysOfWeek.reduce((arr: number[][], val: number, i: number, a: number[]) => {\n if (!i || val !== a[i - 1] + 1) arr.push([]);\n arr[arr.length - 1].push(val);\n return arr;\n }, []);\n\n const stringGroupings: string[] = groupings.map((grouping: number[]) => {\n if (grouping.length == 1) {\n return `${orderedDaysOfWeek[grouping[0]]}`;\n }\n\n if (grouping.length == 2) {\n return `${orderedDaysOfWeek[grouping[0]]}, ${orderedDaysOfWeek[grouping[1]]}`;\n }\n\n if (grouping.length > 2) {\n return `${orderedDaysOfWeek[grouping[0]]} ${texts.to} ${orderedDaysOfWeek[grouping[grouping.length - 1]]}`;\n }\n\n return '';\n });\n\n const humanizedString = stringGroupings.join(' & ');\n\n return humanizedString;\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\nimport { Frequencies } from '@/common/types/schedulingPlan';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n days: translate({ id: 'global.pluralFrequencies.days' }),\n months: translate({ id: 'global.pluralFrequencies.months' }),\n multiDaysPerWeek: translate({ id: 'global.pluralFrequencies.multiDaysPerWeek' }),\n onDemand: translate({ id: 'global.pluralFrequencies.onDemand' }),\n oneTime: translate({ id: 'global.pluralFrequencies.oneTime' }),\n quarterly: translate({ id: 'global.pluralFrequencies.quarterly' }),\n weeks: translate({ id: 'global.pluralFrequencies.weeks' }),\n };\n }, [translate]);\n}\n\nexport function usePluralFrequencies() {\n const texts = useTexts();\n return useMemo(() => {\n return {\n [Frequencies.Daily]: texts.days,\n [Frequencies.Monthly]: texts.months,\n [Frequencies.MultiDaysPerWeek]: texts.multiDaysPerWeek,\n [Frequencies.OnDemand]: texts.onDemand,\n [Frequencies.OneTime]: texts.oneTime,\n [Frequencies.Quarterly]: texts.quarterly,\n [Frequencies.Weekly]: texts.weeks,\n };\n }, [texts]);\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\nimport { Frequencies } from '@/common/types/schedulingPlan';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n days: translate({ id: 'global.singularFrequencies.days' }),\n months: translate({ id: 'global.singularFrequencies.months' }),\n multiDaysPerWeek: translate({ id: 'global.singularFrequencies.multiDaysPerWeek' }),\n onDemand: translate({ id: 'global.singularFrequencies.onDemand' }),\n oneTime: translate({ id: 'global.singularFrequencies.oneTime' }),\n quarterly: translate({ id: 'global.singularFrequencies.quarterly' }),\n weeks: translate({ id: 'global.singularFrequencies.weeks' }),\n };\n }, [translate]);\n}\n\nexport function useSingularFrequencies() {\n const texts = useTexts();\n return useMemo(() => {\n return {\n [Frequencies.Daily]: texts.days,\n [Frequencies.Monthly]: texts.months,\n [Frequencies.MultiDaysPerWeek]: texts.multiDaysPerWeek,\n [Frequencies.OnDemand]: texts.onDemand,\n [Frequencies.OneTime]: texts.oneTime,\n [Frequencies.Quarterly]: texts.quarterly,\n [Frequencies.Weekly]: texts.weeks,\n };\n }, [texts]);\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\nimport { Frequencies } from '@/common/types/schedulingPlan';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n daily: translate({ id: 'global.intervalUnits.daily' }),\n monthly: translate({ id: 'global.intervalUnits.monthly' }),\n multiDaysPerWeek: translate({ id: 'global.intervalUnits.multiDaysPerWeek' }),\n onDemand: translate({ id: 'global.intervalUnits.onDemand' }),\n oneTime: translate({ id: 'global.intervalUnits.oneTime' }),\n quarterly: translate({ id: 'global.intervalUnits.quarterly' }),\n weekly: translate({ id: 'global.intervalUnits.weekly' }),\n };\n }, [translate]);\n}\n\nexport function useHumanizedIntervalUnits() {\n const texts = useTexts();\n return useMemo(() => {\n return {\n [Frequencies.Daily]: texts.daily,\n [Frequencies.Monthly]: texts.monthly,\n [Frequencies.MultiDaysPerWeek]: texts.multiDaysPerWeek,\n [Frequencies.OnDemand]: texts.onDemand,\n [Frequencies.OneTime]: texts.oneTime,\n [Frequencies.Quarterly]: texts.quarterly,\n [Frequencies.Weekly]: texts.weekly,\n };\n }, [texts]);\n}\n","import { SchedulingPlan } from '@/api/services';\nimport { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\nimport { Frequencies } from '@/common/types/schedulingPlan';\nimport { emptyGuid } from '@/common/constants';\nimport { useHumanizedDaysOfWeek } from './useHumanizedDaysOfWeek';\nimport { usePluralFrequencies } from './usePluralFrequencies';\nimport { useSingularFrequencies } from './useSingularFrequencies';\nimport { useHumanizedIntervalUnits } from './useHumanizedIntervalUnits';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n every: translate({ id: 'global.schedulingPlans.every' }),\n noRecurrence: translate({ id: 'global.schedulingPlans.noRecurrence' }),\n to: translate({ id: 'global.schedulingPlans.to' }),\n };\n }, [translate]);\n}\n\nexport const useHumanizedSchedulingPlan = (plan: SchedulingPlan | null): string => {\n const texts = useTexts();\n const humanizedDaysOfWeek = useHumanizedDaysOfWeek(plan);\n const singularFrequencies = useSingularFrequencies();\n const pluralFrequencies = usePluralFrequencies();\n const humanizedIntervalUnits = useHumanizedIntervalUnits();\n\n if (!plan || !plan.intervalUnit || plan.schedulingPlanId == emptyGuid) {\n return '';\n }\n\n const interval = plan.interval ? Number(plan.interval.substring(1, plan.interval.length - 1)) : 0;\n\n if (plan.intervalUnit == Frequencies.OneTime) {\n return texts.noRecurrence;\n }\n\n if (plan.intervalUnit == Frequencies.MultiDaysPerWeek) {\n return humanizedDaysOfWeek;\n }\n\n if (plan.intervalUnit == Frequencies.OnDemand) {\n return humanizedIntervalUnits[plan.intervalUnit];\n }\n\n if (interval == 1) {\n return humanizedIntervalUnits[plan.intervalUnit];\n }\n\n if (plan.intervalUnit == Frequencies.Quarterly && plan.interval == 'P3M' && plan.tolerance == 'P15D') {\n return humanizedIntervalUnits[Frequencies.Quarterly];\n }\n\n const intervalUnit = pluralFrequencies[plan.intervalUnit];\n const tolerance = plan.tolerance.match(/\\d/g)?.join('');\n const toleranceUnit =\n tolerance == '1' ? singularFrequencies[Frequencies.Daily] : pluralFrequencies[Frequencies.Daily];\n const toleranceStr = tolerance && toleranceUnit ? ` \\u00b1 ${tolerance} ${toleranceUnit}` : '';\n\n return `${texts.every} ${interval} ${intervalUnit} ${toleranceStr}`;\n};\n","import { Typography } from '@mui/material';\nimport { AgreementService } from '@/common/types/agreements';\nimport { useHumanizedSchedulingPlan } from '@/common/hooks/schedulingPlan/useHumanizedSchedulingPlan';\n\ninterface Props {\n index: number;\n service: AgreementService;\n}\n\nexport function Service(props: Props) {\n const {\n index,\n service: { interval, intervalUnit, name, schedulingPlanDaysOfWeek, tolerance },\n } = props;\n\n const schedulingPlan = useHumanizedSchedulingPlan({\n daysOfWeek: schedulingPlanDaysOfWeek,\n interval: interval,\n intervalUnit: intervalUnit,\n schedulingPlanId: '',\n tolerance: tolerance,\n });\n\n return (\n <>\n <Typography>\n {index + 1}. {name}\n </Typography>\n <Typography variant=\"caption\" marginLeft={2}>\n {schedulingPlan}\n </Typography>\n </>\n );\n}\n","import { Box, Stack, Typography } from '@mui/material';\nimport { AgreementService } from '@/common/types/agreements';\nimport { Service } from './Service';\n\ninterface Props {\n services: AgreementService[];\n}\n\nexport function Services(props: Props) {\n const { services } = props;\n\n return (\n <Stack direction=\"column\" spacing={1}>\n {services.length > 0 && (\n <Box>\n {services.map((s, i) => (\n <Service index={i} key={i} service={s} />\n ))}\n </Box>\n )}\n\n {services.length == 0 && <Typography>None</Typography>}\n </Stack>\n );\n}\n","import { AgreementDetails } from '@/common/types/agreements';\nimport { humanizedInvoiceModes } from '@/common/types/invoiceMode';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { LongDate } from '@/components/localization';\nimport { Box, Stack } from '@mui/material';\nimport { OpenPDFButton } from '@/components/OpenPDFButton';\nimport { useCallback } from 'react';\nimport { getAgreementReport } from '@/api/agreements';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { AgreementContact } from './listItems/AgreementContact';\nimport { AgreementAddress } from './listItems/AgreementLocation';\nimport { AutopayInformation } from './listItems/AutopayInformation';\nimport { Services } from './listItems/Services';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n details: AgreementDetails;\n}\n\nexport function DetailListItems(props: Props) {\n const {\n details: {\n agreementId,\n agreementServices,\n autoPaymentAccounts,\n billingContact,\n billingLocation,\n endDate,\n hasValidationErrors,\n invoiceMode,\n name,\n serviceContact,\n serviceLocation,\n startDate,\n status,\n },\n } = props;\n const texts = useTexts();\n\n const onAgreementReportClick = useCallback(() => {\n return getAgreementReport(agreementId);\n }, [agreementId]);\n\n return (\n <Stack direction=\"column\" spacing={2}>\n <Box display=\"flex\" alignItems=\"flex-start\">\n <Box flexGrow={1}>\n <DefinitionListItem primary={texts.agreementName} secondary={name} />\n </Box>\n <StatusBadge status={status} />\n </Box>\n\n {!!startDate && <DefinitionListItem primary={texts.startDate} secondary={<LongDate value={startDate} />} />}\n\n {!!endDate && <DefinitionListItem primary={texts.endDate} secondary={<LongDate value={endDate} />} />}\n\n <DefinitionListItem\n primary={texts.serviceContact}\n secondary={<AgreementContact contact={serviceContact} />}\n />\n\n <DefinitionListItem\n primary={texts.serviceLocation}\n secondary={<AgreementAddress address={serviceLocation} />}\n />\n\n <DefinitionListItem\n primary={texts.billingContact}\n secondary={<AgreementContact contact={billingContact} />}\n />\n\n <DefinitionListItem\n primary={texts.billingLocation}\n secondary={<AgreementAddress address={billingLocation} />}\n />\n <DefinitionListItem primary={texts.services} secondary={<Services services={agreementServices} />} />\n\n <DefinitionListItem primary={texts.invoicingType} secondary={humanizedInvoiceModes[invoiceMode]} />\n\n <AutopayInformation\n agreementId={agreementId}\n autoPaymentAccounts={autoPaymentAccounts}\n hasValidationErrors={hasValidationErrors}\n status={status}\n />\n\n <Box>\n <OpenPDFButton onClick={onAgreementReportClick} errorText={texts.failedToDownloadPDF}>\n {texts.agreement} {texts.pdf}\n </OpenPDFButton>\n </Box>\n </Stack>\n );\n}\n","export function isCardExpired(mm: number, yy: number) {\n const today = new Date();\n\n const expirationDate = new Date();\n expirationDate.setFullYear(Number(20 + yy), mm, 0);\n\n if (expirationDate < today) {\n return true;\n }\n\n return false;\n}\n","import { SvgIcon } from '@mui/material';\n\nexport function ACH(props) {\n return (\n <SvgIcon {...props} viewBox=\"0 0 24 24\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M22.8 20.7896H22.4V17.991C22.4 17.3286 21.8628 16.7916 21.2 16.7916H20.4V9.1954H18V16.7916H15.6V9.1954H13.2V16.7916H10.8V9.1954H8.4V16.7916H6V9.1954H3.6V16.7916H2.8C2.13725 16.7916 1.6 17.3286 1.6 17.991V20.7896H1.2C0.53725 20.7896 1.89924e-09 21.3266 1.89924e-09 21.989V22.7886C1.89924e-09 22.8946 0.0421427 22.9963 0.117157 23.0713C0.192172 23.1463 0.293913 23.1884 0.4 23.1884H23.6C23.7061 23.1884 23.8078 23.1463 23.8828 23.0713C23.9579 22.9963 24 22.8946 24 22.7886V21.989C24 21.3266 23.4627 20.7896 22.8 20.7896ZM20 20.7896H4V19.1904H20V20.7896ZM23.6133 4.65058L12.7589 0.123089C12.2663 -0.0410296 11.7337 -0.0410296 11.241 0.123089L0.38665 4.65058C0.272944 4.69381 0.175073 4.77056 0.106019 4.87067C0.0369646 4.97078 -9.67562e-06 5.0895 1.89924e-09 5.21109V6.5967C1.89924e-09 6.92789 0.26865 7.1964 0.6 7.1964H1.6V7.7961C1.6 8.12729 1.86865 8.3958 2.2 8.3958H21.8C22.1313 8.3958 22.4 8.12729 22.4 7.7961V7.1964H23.4C23.7313 7.1964 24 6.92789 24 6.5967V5.21109C24 4.96212 23.8461 4.73908 23.6133 4.65058ZM2.4 5.997L12 2.3988L21.6 5.997H2.4Z\"\n fill=\"#696969\"\n />\n </svg>\n </SvgIcon>\n );\n}\n","import { SvgIcon } from '@mui/material';\n\nexport function AmericanExpress(props) {\n return (\n <SvgIcon {...props} viewBox=\"0 0 40 40\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 40 40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M40 31.428C40 32.7339 38.9414 33.7926 37.6355 33.7926H2.36445C1.05859 33.7927 0 32.7339 0 31.428V8.57144C0 7.26558 1.05859 6.20691 2.36445 6.20691H37.6355C38.9415 6.20691 40 7.26558 40 8.57144V31.428Z\"\n fill=\"#306FC5\"\n />\n <path d=\"M5.82764 17.2457H7.02279L6.42537 15.7246L5.82764 17.2457Z\" fill=\"white\" />\n <path\n d=\"M12.1841 22.3517V23.058H14.1942V23.8187H12.1841V24.6338H14.4113L15.4435 23.4927L14.4657 22.3517H12.1841Z\"\n fill=\"white\"\n />\n <path d=\"M27.8829 15.7246L27.231 17.2457H28.4806L27.8829 15.7246Z\" fill=\"white\" />\n <path d=\"M17.9965 25.0682V21.9718L16.584 23.493L17.9965 25.0682Z\" fill=\"white\" />\n <path\n d=\"M20.657 22.8408C20.6026 22.5149 20.3851 22.3517 20.059 22.3517H18.9185V23.3295H20.1137C20.4396 23.3296 20.657 23.1667 20.657 22.8408Z\"\n fill=\"white\"\n />\n <path\n d=\"M24.4605 23.2214C24.5691 23.167 24.6237 23.0038 24.6237 22.8412C24.678 22.6241 24.5691 22.5152 24.4605 22.4609C24.3521 22.4065 24.1889 22.4065 24.0262 22.4065H22.9395V23.2758H24.0261C24.1888 23.2758 24.352 23.2758 24.4605 23.2214Z\"\n fill=\"white\"\n />\n <path\n d=\"M32.2827 14.3121V14.964L31.957 14.3121H29.4041V14.964L29.078 14.3121H25.6012C25.0037 14.3121 24.5146 14.4209 24.0802 14.6381V14.3121H21.6358V14.3665V14.6381C21.3642 14.421 21.0383 14.3121 20.6037 14.3121H11.8576L11.2598 15.6703L10.6623 14.3121H8.7068H7.89187V14.964L7.62023 14.3121H7.56586H5.23L4.14336 16.8653L2.89406 19.6357L2.87109 19.6902H2.89406H5.66461H5.6993L5.71898 19.6357L6.04508 18.821H6.75125L7.07719 19.6902H10.2277V19.6357V19.0383L10.4995 19.6901H12.0747L12.3462 19.0383V19.6357V19.6902H13.5956H19.8429H19.8973V18.2777H20.0062C20.1147 18.2777 20.1147 18.2777 20.1147 18.4407V19.6358H24.026V19.3099C24.352 19.4731 24.8405 19.6358 25.4925 19.6358H27.1224L27.4484 18.7668H28.2087L28.5346 19.6358H31.6852V19.0927V18.8211L32.1744 19.6358H32.2827H32.3373H34.7275V14.3121H32.2829H32.2827V14.3121ZM13.8674 18.8755H13.3241H12.9982V18.5498V15.8876L12.9438 16.0122V16.0107L11.6801 18.8755H11.6401H11.3495H10.8795L9.57578 15.8876V18.8755H7.72891L7.34867 18.0606H5.50148L5.12117 18.8755H4.16625L5.77328 15.0728H7.13125L8.65227 18.7124V15.0728H8.97812H10.0915L10.1171 15.1272H10.119L10.8044 16.6189L11.2966 17.7366L11.314 17.6803L12.4004 15.0728H13.8673V18.8755H13.8674V18.8755ZM17.6159 15.8876H15.4972V16.5938H17.5615V17.3542H15.4972V18.115H17.6159V18.9296H14.5738V15.0728H17.6159V15.8876ZM21.4905 17.2884C21.4919 17.2896 21.4937 17.2905 21.4954 17.2917C21.5159 17.3134 21.5335 17.3352 21.5485 17.356C21.6526 17.4924 21.7367 17.6953 21.7409 17.9928C21.7413 17.998 21.7415 18.0031 21.7418 18.0082C21.7418 18.0112 21.7423 18.0138 21.7423 18.0168C21.7423 18.0185 21.7422 18.0199 21.7422 18.0215C21.7434 18.0514 21.7442 18.082 21.7442 18.115V18.8756H20.9295V18.4408C20.9295 18.2235 20.9295 17.8975 20.7663 17.6803C20.715 17.6289 20.663 17.5951 20.6065 17.571C20.5251 17.5183 20.3708 17.5174 20.1147 17.5174H19.1366V18.8756H18.2133V15.0728H20.2777C20.7663 15.0728 21.0924 15.0728 21.3641 15.2358C21.6303 15.3956 21.7911 15.6607 21.7972 16.0805C21.7846 16.6586 21.4135 16.9758 21.1467 17.0828C21.1467 17.0828 21.328 17.1192 21.4905 17.2884ZM23.3198 18.8755H22.3962V15.0728H23.3198V18.8755ZM33.9129 18.8755H32.7176L30.9793 15.9962V18.3864L30.9736 18.3808V18.8778H30.0559V18.8756H29.1323L28.8063 18.0607H26.9048L26.5789 18.9297H25.5468C25.1125 18.9297 24.5689 18.8212 24.2431 18.4953C23.9172 18.1693 23.7544 17.7347 23.7544 17.0286C23.7544 16.4854 23.8629 15.9418 24.2431 15.5074C24.5145 15.1812 25.0037 15.0728 25.6011 15.0728H26.4705V15.8876H25.6011C25.2752 15.8876 25.1125 15.9417 24.8948 16.105C24.7321 16.2679 24.6234 16.5938 24.6234 16.974C24.6234 17.4087 24.6777 17.6803 24.8948 17.8975C25.0581 18.0607 25.2752 18.1151 25.5468 18.1151H25.927L27.1763 15.1274H27.7198H28.5345L30.0558 18.767V18.5814V17.3544V17.2459V15.1274H31.4138L32.9888 17.7892V15.1274H33.9127V18.8756H33.9129V18.8755Z\"\n fill=\"white\"\n />\n <path\n d=\"M20.7156 16.6566C20.7315 16.6396 20.7458 16.6204 20.758 16.5984C20.8073 16.5205 20.8637 16.3802 20.8333 16.1887C20.832 16.1711 20.8288 16.1548 20.8251 16.1391C20.8241 16.1348 20.8242 16.1309 20.823 16.1266L20.8225 16.1266C20.7955 16.0336 20.7265 15.9764 20.6576 15.9417C20.5487 15.8876 20.3858 15.8876 20.2229 15.8876H19.1362V16.7569H20.2229C20.3858 16.7569 20.5488 16.7569 20.6576 16.7024C20.674 16.6941 20.6885 16.6829 20.7025 16.6702L20.7026 16.6709C20.7027 16.6708 20.7083 16.665 20.7156 16.6566Z\"\n fill=\"white\"\n />\n <path\n d=\"M37.1175 24.308C37.1175 23.9277 37.009 23.5473 36.8461 23.2758V20.8313H36.8436V20.6681C36.8436 20.6681 34.5666 20.6681 34.2277 20.6681C33.889 20.6681 33.4779 20.994 33.4779 20.994V20.6681H30.9791C30.5987 20.6681 30.1101 20.7769 29.8925 20.994V20.6681H25.4381V20.8313V20.9939C25.1124 20.7225 24.5144 20.668 24.2429 20.668H21.3094V20.8312V20.9938C21.0379 20.7224 20.3857 20.668 20.0596 20.668H16.8007L16.04 21.4829L15.3337 20.668H15.1063H14.7362H10.4448V20.8312V21.2603V26.1549H15.2253L16.0108 25.3692L16.6916 26.1549H16.7462H19.5007H19.6255H19.6799H19.734V25.6117V24.9055H20.0058C20.3857 24.9055 20.8748 24.9055 21.2551 24.7423V26.1003V26.2092H23.6997V26.1003V24.7967H23.808C23.9712 24.7967 23.9712 24.7967 23.9712 24.9597V26.1003V26.2092H31.359C31.8483 26.2092 32.3369 26.1003 32.6084 25.883V26.1003V26.2092H34.9445C35.4331 26.2092 35.9224 26.1549 36.2483 25.9375C36.7485 25.6374 37.0637 25.1062 37.1106 24.4727C37.1128 24.454 37.1155 24.4352 37.1172 24.4164L37.114 24.4134C37.1161 24.3782 37.1175 24.3434 37.1175 24.308ZM20.0058 23.9821H18.9191V24.1447V24.4708V24.7968V25.3944H17.1336L16.0944 24.1991L16.0908 24.2031L16.04 24.1447L14.8449 25.3944H11.3683V21.5918H14.8993L15.864 22.6484L16.0668 22.8697L16.0943 22.8412L17.2352 21.5919H20.1143C20.673 21.5919 21.2987 21.7298 21.5358 22.2983C21.5644 22.4109 21.5809 22.536 21.5809 22.6782C21.5809 23.7646 20.8204 23.9821 20.0058 23.9821ZM25.4381 23.9277C25.5466 24.0902 25.601 24.3079 25.601 24.634V25.3943H24.6776V24.9055C24.6776 24.6879 24.6776 24.3079 24.5144 24.1447C24.4061 23.9821 24.1885 23.9821 23.8628 23.9821H22.8851V25.3944H21.9616V21.5374H24.0258C24.4601 21.5374 24.8403 21.5374 25.1124 21.7002C25.3838 21.8634 25.601 22.135 25.601 22.5696C25.601 23.167 25.2209 23.493 24.9492 23.6018C25.2209 23.71 25.3838 23.819 25.4381 23.9277ZM29.1865 22.352H27.0676V23.0582H29.132V23.8189H27.0676V24.5795H29.1865V25.3943H26.1444V21.5373H29.1865V22.352ZM31.4679 25.3944H29.7295V24.5796H31.4679C31.6306 24.5796 31.7395 24.5796 31.8484 24.4709C31.9028 24.4164 31.9568 24.308 31.9568 24.1992C31.9568 24.0903 31.9028 23.9822 31.8484 23.9277C31.7939 23.8734 31.6851 23.8191 31.5222 23.8191C30.6529 23.7647 29.6208 23.8191 29.6208 22.6241C29.6208 22.0808 29.9468 21.4831 30.9247 21.4831H32.7172V22.4065H31.0333C30.8704 22.4065 30.7616 22.4065 30.6529 22.4609C30.5445 22.5153 30.5445 22.6241 30.5445 22.7326C30.5445 22.8956 30.6529 22.95 30.7615 23.0039C30.8704 23.0584 30.979 23.0584 31.0875 23.0584H31.5765C32.0654 23.0584 32.3913 23.167 32.6086 23.3844C32.7716 23.5474 32.8803 23.8191 32.8803 24.1992C32.8803 25.0138 32.3914 25.3944 31.4679 25.3944ZM36.1397 25.0138C35.9227 25.2314 35.5422 25.3944 34.9988 25.3944H33.2608V24.5796H34.9987C35.1618 24.5796 35.2707 24.5796 35.3792 24.4709C35.4333 24.4164 35.4879 24.308 35.4879 24.1992C35.4879 24.0903 35.4333 23.9822 35.3792 23.9277C35.3248 23.8734 35.2163 23.8191 35.0533 23.8191C34.1844 23.7647 33.1519 23.8191 33.1519 22.6241C33.1519 22.1078 33.4473 21.6414 34.1758 21.5029C34.2629 21.4909 34.355 21.4831 34.4558 21.4831H36.2486V22.4065H35.0533H34.6188H34.5644C34.4014 22.4065 34.2929 22.4065 34.1844 22.4609C34.1297 22.5153 34.0753 22.6241 34.0753 22.7326C34.0753 22.8956 34.1297 22.95 34.2929 23.0039C34.4014 23.0584 34.5101 23.0584 34.6188 23.0584H34.6728H35.1076C35.345 23.0584 35.5245 23.0877 35.6888 23.1454C35.8393 23.1998 36.3374 23.4227 36.4488 24.0043C36.4585 24.0652 36.4656 24.1288 36.4656 24.1992C36.4656 24.5252 36.3569 24.7968 36.1397 25.0138Z\"\n fill=\"white\"\n />\n </svg>\n </SvgIcon>\n );\n}\n","import { SvgIcon } from '@mui/material';\n\nexport function Discover(props) {\n return (\n <SvgIcon {...props} viewBox=\"0 0 40 40\">\n <svg viewBox=\"0 0 40 6.83\">\n <g id=\"layer1\">\n <path\n id=\"path22\"\n fill=\"#201d1c\"\n d=\"M3.3,21.59a2.4,2.4,0,0,1-1.71.51H1.25V17.86h.34a2.3,2.3,0,0,1,1.71.52A2.15,2.15,0,0,1,4,20a2.22,2.22,0,0,1-.69,1.62ZM1.84,16.77H0v6.42H1.83a3.31,3.31,0,0,0,2.29-.75,3.21,3.21,0,0,0-2.28-5.67\"\n transform=\"translate(0 -16.59)\"\n />\n <path id=\"path24\" fill=\"#201d1c\" d=\"M5.86,23.19H7.11V16.77H5.86Z\" transform=\"translate(0 -16.59)\" />\n <path\n id=\"path26\"\n fill=\"#201d1c\"\n d=\"M10.17,19.23c-.75-.28-1-.46-1-.81s.39-.71.93-.71a1.33,1.33,0,0,1,1,.52l.65-.85a2.77,2.77,0,0,0-1.88-.72,1.88,1.88,0,0,0-2,1.84c0,.89.4,1.34,1.57,1.76a4.71,4.71,0,0,1,.87.37.75.75,0,0,1,.37.66.92.92,0,0,1-1,.91,1.48,1.48,0,0,1-1.36-.86l-.81.78A2.51,2.51,0,0,0,9.8,23.34,2.07,2.07,0,0,0,12,21.23c0-1-.42-1.48-1.84-2\"\n transform=\"translate(0 -16.59)\"\n />\n <path\n id=\"path28\"\n fill=\"#201d1c\"\n d=\"M12.41,20a3.32,3.32,0,0,0,3.38,3.35A3.56,3.56,0,0,0,17.36,23V21.48a2,2,0,0,1-1.51.71A2.1,2.1,0,0,1,13.7,20a2.13,2.13,0,0,1,2.09-2.2,2.09,2.09,0,0,1,1.57.72V17a3.17,3.17,0,0,0-1.54-.39A3.37,3.37,0,0,0,12.41,20\"\n transform=\"translate(0 -16.59)\"\n />\n <path\n id=\"path30\"\n fill=\"#201d1c\"\n d=\"M27.28,21.08l-1.71-4.31H24.21l2.72,6.58h.67l2.77-6.58H29l-1.74,4.31\"\n transform=\"translate(0 -16.59)\"\n />\n <path\n id=\"path32\"\n fill=\"#201d1c\"\n d=\"M30.94,23.19h3.55V22.1h-2.3V20.37H34.4V19.28H32.19V17.86h2.3V16.77H30.94v6.42\"\n transform=\"translate(0 -16.59)\"\n />\n <path\n id=\"path34\"\n fill=\"#201d1c\"\n d=\"M36.93,19.72h-.36V17.78H37c.78,0,1.2.33,1.2.95S37.73,19.72,36.93,19.72Zm2.51-1.06c0-1.2-.83-1.89-2.27-1.89H35.32v6.42h1.25V20.61h.16l1.73,2.58H40l-2-2.71a1.7,1.7,0,0,0,1.46-1.82\"\n transform=\"translate(0 -16.59)\"\n />\n <path\n id=\"path78\"\n fill=\"#e66e26\"\n d=\"M17.77,20h0a3.42,3.42,0,0,1,6.83,0h0a3.42,3.42,0,0,1-6.83,0\"\n transform=\"translate(0 -16.59)\"\n />\n </g>\n </svg>\n </SvgIcon>\n );\n}\n","import { SvgIcon } from '@mui/material';\n\nexport function Mastercard(props) {\n return (\n <SvgIcon {...props} viewBox=\"0 0 40 40\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 40 40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M9.9052 32.6813V31.0464C9.91473 30.9089 9.89485 30.7709 9.84689 30.6417C9.79892 30.5125 9.72397 30.395 9.62703 30.297C9.53009 30.1991 9.41339 30.1229 9.28469 30.0736C9.156 30.0242 9.01827 30.0029 8.88068 30.011C8.70059 29.9991 8.52062 30.0359 8.35958 30.1174C8.19854 30.1989 8.06232 30.3221 7.96515 30.4742C7.87657 30.3266 7.74984 30.2057 7.5983 30.1242C7.44676 30.0427 7.27603 30.0036 7.10411 30.011C6.95425 30.0034 6.80502 30.0351 6.67119 30.103C6.53737 30.1708 6.4236 30.2725 6.34117 30.3979V30.0763H5.77441V32.6813H6.34662V31.248C6.33445 31.1589 6.34211 31.0683 6.36905 30.9825C6.39599 30.8967 6.44154 30.818 6.50246 30.7518C6.56338 30.6857 6.63815 30.6339 6.72143 30.6C6.80471 30.5661 6.89445 30.5511 6.98422 30.5559C7.36024 30.5559 7.55098 30.8011 7.55098 31.2426V32.6922H8.12319V31.248C8.11151 31.159 8.11952 31.0686 8.14664 30.983C8.17377 30.8974 8.21935 30.8189 8.28016 30.7529C8.34097 30.6869 8.41553 30.635 8.49858 30.601C8.58163 30.5669 8.67114 30.5516 8.76079 30.5559C9.14771 30.5559 9.333 30.8011 9.333 31.2426V32.6922L9.9052 32.6813ZM18.3711 30.0763H17.4393V29.2862H16.8671V30.0763H16.3493V30.5941H16.878V31.793C16.878 32.3979 17.1123 32.7575 17.7826 32.7575C18.033 32.7584 18.2786 32.6885 18.491 32.5559L18.3275 32.0709C18.1756 32.1616 18.0031 32.2122 17.8262 32.218C17.5537 32.218 17.4502 32.0437 17.4502 31.7821V30.5941H18.3766L18.3711 30.0763ZM23.2049 30.011C23.0667 30.0069 22.93 30.0402 22.8092 30.1073C22.6883 30.1745 22.5878 30.273 22.5183 30.3924V30.0763H21.957V32.6813H22.5237V31.2208C22.5237 30.7902 22.709 30.5505 23.0687 30.5505C23.1899 30.5488 23.3103 30.571 23.4229 30.6159L23.5973 30.0709C23.4679 30.0246 23.3315 30.0006 23.194 30.0001L23.2049 30.011ZM15.897 30.2834C15.5762 30.0927 15.2074 29.9981 14.8344 30.011C14.175 30.011 13.7444 30.327 13.7444 30.8447C13.7444 31.2698 14.0605 31.5314 14.6436 31.6131L14.9161 31.6513C15.2267 31.6949 15.3739 31.7766 15.3739 31.9238C15.3739 32.1254 15.1668 32.2398 14.7799 32.2398C14.4686 32.2488 14.1634 32.1529 13.9134 31.9674L13.6409 32.4088C13.971 32.6393 14.3665 32.7577 14.769 32.7466C15.521 32.7466 15.957 32.3924 15.957 31.8965C15.957 31.4006 15.6137 31.199 15.0469 31.1172L14.7744 31.0791C14.5292 31.0464 14.333 30.9973 14.333 30.8229C14.333 30.6486 14.5183 30.5178 14.8289 30.5178C15.116 30.5211 15.3975 30.598 15.6463 30.7412L15.897 30.2834ZM31.0769 30.011C30.9387 30.0069 30.802 30.0402 30.6811 30.1073C30.5603 30.1745 30.4598 30.273 30.3902 30.3924V30.0763H29.8289V32.6813H30.3957V31.2208C30.3957 30.7902 30.581 30.5505 30.9406 30.5505C31.0618 30.5488 31.1822 30.571 31.2948 30.6159L31.4692 30.0709C31.3398 30.0246 31.2034 30.0006 31.066 30.0001L31.0769 30.011ZM23.7744 31.3734C23.7677 31.5564 23.7992 31.7389 23.867 31.909C23.9349 32.0792 24.0374 32.2333 24.1683 32.3616C24.2991 32.4898 24.4552 32.5893 24.6267 32.6538C24.7981 32.7182 24.9812 32.7461 25.1641 32.7358C25.5044 32.7531 25.8388 32.6422 26.1014 32.4251L25.8289 31.9674C25.633 32.1168 25.3941 32.1989 25.1477 32.2017C24.9382 32.1847 24.7428 32.0895 24.6003 31.9351C24.4578 31.7806 24.3787 31.5781 24.3787 31.3679C24.3787 31.1577 24.4578 30.9552 24.6003 30.8008C24.7428 30.6463 24.9382 30.5511 25.1477 30.5341C25.3941 30.5369 25.633 30.619 25.8289 30.7684L26.1014 30.3107C25.8388 30.0936 25.5044 29.9827 25.1641 30.0001C24.9812 29.9897 24.7981 30.0176 24.6267 30.0821C24.4552 30.1465 24.2991 30.246 24.1683 30.3742C24.0374 30.5025 23.9349 30.6566 23.867 30.8268C23.7992 30.997 23.7677 31.1794 23.7744 31.3625V31.3734ZM29.0823 31.3734V30.0763H28.5156V30.3924C28.4193 30.2686 28.295 30.1694 28.1529 30.1031C28.0107 30.0367 27.8549 30.0052 27.6981 30.011C27.3368 30.011 26.9903 30.1545 26.7348 30.41C26.4793 30.6655 26.3357 31.012 26.3357 31.3734C26.3357 31.7347 26.4793 32.0812 26.7348 32.3367C26.9903 32.5922 27.3368 32.7358 27.6981 32.7358C27.8549 32.7415 28.0107 32.71 28.1529 32.6436C28.295 32.5773 28.4193 32.4781 28.5156 32.3543V32.6704H29.0823V31.3734ZM26.9733 31.3734C26.9824 31.22 27.036 31.0727 27.1278 30.9495C27.2195 30.8263 27.3452 30.7326 27.4895 30.6799C27.6338 30.6273 27.7904 30.618 27.9399 30.6532C28.0894 30.6884 28.2253 30.7665 28.331 30.878C28.4366 30.9895 28.5074 31.1294 28.5345 31.2806C28.5616 31.4318 28.544 31.5876 28.4836 31.7289C28.4233 31.8702 28.323 31.9907 28.1951 32.0757C28.0671 32.1606 27.9171 32.2063 27.7635 32.2071C27.6556 32.2085 27.5486 32.1875 27.4492 32.1455C27.3498 32.1035 27.2602 32.0414 27.186 31.9631C27.1118 31.8848 27.0546 31.792 27.018 31.6905C26.9814 31.589 26.9662 31.481 26.9733 31.3734ZM20.1341 30.011C19.7728 30.016 19.4282 30.1644 19.1763 30.4235C18.9244 30.6826 18.7857 31.0311 18.7908 31.3924C18.7958 31.7538 18.9442 32.0983 19.2033 32.3502C19.4624 32.6021 19.8109 32.7408 20.1722 32.7358C20.5643 32.7559 20.9498 32.6296 21.254 32.3815L20.9815 31.9619C20.7663 32.1345 20.4998 32.2303 20.224 32.2344C20.0367 32.2505 19.8504 32.1929 19.7049 32.0738C19.5594 31.9548 19.466 31.7836 19.4447 31.5968H21.3793C21.3793 31.5259 21.3793 31.4551 21.3793 31.3788C21.3793 30.5614 20.8725 30.0164 20.1423 30.0164L20.1341 30.011ZM20.1341 30.5178C20.2189 30.516 20.3032 30.5309 20.3823 30.5617C20.4613 30.5925 20.5335 30.6385 20.5948 30.6972C20.656 30.7559 20.7051 30.8261 20.7392 30.9038C20.7733 30.9815 20.7917 31.0651 20.7935 31.1499H19.4311C19.441 30.975 19.5189 30.8109 19.6483 30.6928C19.7776 30.5746 19.9481 30.5118 20.1232 30.5178H20.1341ZM34.333 31.3788V29.03H33.788V30.3924C33.6918 30.2686 33.5675 30.1694 33.4253 30.1031C33.2832 30.0367 33.1273 30.0052 32.9706 30.011C32.6093 30.011 32.2627 30.1545 32.0072 30.41C31.7517 30.6655 31.6082 31.012 31.6082 31.3734C31.6082 31.7347 31.7517 32.0812 32.0072 32.3367C32.2627 32.5922 32.6093 32.7358 32.9706 32.7358C33.1273 32.7415 33.2832 32.71 33.4253 32.6436C33.5675 32.5773 33.6918 32.4781 33.788 32.3543V32.6704H34.333V31.3788ZM35.2785 32.3025C35.3139 32.3021 35.3491 32.3086 35.382 32.3216C35.4133 32.3344 35.442 32.3528 35.4665 32.3761C35.4905 32.3996 35.5099 32.4273 35.5237 32.4578C35.5375 32.4896 35.5447 32.524 35.5447 32.5586C35.5447 32.5933 35.5375 32.6276 35.5237 32.6595C35.5099 32.69 35.4905 32.7177 35.4665 32.7412C35.442 32.7644 35.4133 32.7829 35.382 32.7957C35.3494 32.8101 35.3142 32.8175 35.2785 32.8175C35.2268 32.8171 35.1764 32.802 35.133 32.7741C35.0895 32.7461 35.055 32.7063 35.0333 32.6595C35.0196 32.6276 35.0126 32.5933 35.0126 32.5586C35.0126 32.524 35.0196 32.4897 35.0333 32.4578C35.0471 32.4273 35.0665 32.3996 35.0905 32.3761C35.115 32.3528 35.1437 32.3344 35.175 32.3216C35.2104 32.3075 35.2485 32.301 35.2867 32.3025H35.2785ZM35.2785 32.763C35.3057 32.7632 35.3326 32.7576 35.3575 32.7466C35.381 32.7362 35.4022 32.7214 35.4202 32.7031C35.4543 32.6659 35.4732 32.6173 35.4732 32.5668C35.4732 32.5164 35.4543 32.4678 35.4202 32.4306C35.4023 32.4122 35.381 32.3974 35.3575 32.387C35.3326 32.3761 35.3057 32.3705 35.2785 32.3706C35.2513 32.3708 35.2245 32.3763 35.1995 32.387C35.175 32.397 35.1528 32.4118 35.1341 32.4306C35.1 32.4678 35.0811 32.5164 35.0811 32.5668C35.0811 32.6173 35.1 32.6659 35.1341 32.7031C35.1528 32.7217 35.175 32.7365 35.1995 32.7466C35.227 32.7585 35.2568 32.7641 35.2867 32.763H35.2785ZM35.2948 32.4387C35.3203 32.4375 35.3453 32.4452 35.3657 32.4605C35.374 32.4674 35.3806 32.4762 35.3849 32.4862C35.3891 32.4961 35.391 32.507 35.3902 32.5178C35.3906 32.5268 35.3891 32.5359 35.3858 32.5443C35.3825 32.5527 35.3775 32.5604 35.3711 32.5668C35.3553 32.5812 35.3352 32.5898 35.3139 32.5913L35.3929 32.6813H35.3303L35.2567 32.5913H35.2322V32.6813H35.1804V32.4415L35.2948 32.4387ZM35.2349 32.4851V32.5505H35.2948C35.3055 32.5536 35.3169 32.5536 35.3275 32.5505C35.3295 32.5467 35.3305 32.5425 35.3305 32.5382C35.3305 32.5339 35.3295 32.5297 35.3275 32.5259C35.3295 32.5221 35.3305 32.5179 35.3305 32.5137C35.3305 32.5094 35.3295 32.5052 35.3275 32.5014C35.3169 32.4982 35.3055 32.4982 35.2948 32.5014L35.2349 32.4851ZM32.2376 31.3788C32.2467 31.2255 32.3003 31.0781 32.3921 30.9549C32.4838 30.8317 32.6095 30.738 32.7538 30.6854C32.8981 30.6327 33.0547 30.6234 33.2042 30.6586C33.3537 30.6938 33.4896 30.772 33.5953 30.8835C33.701 30.9949 33.7717 31.1349 33.7988 31.2861C33.8259 31.4373 33.8083 31.5931 33.748 31.7343C33.6876 31.8756 33.5873 31.9961 33.4594 32.0811C33.3314 32.1661 33.1814 32.2118 33.0278 32.2126C32.9199 32.214 32.8129 32.193 32.7135 32.151C32.6142 32.109 32.5245 32.0469 32.4503 31.9686C32.3761 31.8903 32.3189 31.7974 32.2823 31.6959C32.2457 31.5944 32.2305 31.4865 32.2376 31.3788ZM13.1014 31.3788V30.0763H12.5346V30.3924C12.4384 30.2686 12.3141 30.1694 12.1719 30.1031C12.0298 30.0367 11.8739 30.0052 11.7172 30.011C11.3559 30.011 11.0093 30.1545 10.7538 30.41C10.4983 30.6655 10.3548 31.012 10.3548 31.3734C10.3548 31.7347 10.4983 32.0812 10.7538 32.3367C11.0093 32.5922 11.3559 32.7358 11.7172 32.7358C11.8739 32.7415 12.0298 32.71 12.1719 32.6436C12.3141 32.5773 12.4384 32.4781 12.5346 32.3543V32.6704H13.1014V31.3788ZM10.9924 31.3788C11.0014 31.2255 11.0551 31.0781 11.1468 30.9549C11.2386 30.8317 11.3643 30.738 11.5086 30.6854C11.6529 30.6327 11.8094 30.6234 11.9589 30.6586C12.1085 30.6938 12.2444 30.772 12.3501 30.8835C12.4557 30.9949 12.5265 31.1349 12.5536 31.2861C12.5807 31.4373 12.563 31.5931 12.5027 31.7343C12.4424 31.8756 12.3421 31.9961 12.2141 32.0811C12.0862 32.1661 11.9362 32.2118 11.7826 32.2126C11.6742 32.2147 11.5666 32.1943 11.4666 32.1526C11.3666 32.111 11.2763 32.049 11.2015 31.9706C11.1267 31.8922 11.069 31.7991 11.032 31.6972C10.9951 31.5954 10.9798 31.4869 10.9869 31.3788H10.9924Z\"\n fill=\"#231F20\"\n />\n <path d=\"M24.2916 10.2262H15.7085V25.6513H24.2916V10.2262Z\" fill=\"#FF5F00\" />\n <path\n d=\"M16.2528 17.9399C16.2512 16.4541 16.5877 14.9875 17.2368 13.651C17.886 12.3146 18.8307 11.1433 19.9994 10.226C18.5523 9.08874 16.8144 8.38154 14.9844 8.18523C13.1544 7.98893 11.3061 8.31144 9.65066 9.1159C7.99527 9.92037 6.59959 11.1743 5.62315 12.7345C4.64672 14.2946 4.12891 16.098 4.12891 17.9385C4.12891 19.7791 4.64672 21.5824 5.62315 23.1426C6.59959 24.7027 7.99527 25.9567 9.65066 26.7612C11.3061 27.5656 13.1544 27.8882 14.9844 27.6919C16.8144 27.4955 18.5523 26.7883 19.9994 25.6511C18.831 24.734 17.8865 23.5632 17.2374 22.2273C16.5883 20.8913 16.2516 19.4252 16.2528 17.9399Z\"\n fill=\"#EB001B\"\n />\n <path\n d=\"M35.8719 17.9401C35.8719 19.7807 35.354 21.5842 34.3773 23.1444C33.4007 24.7046 32.0049 25.9586 30.3492 26.7629C28.6936 27.5673 26.8451 27.8896 25.015 27.693C23.1849 27.4964 21.447 26.7889 20 25.6512C21.1679 24.7334 22.1121 23.5622 22.7614 22.2262C23.4107 20.8902 23.748 19.4241 23.748 17.9387C23.748 16.4533 23.4107 14.9872 22.7614 13.6512C22.1121 12.3152 21.1679 11.144 20 10.2262C21.447 9.08854 23.1849 8.38099 25.015 8.18441C26.8451 7.98782 28.6936 8.31012 30.3492 9.11448C32.0049 9.91883 33.4007 11.1728 34.3773 12.733C35.354 14.2932 35.8719 16.0967 35.8719 17.9373V17.9401Z\"\n fill=\"#F79E1B\"\n />\n <path\n d=\"M34.9345 24.0164V23.7003H35.0625V23.6349H34.7383V23.7003H34.8772V24.0164H34.9345ZM35.5639 24.0164V23.6349H35.4658L35.3514 23.9074L35.2369 23.6349H35.1497V24.0164H35.2206V23.7303L35.3268 23.9782H35.4004L35.5067 23.7303V24.0191L35.5639 24.0164Z\"\n fill=\"#F79E1B\"\n />\n </svg>\n </SvgIcon>\n );\n}\n","import { SvgIcon } from '@mui/material';\n\nexport function Visa(props) {\n return (\n <SvgIcon {...props} viewBox=\"0 0 40 40\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 40 40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M16.0163 14.0477L13.9834 25.9773H17.2346L19.2692 14.0477H16.0163Z\" fill=\"#1257A5\" />\n <path\n d=\"M11.2573 14.0611L8.07291 22.1967L7.7334 20.9683C7.1054 19.4882 5.32256 17.3625 3.22949 16.0229L6.14123 25.9715L9.58146 25.9656L14.7017 14.0586L11.2573 14.0611Z\"\n fill=\"#1257A5\"\n />\n <path\n d=\"M6.49914 14.9149C6.31016 14.1882 5.76243 13.9716 5.08258 13.9457H0.0418113L0 14.1832C3.92273 15.1348 6.51838 17.4277 7.59543 20.1848L6.49914 14.9149Z\"\n fill=\"#1257A5\"\n />\n <path\n d=\"M25.8585 16.3348C26.9222 16.3181 27.6932 16.5506 28.2919 16.7914L28.5854 16.9294L29.0253 14.3438C28.3814 14.1021 27.3721 13.8429 26.1127 13.8429C22.8999 13.8429 20.6354 15.461 20.6179 17.7798C20.597 19.4933 22.231 20.4499 23.4652 21.0211C24.7321 21.6064 25.1569 21.9785 25.1511 22.5012C25.141 23.2998 24.1409 23.666 23.2068 23.666C21.9048 23.666 21.2133 23.4862 20.1454 23.0414L19.7265 22.8507L19.269 25.5208C20.03 25.8544 21.434 26.1413 22.8916 26.1563C26.3092 26.1563 28.5302 24.5574 28.5537 22.0797C28.5679 20.7242 27.7007 19.6898 25.8217 18.841C24.6844 18.2874 23.9887 17.9195 23.9954 17.3609C23.9954 16.865 24.5858 16.3348 25.8585 16.3348Z\"\n fill=\"#1257A5\"\n />\n <path\n d=\"M37.3691 14.0612H34.8571C34.0769 14.0612 33.4966 14.2736 33.1537 15.0512L28.3262 25.9841H31.7405C31.7405 25.9841 32.2974 24.514 32.4237 24.192C32.7975 24.192 36.1148 24.197 36.5872 24.197C36.6842 24.6135 36.9836 25.9841 36.9836 25.9841H39.9999L37.3691 14.0612ZM33.3594 21.7502C33.627 21.0654 34.6547 18.4162 34.6547 18.4162C34.6372 18.4488 34.9198 17.7263 35.0879 17.2773L35.307 18.3058C35.307 18.3058 35.93 21.154 36.0604 21.7502H33.3594Z\"\n fill=\"#1257A5\"\n />\n </svg>\n </SvgIcon>\n );\n}\n","import { useMemo } from 'react';\nimport CreditCardIcon from '@mui/icons-material/CreditCardOutlined';\nimport { ACH, AmericanExpress, Discover, Mastercard, Visa } from '@/components/icons';\n\ninterface Props {\n accountName: string;\n size?: 'small' | 'medium' | 'large';\n}\n\nexport function CardIcon(props: Props) {\n const { accountName, size } = props;\n\n const icon = useMemo(() => {\n if (accountName.startsWith('ACH')) {\n return <ACH fontSize={size ? size : 'small'} />;\n }\n\n if (accountName.startsWith('AmericanExpress') || accountName.startsWith('Amex')) {\n return <AmericanExpress fontSize={size ? size : 'large'} />;\n }\n\n if (accountName.startsWith('Discover')) {\n return <Discover fontSize={size ? size : 'large'} />;\n }\n\n if (accountName.startsWith('Mastercard')) {\n return <Mastercard fontSize={size ? size : 'large'} />;\n }\n\n if (accountName.startsWith('Visa')) {\n return <Visa fontSize={size ? size : 'large'} />;\n }\n\n return <CreditCardIcon />;\n }, [accountName, size]);\n\n return <>{icon}</>;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n addCard: {\n creditCardAdded: translate({ id: 'sections.paymentMethods.drawer.successfullyAddedCreditCard' }),\n infoBox: translate({ id: 'sections.payInvoices.drawer.addCard.infoBox' }),\n infoBoxPayment: translate({ id: 'sections.payInvoices.drawer.addCard.infoBoxPayment' }),\n noOption: translate({ id: 'sections.payInvoices.drawer.addCard.noOption' }),\n paymentFailed: translate({ id: 'sections.payInvoices.drawer.addCard.paymentFailed' }),\n paymentSuccessful: translate({ id: 'sections.payInvoices.drawer.addCard.paymentSuccessful' }),\n prompt: translate({ id: 'sections.payInvoices.drawer.addCard.prompt' }),\n yesOption: translate({ id: 'sections.payInvoices.drawer.addCard.yesOption' }),\n },\n addNewPaymentMethod: translate({ id: 'sections.payInvoices.drawer.paymentMethod.addNewPaymentMethod' }),\n chargePaymentMethod: {\n failed: translate({ id: 'sections.payInvoices.drawer.paymentMethod.chargePaymentMethodFailed' }),\n success: translate({ id: 'sections.payInvoices.drawer.paymentMethod.chargePaymentMethodSuccess' }),\n badRequest: translate({ id: 'sections.payInvoices.drawer.paymentMethod.chargePaymentMethodBadRequest' }),\n },\n confirmationAlert: {\n payment: translate({ id: 'sections.payInvoices.drawer.confirmationAlert.payment' }),\n toMakeA: translate({ id: 'sections.payInvoices.drawer.confirmationAlert.toMakeA' }),\n youAreUsing: translate({ id: 'sections.payInvoices.drawer.confirmationAlert.youAreUsing' }),\n },\n failedToLoadPaymentMethods: translate({\n id: 'sections.payInvoices.drawer.paymentMethod.failedToLoadPaymentMethods',\n }),\n footer: {\n processPayment: translate({ id: 'sections.payInvoices.drawer.paymentMethod.footer.processPayment' }),\n },\n header: {\n addCreditCard: translate({ id: 'sections.payInvoices.drawer.paymentMethod.header.addCreditCard' }),\n selectPaymentMethod: translate({\n id: 'sections.payInvoices.drawer.paymentMethod.header.selectPaymentMethod',\n }),\n },\n noPaymentMethodsAlert: translate({ id: 'sections.payInvoices.drawer.paymentMethod.noPaymentMethodsAlert' }),\n noPaymentMethodsAlertACH: translate({\n id: 'sections.payInvoices.drawer.paymentMethod.noPaymentMethodsAlertACH',\n }),\n noPaymentMethodsAlertCreditCard: translate({\n id: 'sections.payInvoices.drawer.paymentMethod.noPaymentMethodsAlertCreditCard',\n }),\n processingPaymentAlert: translate({\n id: 'sections.payInvoices.drawer.paymentMethod.processingPaymentAlert',\n }),\n select: {\n expires: translate({ id: 'sections.paymentMethods.dropdown.expires' }),\n failedToLoadPaymentMethods: translate({\n id: 'sections.payInvoices.drawer.paymentMethod.failedToLoadPaymentMethods',\n }),\n label: translate({ id: 'sections.paymentMethods.dropdown.label' }),\n noSavedPaymentMethods: translate({\n id: 'sections.paymentMethods.dropdown.noSavedPaymentMethods',\n }),\n noSavedPaymentMethodsACH: translate({\n id: 'sections.paymentMethods.dropdown.noSavedPaymentMethodsACH',\n }),\n noSavedPaymentMethodsCreditCard: translate({\n id: 'sections.paymentMethods.dropdown.noSavedPaymentMethodsCreditCard',\n }),\n },\n useOtherPaymentMethod: translate({ id: 'sections.payInvoices.drawer.paymentMethod.useOtherPaymentMethod' }),\n useSavedPaymentMethod: translate({ id: 'sections.payInvoices.drawer.paymentMethod.useSavedPaymentMethod' }),\n };\n }, [translate]);\n}\n","import { useCallback, useMemo } from 'react';\nimport { useAccountId } from '@/atoms/session';\nimport {\n Alert,\n Box,\n CircularProgress,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n SelectChangeEvent,\n Typography,\n} from '@mui/material';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { PaymentAccount, PaymentAccountTypes } from '@/common/types/payments';\nimport { isCardExpired } from '@/common/utils/isCardExpired';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { CardIcon } from '../../PaymentMethods/PaymentMethodCard/CardIcon';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onSelect: (paymentAccount: PaymentAccount) => void;\n selected: PaymentAccount | null;\n}\n\nexport function PaymentMethodSelect(props: Props) {\n const { onSelect, selected } = props;\n const { select: texts } = useTexts();\n const accountId = useAccountId();\n\n const creditCardEnabled = useFeatureEnabled('enableCreditCardPayment');\n const achEnabled = useFeatureEnabled('enableACHPayment');\n\n const { data: paymentMethods, status } = useQueryPaymentAccounts(accountId || '');\n\n const selectPaymentMethod = useCallback(\n (e: SelectChangeEvent<string>) => {\n const selectedPaymentMethod = paymentMethods?.find(p => p.paymentAccountId == e.target.value);\n\n if (selectedPaymentMethod) {\n onSelect(selectedPaymentMethod);\n }\n },\n [onSelect, paymentMethods],\n );\n\n const noSavedPaymentMethodsText = useMemo(() => {\n if (creditCardEnabled && achEnabled) {\n return texts.noSavedPaymentMethods;\n } else if (creditCardEnabled && !achEnabled) {\n return texts.noSavedPaymentMethodsCreditCard;\n } else if (!creditCardEnabled && achEnabled) {\n return texts.noSavedPaymentMethodsACH;\n } else {\n return texts.noSavedPaymentMethods;\n }\n }, [creditCardEnabled, achEnabled, texts]);\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">{texts.failedToLoadPaymentMethods}</Alert>}\n {status == 'success' && (\n <>\n {!paymentMethods && <Alert severity=\"info\">{noSavedPaymentMethodsText}</Alert>}\n\n {!!paymentMethods && (\n <>\n {paymentMethods.length == 0 && <Alert severity=\"info\">{noSavedPaymentMethodsText}</Alert>}\n\n {paymentMethods.length > 0 && (\n <FormControl fullWidth>\n <InputLabel id=\"payment-method-select-label\">{texts.label}</InputLabel>\n <Select\n labelId=\"payment-method-select-label\"\n id=\"payment-method-select\"\n value={selected?.paymentAccountId || ''}\n label={texts.label}\n onChange={selectPaymentMethod}\n >\n {paymentMethods.map((p, i) => (\n <MenuItem\n key={i}\n value={p.paymentAccountId}\n style={{ width: '100%' }}\n disabled={\n p.accountType == PaymentAccountTypes.CREDIT_CARD &&\n isCardExpired(p.month, p.year)\n }\n >\n <Box display=\"flex\" flexGrow={1}>\n <Box display=\"flex\" pr={2}>\n <CardIcon accountName={p.friendly} size=\"medium\" />\n </Box>\n <Box\n display=\"flex\"\n flexGrow={1}\n alignItems=\"center\"\n justifyContent=\"space-between\"\n >\n <Typography>{p.friendly} </Typography>\n {p.month && p.year && (\n <Typography variant=\"caption\">\n {texts.expires} {p.month.toString().padStart(2, '0')}/\n {p.year}\n </Typography>\n )}\n </Box>\n </Box>\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n )}\n </>\n )}\n </>\n )}\n </>\n );\n}\n","import { getAccount } from '@/atoms/session/store';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { AgreementDetails } from '@/common/types/agreements';\nimport { PaymentAccount } from '@/common/types/payments';\nimport { Alert, Box, Button, Link, Stack, Typography } from '@mui/material';\nimport { useCallback, useEffect } from 'react';\n\nimport { PaymentMethodSelect } from '../../PayInvoices/drawer/PaymentMethodSelect';\nimport { setPaymentAccount, setWizardStep, useAgreementDrawerState, WizardStep } from './store';\nimport { useTexts } from './useTexts';\nimport { useRemoveAutoPayActions } from './hooks/useRemoveAutoPayActions';\n\ninterface Props {\n id: string;\n details: AgreementDetails;\n}\n\nexport function ManageAutopay(props: Props) {\n const { id, details } = props;\n const { paymentAccount } = useAgreementDrawerState();\n const account = getAccount();\n const { data: paymentAccounts } = useQueryPaymentAccounts(account?.accountId || '');\n const texts = useTexts();\n const { handleRemoveAutopay } = useRemoveAutoPayActions(id);\n\n useEffect(() => {\n if (!details.autoPaymentAccounts.length || !details.autoPaymentAccounts[0]) {\n return;\n }\n const selectedPaymentAccount = paymentAccounts?.find(\n x => x.processorPaymentAccountId === details.autoPaymentAccounts[0].processorPaymentAccountId,\n );\n setPaymentAccount(selectedPaymentAccount || null);\n }, [id, details, paymentAccounts]);\n\n const handleOnSelect = useCallback((selected: PaymentAccount) => {\n setPaymentAccount(selected);\n }, []);\n\n const goToAddPaymentMethodStep = useCallback(() => {\n setWizardStep(WizardStep.AddPaymentMethod);\n }, []);\n\n return (\n <Stack direction=\"column\" spacing={2}>\n {details.hasAutoPaymentInstance && <Alert severity=\"info\">{texts.hasAutoPayInstance}</Alert>}\n <Typography gutterBottom>\n {texts.useSavedPaymentMethod}{' '}\n <Link onClick={goToAddPaymentMethodStep}>{texts.addNewPaymentMethod}</Link>\n </Typography>\n <PaymentMethodSelect onSelect={handleOnSelect} selected={paymentAccount} />\n {!!details.autoPaymentAccounts.length && !!details.autoPaymentAccounts[0] && (\n <Box>\n <Button variant=\"outlined\" onClick={handleRemoveAutopay}>\n {texts.disableAutopay}\n </Button>\n </Box>\n )}\n </Stack>\n );\n}\n","import { useQueryAgreementDetails } from '@/common/hooks/query/useQueryAgreementDetail';\nimport { Alert, CircularProgress } from '@mui/material';\nimport { AddPaymentMethod } from './AddPaymentMethod';\nimport { DetailListItems } from './DetailListItems';\nimport { ManageAutopay } from './ManageAutopay';\nimport { useAgreementDrawerState, WizardStep } from './store';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n agreementId: string;\n onClose: () => void;\n}\n\nexport function DrawerContent(props: Props) {\n const { agreementId, onClose } = props;\n const texts = useTexts();\n const { data: details, status } = useQueryAgreementDetails(agreementId);\n const { wizardStep } = useAgreementDrawerState();\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n {status == 'success' && (\n <>\n {!details && <Alert severity=\"error\">{texts.error}</Alert>}\n {details && wizardStep === WizardStep.Detail && <DetailListItems details={details} />}\n {details && wizardStep === WizardStep.ManageAutopay && (\n <ManageAutopay id={agreementId} details={details} />\n )}\n {details && wizardStep === WizardStep.AddPaymentMethod && <AddPaymentMethod onClose={onClose} />}\n </>\n )}\n </>\n );\n}\n","import { AgreementModel } from '@/api/agreements';\nimport AutorenewIcon from '@mui/icons-material/Autorenew';\nimport { Tooltip } from '@mui/material';\nimport WarningAmberRoundedIcon from '@mui/icons-material/WarningAmberRounded';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n item: AgreementModel;\n}\n\nexport function SecondaryIcon(props: Props) {\n const {\n item: { hasAutoPayment, hasExpiredPaymentMethod },\n } = props;\n const texts = useTexts();\n\n return hasExpiredPaymentMethod ? (\n <Tooltip title={texts.autopayMethodIsExpired}>\n <span>\n <WarningAmberRoundedIcon color=\"error\" />\n </span>\n </Tooltip>\n ) : (\n <Tooltip title={hasAutoPayment ? texts.autopayIsEnabled : texts.autopayIsDisabled}>\n <span>\n <AutorenewIcon color={hasAutoPayment ? 'info' : 'inherit'} />\n </span>\n </Tooltip>\n );\n}\n","import { AgreementModel } from '@/api/agreements';\nimport { FormattedDate } from 'react-intl';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n item: AgreementModel;\n}\n\nexport function SubTitle(props: Props) {\n const { item } = props;\n const { agreementDate } = item;\n const texts = useTexts();\n\n return (\n <span>\n <>\n {`${texts.effectiveDate} `}\n <FormattedDate value={agreementDate as Date} day=\"2-digit\" month=\"2-digit\" year=\"2-digit\" />\n </>\n </span>\n );\n}\n","import { useMemo } from 'react';\nimport { AchInput } from '../Drawer';\n\nexport function useIsAchInputValid(achInput: AchInput) {\n return useMemo(() => {\n return !Boolean(\n !achInput.accountNumber ||\n isNaN(Number(achInput.accountNumber)) ||\n !achInput.routingNumber ||\n isNaN(Number(achInput.routingNumber)) ||\n achInput.routingNumber.length != 9,\n );\n }, [achInput]);\n}\n","import { PaymentAccountTypes } from '@/common/types/payments';\nimport { useMemo } from 'react';\nimport { WizardStep, useAgreementDrawerState } from '../../../drawer/store';\nimport { useIsAchInputValid } from '../../../../PaymentMethods/drawers/AddPaymentMethod/hooks/useIsAchInputValid';\n\nexport function useDisableSave() {\n const { achInput, wizardStep, paymentAccount, paymentAccountType } = useAgreementDrawerState();\n const isAchInputValid = useIsAchInputValid(achInput);\n\n const disableSave = useMemo(() => {\n switch (wizardStep) {\n case WizardStep.ManageAutopay:\n return !paymentAccount;\n case WizardStep.AddPaymentMethod:\n return (\n paymentAccountType === PaymentAccountTypes.CREDIT_CARD ||\n (paymentAccountType === PaymentAccountTypes.ACH && !isAchInputValid)\n );\n }\n }, [isAchInputValid, paymentAccount, paymentAccountType, wizardStep]);\n\n return disableSave;\n}\n","import { useCallback } from 'react';\nimport { useToast } from '@/utils/useToast';\nimport { enableAutopayment } from '@/api/autopayments';\nimport { addAchPaymentAccount } from '@/api/paymentAccounts';\nimport { AgreementModel } from '@/api/agreements';\nimport { getAccount } from '@/atoms/session/store';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { queryClient } from '../../../../../services/queryClient';\nimport { WizardStep, setWizardStep, useAgreementDrawerState, setPaymentAccount } from '../../../drawer/store';\nimport { useTexts } from '../../../useTexts';\n\nexport function useAgreementCardActions(item: AgreementModel) {\n const account = getAccount();\n const toast = useToast();\n const texts = useTexts();\n const { wizardStep, paymentAccount, achInput } = useAgreementDrawerState();\n const { refetch: refetchPaymentAccounts } = useQueryPaymentAccounts(account?.accountId || '');\n\n const handleEnableAutopayments = useCallback(async () => {\n const successful = await enableAutopayment(item.agreementId, paymentAccount?.paymentAccountId || '');\n if (successful) {\n toast.success(texts.successfullyEnabledAutopayments);\n } else {\n toast.error(texts.failedToEnableAutopay);\n }\n queryClient.invalidateQueries('activeAgreements');\n queryClient.invalidateQueries('agreements');\n queryClient.invalidateQueries('agreementDetails');\n queryClient.invalidateQueries('paymentAccounts');\n setWizardStep(WizardStep.Detail);\n }, [item.agreementId, paymentAccount?.paymentAccountId, toast, texts]);\n\n const handleAddAchAccount = useCallback(async () => {\n if (!account || !achInput) {\n return;\n }\n try {\n const response = await addAchPaymentAccount({\n accountId: account.accountId,\n accountNumber: achInput.accountNumber,\n businessUnitId: account.businessUnitId,\n processorPaymentAccountId: '',\n routingNumber: achInput.routingNumber,\n });\n\n const paymentAccounts = await refetchPaymentAccounts();\n if (!!paymentAccounts.data && paymentAccounts.data.length) {\n const newPaymentMethod = paymentAccounts.data.find(\n p => p.processorPaymentAccountId == response.processorPaymentAccountId,\n );\n if (newPaymentMethod) {\n setPaymentAccount(newPaymentMethod);\n }\n }\n\n toast.success(texts.successfullyAddedAch);\n } catch {\n toast.error(texts.errorAddingAch);\n }\n\n await refetchPaymentAccounts();\n setWizardStep(WizardStep.ManageAutopay);\n }, [account, achInput, texts, refetchPaymentAccounts, toast]);\n\n const handleOnSave = useCallback(async () => {\n if (wizardStep === WizardStep.ManageAutopay) {\n await handleEnableAutopayments();\n queryClient.invalidateQueries('paymentAccounts');\n }\n if (wizardStep === WizardStep.AddPaymentMethod) {\n await handleAddAchAccount();\n }\n }, [wizardStep, handleEnableAutopayments, handleAddAchAccount]);\n\n return { handleOnSave } as const;\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faAward } from '@fortawesome/pro-regular-svg-icons';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { useCallback, useMemo } from 'react';\nimport { useTexts } from '../../useTexts';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DrawerContent } from '../../drawer/DrawerContent';\nimport { setSelectedItem, useListState } from '../store';\nimport { setWizardStep, useAgreementDrawerState, WizardStep, resetStore as resetDrawerStore } from '../../drawer/store';\nimport { CardProps } from './typings';\nimport { SecondaryIcon } from './SecondaryIcon';\nimport { SubTitle } from './SubTitle';\nimport { useDisableSave } from './hooks/useDisableSave';\nimport { useAgreementCardActions } from './hooks/useAgreementCardActions';\n\nexport const AgreementCard = (props: CardProps) => {\n const { item, disabled } = props;\n const texts = useTexts();\n const layout = useGetUILayout();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const { selected } = useListState();\n const { wizardStep } = useAgreementDrawerState();\n const { handleOnSave } = useAgreementCardActions(item);\n\n const handleOpen = useCallback(() => {\n setSelectedItem(item.agreementId!);\n openDrawer();\n }, [openDrawer, item.agreementId]);\n\n const handleClose = useCallback(() => {\n setSelectedItem('');\n resetDrawerStore();\n closeDrawer();\n }, [closeDrawer]);\n\n const handleBackBtnClick = useCallback(() => {\n if (wizardStep > 0) {\n setWizardStep(wizardStep - 1);\n }\n }, [wizardStep]);\n\n const toolTipText = useMemo(() => {\n return disabled ? texts.locationHasErrors : undefined;\n }, [disabled, texts.locationHasErrors]);\n\n const disableSave = useDisableSave();\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n badge={<StatusBadge status={item.status} />}\n icon={<FontAwesomeIcon icon={faAward} />}\n onClick={handleOpen}\n secondaryIcon={<SecondaryIcon item={item} />}\n selected={item.agreementId === selected}\n subTitle={<SubTitle item={item} />}\n title={item.name}\n disabled={disabled}\n showTooltip={disabled}\n toolTipText={toolTipText}\n />\n ) : (\n <MobileListCard\n badge={<StatusBadge status={item.status} />}\n icon={<FontAwesomeIcon icon={faAward} />}\n onClick={handleOpen}\n secondaryIcon={<SecondaryIcon item={item} />}\n selected={item.agreementId === selected}\n subTitle={<SubTitle item={item} />}\n title={item.name}\n disabled={disabled}\n showTooltip={disabled}\n toolTipText={toolTipText}\n />\n )}\n\n <SideDrawerForm\n isOpen={drawerOpen}\n onClose={handleClose}\n title={texts.drawerTitle}\n onSave={handleOnSave}\n hideFooter={wizardStep === WizardStep.Detail}\n showBackBtn={wizardStep !== WizardStep.Detail}\n disableSave={disableSave}\n onBackBtnClick={handleBackBtnClick}\n >\n <DrawerContent agreementId={item.agreementId} onClose={handleClose} />\n </SideDrawerForm>\n </>\n );\n};\n","import Select from '@mui/material/Select';\nimport MenuItem from '@mui/material/MenuItem';\nimport { useCallback } from 'react';\nimport { AgreementStatus } from '@/common/types/agreements';\nimport { useTexts } from '../../../useTexts';\n\ninterface Props {\n status: AgreementStatus | null;\n setStatus: (status: AgreementStatus | null) => void;\n}\n\nexport function StatusFilter(props: Props) {\n const { setStatus, status: statusProp } = props;\n const status = !!statusProp ? statusProp : '';\n const texts = useTexts();\n\n const handleChange = useCallback(\n e => {\n const val = e.target.value;\n\n if (!val) {\n setStatus(null);\n } else {\n setStatus(val);\n }\n },\n [setStatus],\n );\n\n return (\n <Select value={status} displayEmpty onChange={handleChange}>\n <MenuItem value=\"\">{texts.showAllAgreements}</MenuItem>\n <MenuItem value={AgreementStatus.ACTIVE}>{texts.showActiveAgreements}</MenuItem>\n <MenuItem value={AgreementStatus.CANCELLED}>{texts.showCancelledAgreements}</MenuItem>\n <MenuItem value={AgreementStatus.COMPLETED}>{texts.showCompletedAgreements}</MenuItem>\n </Select>\n );\n}\n","import { SideDrawer } from '@/components/SideDrawer';\nimport Stack from '@mui/material/Stack';\nimport { ClearFiltersButton } from '@/components/cardList/filters/ClearFiltersButton';\nimport { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { ServiceLocationFilter } from '@/components/cardList/filters/ServiceLocationFilter';\nimport { useListActions } from '../hooks';\nimport { useListState } from '../store';\nimport { useTexts } from '../../useTexts';\nimport { StatusFilter } from './StatusFilter';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function FiltersDrawer(props: Props) {\n const { onClose, open } = props;\n const texts = useTexts();\n const { handleResetFilters, handleSetServiceLocations, handleSetStatus } = useListActions();\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations, status } = useListState();\n\n return (\n <SideDrawer isOpen={open} onClose={onClose} title={texts.filtersDrawerTitle}>\n <Stack direction=\"column\" spacing={2}>\n {!!locations && (\n <ServiceLocationFilter\n locations={locations}\n serviceLocations={serviceLocations}\n setServiceLocations={handleSetServiceLocations}\n />\n )}\n <StatusFilter status={status} setStatus={handleSetStatus} />\n <ClearFiltersButton onClick={handleResetFilters} />\n </Stack>\n </SideDrawer>\n );\n}\n","import { AgreementModel } from '@/api/agreements';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { CardList, ListBody, ListFooter } from '@/components/cardList';\nimport { useTexts } from '../useTexts';\nimport { AgreementsListHeader } from './header/AgreementsListHeader';\nimport { AgreementCard } from './cards';\nimport { useListState } from './store';\nimport { useListActions } from './hooks';\nimport { FiltersDrawer } from './filters/FiltersDrawer';\n\ninterface Props {\n items: AgreementModel[];\n total: number;\n}\n\nexport function AgreementsList(props: Props) {\n const { items, total } = props;\n const { page, take } = useListState();\n const texts = useTexts();\n const { handleSetPage } = useListActions();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n return (\n <>\n <CardList\n header={<AgreementsListHeader openDrawer={openDrawer} />}\n body={<ListBody card={AgreementCard} emptyListAlertText={texts.noAgreementsAlert} items={items} />}\n footer={<ListFooter count={Math.ceil(total / take)} page={page + 1} onChange={handleSetPage} />}\n />\n <FiltersDrawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { useAccountId } from '@/atoms/session';\nimport { PageErrorState } from '@/components/PageErrorState/PageErrorState';\nimport { useQueryAgreements } from '@/common/hooks/query/useQueryAgreements';\nimport { useEffect } from 'react';\nimport { LoadingSkeleton } from './LoadingSkeleton';\nimport { AgreementsList } from './AgreementsList';\nimport { resetStore, useListState } from './AgreementsList/store';\n\nexport function AgreementsPage() {\n const { page, take, serviceLocations, status } = useListState();\n const accountId = useAccountId();\n const query = useQueryAgreements(accountId || '', page, take, serviceLocations, status);\n\n useEffect(() => {\n resetStore();\n }, [accountId]);\n\n return (\n <PageWrapper disableScroll>\n {query.status === 'loading' && <LoadingSkeleton />}\n {query.status === 'success' && <AgreementsList items={query.data.items} total={query.data.total} />}\n {query.status === 'error' && <PageErrorState />}\n </PageWrapper>\n );\n}\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface BusinessUnitDetails {\n name: string;\n street1: string;\n street2: string;\n city: string;\n state: string;\n postalCode: string;\n phone: string;\n phoneExt: string;\n}\n\nconst baseUrl = '/api/BusinessUnit';\n\nexport const getBusinessUnitDetails = async (businessUnitId: string) => {\n try {\n const { data, status } = await get<BusinessUnitDetails>(`${baseUrl}/${businessUnitId}/details`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get Business Unit details.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { BusinessUnitDetails, getBusinessUnitDetails } from '@/api/businessUnitDetails';\nimport { useQuery } from 'react-query';\n\nexport const useFetchBusinessUnitDetails = (businessUnitId: string) =>\n useQuery<BusinessUnitDetails, Error>(\n ['businessUnitDetails', businessUnitId],\n () => getBusinessUnitDetails(businessUnitId),\n {\n staleTime: Infinity,\n },\n );\n","import { getAccount } from '@/atoms/session/store';\nimport { useMemo } from 'react';\nimport { useFetchBusinessUnitDetails } from './query/useFetchBusinessUnitDetails';\n\nexport const useBusinessUnitDetails = () => {\n const account = getAccount();\n const { data: details } = useFetchBusinessUnitDetails(account?.businessUnitId || '');\n\n return useMemo(() => {\n return details ? details : false;\n }, [details]);\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n useGreeting: {\n afternoon: translate({ id: 'toolbar.greeting.afternoon' }),\n evening: translate({ id: 'toolbar.greeting.evening' }),\n good: translate({ id: 'toolbar.greeting.good' }),\n howCanWeServeYou: translate({ id: 'toolbar.greeting.howCanWeServeYou' }),\n morning: translate({ id: 'toolbar.greeting.morning' }),\n thankYou: translate({ id: 'toolbar.greeting.thankYou' }),\n },\n };\n }, [translate]);\n}\n","import { getFirstName } from '@/atoms/session/store';\nimport { useTexts } from './useTexts';\n\nexport function useMobileGreeting() {\n const { useGreeting: texts } = useTexts();\n const firstName = getFirstName();\n\n const now: Date = new Date();\n const currentHour: number = now.getHours();\n let timeOfDay: string = '';\n\n if (currentHour < 12) {\n timeOfDay = texts.morning;\n } else if (currentHour < 18) {\n timeOfDay = texts.afternoon;\n } else {\n timeOfDay = texts.evening;\n }\n\n return `${texts.good} ${timeOfDay}, ${firstName}.`;\n}\n","import { useBusinessUnitDetails } from '@/common/hooks/useBusinessUnitDetails';\nimport { useMobileGreeting } from './useMobileGreeting';\nimport { useTexts } from './useTexts';\n\nexport function useDesktopGreeting() {\n const greeting = useMobileGreeting();\n const { useGreeting: texts } = useTexts();\n\n const buDetails = useBusinessUnitDetails();\n const companyName = buDetails ? buDetails.name : '';\n\n return `${greeting} ${!!companyName ? `${texts.thankYou} ${companyName}.` : ''}`;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n greeting: {\n tagLine: translate({ id: 'toolbar.greeting.howCanWeServeYou' }),\n },\n logout: translate({ id: `components.avatar.logout` }),\n viewProfileSettings: translate({ id: `components.avatar.viewProfileSettings` }),\n };\n }, [translate]);\n}\n","import { useDesktopGreeting } from '@/utils/hooks/useDesktopGreeting';\nimport { Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useTexts } from './useTexts';\n\nconst useStyles = makeStyles({\n root: {\n flexGrow: 1,\n fontSize: 16,\n fontWeight: 600,\n },\n});\n\nexport function AppHeaderGreeting() {\n const classes = useStyles();\n const greetingText = useDesktopGreeting();\n const { greeting: texts } = useTexts();\n\n return (\n <Typography component=\"div\" className={classes.root}>\n {`${greetingText} ${texts.tagLine}`}\n </Typography>\n );\n}\n","import { useCallback } from 'react';\n\nimport { logout as logoutAction } from '@/atoms/session/logout';\n\nexport function useLogoutActions() {\n const logout = useCallback((): boolean => {\n try {\n logoutAction();\n return true;\n } catch (e) {\n // TODO: navigate 404 page\n return false;\n }\n }, []);\n\n return logout;\n}\n","import AccountCircleIcon from '@mui/icons-material/AccountCircle';\nimport CloseIcon from '@mui/icons-material/Close';\nimport { Box, Button, Grid, IconButton, Popover, Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\n\nimport { useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { getDisplayName } from '@/atoms/session/store';\nimport { useTexts } from './useTexts';\nimport { useLogoutActions } from './useLogoutActions';\n\nconst useStyles = makeStyles({\n name: {\n flexGrow: 1,\n },\n popover: {\n minWidth: '300px',\n },\n});\n\nexport const Avatar = () => {\n const classes = useStyles();\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);\n const navigate = useNavigate();\n const texts = useTexts();\n const logout = useLogoutActions();\n const displayName = getDisplayName();\n\n const handleMenu = (event: React.MouseEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const goToProfileSettings = (_event: React.MouseEvent<HTMLButtonElement>) => {\n navigate('/profile');\n handleClose();\n };\n\n const handleClose = () => {\n setAnchorEl(null);\n };\n\n const open = Boolean(anchorEl);\n const id = open ? 'simple-popover' : undefined;\n\n return (\n <div>\n <IconButton color=\"primary\" onClick={handleMenu} size=\"medium\" data-testid=\"btn-avatar\">\n <AccountCircleIcon color=\"primary\" />\n </IconButton>\n <Popover\n id={id}\n open={open}\n anchorEl={anchorEl}\n onClose={handleClose}\n anchorOrigin={{\n vertical: 'bottom',\n horizontal: 'center',\n }}\n transformOrigin={{\n vertical: 'top',\n horizontal: 'center',\n }}\n >\n <Box p={2} className={classes.popover}>\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Box display=\"flex\">\n <Box display=\"flex\" flexGrow={1} alignItems=\"center\">\n <Typography variant=\"h4\">{displayName}</Typography>\n </Box>\n <Box>\n <IconButton onClick={handleClose} size=\"small\">\n <CloseIcon />\n </IconButton>\n </Box>\n </Box>\n </Grid>\n <Grid item>\n <Button\n data-testid=\"btn-view-profile-settings\"\n onClick={goToProfileSettings}\n variant=\"text\"\n >\n <Typography variant=\"caption\">{texts.viewProfileSettings}</Typography>\n </Button>\n </Grid>\n <Grid item>\n <Button data-testid=\"btn-log-out\" onClick={logout} variant=\"contained\">\n {texts.logout}\n </Button>\n </Grid>\n </Grid>\n </Box>\n </Popover>\n </div>\n );\n};\n","import { appbarHeight } from '@/common/constants';\nimport { AppBar, Toolbar } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { AppHeaderGreeting } from './AppHeaderGreeting';\nimport { Avatar } from './Avatar';\n\nconst drawerWidth = 256;\n\nconst useStyles = makeStyles(theme => ({\n root: {\n background: theme.palette.background.default,\n width: `calc(100% - ${drawerWidth}px)`,\n marginLeft: drawerWidth,\n height: `${appbarHeight}px`,\n },\n title: {\n flexGrow: 1,\n },\n}));\n\nexport function AppHeaderDesktop() {\n const classes = useStyles();\n\n return (\n <AppBar position=\"fixed\" className={classes.root} elevation={0} color=\"transparent\">\n <Toolbar>\n <AppHeaderGreeting />\n <Avatar />\n </Toolbar>\n </AppBar>\n );\n}\n","import { proxy, useSnapshot } from 'valtio';\n\n// Store state\ninterface SidebarState {\n isOpen: boolean;\n}\n\n// Valtio store initialization\nexport const state = proxy<SidebarState>({ isOpen: false });\n\n// Setter functions\nexport function openSidebar() {\n state.isOpen = true;\n}\n\nexport function closeSidebar() {\n state.isOpen = false;\n}\n\nexport function toggleSidebar() {\n state.isOpen = !state.isOpen;\n}\n\n//Hooks\nexport function useIsOpen() {\n return useSnapshot(state).isOpen;\n}\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport { Box, IconButton } from '@mui/material';\nimport MenuIcon from '@mui/icons-material/Menu';\nimport { useCallback } from 'react';\nimport { useNavigate } from 'react-router';\nimport { makeStyles } from '@mui/styles';\nimport { toggleSidebar } from './store';\n\ninterface Props {\n content: React.ReactNode;\n}\n\nconst useStyles = makeStyles({\n content: {\n cursor: 'pointer',\n display: 'flex',\n flexGrow: 1,\n alignItems: 'center',\n },\n});\n\nexport const Header = (props: Props) => {\n const { content } = props;\n const layout = useGetUILayout();\n const navigate = useNavigate();\n const classes = useStyles();\n\n const handleContentClick = useCallback(() => {\n navigate('/account-overview');\n }, [navigate]);\n\n return (\n <Box p={2} display=\"flex\">\n {layout == 'mobile' && (\n <Box pr={3}>\n <IconButton\n edge=\"start\"\n color=\"inherit\"\n onClick={toggleSidebar}\n data-testid=\"btn-toggle-sidebar\"\n size=\"large\"\n >\n <MenuIcon />\n </IconButton>\n </Box>\n )}\n\n <Box className={classes.content} data-testid=\"logo\" onClick={handleContentClick}>\n {content}\n </Box>\n </Box>\n );\n};\n\nHeader.displayName = 'Header';\n","import { useCallback, useMemo } from 'react';\nimport { useLocation } from 'react-router';\n\nimport { Box, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport ArrowRightIcon from '@mui/icons-material/ArrowRight';\nimport { ListItemWithChildrenProps } from './typings';\n\nconst useStyles = makeStyles({\n icon: {\n fontSize: '24px',\n },\n iconContainer: {\n display: 'flex',\n justifyContent: 'center',\n width: '24px',\n },\n});\n\nexport const ListItemWithChildren = (props: ListItemWithChildrenProps) => {\n const { disabled, hidden, icon, label, path, setSubList, subList } = props;\n const classes = useStyles();\n const location = useLocation();\n\n const handleClick = useCallback(\n () => (_e: React.MouseEvent) => {\n setSubList(subList);\n },\n [setSubList, subList],\n );\n\n const isSelected = useMemo(() => {\n return location.pathname.startsWith(path);\n }, [location.pathname, path]);\n\n return hidden ? null : (\n <ListItemButton onClick={handleClick()} disabled={disabled} selected={isSelected}>\n {!!icon && (\n <ListItemIcon className={classes.icon}>\n <Box className={classes.iconContainer}>{icon}</Box>\n </ListItemIcon>\n )}\n <ListItemText primary={label} />\n <ArrowRightIcon data-testid=\"btn-arrow-right\" />\n </ListItemButton>\n );\n};\n\nListItemWithChildren.displayName = 'ListItemWithChildren';\n","import { List as MuiList } from '@mui/material';\n\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { ListItem, useTexts } from '../../index';\n\nexport function PaymentsSubList() {\n const texts = useTexts();\n const viewAgreementsEnabled = useFeatureEnabled('enableViewAgreements');\n\n return (\n <MuiList>\n <ListItem data-testid=\"btn-pay-invoices\" label={texts.payInvoices} path=\"/payments/pay-invoices\" />\n <ListItem\n hidden={!viewAgreementsEnabled}\n data-testid=\"btn-manageAutopay\"\n label={texts.manageAutopay}\n path=\"/payments/manage-autopay\"\n />\n <ListItem data-testid=\"btn-payment-methods\" label={texts.paymentMethods} path=\"/payments/payment-methods\" />\n </MuiList>\n );\n}\n","import { List as MuiList } from '@mui/material';\n\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { ListItem, useTexts } from '../../index';\n\nexport function YourServicesSubList() {\n const texts = useTexts();\n const requestServiceEnabled = useFeatureEnabled('enableRequestNewService');\n const upcomingServicesEnabled = useFeatureEnabled('enableUpcomingServices');\n const viewAgreementsEnabled = useFeatureEnabled('enableViewAgreements');\n\n return (\n <MuiList>\n <ListItem\n data-testid=\"btn-request-service\"\n hidden={!requestServiceEnabled}\n label={texts.requestService}\n path=\"/your-services/request-service\"\n />\n <ListItem\n data-testid=\"btn-your-requests\"\n hidden={!requestServiceEnabled}\n label={texts.yourRequests}\n path=\"/your-services/your-requests\"\n />\n <ListItem\n data-testid=\"btn-upcoming-services\"\n hidden={!upcomingServicesEnabled}\n label={texts.upcomingServices}\n path=\"/your-services/upcoming-services\"\n />\n <ListItem\n data-testid=\"btn-agreements\"\n hidden={!viewAgreementsEnabled}\n label={texts.agreements}\n path=\"/your-services/agreements\"\n />\n </MuiList>\n );\n}\n","import { faCreditCard } from '@fortawesome/free-regular-svg-icons';\nimport { faCommentAltSmile, faHistory, faTools } from '@fortawesome/pro-regular-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\n\nimport { List as MuiList } from '@mui/material';\nimport DashboardIcon from '@mui/icons-material/Dashboard';\n\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { usePaymentsEnabled } from '@/common/hooks/usePaymentsEnabled';\nimport { ListItem, useTexts } from '../index';\nimport { ListItemWithChildren } from './ListItemWithChildren';\nimport { ListProps } from './typings';\nimport * as SubLists from './SubLists';\n\nexport function List(props: ListProps) {\n const { setSubList } = props;\n const texts = useTexts();\n\n const paymentsEnabled = usePaymentsEnabled();\n const questionsAndCommentsEnabled = useFeatureEnabled('enableQuestionsAndComments');\n const requestServiceEnabled = useFeatureEnabled('enableRequestNewService');\n const serviceHistoryEnabled = useFeatureEnabled('enableServiceHistory');\n const upcomingServicesEnabled = useFeatureEnabled('enableUpcomingServices');\n const viewAgreementsEnabled = useFeatureEnabled('enableViewAgreements');\n const viewBillingHistoryEnabled = useFeatureEnabled('enableBillingHistory');\n const viewPaymentHistoryEnabled = useFeatureEnabled('enableViewPaymentHistory');\n\n return (\n <MuiList>\n <ListItem\n data-testid=\"btn-account-overview\"\n icon={<DashboardIcon />}\n label={texts.accountOverview}\n path=\"/account-overview\"\n />\n <ListItemWithChildren\n data-testid=\"btn-your-services\"\n hidden={!requestServiceEnabled && !upcomingServicesEnabled && !viewAgreementsEnabled}\n icon={<FontAwesomeIcon icon={faTools} />}\n label={texts.yourServices}\n path=\"/your-services\"\n setSubList={setSubList}\n subList={<SubLists.YourServicesSubList />}\n />\n <ListItem\n data-testid=\"btn-service-history\"\n hidden={!serviceHistoryEnabled && !viewPaymentHistoryEnabled && !viewBillingHistoryEnabled}\n icon={<FontAwesomeIcon icon={faHistory} />}\n label={texts.accountHistory}\n path=\"/account-history\"\n />\n <ListItemWithChildren\n data-testid=\"btn-payments\"\n hidden={!paymentsEnabled}\n icon={<FontAwesomeIcon icon={faCreditCard} />}\n label={texts.makePayments}\n path=\"/payments\"\n setSubList={setSubList}\n subList={<SubLists.PaymentsSubList />}\n />\n <ListItem\n data-testid=\"btn-questions-and-comments\"\n hidden={!questionsAndCommentsEnabled}\n icon={<FontAwesomeIcon icon={faCommentAltSmile} />}\n label={texts.questionsAndComments}\n path=\"/questions-and-comments\"\n />\n </MuiList>\n );\n}\n","import { useCallback, useMemo } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\nimport { Box, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { closeSidebar } from '../store';\nimport { ListItemProps } from './typings';\n\nconst useStyles = makeStyles({\n icon: {\n fontSize: '24px',\n },\n iconContainer: {\n display: 'flex',\n justifyContent: 'center',\n width: '24px',\n },\n});\n\nexport const ListItem = (props: ListItemProps) => {\n const { disabled, hidden, icon, label, path } = props;\n const classes = useStyles();\n const navigate = useNavigate();\n const location = useLocation();\n\n const handleClick = useCallback(\n () => (_e: React.MouseEvent) => {\n navigate(path);\n closeSidebar();\n },\n [navigate, path],\n );\n\n const isSelected = useMemo(() => {\n return location.pathname == path;\n }, [location.pathname, path]);\n\n return hidden ? null : (\n <ListItemButton onClick={handleClick()} disabled={disabled} selected={isSelected}>\n {!!icon && (\n <ListItemIcon className={classes.icon}>\n <Box className={classes.iconContainer}>{icon}</Box>\n </ListItemIcon>\n )}\n <ListItemText primary={label} />\n </ListItemButton>\n );\n};\n\nListItem.displayName = 'ListItem';\n","import { Box } from '@mui/material';\n\ninterface Props {\n content: React.ReactNode;\n}\n\nexport const Section = (props: Props) => {\n const { content } = props;\n return <Box p={2}>{content}</Box>;\n};\n\nSection.displayName = 'Section';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n agreements: translate({ id: `navigation.pages.agreements` }),\n accountHistory: translate({ id: `navigation.pages.accountHistory` }),\n accountOverview: translate({ id: `navigation.pages.accountOverview` }),\n makePayments: translate({ id: `navigation.pages.makePayments` }),\n manageAutopay: translate({ id: `navigation.pages.manageAutopay` }),\n payInvoices: translate({ id: `navigation.pages.payInvoices` }),\n paymentMethods: translate({ id: `navigation.pages.paymentMethods` }),\n questionsAndComments: translate({ id: `navigation.pages.questionsAndComments` }),\n requestService: translate({ id: `navigation.pages.requestService` }),\n upcomingServices: translate({ id: `navigation.pages.upcomingServices` }),\n viewPaymentHistory: translate({ id: `navigation.pages.viewPaymentHistory` }),\n yourRequests: translate({ id: 'navigation.pages.yourRequests' }),\n yourServices: translate({ id: 'navigation.pages.yourServices' }),\n };\n }, [translate]);\n}\n","import { get } from '@/utils/http';\nimport { prepareServerError, ServerError } from '@/utils/ServerError';\n\nexport async function fetchAccountsByContactId(contactId: string): Promise<Account.AccountSelect[]> {\n try {\n const { data, status } = await get<Account.AccountSelect[]>(`api/accounts?contactId=${contactId}`);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to retrieve Accounts.`, status);\n } catch (e) {\n throw prepareServerError(e);\n }\n}\n","import { useQuery } from 'react-query';\nimport { fetchAccountsByContactId } from '../../../services/services/accountServices';\n\nexport const useFetchAccountByContactId = contactId =>\n useQuery<Account.AccountSelect[], Error>('accountsByContactId', () => fetchAccountsByContactId(contactId), {\n staleTime: Infinity,\n });\n","import { theme } from '@/theme';\nimport { useCallback } from 'react';\nimport { List, ListItem, Typography, ListItemText, Box } from '@mui/material';\n\nimport makeStyles from '@mui/styles/makeStyles';\n\nexport type Props = {\n accountsList: Account.AccountSelect[];\n onAccountSelected: (account: Account.AccountSelect) => void;\n title: string;\n wrappingContainer?: boolean;\n};\n\nconst useStyles = (props: Props) =>\n makeStyles({\n container: {\n maxHeight: props.wrappingContainer ? '350px' : 'auto',\n overflowY: 'auto',\n },\n list: {\n minWidth: '250px',\n },\n title: {\n paddingLeft: theme.spacing(2),\n },\n });\n\nexport function AccountSwitch(props: Props) {\n const { accountsList, onAccountSelected, title } = props;\n const classes = useStyles(props)();\n\n const handleClick = useCallback(\n (account: Account.AccountSelect) => (_e: React.MouseEvent<HTMLElement>) => {\n onAccountSelected(account);\n },\n [onAccountSelected],\n );\n\n return (\n <>\n <Typography className={classes.title} color=\"primary\" variant=\"body2\">\n {title}\n </Typography>\n <Box className={classes.container}>\n <List className={classes.list}>\n {accountsList.map((value, index) => (\n <ListItem\n dense\n button\n divider={index < accountsList.length - 1}\n key={index}\n onClick={handleClick(value)}\n >\n <ListItemText\n primary={\n <Typography>\n <b>{value.name}</b>\n </Typography>\n }\n secondary={<Typography>Account #{value.number}</Typography>}\n />\n </ListItem>\n ))}\n </List>\n </Box>\n </>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n account: translate({ id: `sections.accountSwitcher.account` }),\n success: translate({ id: `sections.accountSwitcher.success` }),\n switchLink: translate({ id: `sections.accountSwitcher.switchLink` }),\n heading: translate({ id: `sections.accountSwitcher.heading` }),\n };\n }, [translate]);\n}\n","import { setAccountId } from '@/atoms/session';\nimport { AccountSwitch } from '@/components/AccountSwitch';\nimport { toast } from 'react-toastify';\nimport { useFetchCustomerPortalSettings } from '@/common/hooks/query/useFetchCustomerPortalSettings';\nimport { getAccount } from '@/atoms/session/store';\nimport { useTexts } from './useTexts';\n\nexport type AccountSwitchListProps = {\n accountsList: Account.AccountSelect[];\n clearSubList: () => void;\n};\n\nexport const AccountSwitchList = (props: AccountSwitchListProps) => {\n const { accountsList, clearSubList } = props;\n const texts = useTexts();\n const account = getAccount();\n const { refetch } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n\n const onAccountSelected = (account: Account.AccountSelect) => {\n clearSubList();\n setAccountId(account);\n refetch();\n toast.success(texts.success);\n };\n\n return <AccountSwitch title={texts.heading} accountsList={accountsList} onAccountSelected={onAccountSelected} />;\n};\n\nAccountSwitchList.displayName = 'AccountSwitchList';\n","import { Box, Link } from '@mui/material';\nimport { useCallback } from 'react';\nimport { ListProps } from '../List/typings';\nimport { AccountSwitchList } from './AccountSwitchList';\nimport { useTexts } from './useTexts';\n\ntype AccountSwitchActionProps = {\n accountsList: Account.AccountSelect[];\n clearSubList: () => void;\n} & ListProps;\n\nexport const AccountSwitchAction = (props: AccountSwitchActionProps) => {\n const { accountsList, setSubList, clearSubList } = props;\n const texts = useTexts();\n\n const accountSwitch = AccountSwitchList({ accountsList: accountsList, clearSubList: clearSubList });\n\n const handleClick = useCallback(() => {\n setSubList(accountSwitch);\n }, [setSubList, accountSwitch]);\n\n return (\n <Box mt={1}>\n <Link variant=\"button\" onClick={handleClick}>\n {texts.switchLink}\n </Link>\n </Box>\n );\n};\n\nAccountSwitchAction.displayName = 'AccountSwitchAction';\n","import { getAccount, getUser } from '@/atoms/session/store';\nimport { useFetchAccountByContactId } from '@/common/hooks/query/useQueryAccounts';\nimport { Typography, Box } from '@mui/material';\nimport { ListProps } from '../List/typings';\nimport { AccountSwitchAction } from './AccountSwitchAction';\nimport { useTexts } from './useTexts';\n\ntype SwitchAccountViewProps = {\n clearSubList: () => void;\n} & ListProps;\n\nexport const SwitchAccountView = (props: SwitchAccountViewProps) => {\n const { setSubList, clearSubList } = props;\n const texts = useTexts();\n const contactId = getUser()?.contactId ?? '';\n\n const accountFetchResults = useFetchAccountByContactId(contactId);\n\n return (\n <Box pt={2} pl={2} pr={2}>\n <Typography>{getAccount()?.name}</Typography>\n <Typography variant=\"body2\">\n {texts.account} #{getAccount()?.number}\n </Typography>\n {accountFetchResults.isSuccess && accountFetchResults.data.length > 1 && (\n <AccountSwitchAction\n setSubList={setSubList}\n clearSubList={clearSubList}\n accountsList={accountFetchResults.data}\n />\n )}\n </Box>\n );\n};\n\nSwitchAccountView.displayName = 'SwitchAccountView';\n","import { Fragment, useCallback, useState } from 'react';\n\nimport { Box, Divider, IconButton } from '@mui/material';\nimport ArrowBackIcon from '@mui/icons-material/ArrowBack';\n\nimport { Header, Section } from './index';\nimport { ListProps } from './List/typings';\nimport { SwitchAccountView } from './SwitchAccount/SwitchAccountView';\n\ninterface Props {\n footerContent: React.ReactNode;\n headerContent: React.ReactNode;\n list: React.ComponentType<ListProps>;\n}\n\nexport const Sidebar = (props: Props) => {\n const { footerContent, headerContent, list: List } = props;\n const [selectedSubList, setSelectedSubList] = useState<React.ReactElement>();\n\n const setSubList = useCallback((list: React.ReactElement) => {\n setSelectedSubList(list);\n }, []);\n\n const clearSubList = useCallback(() => {\n setSelectedSubList(undefined);\n }, []);\n\n return (\n <Fragment>\n {!selectedSubList && (\n <Box data-testid=\"sidebar-list\">\n <Header content={headerContent} />\n <Divider />\n <SwitchAccountView setSubList={setSubList} clearSubList={clearSubList}></SwitchAccountView>\n <List setSubList={setSubList} />\n <Divider />\n <Section content={footerContent} />\n </Box>\n )}\n\n {!!selectedSubList && (\n <Box data-testid=\"sidebar-sub-list\">\n <Box display=\"flex\" justifyContent=\"flex-end\">\n <IconButton onClick={clearSubList} size=\"large\">\n <ArrowBackIcon />\n </IconButton>\n </Box>\n {selectedSubList}\n </Box>\n )}\n </Fragment>\n );\n};\n\nSidebar.displayName = 'Sidebar';\n","export interface SplittableAddress {\n city: string;\n postalCode: string;\n state: string;\n street1: string;\n street2: string | null;\n}\n\nexport function splitAddress(l: SplittableAddress | null) {\n if (!l) {\n return '';\n }\n\n const parts: string[] = [];\n\n parts.push(l.street1);\n if (l.street2) parts.push(l.street2);\n parts.push(`${l.city}, ${l.state} ${l.postalCode}`);\n\n return parts;\n}\n","import { useMemo } from 'react';\nimport { splitAddress, SplittableAddress } from '../utils/splitAddress';\n\nexport const useSplitAddress = (l: SplittableAddress | null) => {\n const address = useMemo(() => {\n return splitAddress(l);\n }, [l]);\n\n return address;\n};\n","import makeStyles from '@mui/styles/makeStyles';\nimport { Box, Typography } from '@mui/material';\nimport { useSplitAddress } from '@/common/hooks/useSplitAddress';\nimport { useBusinessUnitDetails } from '@/common/hooks/useBusinessUnitDetails';\nimport { PhoneNumber } from '@/components/localization/PhoneNumber';\n\nconst useStyles = makeStyles(theme => ({\n phoneNumber: {\n paddingTop: theme.spacing(2),\n },\n}));\n\nexport function FooterContent() {\n const details = useBusinessUnitDetails();\n const companyName = details ? details.name : '';\n const address = useSplitAddress(details || null);\n const classes = useStyles();\n\n return (\n <>\n {details && (\n <Typography variant=\"caption\">\n <Box>{companyName}</Box>\n <Box>{address[0]}</Box>\n <Box>{address[1]}</Box>\n {address[2] && <Box>{address[2]}</Box>}\n {details && (\n <Box className={classes.phoneNumber}>\n <PhoneNumber phone={details.phone} phoneExt={details.phoneExt} />\n </Box>\n )}\n </Typography>\n )}\n </>\n );\n}\n","import { emptyGuid } from '@/common/constants';\nimport { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/Image';\n\nexport const getLogoUrl = async (imageId: string | undefined) => {\n try {\n if (!imageId || imageId === emptyGuid) {\n return '';\n }\n const response = await get<string>(`${baseUrl}/${imageId}`, {\n responseType: 'arraybuffer',\n });\n if (response.status === 200) {\n const blob = new Blob([response.data], { type: response.headers['content-type'] });\n return URL.createObjectURL(blob);\n }\n\n throw new ServerError(`Failed to get logo.`, response.status);\n } catch (e) {\n throw e;\n }\n};\n","import { useQuery } from 'react-query';\nimport { getLogoUrl } from '@/api/logo';\nimport { getAccount } from '@/atoms/session/store';\nimport { useFetchCustomerPortalSettings } from './useFetchCustomerPortalSettings';\n\nexport const useFetchLogoUrl = () => {\n const account = getAccount();\n const { data: settings } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n\n return useQuery<string, Error>(\n ['logo-url', account?.accountId, account?.businessUnitId, settings?.companyLogoImageId],\n () => getLogoUrl(settings?.companyLogoImageId),\n {\n staleTime: Infinity,\n },\n );\n};\n","import { getAccount } from '@/atoms/session/store';\nimport { emptyGuid } from '@/common/constants';\nimport { useFetchCustomerPortalSettings } from '@/common/hooks/query/useFetchCustomerPortalSettings';\nimport { useMemo } from 'react';\n\nexport const useCompanyLogoExists = () => {\n const account = getAccount();\n const { data: settings } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n\n return useMemo(() => {\n return !!settings?.companyLogoImageId && settings?.companyLogoImageId != emptyGuid;\n }, [settings?.companyLogoImageId]);\n};\n","import { useBusinessUnitDetails } from '@/common/hooks/useBusinessUnitDetails';\nimport { Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useFetchLogoUrl } from '../../hooks/query/useFetchLogoUrl';\nimport { useCompanyLogoExists } from './useCompanyLogoExists';\n\nconst useStyles = makeStyles({\n logoImg: {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n overflow: 'hidden',\n width: '100%',\n height: '100%',\n },\n});\n\nexport function LogoDisplay() {\n const classes = useStyles();\n const businessUnitDetails = useBusinessUnitDetails();\n const companyLogoExists = useCompanyLogoExists();\n const { status, data: logoUrl } = useFetchLogoUrl();\n\n return (\n <>\n {!companyLogoExists && !!businessUnitDetails && (\n <Typography variant=\"h4\">{businessUnitDetails.name}</Typography>\n )}\n\n {companyLogoExists && status == 'success' && <img src={logoUrl} className={classes.logoImg}></img>}\n </>\n );\n}\n","import { LogoDisplay } from '@/common/components/LogoDisplay/LogoDisplay';\n\nexport function HeaderContent() {\n return <LogoDisplay />;\n}\n","import { Drawer } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { Sidebar } from './Sidebar';\n\nimport { FooterContent, HeaderContent } from './content';\nimport { List } from './List/List';\nimport { closeSidebar, useIsOpen } from './store';\n\nconst drawerWidth = 256;\n\nconst useStyles = makeStyles({\n drawer: {\n flexShrink: 0,\n width: drawerWidth,\n },\n drawerPaper: {\n width: drawerWidth,\n },\n});\n\nexport const SidebarDrawer = () => {\n const classes = useStyles();\n const isOpen = useIsOpen();\n const layout = useGetUILayout();\n\n return (\n <Drawer\n anchor=\"left\"\n className={classes.drawer}\n classes={{\n paper: classes.drawerPaper,\n }}\n data-testid=\"sidebar-drawer\"\n onClose={closeSidebar}\n open={isOpen}\n variant={layout == 'mobile' ? 'temporary' : 'permanent'}\n >\n <Sidebar\n data-testid=\"sidebar\"\n list={List}\n footerContent={<FooterContent />}\n headerContent={<HeaderContent />}\n />\n </Drawer>\n );\n};\n\nSidebarDrawer.displayName = 'SidebarDrawer';\n","import { mobileAppbarHeight } from '@/common/constants';\nimport { AppBar, IconButton, Toolbar, Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport MenuIcon from '@mui/icons-material/Menu';\n\nimport { useMobileGreeting } from '@/utils/hooks/useMobileGreeting';\nimport { SidebarDrawer } from '../sidebar/SidebarDrawer';\nimport { toggleSidebar } from '../sidebar/store';\nimport { Avatar } from './Avatar';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n background: theme.palette.white,\n height: `${mobileAppbarHeight}px`,\n },\n menuButton: {\n marginRight: theme.spacing(2),\n },\n title: {\n flexGrow: 1,\n },\n}));\n\nexport function AppHeaderMobile() {\n const classes = useStyles();\n const greeting = useMobileGreeting();\n\n return (\n <>\n <AppBar className={classes.root} position=\"fixed\">\n <Toolbar>\n <IconButton\n className={classes.menuButton}\n data-testid=\"btn-toggle-sidebar\"\n edge=\"start\"\n onClick={toggleSidebar}\n size=\"large\"\n >\n <MenuIcon />\n </IconButton>\n <Typography className={classes.title} variant=\"h6\" noWrap>\n {greeting}\n </Typography>\n <Avatar />\n </Toolbar>\n </AppBar>\n <SidebarDrawer />\n </>\n );\n}\n","import { Outlet } from 'react-router-dom';\n\nimport { AppHeaderDesktop } from '@/components/appHeader';\nimport { SidebarDrawer } from '@/components/sidebar/SidebarDrawer';\nimport makeStyles from '@mui/styles/makeStyles';\n\nconst drawerWidth = 256;\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n },\n appBar: {\n width: `calc(100% - ${drawerWidth}px)`,\n marginLeft: drawerWidth,\n },\n drawer: {\n width: drawerWidth,\n flexShrink: 0,\n },\n drawerPaper: {\n width: drawerWidth,\n },\n toolbar: theme.mixins.toolbar,\n content: {\n flexGrow: 1,\n backgroundColor: theme.palette.background.default,\n },\n}));\n\nexport function AppDesktop() {\n const classes = useStyles();\n\n return (\n <div className={classes.root}>\n <AppHeaderDesktop />\n <SidebarDrawer />\n <main className={classes.content}>\n <div className={classes.toolbar} />\n <Outlet />\n </main>\n </div>\n );\n}\n","import { Fragment } from 'react';\nimport { Outlet } from 'react-router-dom';\n\nimport { AppHeaderMobile } from '@/components/appHeader';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { mobileAppbarHeight } from '@/common/constants';\n\nconst useStyles = makeStyles({\n content: {\n height: `calc(100vh - ${mobileAppbarHeight}px)`,\n marginTop: `${mobileAppbarHeight}px`,\n overflowX: 'hidden',\n overflowY: 'hidden',\n },\n});\n\nexport function AppMobile() {\n const classes = useStyles();\n\n return (\n <Fragment>\n <AppHeaderMobile />\n <div className={classes.content}>\n <Outlet />\n </div>\n </Fragment>\n );\n}\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport { AppDesktop } from './AppDesktop';\nimport { AppMobile } from './AppMobile';\n\nexport function App() {\n const layout = useGetUILayout();\n\n switch (layout) {\n case 'desktop':\n return <AppDesktop />;\n\n case 'mobile':\n return <AppMobile />;\n }\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n unauthorized: translate({ id: `sections.forbidden.unauthorized` }),\n };\n }, [translate]);\n}\n","import Box from '@mui/material/Box';\n\nimport { ContentContainer } from '@/components/ContentContainer';\nimport { ContentPaper } from '@/components/ContentPaper';\n\nimport { useTexts } from './useTexts';\n\nexport function Forbidden() {\n const texts = useTexts();\n\n return (\n <ContentContainer>\n <ContentPaper fullWidth>\n <Box width=\"100%\" height=\"300px\" display=\"flex\" justifyContent=\"center\" alignItems=\"center\">\n {texts.unauthorized}\n </Box>\n </ContentPaper>\n </ContentContainer>\n );\n}\n","import type { FormError, FormField, FormState } from '../types';\n\nfunction throwError() {\n if (process.env.NODE_ENV === 'development') {\n throw new Error(`You cannot use a FormState Context without mounting a FormRoot component as an ancestor.`);\n }\n}\n\nconst safeNoop = () => void throwError();\nconst safeNoopBool = () => {\n throwError();\n return false;\n};\n\n/**\n * @private\n *\n * Helper function to create an empty placeholder for a Form State.\n * Used internally by the `Form React Context` as default value.\n *\n * @returns A valid Form State placeholder.\n */\nexport function createEmptyFormState(): FormState<Record<string, FormField>, FormError<string>> {\n return {\n api: {\n setDebugMode: safeNoop,\n\n getErrors: () => {\n throwError();\n return {};\n },\n getField: () => {\n throwError();\n return { value: '', status: 'pristine' };\n },\n registerField: () => {\n throwError();\n return false;\n },\n deregisterField: () => {\n throwError();\n },\n getFieldErrors: () => {\n throwError();\n return [];\n },\n getMeta: () => {\n throwError();\n return {\n disabled: false,\n submitting: false,\n validating: false,\n status: 'pristine',\n };\n },\n getValues: () => {\n throwError();\n return {};\n },\n getInitialValues: () => {\n throwError();\n return {};\n },\n\n reset: safeNoop,\n change: safeNoop,\n batch: safeNoop,\n\n setFieldVisibleState: safeNoop,\n setFieldDisabledState: safeNoop,\n setFieldRequiredState: safeNoop,\n\n addFormMutation: safeNoop,\n removeFormMutation: safeNoopBool,\n addFieldMutation: safeNoop,\n removeFieldMutation: safeNoopBool,\n\n setDisabled: safeNoop,\n setSubmitting: safeNoop,\n\n clearValidation: safeNoop,\n validate: async () => {\n throwError();\n return false;\n },\n addValidation: safeNoop,\n getValidator: safeNoop,\n removeValidation: safeNoopBool,\n\n subscribeToForm: () => safeNoop,\n subscribeToMeta: () => safeNoop,\n subscribeToField: () => safeNoop,\n\n removeAllListeners: safeNoop,\n },\n\n store: {\n id: '_____defaultEmptyState_____',\n initialValues: {},\n values: {},\n errors: {},\n fields: {},\n meta: {\n disabled: false,\n submitting: false,\n validating: false,\n\n status: 'pristine',\n },\n },\n };\n}\n","import type {\n FormField,\n FormApi,\n FormData,\n FormError,\n FormFieldMutation,\n FormMeta,\n FormMutation,\n FormState,\n FormValidator,\n FormValues,\n FormStatus,\n FormMode,\n} from './types';\nimport { castDraft, Draft, produce } from 'immer';\n\nexport type FormConfig<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>> = {\n mode?: FormMode;\n overrideValues?: Partial<FormValues<FIELDS>>;\n formMutations?: { id: string; mutation: FormMutation<FIELDS, ERROR> }[];\n fieldMutations?: { field: keyof FIELDS; mutation: FormFieldMutation<FIELDS, ERROR> }[];\n validations?: {\n id: string;\n validator: FormValidator<FIELDS, ERROR>;\n fields?: keyof FIELDS;\n }[];\n};\n\n// ---------------------------------------------------------------------------\n// Debug output styles\n// ---------------------------------------------------------------------------\n\nconst prefixStyles = [\n 'color: lightCoral',\n 'font-size: 12px',\n 'font-weight: bolder',\n 'padding-left: 10px',\n 'padding-right: 5px',\n].join(';');\n\nconst contextStyles = ['color: goldenRod', 'font-size: 12px', 'font-weight: bolder', 'padding-right: 10px'].join(';');\n\nconst emptyErrorArray = [];\n\n/**\n *\n * @param id Form unique identifier. Used for debug purposes and for React Context access.\n * @param baseFields Form Fields configuration.\n * @param config Optional Advanced configuration.\n * @returns A valid FormState object, exposing the Form public API and direct access to the internal `store`. The `store` is meant to be used only by provided `React hooks` or advanced usage. It must be considered `readonly`.\n */\nexport function createForm<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>>(\n id: string,\n baseFields?: FIELDS,\n config?: FormConfig<FIELDS, ERROR>,\n): FormState<FIELDS, ERROR> {\n // ---------------------------------------------------\n // Form Mede\n // ---------------------------------------------------\n\n function isStrictMode() {\n return config?.mode === 'strict';\n }\n\n function isDynamicMode() {\n return config?.mode !== 'strict';\n }\n\n // ---------------------------------------------------\n // Debug API\n // ---------------------------------------------------\n\n let debugMode: 'silent' | 'verbose' = 'silent';\n\n /**\n * Debug helper used to print out detailed internal events in the browser console.\n * Disabled by default, can be enabled through the public form API.\n *\n * @param context Main identifier, rendered in a different color\n * @param args whatever must be printed to the browser console output\n */\n function log(context: string, ...args: any[]) {\n if (debugMode === 'verbose') {\n console.log(`%c[${id}] %c${context}`, prefixStyles, contextStyles, ...args);\n }\n }\n\n // ---------------------------------------------------\n // Store initialization\n // ---------------------------------------------------\n\n /**\n * Helper function used to initialize the Form internal store.\n * It takes care of initializing Fields values and their initial values.\n * It also adds sane defaults for provided Fields for missing keys.\n */\n function createStore(): FormData<FIELDS, ERROR> {\n const fields = baseFields\n ? produce(baseFields, draft => {\n if (config?.overrideValues) {\n for (const [key, value] of Object.entries(config.overrideValues)) {\n draft[key].value = value;\n\n // when a value override is provided also the `initialValue` will change\n draft[key].initialValue = value;\n }\n }\n\n // force sane default values for omitted Field properties\n for (const key of Object.keys(draft)) {\n draft[key].initialValue ??= draft[key].value;\n\n draft[key].visible ??= true;\n draft[key].disabled ??= false;\n draft[key].required ??= false;\n draft[key].validating ??= false;\n draft[key].status ??= 'pristine';\n }\n })\n : // If `baseFields` is missing set the form to an empty object\n ({} as FIELDS);\n\n const initialValues = {} as FormValues<FIELDS>;\n let initialStatus: FormStatus = 'pristine';\n\n for (const [key, field] of Object.entries(fields)) {\n initialValues[key as keyof FIELDS] = field.value;\n\n // TODO: should it properly reduce also to valid|invalid?\n initialStatus = field.status !== 'pristine' ? 'indeterminate' : initialStatus;\n }\n\n return {\n id,\n initialValues,\n values: { ...initialValues },\n\n fields,\n errors: {},\n\n meta: {\n disabled: false,\n submitting: false,\n validating: false,\n\n status: initialStatus,\n },\n };\n }\n\n /**\n * Form internal Store state.\n * This object should never been modified directly but always through `immer`,\n * and only it's properties. Never the object itself.\n */\n const store = createStore();\n\n // ---------------------------------------------------\n // Store maintenance\n // ---------------------------------------------------\n\n /**\n * Helper used by the Form `reset` API.\n *\n * @param mode Update fields mode. `preserve` updates the provided fields initial values but leaves untouched the current field values and states.\n * @param initialValues Partial object of new initial values for the Form Fields.\n */\n function updateFieldInitialValues(mode: 'force' | 'preserve', initialValues?: Partial<FormValues<FIELDS>>) {\n if (initialValues) {\n store.initialValues = produce(store.initialValues, draft => {\n for (const [fieldName, value] of Object.entries(initialValues)) {\n draft[fieldName] = value;\n }\n });\n }\n\n store.fields = produce(store.fields, draft => {\n for (const [fieldName, field] of Object.entries(draft)) {\n if (mode === 'force') {\n field.value = store.initialValues[fieldName as keyof FormValues<FIELDS>];\n field.status = 'pristine';\n }\n }\n });\n\n store.values = produce(store.values, draft => {\n for (const fieldName of Object.keys(draft)) {\n draft[fieldName] = store.fields[fieldName as keyof FIELDS].value;\n }\n });\n }\n\n // ---------------------------------------------------\n // Private State\n // ---------------------------------------------------\n\n // Stable map of Errors grouped by Fields. The Map is updated every time any error change, is added, or deleted.\n const errorsByField: Map<keyof FIELDS, ERROR[]> = new Map();\n\n /**\n * Flag used to monitor any global validation running.\n * All Fields validations store their running status in the Field itself but there's non Field for global validations.\n * Hence this variable.\n */\n let globalValidationRunning = false;\n\n // Validator functions mapped by their unique ID\n const validatorsById: Map<string, FormValidator<FIELDS, ERROR>> = new Map();\n\n // Inverse Map connecting Validator functions to their IDs\n const validatorIdByFunction: Map<FormValidator<FIELDS, ERROR>, string> = new Map();\n\n // Validator functions mapped by their fields, or global.\n const validatorsByField: Map<keyof FIELDS, Set<FormValidator<FIELDS, ERROR>>> = new Map();\n\n /**\n * Map of running async validations. Every async validation register itself when it starts.\n * Only the latest ticket is kept. All the stale validations are simply ignored.\n */\n const activeAsyncValidation: Map<FormValidator<FIELDS, ERROR>, number> = new Map();\n\n /**\n * Map of all the running async validation grouped per Field.\n * This map is used to track when all async validations of a given Field have finished.\n */\n const runningValidationsByField: Map<keyof FIELDS, Set<string>> = new Map();\n\n // ---------------------------------------------------\n // Batched validation\n // ---------------------------------------------------\n\n /**\n * Active validation Promise.\n * Every time a new validation is requested the invoker receives a Promise.\n * The Form keep only a single validation Promise at time and it resolves it when all the running\n * async validations complete.\n */\n let validationPending: Promise<boolean> | undefined;\n\n /**\n * Helper function used to resolve the pending Promise for batched notification of running async validations.\n */\n let resolvePendingValidation: (value: boolean) => void = () => undefined;\n\n /**\n * Helper function used by `api.validate`.\n * @returns A batched Promise that will resolve when all pending async validations will complete. If no async validation is running it will resolve immediately.\n */\n function waitForValidation() {\n if (!store.meta.validating) {\n const isValid = store.meta.status === 'valid';\n\n log('resolvePendingValidation SYNC', isValid);\n\n if (validationPending) {\n resolvePendingValidation(isValid);\n }\n\n return Promise.resolve(isValid);\n }\n\n if (!validationPending) {\n validationPending = new Promise<boolean>(resolve => {\n resolvePendingValidation = (value: boolean) => {\n log('resolvePendingValidation ASYNC', value);\n\n resolve(value);\n\n // reset the resolver\n resolvePendingValidation = () => undefined;\n\n // clear the pending promise\n validationPending = undefined;\n };\n });\n }\n\n return validationPending;\n }\n\n // ---------------------------------------------------\n // Fields Mutation\n // ---------------------------------------------------\n\n /**\n * Map of all registered Form Mutations.\n */\n const formMutations: Map<string, FormMutation<FIELDS, ERROR>> = new Map();\n\n /**\n * Map of all registered Field Mutations. Only one Mutation per Field is allowed.\n */\n const fieldMutations: Map<keyof FIELDS, FormFieldMutation<FIELDS, ERROR>> = new Map();\n\n /**\n * Helper function used to process Fields mutations after one or more Form Fields change through the Form API.\n *\n * @param initialChangedValues Object containing changed field values\n * @param fieldToSkip Optional field that should not apply its registered Field Mutation. Required for Single Field changes to avoid self-induced mutations.\n * @returns Object of changed field values including applied field and form mutations.\n */\n function applyMutations<FIELD_NAME extends keyof FIELDS>(\n initialChangedValues: Partial<FormValues<FIELDS>>,\n fieldToSkip?: FIELD_NAME,\n ): Partial<FormValues<FIELDS>> {\n const changedValues = { ...initialChangedValues };\n\n // Apply all Fields mutations.\n // ATTENTION: The order doesn't matter unless there are chained Field mutations. That should be discouraged.\n // For dependant or chained Mutations a user should opt to create a Form Mutation.\n for (const [targetFieldName, fieldMutation] of fieldMutations) {\n // skip the mutation for the original changed field, if provided\n if (fieldToSkip && targetFieldName === fieldToSkip) continue;\n\n if (fieldMutation) {\n const mutatedValue = fieldMutation(api, changedValues, initialChangedValues, targetFieldName);\n\n if (store.fields[targetFieldName].value !== mutatedValue) {\n // if the mutation output differs from the current Form values the Changes Map it's updated\n changedValues[targetFieldName] = mutatedValue;\n } else {\n // if the mutation output equals to the current Form values the field is removed from the Changes Map\n delete changedValues[targetFieldName as string];\n }\n }\n }\n\n // Apply all Form Mutations.\n // ATTENTION: All Form Mutations are applied in their registration order.\n // Complex scenario should be resolved inside a single Form Mutation.\n for (const [, formMutation] of formMutations) {\n const mutatedValues = formMutation(api, changedValues, initialChangedValues);\n\n if (mutatedValues) {\n // shallow diff to prune out unmodified fields\n for (const [targetFieldName, mutatedValue] of Object.entries(mutatedValues)) {\n if (store.fields[targetFieldName].value !== mutatedValue) {\n // if the mutation output differs from the current Form values the Changes Map it's updated\n changedValues[targetFieldName as keyof FIELDS] = mutatedValue;\n } else {\n // if the mutation output equals to the current Form values the field is removed from the Changes Map\n delete changedValues[targetFieldName];\n }\n }\n }\n }\n\n return changedValues;\n }\n\n // ---------------------------------------------------\n // Pub-Sub subscriptions\n // ---------------------------------------------------\n\n type FieldSubscription = [\n field: keyof FIELDS,\n subscriber: (\n field: Readonly<FIELDS[keyof FIELDS]>,\n errors: Readonly<FormError<keyof FIELDS>[]>,\n api: Readonly<FormApi<FIELDS, ERROR>>,\n ) => void,\n ];\n\n /**\n * Collection of subscribers to a Field's update.\n * A subscription is linked to a single Field.\n */\n const fieldSubscribers = new Set<FieldSubscription>();\n\n // ----------------------------\n\n type FormSubscription = (api: Readonly<FormApi<FIELDS, ERROR>>) => void;\n\n /**\n * Collection of subscribers to any From update.\n */\n const formSubscribers = new Set<FormSubscription>();\n\n // ----------------------------\n\n type FormMetaSubscription = (meta: Readonly<FormMeta>, api: Readonly<FormApi<FIELDS, ERROR>>) => void;\n\n /**\n * Collection of subscribers interested only when the From Meta states change.\n */\n const formMetaSubscribers = new Set<FormMetaSubscription>();\n\n // ---------------------------------------------------\n // Form notifications\n // ---------------------------------------------------\n\n /**\n * Batched Form Notification\n * All notification emitted to Form Subscriptions are batched.\n */\n let notifyFormSubscribersPending: Promise<void> | undefined;\n\n /**\n * Helper function used to notify Form Subscribers.\n * The notification is batched.\n */\n function notifyFormSubscribers() {\n if (!notifyFormSubscribersPending) {\n notifyFormSubscribersPending = Promise.resolve().then(() => {\n log('notifyFormSubscribers');\n\n formSubscribers.forEach(subscriber => {\n subscriber(api);\n });\n\n notifyFormSubscribersPending = undefined;\n });\n }\n\n return notifyFormSubscribersPending;\n }\n\n // ---------------------------------------------------\n // Form META notifications\n // ---------------------------------------------------\n\n /**\n * Batched Form Meta Notification\n * All notification emitted to Form Meta Subscriptions are batched.\n */\n let notifyMetaSubscribersPending: Promise<void> | undefined;\n\n /**\n * Helper function used to notify Form Meta Subscribers.\n * The notification is batched.\n */\n function notifyMetaSubscribers() {\n if (!notifyMetaSubscribersPending) {\n notifyMetaSubscribersPending = Promise.resolve().then(() => {\n const meta = api.getMeta();\n\n log('notifyMetaSubscribers');\n\n formMetaSubscribers.forEach(subscriber => {\n subscriber(meta, api);\n });\n\n notifyMetaSubscribersPending = undefined;\n });\n }\n\n return notifyMetaSubscribersPending;\n }\n\n // ---------------------------------------------------\n // Fields notifications\n // ---------------------------------------------------\n\n /**\n * Helper function used to notify all Field Subscribers for a specific Field.\n */\n function notifyFieldSubscriber<FIELD_NAME extends keyof FIELDS>(fieldName: FIELD_NAME) {\n if (store.fields[fieldName]) {\n const field = api.getField(fieldName);\n const errors = api.getFieldErrors(fieldName);\n\n log('notifyFieldSubscriber', fieldName);\n\n fieldSubscribers.forEach(([subName, subscriber]) => {\n if (fieldName === subName) {\n subscriber(field, errors, api);\n }\n });\n }\n }\n\n /**\n * Helper function used to notify all Field Subscribers of a list of changed Fields.\n */\n function notifyFieldSubscribers(fieldNames: (keyof FIELDS)[]) {\n for (const fieldName of fieldNames) {\n notifyFieldSubscriber(fieldName);\n }\n }\n\n // ---------------------------------------------------\n // Store and internal State helpers\n // ---------------------------------------------------\n\n /**\n * Helper function used to refresh the Form Meta `validating` flag.\n * Invoked by the validation logic, after an async validation starts or completes.\n *\n * @param silent Optional flag to prevent the function to notify Form and Form Meta subscribers.\n * @returns A boolean value. When true it means the value of `form.meta.validating` has changed.\n */\n function refreshFormMetaValidatingState(silent?: boolean): boolean {\n const validating = globalValidationRunning || Object.values(store.fields).some(field => field.validating);\n\n log('refreshFormMetaValidatingState');\n\n if (validating !== store.meta.validating) {\n store.meta = produce(store.meta, draft => {\n draft.validating = validating;\n });\n\n // TODO: considering that Form level notification are batched the silent flag could be removed\n if (!silent) {\n notifyMetaSubscribers();\n notifyFormSubscribers();\n }\n\n return true;\n }\n\n return false;\n }\n\n /**\n * Helper function used to refresh a Form Field `status`.\n *\n * @param fieldsToValidate Target Field name\n * @param silent Optional flag to prevent the function to notify Form and Field subscribers.\n * @returns A boolean value. When true it means the value of `form.meta.validating` has changed.\n */\n function refreshFieldsStatus(fieldsToValidate: (keyof FIELDS)[], silent?: boolean): boolean {\n log('refreshFieldsStatus', fieldsToValidate);\n\n // update single fields validity status\n type ReducedErrors = { [key in keyof FIELDS]: true };\n const reducedErrors = Object.values(store.errors).reduce<ReducedErrors>((acc, error) => {\n // update only fields under active validation\n if (fieldsToValidate.includes(error.field)) {\n acc[error.field] ??= true;\n }\n\n return acc;\n }, {} as ReducedErrors);\n\n const prevStoreFields = store.fields;\n\n store.fields = produce(store.fields, draft => {\n for (const [fieldName, field] of Object.entries(draft)) {\n if (fieldsToValidate.includes(fieldName)) {\n const hasErrors = reducedErrors[fieldName];\n field.status = hasErrors ? 'invalid' : 'valid';\n }\n }\n });\n\n let changed = false;\n for (const [fieldName, field] of Object.entries(store.fields)) {\n const prevFieldStatus = prevStoreFields[fieldName].status;\n\n if (field.status !== prevFieldStatus) {\n changed = true;\n\n if (!silent) {\n notifyFieldSubscriber(fieldName);\n }\n }\n }\n\n // TODO: considering that Form level notification are batched the silent flag could be removed\n if (changed && !silent) {\n notifyFormSubscribers();\n }\n\n return changed;\n }\n\n /**\n * Helper function that keep the Form errors updated.\n * It affects both `store.errors` and `errorsByField`.\n *\n * @param validation Validation result as provided by a registered Form Validator.\n */\n function updateStoreErrors(validation: Record<string, ERROR | null>) {\n const affectedFieldNames = new Set<keyof FIELDS>();\n\n // update the main errors map\n store.errors = produce<Record<string, ERROR>>(store.errors, draft => {\n for (const [errorId, value] of Object.entries(validation)) {\n const currentError = draft[errorId];\n\n if (value) {\n affectedFieldNames.add(value.field);\n } else if (currentError && typeof currentError.field === 'string') {\n affectedFieldNames.add(currentError.field);\n }\n\n if (value === null) {\n // remove nullified Errors\n delete draft[errorId];\n } else {\n // updated/add still existing errors\n draft[errorId] = castDraft(value);\n }\n }\n });\n\n log('updateStoreErrors', affectedFieldNames);\n\n for (const fieldName of affectedFieldNames) {\n // fetch or initialize the interested Field array of errors\n const errorsList = errorsByField.get(fieldName) ?? [];\n\n // update the stored array of errors\n errorsByField.set(\n fieldName,\n produce(errorsList, draft => {\n for (const [errorId, value] of Object.entries(validation)) {\n // find for a matching existent error instance\n const index = draft.findIndex(err => err.id === errorId);\n\n if (index > -1) {\n // always remove the previous instance of a given error\n draft.splice(index, 1);\n }\n\n if (value !== null) {\n // add the error again if it's not NULL\n draft.push(castDraft(value));\n }\n }\n\n // sort the Field's errors by priority\n draft.sort(({ priority: prev = 0 }, { priority: next = 0 }) => {\n return next - prev;\n });\n }),\n );\n }\n }\n\n /**\n * Helper function used to refresh the Form Meta `status`.\n *\n * @param silent Optional flag to prevent the function to notify Form and Field subscribers.\n * @returns A boolean value. When true it means the value of `form.meta.validating` has changed.\n */\n function refreshFormStatus(silent?: boolean) {\n type Meta = {\n pristine: boolean;\n indeterminate: boolean;\n valid: boolean;\n invalid: boolean;\n };\n\n // reduce all Form Fields status and flag to a finite set of boolean values\n const meta = Object.values(store.fields).reduce<Meta>(\n (acc, field) => {\n const { pristine, indeterminate, valid, invalid } = acc;\n\n return {\n valid: valid && field.status === 'valid',\n invalid: invalid || field.status === 'invalid',\n pristine: pristine && field.status === 'pristine',\n indeterminate: indeterminate || field.status === 'indeterminate',\n };\n },\n {\n pristine: true,\n indeterminate: false,\n valid: true,\n invalid: false,\n },\n );\n\n // compute the next Form Status\n const nextStatus: FormStatus = meta.pristine\n ? 'pristine'\n : meta.valid\n ? 'valid'\n : meta.invalid\n ? 'invalid'\n : 'indeterminate';\n\n log('refreshFormStatus', nextStatus);\n\n if (nextStatus !== store.meta.status) {\n store.meta = produce(store.meta, draft => {\n draft.status = nextStatus;\n });\n\n // TODO: considering that Form level notification are batched the silent flag could be removed\n if (!silent) {\n notifyMetaSubscribers();\n notifyFormSubscribers();\n }\n\n return true;\n }\n\n return false;\n }\n\n // ---------------------------------------------------\n // ---------------------------------------------------\n\n /**\n * Return a field or create it if doesn't exist yet.\n *\n * @param fieldName Name of the field to add\n * @param value Optional value for the field\n * @returns the generated Field or the already existent one.\n */\n function tryToAddDynamicField<FIELD_NAME extends keyof FIELDS>(\n fieldName: FIELD_NAME,\n value?: FIELDS[FIELD_NAME]['value'],\n ): Readonly<FIELDS[FIELD_NAME]> {\n if (store.fields[fieldName]) {\n return store.fields[fieldName];\n }\n\n store.fields = produce(store.fields, draft => {\n const draftFieldName = fieldName as keyof Draft<FIELDS>;\n\n draft[draftFieldName] = {\n value: value,\n initialValue: undefined,\n visible: true,\n disabled: false,\n required: false,\n validating: false,\n status: 'pristine',\n } as Draft<FIELDS>[keyof Draft<FIELDS>];\n });\n\n store.values = produce(store.values, draft => {\n Object.assign(draft, { [fieldName]: store.fields[fieldName].value });\n });\n\n notifyFieldSubscribers([fieldName]);\n\n refreshFormStatus();\n\n notifyMetaSubscribers();\n notifyFormSubscribers();\n\n return store.fields[fieldName];\n }\n\n // ---------------------------------------------------\n // Main API\n // ---------------------------------------------------\n\n const api: Readonly<FormApi<FIELDS, ERROR>> = {\n // ------------------------------------------\n // UTILITIES\n // ------------------------------------------\n\n setDebugMode: mode => {\n debugMode = mode;\n },\n\n // ------------------------------------------\n // ERRORS\n // ------------------------------------------\n\n getErrors: () => {\n return store.errors;\n },\n\n // @ts-expect-error: TS is unable to reconcile ERROR[] with FormError<FIELD_NAME >[]\n getFieldErrors: fieldName => {\n const field = store.fields[fieldName];\n\n if (!field) {\n if (isStrictMode()) {\n throw new Error(\n `Trying to access an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n // if the field doesn't exists always return a placeholder array\n return emptyErrorArray;\n }\n\n const fieldErrors = errorsByField.get(fieldName) ?? [];\n errorsByField.set(fieldName, fieldErrors);\n\n return fieldErrors;\n },\n\n // ------------------------------------------\n // FIELDS\n // ------------------------------------------\n\n registerField: (fieldName, field) => {\n if (isStrictMode()) {\n throw new Error(`Trying to register a field: ${fieldName} with strict mode enabled. This is a no-op.`);\n }\n\n if (store.fields[fieldName]) {\n return false;\n }\n\n store.fields = produce(store.fields, draft => {\n const draftFieldName = fieldName as keyof Draft<FIELDS>;\n const draftField = castDraft(field) as Draft<FIELDS>[keyof Draft<FIELDS>];\n\n draft[draftFieldName] = { ...draftField };\n\n // apply sane default values\n draft[draftFieldName].initialValue ??= field.value;\n draft[draftFieldName].visible ??= true;\n draft[draftFieldName].disabled ??= false;\n draft[draftFieldName].required ??= false;\n draft[draftFieldName].validating ??= false;\n draft[draftFieldName].status ??= 'pristine';\n });\n\n store.values = produce(store.values, draft => {\n Object.assign(draft, { [fieldName]: store.fields[fieldName].value });\n });\n\n notifyFieldSubscribers([fieldName]);\n\n refreshFormStatus();\n\n notifyMetaSubscribers();\n notifyFormSubscribers();\n\n return true;\n },\n\n deregisterField: (fieldName, destroy = false) => {\n if (isStrictMode()) {\n throw new Error(\n `Trying to deregister a field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n if (destroy) {\n // ---------------------------------------\n // clear field subscriptions\n\n for (const subscription of fieldSubscribers) {\n const [field] = subscription;\n\n if (field === fieldName) {\n fieldSubscribers.delete(subscription);\n }\n }\n\n // ---------------------------------------\n // clear field validations\n\n const validators = validatorsByField.get(fieldName);\n if (validators) {\n for (const validator of validators) {\n const id = validatorIdByFunction.get(validator);\n\n if (id) validatorsById.delete(id);\n validatorIdByFunction.delete(validator);\n }\n }\n validatorsByField.delete(fieldName);\n\n // ---------------------------------------\n // clear field-level mutations\n\n fieldMutations.delete(fieldName);\n }\n\n // ---------------------------------------\n // Remove all Fields data form the FormData\n\n store.fields = produce(store.fields, draft => {\n const draftFieldName = fieldName as keyof Draft<FIELDS>;\n delete draft[draftFieldName];\n });\n\n store.values = produce(store.values, draft => {\n const draftFieldName = fieldName as keyof Draft<FormValues<FIELDS>>;\n delete draft[draftFieldName];\n });\n\n store.initialValues = produce(store.initialValues, draft => {\n const draftFieldName = fieldName as keyof Draft<FormValues<FIELDS>>;\n delete draft[draftFieldName];\n });\n\n store.errors = produce(store.errors, draft => {\n for (const [errorId, error] of Object.entries(draft)) {\n if (error.field === fieldName) {\n delete draft[errorId];\n }\n }\n });\n\n errorsByField.delete(fieldName);\n\n notifyFieldSubscribers([fieldName]);\n\n // refresh form status and notify subscribers\n refreshFormStatus();\n\n notifyMetaSubscribers();\n notifyFormSubscribers();\n },\n\n getField: fieldName => {\n if (store.fields[fieldName]) {\n return store.fields[fieldName];\n }\n\n if (isStrictMode()) {\n throw new Error(\n `Trying to access an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n return tryToAddDynamicField(fieldName);\n },\n\n getValues: () => {\n return store.values;\n },\n\n getInitialValues: () => {\n return store.initialValues;\n },\n\n // ------------------------------------------\n // CHANGE VALUES\n // ------------------------------------------\n\n change: (fieldName, value) => {\n log('change', fieldName);\n\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to write an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n const initialChangedValues = {\n [fieldName]: value,\n } as Partial<FormValues<FIELDS>>;\n\n const changedValues = applyMutations(initialChangedValues, fieldName);\n\n store.fields = produce(store.fields, draft => {\n for (const [targetFieldName, fieldValue] of Object.entries(changedValues)) {\n // if the field doesn't exist let's add it\n if (!draft[targetFieldName]) {\n draft[targetFieldName as keyof Draft<FIELDS>] = {\n value: fieldValue,\n initialValue: undefined,\n visible: true,\n disabled: false,\n required: false,\n validating: false,\n status: 'indeterminate',\n } as Draft<FIELDS>[keyof Draft<FIELDS>];\n } else {\n draft[targetFieldName].value = fieldValue;\n draft[targetFieldName].status = 'indeterminate';\n }\n }\n });\n\n store.values = produce(store.values, draft => {\n Object.assign(draft, changedValues);\n });\n\n notifyFieldSubscribers(Object.keys(changedValues));\n\n refreshFormStatus();\n notifyFormSubscribers();\n },\n\n batch: fields => {\n log('batch', fields);\n\n const initialChangedValues: Partial<FormValues<FIELDS>> = {};\n\n for (const [fieldName, value] of Object.entries(fields)) {\n initialChangedValues[fieldName as keyof FIELDS] = value;\n\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to write an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n }\n\n const changedValues = applyMutations(initialChangedValues);\n\n store.fields = produce(store.fields, draft => {\n for (const [targetFieldName, fieldValue] of Object.entries(changedValues)) {\n // if the field doesn't exist let's add it\n if (!draft[targetFieldName]) {\n draft[targetFieldName as keyof Draft<FIELDS>] = {\n value: fieldValue,\n initialValue: undefined,\n visible: true,\n disabled: false,\n required: false,\n validating: false,\n status: 'indeterminate',\n } as Draft<FIELDS>[keyof Draft<FIELDS>];\n } else {\n draft[targetFieldName].value = fieldValue;\n draft[targetFieldName].status = 'indeterminate';\n }\n }\n });\n\n store.values = produce(store.values, draft => {\n Object.assign(draft, changedValues);\n });\n\n notifyFieldSubscribers(Object.keys(changedValues));\n\n refreshFormStatus();\n notifyFormSubscribers();\n },\n\n reset: (mode = 'preserve', initialValues, silent) => {\n log('reset', mode);\n\n updateFieldInitialValues(mode, initialValues);\n\n refreshFormStatus(silent);\n\n if (!silent) {\n notifyFieldSubscribers(Object.keys(store.fields));\n notifyMetaSubscribers();\n notifyFormSubscribers();\n }\n },\n\n // ------------------------------------------\n // FIELD META STATE\n // ------------------------------------------\n\n setFieldDisabledState: (fieldName, value) => {\n log('setFieldDisabledState', fieldName, value);\n\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to write the disabled state for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n if (isDynamicMode()) {\n // ensure the field exist\n tryToAddDynamicField(fieldName);\n }\n\n const prevDisabled = store.fields[fieldName].disabled;\n\n store.fields = produce(store.fields, draft => {\n draft[fieldName as keyof Draft<FIELDS>].disabled = value;\n });\n\n if (prevDisabled !== store.fields[fieldName].disabled) {\n notifyFieldSubscriber(fieldName);\n notifyFormSubscribers();\n }\n },\n\n setFieldVisibleState: (fieldName, value) => {\n log('setFieldVisibleState', fieldName, value);\n\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to write the visible state for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n if (isDynamicMode()) {\n // ensure the field exist\n tryToAddDynamicField(fieldName);\n }\n\n const prevVisible = store.fields[fieldName].visible;\n\n store.fields = produce(store.fields, draft => {\n draft[fieldName as keyof Draft<FIELDS>].visible = value;\n });\n\n if (prevVisible !== store.fields[fieldName].visible) {\n notifyFieldSubscriber(fieldName);\n notifyFormSubscribers();\n }\n },\n\n setFieldRequiredState: (fieldName, value) => {\n log('setFieldRequiredState', fieldName, value);\n\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to write the required state for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n if (isDynamicMode()) {\n // ensure the field exist\n tryToAddDynamicField(fieldName);\n }\n\n store.fields = produce(store.fields, draft => {\n draft[fieldName as keyof Draft<FIELDS>].required = value;\n\n // changing the REQUIRED state will affect the validation of the field. It's marked to be validate again.\n draft[fieldName as keyof Draft<FIELDS>].status = 'indeterminate';\n });\n\n notifyFieldSubscriber(fieldName);\n\n refreshFormStatus();\n notifyFormSubscribers();\n },\n\n // ------------------------------------------\n // MUTATIONS\n // ------------------------------------------\n\n addFormMutation: (id, mutation) => {\n if (formMutations.has(id)) {\n throw new Error(`Trying to register a Form Mutation with ID: ${id} but it's already registered.`);\n }\n\n formMutations.set(id, mutation);\n },\n\n removeFormMutation: id => {\n return formMutations.delete(id);\n },\n\n addFieldMutation: (fieldName, mutation) => {\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to register a field-level mutation for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n if (fieldMutations.has(fieldName)) {\n console.warn(`Overwriting the Form Mutation registered for the field: ${fieldName}.`);\n }\n\n fieldMutations.set(fieldName, mutation);\n },\n\n removeFieldMutation: fieldName => {\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to remove a field-level mutation for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n return fieldMutations.delete(fieldName);\n },\n\n // ------------------------------------------\n // META STATES\n // ------------------------------------------\n\n getMeta: () => {\n return store.meta;\n },\n\n setDisabled: value => {\n log('setDisabled', value);\n\n store.meta = produce(store.meta, draft => {\n draft.disabled = value;\n });\n\n notifyFieldSubscribers(Object.keys(store.fields));\n notifyMetaSubscribers();\n notifyFormSubscribers();\n },\n\n setSubmitting: value => {\n log('setSubmitting', value);\n\n store.meta = produce(store.meta, draft => {\n draft.submitting = value;\n });\n\n notifyFieldSubscribers(Object.keys(store.fields));\n notifyMetaSubscribers();\n notifyFormSubscribers();\n },\n\n // ------------------------------------------\n // VALIDATION\n // ------------------------------------------\n\n clearValidation: (...userFields) => {\n log('clearValidation', userFields);\n\n const targetFields: (keyof FIELDS)[] = userFields.length > 0 ? userFields : Object.keys(store.fields);\n\n store.errors = produce(store.errors, draft => {\n for (const fieldName of Object.keys(draft)) {\n if (targetFields.includes(fieldName)) {\n delete draft[fieldName];\n }\n }\n });\n\n store.fields = produce(store.fields, draft => {\n for (const [fieldName, field] of Object.entries(draft)) {\n if (targetFields.includes(fieldName)) {\n field.status = 'indeterminate';\n notifyFieldSubscriber(fieldName);\n }\n }\n });\n\n refreshFormStatus();\n notifyFormSubscribers();\n },\n\n validate: (...userFields) => {\n log('validate', userFields);\n\n // resolve which fields will be validated\n const fieldsToValidate: (keyof FIELDS)[] = userFields.length > 0 ? userFields : Object.keys(store.fields);\n\n // always add the special FIELD `global` to any validation\n const fieldsToValidateAndGlobal = [...fieldsToValidate, 'global'];\n\n // Iterate over all fields to validate\n fieldsValidation: for (const fieldName of fieldsToValidateAndGlobal) {\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to validate an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n // access and/or initialize the list of running validation for the Field\n const runningValidations = runningValidationsByField.get(fieldName) ?? new Set();\n runningValidationsByField.set(fieldName, runningValidations);\n\n // retrieve all registered validators for the Field\n const validators = validatorsByField.get(fieldName);\n\n // if no validation exist move to the next Field\n if (!validators) continue fieldsValidation;\n\n // Unique ticket for async validations\n const validationTicket = performance.now();\n\n // Iterate over the registered validator functions for the Field\n validationLoop: for (const validator of validators) {\n // Always pass the name of the Field under validation unless it's `global`\n const validatorFieldName = fieldName === 'global' ? undefined : fieldName;\n\n // Run the validation\n const validation = validator(api, validatorFieldName);\n\n // If the Validation returns `undefined` move to the next validation\n if (!validation) continue validationLoop;\n\n // retrieve the Unique ID used to register the validation\n const validatorId = validatorIdByFunction.get(validator);\n if (!validatorId) {\n throw new Error(`Impossible to retrieve validator ID for function: ${validator.toString()}`);\n }\n\n // If the validation returns a Promise it means it's async, otherwise will be treated as sync.\n if (validation instanceof Promise) {\n // -------------------------------------------------\n // ASYNC VALIDATION\n // -------------------------------------------------\n\n // Record the running validator function with the current unique ticket\n activeAsyncValidation.set(validator, validationTicket);\n\n // Add the validation ID to the list of running validation for the Field\n runningValidations.add(validatorId);\n\n if (fieldName === 'global') {\n // for global validation set the Global Validation Flag to true\n globalValidationRunning = true;\n } else {\n // For Fields validation set the target Field `validating` flag to true\n store.fields = produce(store.fields, draft => {\n draft[fieldName as string].validating = true;\n });\n\n notifyFieldSubscriber(fieldName);\n }\n\n // Recompute the Form validating status\n refreshFormMetaValidatingState();\n\n // wait for the resolution of the async validation\n validation\n .then(validationResult => {\n // retrieve the registered ticket for the validator function\n const latestValidationTicket = activeAsyncValidation.get(validator);\n\n // stop if a more recent validation happened\n if (latestValidationTicket !== validationTicket) return;\n\n if (validationResult) {\n // if an errors Map it's returned process it\n\n // Dev warning, the registered Validation ID is a reserved error name, used to expose un-managed exceptions\n // during the async validation execution.\n if (\n process.env.NODE_ENV === 'development' &&\n validationResult.hasOwnProperty(validatorId)\n ) {\n console.warn(\n `[Form State] Using a validation function UID as an error ID is a noop. (${validatorId})`,\n );\n }\n\n // always ensure the reserved validation ID it's cleared after a successful validation\n const val = {\n ...validationResult,\n [validatorId]: null,\n } as Record<string, ERROR | null>;\n\n // refresh the Field's stored errors\n updateStoreErrors(val);\n } else {\n const val = { [validatorId]: null };\n\n // always ensure the reserved validation ID it's cleared after a successful validation\n updateStoreErrors(val);\n }\n\n // remove the validation from the list of running async validations for the Field\n runningValidations.delete(validatorId);\n\n // When the list of running async validation for the Field it's empty\n // set the Field's validating state to FALSE\n if (runningValidations.size === 0) {\n if (fieldName === 'global') {\n globalValidationRunning = false;\n } else {\n store.fields = produce(store.fields, draft => {\n draft[fieldName as string].validating = false;\n });\n }\n }\n\n // clear the queue of running validations\n activeAsyncValidation.delete(validator);\n\n if (fieldName === 'global') {\n // update single fields validity status\n refreshFieldsStatus(fieldsToValidate, true);\n\n notifyFieldSubscribers(fieldsToValidate);\n } else {\n // update single fields validity status\n refreshFieldsStatus([fieldName], true);\n\n notifyFieldSubscriber(fieldName);\n }\n\n // Recompute the Form validating status\n refreshFormMetaValidatingState();\n\n // Recompute the Form status\n refreshFormStatus();\n\n notifyFormSubscribers();\n\n if (!store.meta.validating) {\n // after refreshing the form validating state notify pending validation listeners\n // if all the async validation for the Fields have completed\n resolvePendingValidation(store.meta.status === 'valid');\n }\n })\n .catch(reason => {\n // retrieve the registered ticket for the validator function\n const latestValidationTicket = activeAsyncValidation.get(validator);\n\n // stop if a more recent validation happened\n if (latestValidationTicket !== validationTicket) return;\n\n // Try to infer the best error message\n const errorMessage =\n typeof reason === 'string'\n ? reason\n : reason instanceof Error\n ? reason.message\n : 'unknown';\n\n // prepare the Unexpected Error object\n // using its reserved ID\n const error = {\n id: validatorId,\n field: fieldName,\n message: errorMessage,\n } as ERROR;\n\n // refresh the Field's stored errors\n updateStoreErrors({ [validatorId]: error });\n\n // remove it from the open queue\n runningValidations.delete(validatorId);\n\n // When the list of running async validation for the Field it's empty\n // set the Field's validating state to FALSE\n if (runningValidations.size === 0) {\n if (fieldName === 'global') {\n globalValidationRunning = false;\n } else {\n store.fields[fieldName] = produce(store.fields[fieldName], draft => {\n draft.validating = false;\n });\n }\n }\n\n // clear the queue of running validations\n activeAsyncValidation.delete(validator);\n\n if (fieldName === 'global') {\n // update single fields validity status\n refreshFieldsStatus(fieldsToValidate, true);\n\n notifyFieldSubscribers(fieldsToValidate);\n } else {\n // update single fields validity status\n refreshFieldsStatus([fieldName], true);\n\n notifyFieldSubscriber(fieldName);\n }\n\n // Recompute the Form validating status\n refreshFormMetaValidatingState();\n\n // Recompute the Form status\n refreshFormStatus();\n\n notifyFormSubscribers();\n\n if (!store.meta.validating) {\n // after refreshing the form validating state notify pending validation listeners if the validation has been completed\n resolvePendingValidation(store.meta.status === 'valid');\n }\n });\n } else {\n // -------------------------------------------------\n // SYNC VALIDATION\n // -------------------------------------------------\n\n // Dev warning, the registered Validation ID is a reserved error name, used to expose un-managed exceptions\n // during the async validation execution.\n if (process.env.NODE_ENV === 'development' && validation.hasOwnProperty(validatorId)) {\n console.warn(\n `[Form State] Using a validation function UID as an error ID is a noop. (${validatorId})`,\n );\n }\n\n // refresh the Field's stored errors\n updateStoreErrors(validation as Record<string, ERROR | null>);\n\n if (fieldName === 'global') {\n notifyFieldSubscribers(fieldsToValidate);\n } else {\n notifyFieldSubscriber(fieldName);\n }\n }\n }\n }\n\n // update single fields validity status\n // necessary for sync validations\n refreshFieldsStatus(fieldsToValidate);\n\n refreshFormStatus();\n\n notifyFormSubscribers();\n\n // return a promise that resolve when all running validations (sync and async) finish\n return waitForValidation();\n },\n\n getValidator: id => {\n return validatorsById.get(id);\n },\n\n addValidation: (id, validator, fieldName) => {\n if (isStrictMode() && !!fieldName && !store.fields[fieldName]) {\n throw new Error(\n `Trying to register a field-level validation for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n if (validatorsById.has(id)) {\n throw new Error(`Trying to register a validator with ID: ${id} but it's already registered.`);\n }\n\n validatorsById.set(id, validator);\n validatorIdByFunction.set(validator, id);\n\n if (fieldName === undefined) {\n validatorsByField.set('global', validatorsByField.get('global') ?? new Set());\n validatorsByField.get('global')?.add(validator);\n } else {\n // Add it as validation for a single field\n validatorsByField.set(fieldName, validatorsByField.get(fieldName) ?? new Set());\n validatorsByField.get(fieldName)?.add(validator);\n }\n },\n\n removeValidation: id => {\n const validator = validatorsById.get(id);\n validatorsById.delete(id);\n\n if (!validator) return false;\n\n validatorIdByFunction.delete(validator);\n\n for (const [, validators] of validatorsByField) {\n validators.delete(validator);\n }\n\n return true;\n },\n\n // ------------------------------------------\n // SUBSCRIPTIONS\n // ------------------------------------------\n\n subscribeToField: (fieldName, subscriber) => {\n if (isStrictMode() && !store.fields[fieldName]) {\n throw new Error(\n `Trying to subscribe to field events for an unknown field: ${fieldName} with strict mode enabled. This is a no-op.`,\n );\n }\n\n // FIXME: find a way to properly narrow down the type\n const subscription = [fieldName, subscriber] as any as FieldSubscription;\n fieldSubscribers.add(subscription);\n\n return () => {\n fieldSubscribers.delete(subscription);\n };\n },\n\n subscribeToForm: subscriber => {\n formSubscribers.add(subscriber);\n\n return () => {\n formSubscribers.delete(subscriber);\n };\n },\n\n subscribeToMeta: subscriber => {\n formMetaSubscribers.add(subscriber);\n\n return () => {\n formMetaSubscribers.delete(subscriber);\n };\n },\n\n removeAllListeners: () => {\n formSubscribers.clear();\n fieldSubscribers.clear();\n formMetaSubscribers.clear();\n },\n };\n\n // ---------------------------------------------------------------------------\n // Custom User Config\n // ---------------------------------------------------------------------------\n\n if (config?.fieldMutations) {\n for (const { field, mutation } of config.fieldMutations) {\n api.addFieldMutation(field, mutation);\n }\n }\n\n if (config?.formMutations) {\n for (const { id, mutation } of config.formMutations) {\n api.addFormMutation(id, mutation);\n }\n }\n\n if (config?.validations) {\n for (const { id, validator, fields } of config.validations) {\n api.addValidation(id, validator, fields);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Exposed API\n // ---------------------------------------------------------------------------\n\n return {\n api,\n store,\n };\n}\n","import type { FormField, FormError, FormValidator, FormFieldMutation, FormApi } from '../types';\n\n/**\n * Field level API.\n *\n * Set of API exposed to simplify actions on a single Form Field.\n */\nexport type FormFieldApi<\n FIELD_NAME extends keyof FIELDS,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n> = {\n /**\n * @returns the Field controlled by the Field API instance\n */\n getField: () => Readonly<FIELDS[FIELD_NAME]>;\n\n /**\n * Change the value of the Field.\n *\n * @param value The new Field value.\n */\n change: (value: FIELDS[FIELD_NAME]['value']) => void;\n\n /**\n * Change the value of the Field.\n *\n * @param force Optional flag used to run the validation also when it shouldn't be necessary.\n * @returns A Promise resolving when all validations are complete.\n */\n validate: (force?: boolean) => Promise<void>;\n\n /**\n * Set the `required` state for the Field.\n *\n * @param value The new `required` state.\n */\n setRequired: (value: boolean) => void;\n\n /**\n * Set the `visible` state for the Field.\n *\n * @param value The new `visible` state.\n */\n setVisible: (value: boolean) => void;\n\n /**\n * Set the `disabled` state for the Field.\n *\n * @param value The new `disabled` state.\n */\n setDisabled: (value: boolean) => void;\n\n /**\n * Clear all errors for the Field.\n */\n clearValidation: () => void;\n\n /**\n * Register a new Validation for the Field.\n *\n * @param id Unique identifier of the validation.\n * @param validator Validator function.\n */\n addValidation: (id: string, validator: FormValidator<FIELDS, ERROR>) => void;\n\n /**\n * Unregister a Validator function.\n *\n * @param id Unique identifier of the validation.\n * @returns A boolean value indicating if the Validation was registered and it's been removed (`true`) or if it was not registered (`false`)\n */\n removeValidation: (id: string) => void;\n\n /**\n * Register a Mutation for the Field.\n *\n * @param mutation The Mutation function.\n */\n addMutation: (mutation: FormFieldMutation<FIELDS, ERROR>) => void;\n\n /**\n * Unregister the Field Mutation.\n *\n * @returns A boolean value indicating if the Mutation was registered and it's been removed (`true`) or if it was not registered (`false`)\n */\n removeMutation: () => boolean;\n};\n\n/**\n *\n * @param formApi Full Form API\n * @param fieldName The target Field name.\n * @returns A Form Field API connected to the provided Field.\n */\nexport function createFieldApi<\n FIELD_NAME extends keyof FIELDS,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n>(formApi: Readonly<FormApi<FIELDS, ERROR>>, fieldName: FIELD_NAME): Readonly<FormFieldApi<FIELD_NAME, FIELDS, ERROR>> {\n return {\n getField: () => {\n return formApi.getField(fieldName);\n },\n\n change: (value: FIELDS[FIELD_NAME]['value']) => {\n formApi.change(fieldName, value);\n },\n\n validate: (force?: boolean) => {\n const targetField = formApi.getField(fieldName);\n\n if (force || targetField.status === 'indeterminate') {\n return formApi.validate(fieldName).then();\n }\n\n return Promise.resolve();\n },\n\n setDisabled: (value: boolean) => {\n formApi.setFieldDisabledState(fieldName, value);\n },\n\n setVisible: (value: boolean) => {\n formApi.setFieldVisibleState(fieldName, value);\n },\n\n setRequired: (value: boolean) => {\n formApi.setFieldRequiredState(fieldName, value);\n },\n\n clearValidation: () => {\n formApi.clearValidation(fieldName);\n },\n\n addValidation: (id: string, validator: FormValidator<FIELDS, ERROR>) => {\n formApi.addValidation(id, validator, fieldName);\n },\n\n removeValidation: (id: string) => {\n formApi.removeValidation(id);\n },\n\n addMutation: (mutation: FormFieldMutation<FIELDS, ERROR>) => {\n formApi.addFieldMutation(fieldName, mutation);\n },\n\n removeMutation: () => {\n return formApi.removeFieldMutation(fieldName);\n },\n };\n}\n","import type { FormField, FormError, FormState } from '../types';\nimport { ReactElement, useContext, createContext } from 'react';\n\nimport { createEmptyFormState } from './createEmptyFormState';\n\nconst formContext = createContext<FormState<Record<string, FormField>, FormError<string>>>(createEmptyFormState());\n\ntype FormRootProps<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>> = {\n children: ReactElement;\n formState: FormState<FIELDS, ERROR>;\n};\n\n/**\n * Root component exposing a `React Context` to all its descendant.\n *\n * Required to be able to use the Form React hooks.\n */\nexport function FormRoot<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>>(\n props: FormRootProps<FIELDS, ERROR>,\n) {\n const { children, formState } = props;\n\n // TODO: FIX GENERIC cast issue\n return <formContext.Provider value={formState as any}>{children}</formContext.Provider>;\n}\n\n/**\n * @private\n */\nexport function useFormInternalContext<\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n>() {\n // TODO: FIX GENERIC cast issue\n const ctx = useContext(formContext) as any as FormState<FIELDS, ERROR>;\n\n if (process.env.NODE_ENV === 'development' && ctx.store.id === '_____defaultEmptyState_____') {\n throw new Error(`You cannot use a FormState Context without mounting a FormRoot component as an ancestor.`);\n }\n\n return ctx;\n}\n","import type { FormState } from '../types';\nimport type { FormConfig } from '../createForm';\nimport { useRef, useState, useEffect } from 'react';\nimport { FormField, FormError } from '../types';\n\nimport { createForm } from '../createForm';\n\n/**\n * Helper Hook used to create and maintain a Form State instance.\n *\n * @param id Unique Form identifier.\n * @param baseFields Form Fields Shape.\n * @param config Optional Form configuration\n * @returns A complete Form State\n */\nexport function useCreateForm<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>>(\n id: string,\n baseFields?: FIELDS,\n config?: FormConfig<FIELDS, ERROR>,\n): FormState<FIELDS, ERROR> {\n const rInitialized = useRef(false);\n\n const [formState] = useState<FormState<FIELDS, ERROR>>(() => {\n return createForm(id, baseFields, config);\n });\n\n useEffect(() => {\n if (rInitialized.current && process.env.NODE_ENV === 'development') {\n console.warn(`[useCreateForm] Unsupported action. The form ID changed to: ${id}.`);\n }\n }, [id]);\n\n useEffect(() => {\n if (rInitialized.current && process.env.NODE_ENV === 'development') {\n console.warn(`[useCreateForm] Unsupported action. The form baseFields changed.`, baseFields);\n }\n }, [baseFields]);\n\n useEffect(() => {\n if (rInitialized.current && process.env.NODE_ENV === 'development') {\n console.warn(`[useCreateForm] Unsupported action. The form config changed.`, config);\n }\n }, [config]);\n\n useEffect(() => {\n rInitialized.current = true;\n }, []);\n\n return formState;\n}\n","import type { FormField, FormError, FormValues, FormApi, FormMeta } from '../types';\nimport { useEffect, useState } from 'react';\n\nimport { useFormInternalContext } from '../utils/formContext';\n\nexport type UseForm<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>> = {\n values: Readonly<FormValues<FIELDS>>;\n errors: Readonly<Record<string, ERROR>>;\n meta: Readonly<FormMeta>;\n api: Readonly<FormApi<FIELDS, ERROR>>;\n};\n\n/**\n * React Hook connecting to a Form and exposing its API\n * @returns [formValues, formErrors, formMeta, formApi]\n */\nexport function useForm<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>>(): UseForm<\n FIELDS,\n ERROR\n> {\n const { api } = useFormInternalContext<FIELDS, ERROR>();\n\n type State = {\n values: ReturnType<typeof api.getValues>;\n errors: ReturnType<typeof api.getErrors>;\n meta: ReturnType<typeof api.getMeta>;\n };\n\n const [{ values, errors, meta }, setState] = useState<State>(() => {\n return {\n values: api.getValues(),\n errors: api.getErrors(),\n meta: api.getMeta(),\n };\n });\n\n useEffect(() => {\n let effectCleared = false;\n\n const unsubscribe = api.subscribeToForm(formApi => {\n if (effectCleared) return;\n\n setState({\n values: formApi.getValues(),\n errors: formApi.getErrors(),\n meta: formApi.getMeta(),\n });\n });\n\n return () => {\n effectCleared = true;\n unsubscribe();\n };\n }, [api]);\n\n return { values, errors, meta, api };\n}\n","import type { FormField, FormError } from '../types';\nimport { useFormInternalContext } from '../utils/formContext';\n\n/**\n * React Hook exposing a form instance API\n * @returns a formApi instance\n */\nexport function useFormApi<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>>() {\n const { api } = useFormInternalContext<FIELDS, ERROR>();\n return api;\n}\n","import type { FormField, FormError, FormMeta, FormApi } from '../types';\nimport { useEffect, useState } from 'react';\n\nimport { useFormInternalContext } from '../utils/formContext';\n\nexport type UseFormMeta<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>> = {\n meta: Readonly<FormMeta>;\n api: Readonly<FormApi<FIELDS, ERROR>>;\n};\n\n/**\n * React Hook connecting to a Form Meta state and exposing its API\n * @returns [formMeta, formApi]\n */\nexport function useFormMeta<\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n>(): UseFormMeta<FIELDS, ERROR> {\n const { api } = useFormInternalContext<FIELDS, ERROR>();\n\n type State = ReturnType<typeof api.getMeta>;\n const [meta, setState] = useState<State>(() => {\n return api.getMeta();\n });\n\n useEffect(() => {\n let effectCleared = false;\n\n const unsubscribe = api.subscribeToMeta(meta => {\n if (effectCleared) return;\n\n setState(meta);\n });\n\n return () => {\n effectCleared = true;\n unsubscribe();\n };\n }, [api]);\n\n return { meta, api };\n}\n","import type { FormField, FormApi, FormError, FormValidator, FormFieldMutation } from '../types';\nimport { useState, useCallback, useEffect, useLayoutEffect, useReducer, useRef } from 'react';\n\nimport { useFormInternalContext } from '../utils/formContext';\nimport { createFieldApi, FormFieldApi } from '../utils/createFieldApi';\n\nexport type UseFormField<\n FIELD_NAME extends keyof FIELDS,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n> = {\n field: Readonly<FIELDS[FIELD_NAME]>;\n errors: Readonly<FormError<keyof FIELDS>[]>;\n fieldApi: Readonly<FormFieldApi<FIELD_NAME, FIELDS, ERROR>>;\n formApi: Readonly<FormApi<FIELDS, ERROR>>;\n};\n\nexport type UseFormFieldOptions<FIELDS extends Record<string, FormField>, ERROR extends FormError<keyof FIELDS>> = {\n // When dynamic mode is set\n dynamic?: {\n field: FormField;\n clearOnUnmount: 'never' | 'data-only' | 'all';\n };\n hidden?: boolean;\n disabled?: boolean;\n required?: boolean;\n mutation?: FormFieldMutation<FIELDS, ERROR>;\n validations?: Record<string, FormValidator<FIELDS, ERROR>>;\n fieldsOfInterest?: (keyof FormField | 'errors')[];\n};\n\nexport type LazyUseFormFieldOptions<\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n> = () => UseFormFieldOptions<FIELDS, ERROR>;\n\nconst emptyPlaceholder = {};\n\n/**\n * React Hook connecting to a single Form Field and exposing its Field API.\n * TODO: Add documentation for lazy initialization\n *\n * @param fieldName Target Field name.\n * @param options.mutation Optional Mutation to register for the field\n * @param options.validations Optional Record of validation to register for the field\n * @param options.fieldsOfInterest Optional list of Form Fields that will trigger a re-render of the parent React Component. Defaults to All Fields.\n * @returns [field, fieldErrors, fieldApi, formApi]\n */\nexport function useFormField<\n FIELD_NAME extends keyof FIELDS,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n>(fieldName: FIELD_NAME, options?: UseFormFieldOptions<FIELDS, ERROR>): UseFormField<FIELD_NAME, FIELDS, ERROR>;\nexport function useFormField<\n FIELD_NAME extends keyof FIELDS,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n>(fieldName: FIELD_NAME, lazyOptions?: LazyUseFormFieldOptions<FIELDS, ERROR>): UseFormField<FIELD_NAME, FIELDS, ERROR>;\nexport function useFormField<\n FIELD_NAME extends keyof FIELDS,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS>,\n>(\n fieldName: FIELD_NAME,\n maybeLazyOptions?: UseFormFieldOptions<FIELDS, ERROR> | LazyUseFormFieldOptions<FIELDS, ERROR>,\n): UseFormField<FIELD_NAME, FIELDS, ERROR> {\n // ------------------------------------------------------------------------\n // Core Form API through React context\n // ------------------------------------------------------------------------\n\n const { api: formApi } = useFormInternalContext<FIELDS, ERROR>();\n\n // ------------------------------------------------------------------------\n // Core Field API\n // ------------------------------------------------------------------------\n\n const [fieldApi, setFieldApi] = useState(() => {\n return createFieldApi<FIELD_NAME, FIELDS, ERROR>(formApi, fieldName);\n });\n\n useEffect(() => {\n setFieldApi(createFieldApi<FIELD_NAME, FIELDS, ERROR>(formApi, fieldName));\n }, [formApi, fieldName]);\n\n // ------------------------------------------------------------------------\n // Options initializations\n // ------------------------------------------------------------------------\n\n // Flag required to avoid unnecessary invocation to `maybeLazyOptions` when is a function\n const rOptionsInitialized = useRef(false);\n\n // initialize the Options' ref as first thing\n const rOptions = useRef<UseFormFieldOptions<FIELDS, ERROR>>(\n rOptionsInitialized.current\n ? // when already initialized a placeholder empty option object is used\n emptyPlaceholder\n : // the first render, when possible, initialize the ref value\n (typeof maybeLazyOptions === 'function' ? maybeLazyOptions() : maybeLazyOptions) ?? emptyPlaceholder,\n );\n\n // mark the Options' ref as initialized\n rOptionsInitialized.current = true;\n\n // Keep options updated when necessary\n useLayoutEffect(() => {\n if (typeof maybeLazyOptions === 'function') {\n // lazy options are read once and then forget\n if (Object.keys(rOptions.current).length === 0) {\n rOptions.current = maybeLazyOptions();\n }\n } else {\n // non-lazy options are updated\n rOptions.current = maybeLazyOptions ?? rOptions.current;\n }\n }, [maybeLazyOptions]);\n\n // expose computed options for effects usage\n const { mutation, validations, hidden, disabled, required } = rOptions.current;\n\n // ------------------------------------------------------------------------\n // Dynamic Field Cleanup\n // ------------------------------------------------------------------------\n\n // when dynamic, cleanup the field accordingly to the provided rules\n useEffect(() => {\n const { dynamic } = rOptions.current;\n\n if (!dynamic) return;\n\n const { clearOnUnmount } = dynamic;\n\n return () => {\n if (clearOnUnmount === 'never') return;\n\n // when `clearOnUnmount` is set to `all` all subscriptions, field-mutations and field-validations will be removed\n const completeFieldDestruction = clearOnUnmount === 'all';\n formApi.deregisterField(fieldName, completeFieldDestruction);\n };\n }, [formApi, fieldName]);\n\n // ------------------------------------------------------------------------\n // Local State\n // ------------------------------------------------------------------------\n\n type State = {\n field: Readonly<FIELDS[FIELD_NAME]>;\n errors: Readonly<FormError<keyof FIELDS>[]>;\n };\n\n const [, forceRender] = useReducer(s => s + 1, 0);\n\n // helper function used to initialize and maintain a local stored state\n const getState = useCallback((): State => {\n // Dynamic Field initialization\n const { dynamic } = rOptions.current;\n\n if (dynamic) {\n const { field } = dynamic;\n\n // it's safe to invoke multiple times `formApi.registerField`\n // after the first invocation the form simply ignore the request\n formApi.registerField(fieldName, field);\n }\n\n // return the\n return {\n field: formApi.getField(fieldName),\n errors: formApi.getFieldErrors(fieldName),\n };\n }, [formApi, fieldName]);\n\n // initialize the local state from the very begin, to ensure data consistency across different render passes\n const rState = useRef<State>(getState());\n\n // it ensures to recreate the field values when fieldName change\n // useLayoutEffect(() => void getState(true), [getState, fieldName])\n useLayoutEffect(() => void Object.assign(rState.current, getState()), [getState, fieldName]);\n\n // ------------------------------------------------------------------------\n // Form Field Subscription\n // ------------------------------------------------------------------------\n\n useEffect(() => {\n let effectCleared = false;\n\n const { fieldsOfInterest } = rOptions.current;\n\n const unsubscribe = formApi.subscribeToField(fieldName, (field, errors, _formApi) => {\n if (effectCleared) return;\n\n const changedFields = new Set<keyof FormField | 'errors'>();\n\n if (fieldsOfInterest?.length) {\n for (const key of Object.keys(field)) {\n const fieldKey = key as keyof FormField;\n\n if (field[fieldKey] !== rState.current.field[fieldKey]) {\n changedFields.add(fieldKey);\n }\n }\n }\n\n rState.current.field = field;\n rState.current.errors = errors;\n\n if (!fieldsOfInterest?.length) return forceRender();\n\n if (fieldsOfInterest.some(f => changedFields.has(f))) {\n forceRender();\n }\n });\n\n return () => {\n effectCleared = true;\n unsubscribe();\n };\n }, [formApi, fieldName]);\n\n // ------------------------------------------------------------------------\n // Add/Remove mutations\n // ------------------------------------------------------------------------\n\n useEffect(() => {\n if (mutation) {\n // add new mutation\n fieldApi.addMutation(mutation);\n }\n\n return () => {\n if (mutation) {\n // if it was previously registered remove it\n fieldApi.removeMutation();\n }\n };\n }, [fieldApi, mutation]);\n\n // ------------------------------------------------------------------------\n // Force Field meta states\n // ------------------------------------------------------------------------\n\n useEffect(() => {\n if (hidden !== undefined) {\n fieldApi.setVisible(!hidden);\n }\n }, [fieldApi, hidden]);\n\n useEffect(() => {\n if (required !== undefined) {\n fieldApi.setRequired(required);\n }\n }, [fieldApi, required]);\n\n useEffect(() => {\n if (disabled !== undefined) {\n fieldApi.setDisabled(disabled);\n }\n }, [fieldApi, disabled]);\n\n // ------------------------------------------------------------------------\n // Add/Remove validations\n // ------------------------------------------------------------------------\n\n useEffect(() => {\n if (validations) {\n // add new validations\n for (const [validationID, validator] of Object.entries(validations)) {\n fieldApi.addValidation(validationID, validator);\n }\n }\n\n return () => {\n if (validations) {\n // remove previously registered validation\n for (const validationID of Object.keys(validations)) {\n fieldApi.removeValidation(validationID);\n }\n }\n };\n }, [fieldApi, validations]);\n\n // ------------------------------------------------------------------------\n // ------------------------------------------------------------------------\n\n return { field: rState.current.field, errors: rState.current.errors, fieldApi, formApi };\n}\n","import type { FormError, FormField } from '@/formState';\n\nconst emailField: FormField<string> = { value: '', required: true };\n\nexport const formFields = {\n email: emailField,\n};\n\nexport type FormFields = typeof formFields;\nexport type FormErrors = FormError<keyof FormFields>;\n","import type { ScrollbarOptions, Scrollbar } from 'smooth-scrollbar/interfaces';\nimport type { Props } from '../types';\n\nimport { MutableRefObject, useEffect, useRef } from 'react';\n\nexport function useScrollbarOptions(props: Props, scrollbarRef: MutableRefObject<Scrollbar | undefined>) {\n const {\n damping = 1,\n thumbMinSize = 40,\n continuousScrolling,\n delegateTo,\n plugins,\n trackVisible = 'always',\n renderByPixels = true,\n } = props;\n\n const rOptions = useRef<Partial<ScrollbarOptions>>({\n damping,\n thumbMinSize,\n continuousScrolling,\n delegateTo,\n plugins,\n alwaysShowTracks: trackVisible === 'always',\n // improve performances\n renderByPixels,\n });\n\n useEffect(() => {\n rOptions.current.damping = damping;\n if (!scrollbarRef.current) return;\n\n scrollbarRef.current.options.damping = damping;\n }, [damping, scrollbarRef]);\n\n useEffect(() => {\n rOptions.current.thumbMinSize = thumbMinSize;\n if (!scrollbarRef.current) return;\n\n scrollbarRef.current.options.thumbMinSize = thumbMinSize;\n }, [thumbMinSize, scrollbarRef]);\n\n useEffect(() => {\n rOptions.current.continuousScrolling = continuousScrolling;\n if (!scrollbarRef.current) return;\n\n scrollbarRef.current.options.continuousScrolling = !!continuousScrolling;\n }, [continuousScrolling, scrollbarRef]);\n\n useEffect(() => {\n rOptions.current.delegateTo = delegateTo;\n if (!scrollbarRef.current) return;\n\n scrollbarRef.current.options.delegateTo = delegateTo ?? null;\n }, [delegateTo, scrollbarRef]);\n\n useEffect(() => {\n rOptions.current.renderByPixels = renderByPixels;\n if (!scrollbarRef.current) return;\n\n scrollbarRef.current.options.renderByPixels = renderByPixels;\n }, [renderByPixels, scrollbarRef]);\n\n useEffect(() => {\n rOptions.current.plugins = plugins;\n if (!scrollbarRef.current || typeof plugins === 'undefined') return;\n\n scrollbarRef.current.options.plugins = plugins;\n\n Object.keys(plugins ?? {}).forEach(pluginName =>\n scrollbarRef.current?.updatePluginOptions(pluginName, plugins[pluginName]),\n );\n }, [plugins, scrollbarRef]);\n\n useEffect(() => {\n const alwaysShowTracks = trackVisible === 'always';\n rOptions.current.alwaysShowTracks = alwaysShowTracks;\n if (!scrollbarRef.current) return;\n\n scrollbarRef.current.options.alwaysShowTracks = alwaysShowTracks;\n }, [trackVisible, scrollbarRef]);\n\n return rOptions.current;\n}\n","import type { MutableRefObject } from 'react';\nimport type { Scrollbar } from 'smooth-scrollbar/interfaces';\nimport type { InternalProps as Props } from '../types';\n\nimport { useEffect } from 'react';\n\nimport CoreSmoothScrollbar from 'smooth-scrollbar';\n\nimport { useScrollbarOptions } from './useScrollbarOptions';\n\nexport function useInitSmoothScrollbar(\n props: Props,\n scrollbarRef: MutableRefObject<Scrollbar | undefined>,\n container: HTMLElement | null,\n) {\n const options = useScrollbarOptions(props, scrollbarRef);\n\n // initialize the Scrollbar\n useEffect(() => {\n if (!container) return;\n scrollbarRef.current = CoreSmoothScrollbar.init(container, options);\n\n return () => {\n scrollbarRef.current?.destroy();\n scrollbarRef.current = undefined;\n };\n }, [container, options, scrollbarRef]);\n}\n","import type { MutableRefObject } from 'react';\nimport type { Scrollbar, ScrollStatus } from 'smooth-scrollbar/interfaces';\nimport type { InternalProps as Props } from '../types';\n\nimport { useEffect } from 'react';\n\nexport function useOnScroll(onScroll: Props['onScroll'], scrollbarRef: MutableRefObject<Scrollbar | undefined>) {\n // update the onScroll callback\n useEffect(() => {\n const handleOnScroll = (status: ScrollStatus) => {\n onScroll?.(status, scrollbarRef.current);\n };\n\n const scrollbar = scrollbarRef.current;\n scrollbar?.addListener(handleOnScroll);\n\n return () => {\n scrollbar?.removeListener(handleOnScroll);\n };\n }, [scrollbarRef, onScroll]);\n}\n","import type { Scrollbar, ScrollIntoViewOptions } from 'smooth-scrollbar/interfaces';\n\nimport { MutableRefObject, useEffect } from 'react';\n\nexport function useTestActions(\n rScrollbar: MutableRefObject<Scrollbar | undefined>,\n qa?: 'enable' | 'disable',\n testId?: string,\n) {\n // ------------------------------------------------------------------------------------\n // TEST ACTIONS\n // ------------------------------------------------------------------------------------\n const qaEnabled = isQaEnabled(qa);\n useEffect(() => {\n // register the test action\n\n if (!qaEnabled || !testId) return;\n\n try {\n globalThis.testActions ??= {};\n globalThis.testActions[testId] ??= {};\n\n // allows QA to programmatically scroll elements into view\n globalThis.testActions[testId].scrollElementIntoView = (\n el: HTMLElement,\n options?: Partial<ScrollIntoViewOptions>,\n ) => {\n if (!el) console.error('Invalid HTMLElement');\n if (!rScrollbar.current) console.error('No scrollbar yet');\n rScrollbar.current?.scrollIntoView(el, options);\n };\n\n return () => {\n // delete the test action\n if (testId) delete globalThis.testActions?.[testId]?.scrollElementIntoView;\n };\n } catch (e) {\n console.warn(e);\n }\n }, [qaEnabled, testId, rScrollbar]);\n}\n\nfunction isQaEnabled(qa?: 'enable' | 'disable') {\n // if present, the passed prop supersedes the environment variable\n if (qa) return qa === 'enable';\n\n // allow @ts-ignore usage\n /* eslint-disable @typescript-eslint/prefer-ts-expect-error */\n\n try {\n // @ts-ignore avoids the developer to add add type for Vite's env variable\n return import.meta.env.VITE_QA === 'enable';\n } catch {\n // @ts-ignore avoids the developer to add add type for the env variable\n return process.env.QA === 'enable';\n }\n\n /* eslint-enable @typescript-eslint/prefer-ts-expect-error */\n}\n","import type { Scrollbar } from 'smooth-scrollbar/interfaces';\nimport type { ScrollTo } from '../types';\n\nimport { useEffect } from 'react';\n\nexport function useOnScrollTo(scrollTo: ScrollTo | undefined, scrollbar: Scrollbar | undefined) {\n // the scrollTo has not been spread in the deps because otherwise we could fall into a case like this\n // - the code logic call programmatically scrollTo({0, 100}) (duration and options are constant so you can remove it from the logic)\n // - the user then scroll the content\n // - the code logic will trigger again with {0, 100} but the effect will ignore this case and we fall into a unwanted behavior\n // using the Scrollbars component however more expressive api are exposed via context\n useEffect(() => {\n if (!scrollbar || !scrollTo) return;\n const { x, y, duration, options } = scrollTo;\n scrollbar.scrollTo(x, y, duration, options);\n }, [scrollTo, scrollbar]);\n}\n","import type { Scrollbar } from 'smooth-scrollbar/interfaces';\nimport type { ScrollIntoView } from '../types';\n\nimport { useEffect } from 'react';\n\nexport function useOnScrollIntoView(scrollIntoView: ScrollIntoView | undefined, scrollbar: Scrollbar | undefined) {\n // the scrollIntoView has not been spread in the deps because otherwise we could fall into the case described into useOnScrollTo\n // using the Scrollbars component however more expressive api are exposed via context\n useEffect(() => {\n if (!scrollbar || !scrollIntoView) return;\n const { elem, options } = scrollIntoView;\n scrollbar.scrollIntoView(elem, options);\n }, [scrollIntoView, scrollbar]);\n}\n","import type { Scrollbar, ScrollbarSize } from 'smooth-scrollbar/interfaces';\nimport type { Props } from '../types';\n\nimport { useEffect, useRef } from 'react';\n\nconst emptyScrollbarSize = {\n container: { width: 0, height: 0 },\n content: { width: 0, height: 0 },\n} as const;\n\nexport function useNotifyListeners(\n scrollbar: Scrollbar | undefined,\n onChangeScrollbarVisibility?: Props['onChangeScrollbarVisibility'],\n onChangeOutOfViewportHeight?: Props['onChangeOutOfViewportHeight'],\n) {\n const rScrollbarSize = useRef<ScrollbarSize>(emptyScrollbarSize);\n\n // notify listeners when scroll viewport updates\n useEffect(() => {\n let sizeChanged: boolean;\n let prevVisible: boolean;\n let timerStart: number;\n let rafId: number;\n\n // bail out if no callback are provided\n if (!onChangeOutOfViewportHeight && !onChangeScrollbarVisibility) return;\n\n function tick(timestamp: number) {\n // if no scrollbar or no callback to be called bail out immediately\n if (!scrollbar) return;\n\n timerStart ??= timestamp;\n\n const elapsed = timestamp - timerStart;\n\n scrollbar?.update();\n const size = scrollbar?.getSize() ?? emptyScrollbarSize;\n sizeChanged = isScrollbarSizeChanged(rScrollbarSize.current, size);\n prevVisible = isScrollbarVisible(rScrollbarSize.current);\n rScrollbarSize.current = size;\n\n if (sizeChanged) {\n onChangeOutOfViewportHeight?.(getOutOfViewportHeight(size), size);\n }\n\n const visible = isScrollbarVisible(size);\n if (visible !== prevVisible) {\n onChangeScrollbarVisibility?.(visible);\n }\n\n if (elapsed > 200) {\n rafId = globalThis.requestAnimationFrame(tick);\n }\n }\n\n rafId = globalThis.requestAnimationFrame(tick);\n\n return () => {\n globalThis.cancelAnimationFrame(rafId);\n };\n }, [scrollbar, onChangeOutOfViewportHeight, onChangeScrollbarVisibility]);\n}\n\nfunction isScrollbarSizeChanged(prevSize: ScrollbarSize, nextSize: ScrollbarSize) {\n return (\n prevSize.container.width !== nextSize.container.width ||\n prevSize.container.height !== nextSize.container.height ||\n prevSize.content.width !== nextSize.content.width ||\n prevSize.content.height !== nextSize.content.height\n );\n}\n\nfunction isScrollbarVisible(size: ScrollbarSize) {\n return size.container.width < size.content.width || size.container.height < size.content.height;\n}\n\nfunction getOutOfViewportHeight(size: ScrollbarSize) {\n return size.content.height - size.container.height;\n}\n","import type { ScrollbarPosition } from '../types';\nimport { CSSProperties, useMemo } from 'react';\n\nexport function useStyles(\n width: number | string = 'auto',\n height: number | string = 'auto',\n scrollbarPosition: ScrollbarPosition,\n): CSSProperties {\n return useMemo(() => {\n const paddingRight = scrollbarPosition.position === 'asideContent' ? scrollbarPosition.gap ?? 20 : 0;\n\n return {\n width,\n height,\n paddingRight,\n };\n }, [width, height, scrollbarPosition]);\n}\n","import type { Scrollbar } from 'smooth-scrollbar/interfaces';\nimport type { Props } from './types';\n\nimport { useRef, useImperativeHandle, forwardRef } from 'react';\n\nimport { useInitSmoothScrollbar } from './hooks/useInitSmoothScrollbar';\nimport { useOnScroll } from './hooks/useOnScroll';\nimport { useTestActions } from './hooks/useTestActions';\nimport { useOnScrollTo } from './hooks/useOnScrollTo';\nimport { useOnScrollIntoView } from './hooks/useOnScrollIntoView';\nimport { useNotifyListeners } from './hooks/useNotifyListeners';\nimport { useStyles } from './hooks/useStyles';\n\nconst defaultScrollbarPosition = {\n position: 'asideContent',\n gap: 20,\n} as const;\n\n/**\n * ATTENTION: If the QA mode enabled and a `testId` is provided, a test action is exposed on the\n * global window object. The test action is `window.testActions[testId].scrollElementIntoView` and\n * allows to scroll an element into the view. The QA mode can be enabled\n * - through the `qa` prop (accepted values: 'enable' and 'disable')\n * - through the process.env.QA or the import.meta.env.VITE_QA variables (accepted values: 'enable' and 'disable')\n * Please note that the `qa` pros supersedes the env variable.\n */\nexport const SmoothScrollbar = forwardRef<\n Scrollbar | undefined,\n Omit<JSX.IntrinsicElements['section'], 'onScroll'> & Props\n>((props, forwardedRef) => {\n const {\n children,\n testId,\n scrollbarPosition = defaultScrollbarPosition,\n qa,\n onScroll,\n scrollTo,\n scrollIntoView,\n onChangeScrollbarVisibility,\n onChangeOutOfViewportHeight,\n } = props;\n const rContainer = useRef<HTMLElement | null>(null);\n const rScrollbar = useRef<Scrollbar>();\n\n // initialize the SmoothScrollbar library\n useInitSmoothScrollbar(props, rScrollbar, rContainer.current);\n\n // register/unregister onScroll\n useOnScroll(onScroll, rScrollbar);\n\n // QA test actions\n useTestActions(rScrollbar, qa, testId);\n\n // Expose scrollbar to the consumers via forwardedRef\n useImperativeHandle(forwardedRef, () => rScrollbar.current);\n\n // react to scrollTo\n useOnScrollTo(scrollTo, rScrollbar.current);\n\n // react to scrollIntoView\n useOnScrollIntoView(scrollIntoView, rScrollbar.current);\n\n // notify listeners that scrollbar has been updated\n useNotifyListeners(rScrollbar.current, onChangeScrollbarVisibility, onChangeOutOfViewportHeight);\n\n const styles = useStyles(props.width, props.height, scrollbarPosition);\n\n return (\n <section data-scrollbar ref={rContainer} style={styles} data-testid={testId} data-testActions={testId}>\n <div>{children}</div>\n </section>\n );\n});\n\nSmoothScrollbar.displayName = 'SmoothScrollbar';\n","import type { ReactElement } from 'react';\n\nimport { forwardRef } from 'react';\n\nimport makeStyles from '@mui/styles/makeStyles';\n\ninterface Props {\n children: ReactElement;\n}\n\nconst useClasses = makeStyles({\n root: {\n position: 'absolute',\n top: 0,\n left: 0,\n height: '100%',\n width: '100%',\n },\n});\n\n// FitBox will occupy in absolute position his parent\n// doing so `children` will not break any layout rule\nexport const FitBox = forwardRef<HTMLDivElement, Props>((props, ref) => {\n const classes = useClasses();\n\n return (\n <div className={classes.root} ref={ref}>\n {props.children}\n </div>\n );\n});\n\nFitBox.displayName = 'FitBox';\n","import type { ScrollIntoView } from '../../SmoothScrollbar';\n\nimport { createContext } from 'react';\n\nexport interface Context {\n scrollTo: (id: string) => void;\n scrollIntoView?: ScrollIntoView;\n}\n\nexport const ScrollContext = createContext<Context>({\n scrollTo: () => {\n if (process.env.NODE_ENV === 'development') {\n console.warn('Missing provider for scrollTo');\n }\n },\n});\n","import { FormHelperText } from '@mui/material';\n\ninterface Props {\n error?: boolean;\n helperText?: string;\n errorText?: string;\n}\n\nexport function FieldMessage(props: Props) {\n const { error, errorText, helperText } = props;\n return (\n <>\n {!!error && !!errorText && <FormHelperText>{errorText}</FormHelperText>}\n {!!helperText && !error && <FormHelperText>{helperText}</FormHelperText>}\n </>\n );\n}\n","import { ReactElement } from 'react';\nimport makeStyles from '@mui/styles/makeStyles';\n\ninterface Props {\n children: ReactElement | ReactElement[];\n}\n\nconst useClasses = makeStyles(theme => ({\n fieldsContainer: {\n // Spacer that allow the label to not be cut (outlined label will overflow the container)\n paddingTop: '5px',\n // this rule will remove the spacing in the last field\n // this because of the \"scrolling\" footer that requires some padding\n // if the last field has this padding too the result will be doubling the space\n '& > *:last-child': {\n paddingBottom: theme.spacing(0),\n },\n },\n}));\n\nexport function FieldsContainer(props: Props) {\n const classes = useClasses();\n\n return <div className={classes.fieldsContainer}>{props.children}</div>;\n}\n","import type { ValidateOn } from '../Generic/types';\n\nimport { useMemo } from 'react';\n\nconst noop = () => undefined;\n\nexport function useValidateOn(validate: (force?: boolean) => void | Promise<void>, validateOn: ValidateOn) {\n return useMemo(() => {\n return {\n validateOnBlur: validateOn.includes('blur') ? validate : noop,\n validateOnFocus: validateOn.includes('focus') ? validate : noop,\n validateOnChange: validateOn.includes('change') ? validate : noop,\n };\n }, [validate, validateOn]);\n}\n","import type { Option } from './types';\n\nimport { Box, FormHelperText, Radio, FormControlLabel } from '@mui/material';\n\nimport makeStyles from '@mui/styles/makeStyles';\n\nconst useClasses = makeStyles({\n root: {\n alignItems: 'flex-start',\n },\n});\n\ninterface Props<VALUE extends string> {\n option: Option<VALUE>;\n}\n\nexport function RadioGroupOption<VALUE extends string>(props: Props<VALUE>) {\n const { value, disabled, label, description } = props.option;\n\n const classes = useClasses();\n\n return (\n <FormControlLabel\n control={<Radio />}\n value={value}\n disabled={disabled}\n className={classes.root}\n label={\n <>\n <Box paddingTop=\"9px\">{label}</Box>\n {description && <FormHelperText>{description}</FormHelperText>}\n </>\n }\n />\n );\n}\n","import { useRef, useEffect, useCallback, ChangeEvent, useState } from 'react';\n\ntype OnChange = (value: string) => void;\n\nconst emptyTimeout = setTimeout(() => undefined, 0);\n\ntype UseDebounceText = [value: string, onChange: (event: ChangeEvent<HTMLInputElement>) => void];\n\nexport function useDebounceText(value: string, onChange: OnChange, delay?: number): UseDebounceText {\n const rTimer = useRef<NodeJS.Timer>(emptyTimeout);\n\n const [localValue, setLocalValue] = useState(value);\n const rLocalValue = useRef(localValue);\n\n useEffect(() => {\n setLocalValue(value);\n rLocalValue.current = value;\n return () => clearTimeout(rTimer.current);\n }, [value]);\n\n const debounceOnChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n clearTimeout(rTimer.current);\n if (!delay) return;\n const value = event.currentTarget.value;\n setLocalValue(value);\n rLocalValue.current = value;\n rTimer.current = globalThis.setTimeout(() => onChange(rLocalValue.current), delay);\n },\n [onChange, delay],\n );\n\n const noDebounceOnChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n onChange(event.currentTarget.value);\n },\n [onChange],\n );\n\n return delay === undefined ? [value, noDebounceOnChange] : [localValue, debounceOnChange];\n}\n","import type { TextFieldProps as MuiTextFieldProps } from '@mui/material';\n\nimport type { ValidateOn } from './types';\nimport type { FormError, FormField, NarrowFieldsByValueType, UseFormFieldOptions } from '@/formState';\n\nimport { useCallback } from 'react';\nimport { TextField as MuiTextField, FormControl } from '@mui/material';\n\nimport { useFormField } from '@/formState';\n\nimport { FieldMessage } from '../../FieldMessage';\nimport { useDebounceText } from '../hooks/useDebounceText';\nimport { useValidateOn } from '../hooks/useValidateOn';\n\ntype RequiredFormField = string;\n\ntype Props<\n FIELD_NAME extends NarrowFieldsByValueType<RequiredFormField, FIELDS>,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS> = FormError<keyof FIELDS>,\n> = {\n label: string;\n name: FIELD_NAME;\n validateOn: ValidateOn;\n helperText?: string;\n placeholder?: string;\n autoFocus?: boolean;\n debounce?: number;\n // custom MUI properties\n // TODO: it should oOmit all props not allowed to configure\n // TODO: or it could ONLY expose the props we want to be customizable\n textField?: {\n type?: 'text' | 'password' | 'email';\n fullWidth?: boolean;\n variant?: 'standard' | 'outlined' | 'filled';\n };\n // ATTENTION: use it carefully\n UNSTABLE_textField?: Partial<MuiTextFieldProps>;\n} & UseFormFieldOptions<FIELDS, ERROR>;\n\nexport function TextField<\n FIELD_NAME extends NarrowFieldsByValueType<RequiredFormField, FIELDS>,\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS> = FormError<keyof FIELDS>,\n>(props: Props<FIELD_NAME, FIELDS, ERROR>) {\n const {\n placeholder,\n helperText,\n validateOn,\n autoFocus,\n label,\n name,\n debounce,\n textField = {},\n UNSTABLE_textField = {},\n ...options\n } = props;\n\n // internal type used to resolve the connected Form Field to a `string` instead of a dynamically derived type,\n // not resolved inside the reusable component\n type PartialForm = Record<string, FormField<RequiredFormField>>;\n\n const {\n field,\n errors,\n fieldApi: { change: apiChange, validate },\n formApi,\n } = useFormField<FIELD_NAME, PartialForm, FormError<FIELD_NAME>>(\n name,\n options as UseFormFieldOptions<PartialForm, FormError<FIELD_NAME>>,\n );\n\n const { required, status, disabled, visible } = field;\n\n const { validateOnBlur, validateOnChange, validateOnFocus } = useValidateOn(validate, validateOn);\n\n const changeAndValidate = useCallback(\n (value: string) => {\n apiChange(value);\n validateOnChange();\n },\n [validateOnChange, apiChange],\n );\n\n const [value, onChange] = useDebounceText(field.value, changeAndValidate, debounce);\n\n const onBlur = useCallback(() => {\n validateOnBlur();\n }, [validateOnBlur]);\n\n const onFocus = useCallback(() => {\n validateOnFocus();\n }, [validateOnFocus]);\n\n // Resolve the field meta states to improve code readability\n const fieldInvalid = status === 'invalid';\n const fieldIndeterminate = status === 'indeterminate';\n const fieldHasError = fieldInvalid || (fieldIndeterminate && errors.length > 0);\n\n const errorText = fieldHasError ? errors[0]?.message ?? 'Unknown Error' : undefined;\n\n // Disable the field also while the form is submitting\n const fieldDisabled = disabled || formApi.getMeta().submitting || formApi.getMeta().disabled;\n\n if (!visible) return null;\n\n return (\n <FormControl error={fieldHasError} fullWidth={textField?.fullWidth}>\n <MuiTextField\n // spread it first to avoid overwriting necessary props managed by the Field\n fullWidth={false}\n {...UNSTABLE_textField}\n {...textField}\n name={name}\n label={label}\n required={required}\n error={fieldHasError}\n placeholder={placeholder}\n value={value}\n onChange={onChange}\n onBlur={onBlur}\n onFocus={onFocus}\n disabled={fieldDisabled}\n autoFocus={autoFocus}\n />\n <FieldMessage error={fieldHasError} helperText={helperText} errorText={errorText} />\n </FormControl>\n );\n}\n","import makeStyles from '@mui/styles/makeStyles';\n\nexport const useStyles = makeStyles({\n popover: {\n width: '100%',\n pointerEvents: 'none',\n },\n menu: {\n maxHeight: 300,\n overflowX: 'hidden',\n overflowY: 'scroll',\n pointerEvents: 'all',\n\n '& .MuiMenu-paper': {\n marginTop: 25,\n width: '100%',\n transitionDuration: '0s !important',\n },\n },\n});\n","import { FormField } from '@/formState';\n\nconst minCharacterLimit = (stringToTest: string, minChars: number) => {\n return stringToTest.length >= minChars;\n};\n\nconst hasLowerCaseChar = (stringToTest: string) => /[a-z]/.test(stringToTest);\n\nconst hasUpperCaseChar = (stringToTest: string) => /[A-Z]/.test(stringToTest);\n\nconst hasNum = (stringToTest: string) => /[0-9]/.test(stringToTest);\n\nconst hasSpecialChar = (stringToTest: string) => /[!@#$%^&]/.test(stringToTest);\n\nexport const getPasswordErrors = (\n password: Readonly<FormField<string>>,\n confirmPassword: Readonly<FormField<string>>,\n texts: {\n passwordMust: string;\n minLength: string;\n includeLower: string;\n includeUpper: string;\n includeNumber: string;\n includeSpecial: string;\n mustMatch: string;\n },\n) => {\n const errors = {\n minChar: minCharacterLimit(password.value, 8)\n ? null\n : {\n id: 'minChar',\n field: 'password' as const,\n message: texts.minLength,\n },\n missingLower: hasLowerCaseChar(password.value)\n ? null\n : {\n id: 'missingLower',\n field: 'password' as const,\n message: texts.includeLower,\n },\n missingUpper: hasUpperCaseChar(password.value)\n ? null\n : {\n id: 'missingUpper',\n field: 'password' as const,\n message: texts.includeUpper,\n },\n missingNum: hasNum(password.value)\n ? null\n : {\n id: 'missingNum',\n field: 'password' as const,\n message: texts.includeNumber,\n },\n missingSpecial: hasSpecialChar(password.value)\n ? null\n : {\n id: 'missingSpecial',\n field: 'password' as const,\n message: texts.includeSpecial,\n },\n missingMatch:\n password.value === confirmPassword.value\n ? null\n : {\n id: 'missingMatch',\n field: 'password' as const,\n message: texts.mustMatch,\n },\n };\n\n return errors;\n};\n\nconst isValidEmail = (stringToTest: string) =>\n /^(?:[\\w\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+\\.)*[\\w\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\`\\{\\|\\}\\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\\-](?!\\.)){0,61}[a-zA-Z0-9]?\\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\\[(?:(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\.){3}(?:[01]?\\d{1,2}|2[0-4]\\d|25[0-5])\\]))$/.test(\n stringToTest.toLowerCase(),\n );\n\nexport const getEmailErrors = (email: Readonly<FormField<string>>, mustBeValidEmail: string) => {\n const errors = {\n validEmail: isValidEmail(email.value)\n ? null\n : {\n id: 'validEmail',\n field: 'email' as const,\n message: mustBeValidEmail,\n },\n };\n return errors;\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n emailLabel: translate({ id: `sections.forgotPassword.emailLabel` }),\n resetPassword: translate({ id: `sections.forgotPassword.resetPassword` }),\n enterEmail: translate({ id: `sections.forgotPassword.enterEmail` }),\n sendEmail: translate({ id: `sections.forgotPassword.sendEmail` }),\n failedToSendEmail: translate({ id: `sections.forgotPassword.failedToSendEmail` }),\n emailHasBeenSent: translate({ id: `sections.forgotPassword.emailHasBeenSent` }),\n resetRequested: translate({ id: `sections.forgotPassword.resetRequested` }),\n close: translate({ id: `sections.forgotPassword.close` }),\n mustBeValidEmail: translate({ id: `sections.emailRequirements.mustBeValidEmail` }),\n };\n }, [translate]);\n}\n","import type { ReactElement } from 'react';\n\nimport { QueryClientProvider } from 'react-query';\n\nimport { queryClient } from './queryClient';\n\ninterface Props {\n children: ReactElement;\n}\n\n/**\n * react-query provider.\n * Rendered using a custom client cache.\n */\nexport function ReactQueryProvider(props: Props) {\n const { children } = props;\n\n return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;\n}\n","import axios from 'axios';\nimport { post, put, get } from '@/utils/http';\nimport { prepareServerError, ServerError } from '@/utils/ServerError';\n\nexport const requestResetPasswordLink = async (email: string, abortSignal?: AbortSignal) => {\n const source = axios.CancelToken.source();\n\n const handleOnAbort = () => source.cancel();\n abortSignal?.addEventListener('abort', handleOnAbort);\n const options = abortSignal\n ? { cancelToken: source.token, headers: { 'Content-Type': 'application/json' } }\n : { headers: { 'Content-Type': 'application/json' } };\n\n try {\n const response = await post('/api/customerPortalUsers/password', JSON.stringify(email), options);\n if (response.status === 200 || response.status === 201) {\n return response.data;\n }\n\n throw new Error(`${response.status} - ${response.statusText}`);\n } catch (e) {\n throw e;\n } finally {\n abortSignal?.removeEventListener('abort', handleOnAbort);\n }\n};\n\nexport const resetPassword = async (linkHash: string, newPassword: string, abortSignal?: AbortSignal) => {\n const source = axios.CancelToken.source();\n\n const handleOnAbort = () => source.cancel();\n abortSignal?.addEventListener('abort', handleOnAbort);\n const options = abortSignal ? { cancelToken: source.token } : undefined;\n\n try {\n const response = await put(\n '/api/customerPortalUsers/password',\n { linkHash: linkHash, newPassword: newPassword },\n options,\n );\n if (response.status === 200 || response.status === 201) {\n return response.data;\n }\n\n throw new Error(`${response.status} - ${response.statusText}`);\n } catch (e) {\n throw e;\n } finally {\n abortSignal?.removeEventListener('abort', handleOnAbort);\n }\n};\n\nexport const changePassword = async (oldPassword: string, newPassword: string) => {\n try {\n const { data, status } = await put<boolean>(`api/customerPortalUsers`, {\n oldPassword: oldPassword,\n newPassword: newPassword,\n });\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(data + '', status);\n } catch (e) {\n throw prepareServerError(e);\n }\n};\n\nexport const validateLinkHash = async (linkHash: string) => {\n try {\n const { data, status } = await get<boolean>(`api/customerPortalUsers/resetPasswordLinkHash/${linkHash}/`);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(data + '', status);\n } catch (e) {\n throw prepareServerError(e);\n }\n};\n","import { useState, useRef, useEffect, useCallback } from 'react';\n\nimport { requestResetPasswordLink } from '@/services';\nimport { useToast } from '@/utils/useToast';\n\nexport function useForgotPasswordActions() {\n const toast = useToast();\n\n // --------------------------------------\n // Mounted state ref for async callbacks\n\n const unmounted = useRef(false);\n useEffect(() => () => void (unmounted.current = true));\n\n // --------------------------------------\n // local state to track state of the login request\n\n const [submitting, setSubmitting] = useState(false);\n\n // --------------------------------------\n // callbacks\n const resetPassword = useCallback(async (email: string): Promise<null> => {\n try {\n setSubmitting(true);\n\n const resetPasswordRequest = await requestResetPasswordLink(email);\n\n if (!unmounted.current) setSubmitting(false);\n\n if (resetPasswordRequest === true) {\n return null;\n } else {\n console.log(`Error during request`);\n // TODO: navigate 404 page\n return null;\n }\n } catch (e) {\n // TODO: navigate 404 page\n return null;\n } finally {\n setSubmitting(false);\n }\n }, []);\n\n const notifyError = useCallback((message: string) => toast.error(message), [toast]);\n\n const notifySuccess = useCallback((message: string) => toast.success(message), [toast]);\n\n // --------------------------------------\n // --------------------------------------\n return {\n submitting,\n\n resetPassword,\n notifyError,\n notifySuccess,\n } as const;\n}\n","import type { FormFields } from './formFields';\nimport type { FormError } from '@/formState';\nimport Button from '@mui/material/Button';\nimport Box from '@mui/material/Box';\nimport LinearProgress from '@mui/material/LinearProgress';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Typography from '@mui/material/Typography';\nimport { useFormMeta } from '@/formState';\nimport { useCallback, MouseEvent } from 'react';\n\ninterface Props {\n handleOnSubmit: () => Promise<void>;\n buttonText: string;\n failedText?: string;\n disabled?: boolean;\n}\n\nexport function Footer(props: Props) {\n const { handleOnSubmit, buttonText, failedText, disabled = false } = props;\n const { meta, api } = useFormMeta<FormFields, FormError<keyof FormFields>>();\n\n const formInvalid = meta.status === 'invalid';\n const formIndeterminate = meta.status === 'indeterminate';\n const formHasError = formInvalid || (formIndeterminate && Object.keys(api.getErrors()).length > 0);\n\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n handleOnSubmit();\n },\n [handleOnSubmit],\n );\n\n return (\n <Box width=\"100%\">\n {meta.validating && <LinearProgress />}\n <Button\n fullWidth\n color=\"primary\"\n variant=\"contained\"\n onClick={handleClick}\n disabled={meta.submitting || disabled}\n size=\"small\"\n type=\"submit\"\n data-testid=\"btn-forgotPassword\"\n >\n {meta.submitting && <CircularProgress size={16} />}\n <Box ml={1}>{buttonText}</Box>\n </Button>\n {formHasError && !!failedText ? <Typography color=\"error\">{failedText}</Typography> : null}\n </Box>\n );\n}\n","import Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useCallback, useEffect, useState } from 'react';\nimport { useFormMeta, FormError, FormValidator } from '@/formState';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport Grid from '@mui/material/Grid';\nimport { useNavigate } from 'react-router';\nimport { TextField } from '@/formUI';\nimport { getEmailErrors } from '@/components/PasswordRequirements/utils';\nimport { useTexts } from '../useTexts';\nimport { useForgotPasswordActions } from '../useForgotPasswordActions';\nimport { Footer } from './Footer';\nimport { FormErrors, FormFields } from './formFields';\n\nconst useStyles = makeStyles({\n section: {\n width: '350px',\n },\n container: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n },\n});\n\nenum formStates {\n ForgotPassword,\n ResetRequested,\n}\n\nexport const Form = () => {\n const texts = useTexts();\n const [formState, setFormState] = useState<formStates>(formStates.ForgotPassword);\n const { resetPassword } = useForgotPasswordActions();\n const { api, meta } = useFormMeta<FormFields, FormError<keyof FormFields>>();\n const classes = useStyles();\n const navigate = useNavigate();\n\n const handleOnResetPassword = useCallback(async () => {\n api.setSubmitting(true);\n const values = api.getValues();\n await resetPassword(values.email);\n setFormState(formStates.ResetRequested);\n api.setSubmitting(false);\n }, [api, resetPassword]);\n\n const validateForm: FormValidator<FormFields, FormErrors> = formApi => {\n const email = formApi.getField('email');\n\n const errors = getEmailErrors(email, texts.mustBeValidEmail);\n return errors;\n };\n\n useEffect(() => {\n validateForm;\n if (!api.getValidator('validEmail')) {\n api.addValidation('validEmail', validateForm);\n }\n });\n\n return (\n <Box className={classes.container}>\n <Section className={classes.section}>\n {formState === formStates.ForgotPassword && (\n <form>\n <SectionHeader title={texts.resetPassword} />\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Typography>{texts.enterEmail}</Typography>\n </Grid>\n <Grid item>\n <TextField<'email', FormFields, FormErrors>\n name=\"email\"\n textField={{\n type: 'email',\n fullWidth: true,\n }}\n validateOn=\"change\"\n label={texts.emailLabel}\n />\n </Grid>\n <Grid item>\n <Footer\n handleOnSubmit={handleOnResetPassword}\n buttonText={texts.sendEmail}\n disabled={meta.status !== 'valid'}\n />\n </Grid>\n </Grid>\n </form>\n )}\n\n {formState === formStates.ResetRequested && (\n <>\n <SectionHeader title={texts.emailHasBeenSent} />\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Typography>{texts.resetRequested}</Typography>\n </Grid>\n <Grid item>\n <Footer\n handleOnSubmit={async () => {\n navigate('/login');\n }}\n buttonText={texts.close}\n />\n </Grid>\n </Grid>\n </>\n )}\n </Section>\n </Box>\n );\n};\n","import { FormRoot, useCreateForm } from '@/formState';\nimport { formFields } from './formFields';\nimport { Form } from './Form';\n\nexport function FormProvider() {\n const formState = useCreateForm('forgot-password-form', formFields);\n\n return (\n <FormRoot formState={formState}>\n <Form />\n </FormRoot>\n );\n}\n","import { ContentContainer } from '@/components/ContentContainer';\nimport { ContentPaper } from '@/components/ContentPaper';\nimport { FormProvider } from './form/FormProvider';\n\nexport const ForgotPassword = () => {\n return (\n <ContentContainer>\n <ContentPaper fullWidth>\n <FormProvider />\n </ContentPaper>\n </ContentContainer>\n );\n};\n","import type { FormError, FormField } from '@/formState';\n\nconst emailField: FormField<string> = { value: '', required: true };\nconst passwordField: FormField<string> = { value: '', required: true };\n\nexport const formFields = {\n email: emailField,\n password: passwordField,\n};\n\nexport type FormFields = typeof formFields;\nexport type FormErrors = FormError<keyof FormFields>;\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n welcome: translate({ id: `sections.login.welcome` }),\n header: translate({ id: `sections.login.header` }),\n login: translate({ id: `sections.login.login` }),\n loginFailed: translate({ id: `sections.login.loginFailed` }),\n rememberMe: translate({ id: `sections.login.rememberMe` }),\n forgotPassword: translate({ id: `sections.login.forgotPassword` }),\n emailLabel: translate({ id: `sections.login.emailLabel` }),\n passwordLabel: translate({ id: `sections.login.passwordLabel` }),\n selectAnAccount: translate({ id: `sections.login.selectAnAccount` }),\n };\n }, [translate]);\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { getUser, login as loginAction, setAccountId } from '@/atoms/session';\nimport { useToast } from '@/utils/useToast';\nimport { useFormApi } from '@/formState';\nimport { fetchAccountsByContactId } from '@/services';\nimport { useFetchCustomerPortalSettings } from '@/common/hooks/query/useFetchCustomerPortalSettings';\nimport { FormErrors, FormFields } from '../form/formFields';\nimport { setAccountSelect, setError } from '../store';\nimport { useTexts } from './useTexts';\n\nexport function useLoginActions() {\n const toast = useToast();\n const navigate = useNavigate();\n const api = useFormApi<FormFields, FormErrors>();\n const texts = useTexts();\n const [selectedBusinessUnitId, setSelectedBusinessUnitId] = useState<string>('');\n const { refetch } = useFetchCustomerPortalSettings(selectedBusinessUnitId);\n\n // --------------------------------------\n // Mounted state ref for async callbacks\n\n const unmounted = useRef(false);\n useEffect(() => () => void (unmounted.current = true), []);\n\n // --------------------------------------\n // callbacks\n const afterLoginRedirect = useCallback(() => {\n navigate('/account-overview');\n document.body.scrollIntoView();\n }, [navigate]);\n\n const notifyError = useCallback((message: string) => toast.error(message), [toast]);\n\n const handleOnAccountSelect = useCallback(\n async (account: Account.AccountSelect) => {\n if (!!account) {\n setAccountId(account);\n setSelectedBusinessUnitId(account.businessUnitId);\n refetch();\n afterLoginRedirect();\n }\n },\n [afterLoginRedirect, refetch],\n );\n\n const login = useCallback(async () => {\n try {\n if (!unmounted.current) {\n setError('');\n }\n api.setSubmitting(true);\n\n const { email, password } = api.getValues();\n const loginRequest = await loginAction(email, password);\n\n if (loginRequest === true) {\n const user = getUser();\n if (!!user) {\n const accounts = await fetchAccountsByContactId(user.contactId);\n\n if (accounts?.length == 1) {\n handleOnAccountSelect(accounts[0]);\n } else if (!!accounts?.length && accounts.length > 1) {\n setAccountSelect(accounts);\n } else {\n if (!unmounted.current) {\n setError('');\n }\n }\n }\n return true;\n } else {\n setError(texts.loginFailed);\n console.log(`Error during login`);\n return false;\n }\n } catch (e) {\n return false;\n } finally {\n api.setSubmitting(false);\n }\n }, [api, texts, handleOnAccountSelect]);\n\n const handleOnForgotPasswordClick = useCallback(() => {\n navigate('/forgot-password');\n }, [navigate]);\n\n return {\n login,\n notifyError,\n afterLoginRedirect,\n handleOnAccountSelect,\n handleOnForgotPasswordClick,\n } as const;\n}\n","import type { FormFields } from './formFields';\nimport type { FormError } from '@/formState';\nimport Button from '@mui/material/Button';\nimport Box from '@mui/material/Box';\nimport LinearProgress from '@mui/material/LinearProgress';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Typography from '@mui/material/Typography';\nimport { useFormMeta } from '@/formState';\nimport { useCallback, MouseEvent } from 'react';\nimport { useTexts } from '../hooks/useTexts';\n\ninterface Props {\n handleOnSubmit: () => Promise<boolean>;\n}\n\nexport function Footer(props: Props) {\n const { handleOnSubmit } = props;\n const { meta, api } = useFormMeta<FormFields, FormError<keyof FormFields>>();\n const texts = useTexts();\n\n const formInvalid = meta.status === 'invalid';\n const formIndeterminate = meta.status === 'indeterminate';\n const formHasError = formInvalid || (formIndeterminate && Object.keys(api.getErrors()).length > 0);\n\n const handleOnClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n handleOnSubmit();\n },\n [handleOnSubmit],\n );\n\n return (\n <Box width=\"100%\">\n {meta.validating && <LinearProgress />}\n\n <Button\n fullWidth\n color=\"primary\"\n variant=\"contained\"\n onClick={handleOnClick}\n disabled={meta.submitting}\n size=\"small\"\n type=\"submit\"\n data-testid=\"btn-signIn\"\n >\n {meta.submitting && <CircularProgress size={16} />}\n <Box ml={1}>{texts.login}</Box>\n </Button>\n\n {formHasError ? <Typography color=\"error\">{texts.loginFailed}</Typography> : null}\n </Box>\n );\n}\n","import MuiButton, { ButtonProps as MuiButtonProps } from '@mui/material/Button';\n\ninterface ButtonProps extends MuiButtonProps {\n children?: string;\n}\n\nexport const Button = (props: ButtonProps) => {\n const { children, ...MuiProps } = props;\n return (\n <MuiButton variant=\"contained\" size=\"small\" {...MuiProps}>\n {children}\n </MuiButton>\n );\n};\n","import { Button } from '@/components/Button';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useTexts } from '../hooks/useTexts';\n\nconst useStyles = makeStyles({\n button: {\n textTransform: 'none',\n },\n});\n\ninterface Props {\n handleClick: React.MouseEventHandler;\n}\n\nexport const ForgotPasswordButton = (props: Props) => {\n const { handleClick } = props;\n const classes = useStyles();\n const texts = useTexts();\n return (\n <Button variant=\"text\" color=\"primary\" className={classes.button} onClick={handleClick}>\n {texts.forgotPassword}\n </Button>\n );\n};\n","import { AccountSwitch } from '@/components/AccountSwitch';\nimport Typography from '@mui/material/Typography';\nimport Box from '@mui/material/Box';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport Grid from '@mui/material/Grid';\nimport { TextField } from '@/formUI';\nimport { useLoginActions } from '../hooks/useLoginActions';\nimport { useTexts } from '../hooks/useTexts';\nimport { useLoginState } from '../store';\nimport { Footer } from './Footer';\nimport { FormErrors, FormFields } from './formFields';\nimport { ForgotPasswordButton } from './ForgotPasswordButton';\n\nconst useStyles = makeStyles({\n section: {\n width: '350px',\n },\n container: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n },\n});\n\nexport const Form = () => {\n const texts = useTexts();\n const { accountSelect, error } = useLoginState();\n const { login, handleOnAccountSelect, handleOnForgotPasswordClick } = useLoginActions();\n const classes = useStyles();\n\n return (\n <Box className={classes.container}>\n <Section className={classes.section}>\n {!accountSelect.length && (\n <form>\n <SectionHeader title={texts.welcome} />\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Typography>{texts.header}</Typography>\n </Grid>\n <Grid item>\n <TextField<'email', FormFields, FormErrors>\n name=\"email\"\n label={texts.emailLabel}\n validateOn=\"change blur\"\n textField={{\n 'type': 'email',\n }}\n UNSTABLE_textField={{\n 'autoComplete': 'username',\n 'inputProps': { 'data-testid': 'textField-email' },\n }}\n />\n </Grid>\n <Grid item>\n <TextField<'password', FormFields, FormErrors>\n name=\"password\"\n label={texts.passwordLabel}\n validateOn=\"change blur\"\n textField={{\n 'type': 'password',\n }}\n UNSTABLE_textField={{\n 'autoComplete': 'current-password',\n 'inputProps': { 'data-testid': 'textField-password' },\n }}\n />\n </Grid>\n <Grid item>\n <Footer handleOnSubmit={login} />\n </Grid>\n <Grid item>\n <Box display=\"flex\" flexDirection=\"row-reverse\" alignItems=\"center\">\n <ForgotPasswordButton handleClick={handleOnForgotPasswordClick} />\n </Box>\n </Grid>\n {!!error && (\n <Grid item>\n <Typography color=\"error\">{error}</Typography>\n </Grid>\n )}\n </Grid>\n </form>\n )}\n\n {!!accountSelect.length && (\n <AccountSwitch\n title={texts.selectAnAccount}\n onAccountSelected={handleOnAccountSelect}\n accountsList={accountSelect}\n wrappingContainer={true}\n />\n )}\n </Section>\n </Box>\n );\n};\n","import { FormRoot, useCreateForm } from '@/formState';\nimport { formFields } from './formFields';\nimport { Form } from './Form';\n\nexport function FormProvider() {\n const formState = useCreateForm('login-form', formFields);\n\n return (\n <FormRoot formState={formState}>\n <Form />\n </FormRoot>\n );\n}\n","import { tenantService } from '@/atoms/session';\nimport { useQuery } from 'react-query';\n\nexport const useFetchTenantId = () =>\n useQuery('tenantId', () => tenantService(), {\n staleTime: Infinity,\n });\n","import { useFetchTenantId } from '@/common/hooks/query/useQueryLoadTenant';\nimport { useEffect, useState } from 'react';\nimport { useNavigate } from 'react-router';\n\nexport const useCheckSubdomain = () => {\n const result = useFetchTenantId();\n const navigate = useNavigate();\n const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading');\n\n useEffect(() => {\n let unmounted = false;\n if (unmounted) return;\n\n if (result.isFetched) {\n if (result.isSuccess) {\n setStatus('success');\n } else {\n setStatus('error');\n navigate('/unknown');\n }\n } else {\n setStatus('loading');\n }\n return () => void (unmounted = true);\n }, [navigate, result]);\n\n return status;\n};\n","import { ContentContainer } from '@/components/ContentContainer';\nimport { Box } from '@mui/material';\nimport { FormProvider } from './form/FormProvider';\nimport { useCheckSubdomain } from './hooks/useCheckSubdomain';\n\nexport const Login = () => {\n const status = useCheckSubdomain();\n\n return (\n <>\n {status === 'success' && (\n <ContentContainer>\n <Box display=\"flex\" justifyContent=\"center\" alignItems=\"center\" width=\"100%\">\n <FormProvider />\n </Box>\n </ContentContainer>\n )}\n </>\n );\n};\n","import { getDefaultBillingLocation } from '@/api/accounts';\nimport { BillingLocation } from '@/api/billingLocations';\nimport { useQuery } from 'react-query';\n\nexport const useFetchDefaultBillingLocation = (accountId: string) =>\n useQuery<BillingLocation, Error>(\n [accountId, 'defaultBillingLocation'],\n () => getDefaultBillingLocation(accountId),\n {\n staleTime: Infinity,\n },\n );\n","import { Box, Typography } from '@mui/material';\n\ninterface Props {\n description?: string;\n title: string;\n}\n\nexport function PageHeader(props: Props) {\n const { description, title } = props;\n\n return (\n <Box>\n <Typography variant=\"h2\" gutterBottom>\n {title}\n </Typography>\n {!!description && <Typography>{description}</Typography>}\n </Box>\n );\n}\n","interface staggeredPagination {\n page: number;\n take: number;\n skip: number;\n}\n\nexport function staggerPagination(page: number, take: number, stagger: number): staggeredPagination | undefined {\n const n = (page + 1) * take;\n\n // The take in this case would be 0, which would throw an error in the API.\n // Add handling in the function that calls this one if this is a possibility.\n if (n <= stagger) {\n return undefined;\n }\n\n const adjN = n - stagger;\n const adjTake = adjN >= take ? take : adjN;\n const adjPage = Math.floor(adjN / adjTake) - 1;\n const skip = adjN % adjTake;\n\n return {\n page: adjPage,\n take: adjTake,\n skip: skip,\n };\n}\n","import { getOpenInvoices } from '@/api/accounts';\nimport { GetOpenInvoicesResponse } from '@/common/types/invoices';\nimport { staggerPagination } from '@/common/utils/staggerPagination';\nimport { useQuery } from 'react-query';\n\nexport const useFetchOpenInvoices = (accountId: string, page: number, take: number, stagger?: number) =>\n useQuery<GetOpenInvoicesResponse, Error>(\n ['open-invoices', accountId, page, take],\n () => {\n const { page: adjustedPage, take: adjustedTake, skip } = staggerPagination(page, take, stagger || 0)!;\n return getOpenInvoices(accountId, adjustedPage, adjustedTake, skip);\n },\n {\n staleTime: Infinity,\n },\n );\n","import { getUnappliedStartingBalance } from '@/api/accounts';\nimport { useQuery } from 'react-query';\n\nexport const useFetchUnappliedStartingBalance = (accountId: string) =>\n useQuery<number, Error>(['unapplied-starting-balance', accountId], () => getUnappliedStartingBalance(accountId), {\n staleTime: Infinity,\n });\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n deselect: translate({ id: 'global.deselect' }),\n invoice: translate({ id: 'global.invoice' }),\n invoiceTotal: {\n invoicePlural: translate({ id: 'sections.payInvoices.invoiceTotal.invoicePlural' }),\n invoiceSingular: translate({ id: 'sections.payInvoices.invoiceTotal.invoiceSingular' }),\n paymentTotalFor: translate({ id: 'sections.payInvoices.invoiceTotal.paymentTotalFor' }),\n selectPaymentMethod: translate({ id: 'sections.payInvoices.invoiceTotal.selectPaymentMethod' }),\n },\n locationHasErrors: translate({ id: 'sections.payInvoices.locationHasErrors' }),\n noInvoicesToDisplay: translate({ id: 'sections.payInvoices.list.noInvoicesToDisplay' }),\n notImplementedYet: translate({ id: 'global.notImplementedYet' }),\n open: translate({ id: 'global.open' }),\n pageDescription: translate({ id: 'sections.payInvoices.pageDescription' }),\n pageSubtitle: translate({ id: 'sections.payInvoices.pageSubtitle' }),\n pageTitle: translate({ id: 'sections.payInvoices.pageTitle' }),\n select: translate({ id: 'global.select' }),\n unappliedStartingBalance: translate({ id: 'sections.payInvoices.unappliedStartingBalance' }),\n };\n }, [translate]);\n}\n","import * as _ from 'lodash';\nimport { proxy, useSnapshot } from 'valtio';\nimport { InvoiceListItem } from '@/common/types/invoices';\nimport { PaymentAccount } from '@/common/types/payments';\n\nexport enum InvoiceWizardStep {\n SelectSavedPaymentMethod = 1,\n NewCardSave = 2,\n NewCardOneTime = 3,\n}\nexport interface PayInvoicesState {\n invoicePagination: {\n page: number;\n take: number;\n };\n paymentMethod: PaymentAccount | null;\n invoicesSelected: InvoiceListItem[];\n startingBalancePayment: number;\n status: 'error' | 'loading' | 'success';\n wizardStep: InvoiceWizardStep;\n}\n\nexport const initialState: PayInvoicesState = {\n invoicePagination: {\n page: 0,\n take: 10,\n },\n paymentMethod: null,\n invoicesSelected: [],\n startingBalancePayment: 0,\n status: 'loading',\n wizardStep: InvoiceWizardStep.SelectSavedPaymentMethod,\n};\n\nexport function resetPayInvoicesState() {\n state.invoicePagination = {\n page: 0,\n take: 10,\n };\n state.paymentMethod = null;\n state.invoicesSelected = [];\n state.startingBalancePayment = 0;\n state.status = 'loading';\n state.wizardStep = InvoiceWizardStep.SelectSavedPaymentMethod;\n}\n\n// Valtio store initialization\nconst state = proxy<PayInvoicesState>(initialState);\n\n// Setter functions\nexport function addInvoice(invoice: InvoiceListItem) {\n state.invoicesSelected.push(invoice);\n}\n\nexport function clearSelectedInvoices() {\n state.invoicesSelected = [];\n}\n\nexport function removeInvoice(invoice: InvoiceListItem) {\n const updatedInvoices = _.cloneDeep(state.invoicesSelected.filter(i => i.invoiceId != invoice.invoiceId));\n state.invoicesSelected = updatedInvoices;\n}\n\nexport function selectUnappliedStartingBalance(balance: number) {\n state.startingBalancePayment = balance;\n}\n\nexport function unSelectUnappliedStartingBalance() {\n state.startingBalancePayment = 0;\n}\n\nexport function resetInvoicePaymentDetails() {\n state.paymentMethod = null;\n state.wizardStep = InvoiceWizardStep.SelectSavedPaymentMethod;\n}\n\nexport function setPaymentMethod(paymentAccount: PaymentAccount) {\n state.paymentMethod = { ...paymentAccount };\n}\n\nexport function setPage(pageNumber: number) {\n state.invoicePagination.page = pageNumber;\n}\n\nexport function setWizardStep(step: InvoiceWizardStep) {\n state.wizardStep = step;\n}\n\n// Hooks\nexport function usePayInvoicesState() {\n return useSnapshot(state);\n}\n\nexport function usePaymentTotal() {\n const snapshot = useSnapshot(state);\n return snapshot.invoicesSelected.reduce((a, b) => a + b.balance || 0, 0) + snapshot.startingBalancePayment;\n}\n\nexport function useIsInvoiceSelected(invoice: InvoiceListItem) {\n return useSnapshot(state).invoicesSelected.filter(i => i.invoiceId == invoice.invoiceId).length > 0;\n}\n\nexport function useIsPaymentMethodSelected(paymentMethod: PaymentAccount) {\n return useSnapshot(state).paymentMethod?.paymentAccountId == paymentMethod.paymentAccountId;\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faFileInvoiceDollar } from '@fortawesome/pro-regular-svg-icons';\nimport { useCallback } from 'react';\nimport { Currency, ShortDate } from '@/components/localization';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport { InvoiceListItem } from '@/common/types/invoices';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { Box, Typography } from '@mui/material';\nimport { useTexts } from './useTexts';\nimport { addInvoice, removeInvoice, useIsInvoiceSelected } from './store';\n\ninterface TitleProps {\n date: Date;\n invoiceNumber: string;\n}\n\nfunction Title(props: TitleProps) {\n const { date, invoiceNumber } = props;\n const texts = useTexts();\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Typography noWrap>\n <ShortDate value={date} />\n {` ${texts.invoice} #${invoiceNumber}`}\n </Typography>\n </Box>\n );\n}\n\ninterface Props {\n invoice: InvoiceListItem;\n disableSelection: boolean;\n}\n\nexport function InvoiceCard(props: Props) {\n const { invoice, disableSelection } = props;\n const texts = useTexts();\n const layout = useGetUILayout();\n\n const isSelected = useIsInvoiceSelected(invoice);\n\n const handleClick = useCallback(() => {\n isSelected ? removeInvoice(invoice) : addInvoice(invoice);\n }, [invoice, isSelected]);\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n actionBtnText={isSelected ? texts.deselect : texts.select}\n icon={<FontAwesomeIcon icon={faFileInvoiceDollar} />}\n onClick={handleClick}\n selected={isSelected}\n subTitle={<Currency value={invoice.balance || 0} />}\n title={<Title date={invoice.invoiceDate} invoiceNumber={invoice.invoiceNum} />}\n disabled={disableSelection}\n showTooltip={disableSelection}\n toolTipText={texts.locationHasErrors}\n />\n ) : (\n <MobileListCard\n actionBtnText={isSelected ? texts.deselect : texts.select}\n icon={<FontAwesomeIcon icon={faFileInvoiceDollar} />}\n onClick={handleClick}\n selected={isSelected}\n subTitle={<Currency value={invoice.balance || 0} />}\n title={<Title date={invoice.invoiceDate} invoiceNumber={invoice.invoiceNum} />}\n disabled={disableSelection}\n showTooltip={disableSelection}\n toolTipText={texts.locationHasErrors}\n />\n )}\n </>\n );\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faFileInvoiceDollar } from '@fortawesome/pro-regular-svg-icons';\nimport { Currency } from '@/components/localization';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { Box, Typography } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport { useTexts } from './useTexts';\nimport { selectUnappliedStartingBalance, unSelectUnappliedStartingBalance, usePayInvoicesState } from './store';\n\nfunction Title() {\n const texts = useTexts();\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Typography noWrap>{texts.unappliedStartingBalance}</Typography>\n </Box>\n );\n}\n\ninterface Props {\n balance: number;\n}\n\nexport function UnappliedStartingBalanceCard(props: Props) {\n const { balance } = props;\n const texts = useTexts();\n const layout = useGetUILayout();\n\n const { startingBalancePayment } = usePayInvoicesState();\n\n const isSelected = useMemo(() => startingBalancePayment > 0, [startingBalancePayment]);\n\n const handleClick = useCallback(() => {\n isSelected ? unSelectUnappliedStartingBalance() : selectUnappliedStartingBalance(balance);\n }, [isSelected, balance]);\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n actionBtnText={isSelected ? texts.deselect : texts.select}\n icon={<FontAwesomeIcon icon={faFileInvoiceDollar} />}\n onClick={handleClick}\n selected={isSelected}\n subTitle={<Currency value={balance} />}\n title={<Title />}\n />\n ) : (\n <MobileListCard\n actionBtnText={isSelected ? texts.deselect : texts.select}\n icon={<FontAwesomeIcon icon={faFileInvoiceDollar} />}\n onClick={handleClick}\n selected={isSelected}\n subTitle={<Currency value={balance} />}\n title={<Title />}\n />\n )}\n </>\n );\n}\n","import { useFetchOpenInvoices } from '@/common/hooks/query/useFetchOpenInvoices';\nimport { useFetchUnappliedStartingBalance } from '@/common/hooks/query/useFetchUnappliedStartingBalance';\nimport { PageErrorState } from '@/components/PageErrorState/PageErrorState';\nimport { Alert, Pagination, Stack } from '@mui/material';\nimport { useMemo } from 'react';\nimport { LoadingSkeleton } from '../AccountHistory/LoadingSkeleton';\nimport { InvoiceCard } from './InvoiceCard';\nimport { setPage, usePayInvoicesState } from './store';\nimport { UnappliedStartingBalanceCard } from './UnappliedStartingBalanceCard';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n accountId: string;\n disableSelection: boolean;\n}\n\nexport function InvoiceList(props: Props) {\n const { accountId, disableSelection } = props;\n const {\n invoicePagination: { page, take },\n } = usePayInvoicesState();\n\n const unappliedStartingBalance = useFetchUnappliedStartingBalance(accountId || '');\n const hasStartingBalance = useMemo(\n () => unappliedStartingBalance.status === 'success' && unappliedStartingBalance.data > 0,\n [unappliedStartingBalance],\n );\n const stagger = hasStartingBalance ? 1 : 0;\n const query = useFetchOpenInvoices(accountId, page, take, stagger);\n const texts = useTexts();\n\n return (\n <>\n {query.status === 'loading' && <LoadingSkeleton />}\n {query.status === 'success' && unappliedStartingBalance.status === 'success' && query.data && (\n <>\n {(query.data.items.length > 0 || hasStartingBalance) && (\n <Stack direction=\"column\">\n {hasStartingBalance && page == 0 && (\n <UnappliedStartingBalanceCard balance={unappliedStartingBalance.data} />\n )}\n {query.data.items.map((invoice, i) => (\n <InvoiceCard key={i} invoice={invoice} disableSelection={disableSelection} />\n ))}\n <Pagination\n color=\"primary\"\n count={Math.ceil(\n (query.data.total + (unappliedStartingBalance.data > 0 ? 1 : 0)) / take,\n )}\n onChange={(_e, p) => {\n setPage(p - 1);\n }}\n page={page + 1}\n sx={{ mb: 2 }}\n />\n </Stack>\n )}\n\n {query.data.items.length == 0 && !hasStartingBalance && (\n <Alert severity=\"info\">{texts.noInvoicesToDisplay}</Alert>\n )}\n </>\n )}\n {query.status === 'error' && <PageErrorState />}\n </>\n );\n}\n","import {\n HostedPaymentStatus,\n PaymentMethodMapping,\n PaymentSource,\n PaymentStatus,\n TransactionSetupMethod,\n} from '@/common/types/payments';\nimport { useToast } from '@/utils/useToast';\nimport { Alert, FormControl, FormControlLabel, Radio, RadioGroup, Typography } from '@mui/material';\nimport { useCallback, useState } from 'react';\nimport { Currency } from '@/components/localization';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { useAccountId } from '@/atoms/session';\nimport { processPayment } from '@/api/payments';\nimport { getAccount, getUser } from '@/atoms/session/store';\nimport { isServerError } from '@/utils/ServerError';\nimport { useFetchOpenInvoices } from '@/common/hooks/query/useFetchOpenInvoices';\nimport { useFetchAccountSummary } from '@/common/hooks/query/useFetchAccountSummary';\nimport { useFetchUnappliedStartingBalance } from '@/common/hooks/query/useFetchUnappliedStartingBalance';\nimport { CreditCardEntry } from '../../PaymentMethods/drawers/AddPaymentMethod/CreditCardEntry';\nimport { queryClient } from '../../../services/queryClient';\nimport {\n InvoiceWizardStep,\n resetPayInvoicesState,\n setPaymentMethod,\n setWizardStep,\n usePaymentTotal,\n usePayInvoicesState,\n} from '../store';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onClose: () => void;\n}\n\nexport function AddNewCreditCard(props: Props) {\n const { onClose } = props;\n const accountId = useAccountId();\n const user = getUser();\n const account = getAccount();\n const [selection, setSelection] = useState<TransactionSetupMethod>(TransactionSetupMethod.PaymentAccountCreate);\n const toast = useToast();\n const total = usePaymentTotal();\n const { addCard: texts } = useTexts();\n const { refetch } = useQueryPaymentAccounts(accountId || '');\n const { invoicesSelected, startingBalancePayment } = usePayInvoicesState();\n const {\n invoicePagination: { page, take },\n } = usePayInvoicesState();\n const { refetch: refetchOpenInvoices } = useFetchOpenInvoices(accountId || '', page, take);\n const { refetch: refetchAccountSummary } = useFetchAccountSummary(accountId || '');\n const { refetch: refetchUnappliedStartingBalance } = useFetchUnappliedStartingBalance(accountId || '');\n\n const handleSelection = (event: React.ChangeEvent<{ value: unknown }>) => {\n const value = event.target.value as TransactionSetupMethod;\n setSelection(value);\n };\n\n const handleCancel = useCallback(() => {\n setWizardStep(InvoiceWizardStep.SelectSavedPaymentMethod);\n }, []);\n\n const onOneTimePaymentSuccess = useCallback(\n async (\n _paymentAccountId: string,\n paymentStatus: HostedPaymentStatus,\n friendlyValue: string,\n transactionId: string,\n transactionReferenceNumber?: string,\n processorTransactionLogId?: string,\n partnerRefId?: string,\n ) => {\n if (!account || !user) return;\n\n try {\n const response = await processPayment({\n accountId: account.accountId,\n amount: total,\n businessUnitId: account.businessUnitId,\n employeeId: user.identityUserId,\n friendlyValue: friendlyValue,\n invoicePayments: invoicesSelected.map(i => ({\n amount: i.balance,\n invoiceId: i.invoiceId,\n paymentDate: new Date(),\n })),\n paymentMethod: PaymentMethodMapping.CREDIT_CARD,\n paymentSource: PaymentSource.PORTAL,\n paymentStatus:\n paymentStatus == HostedPaymentStatus.SUCCESS\n ? PaymentStatus.SUCCEEDED\n : PaymentStatus.CANCELLED,\n processorTransactionId: processorTransactionLogId,\n startingBalancePayment: startingBalancePayment || 0,\n transactionId: transactionId,\n transactionReferenceNumber: transactionReferenceNumber,\n partnerRefId: partnerRefId,\n });\n\n if (isServerError(response)) {\n toast.error(texts.paymentFailed);\n }\n\n toast.success(texts.paymentSuccessful);\n queryClient.invalidateQueries(['account-summary', 'open-invoices', 'unapplied-starting-balance']);\n await Promise.all([refetchOpenInvoices(), refetchAccountSummary(), refetchUnappliedStartingBalance()]);\n resetPayInvoicesState();\n onClose();\n } catch (e) {\n toast.error(texts.paymentFailed);\n }\n },\n [\n account,\n onClose,\n refetchAccountSummary,\n refetchOpenInvoices,\n refetchUnappliedStartingBalance,\n startingBalancePayment,\n invoicesSelected,\n texts,\n toast,\n total,\n user,\n ],\n );\n\n const onSaveCreditCardSuccess = useCallback(\n async (processorPaymentAccountId: string) => {\n try {\n const response = await refetch();\n\n if (!!response.data && response.data.length) {\n const newPaymentMethod = response.data.find(\n p => p.processorPaymentAccountId == processorPaymentAccountId,\n );\n if (newPaymentMethod) {\n setPaymentMethod(newPaymentMethod);\n }\n }\n setWizardStep(InvoiceWizardStep.SelectSavedPaymentMethod);\n } catch {\n setWizardStep(InvoiceWizardStep.SelectSavedPaymentMethod);\n }\n },\n [refetch],\n );\n\n return (\n <>\n <Typography>{texts.prompt}</Typography>\n <FormControl component=\"fieldset\">\n <RadioGroup onChange={handleSelection} value={selection}>\n <FormControlLabel\n checked={selection == TransactionSetupMethod.PaymentAccountCreate}\n control={<Radio />}\n label={texts.yesOption}\n value={TransactionSetupMethod.PaymentAccountCreate}\n />\n <FormControlLabel\n checked={selection == TransactionSetupMethod.CreditCardSale}\n control={<Radio />}\n label={texts.noOption}\n value={TransactionSetupMethod.CreditCardSale}\n />\n </RadioGroup>\n </FormControl>\n\n {selection == TransactionSetupMethod.CreditCardSale && (\n <>\n <Alert severity=\"info\">\n {texts.infoBox} <Currency value={total} /> {texts.infoBoxPayment}\n </Alert>\n <CreditCardEntry\n amount={total}\n onCancel={handleCancel}\n onSuccess={onOneTimePaymentSuccess}\n transactionSetupMethod={TransactionSetupMethod.CreditCardSale}\n />\n </>\n )}\n\n {selection == TransactionSetupMethod.PaymentAccountCreate && (\n <CreditCardEntry\n onCancel={handleCancel}\n onSuccess={onSaveCreditCardSuccess}\n transactionSetupMethod={TransactionSetupMethod.PaymentAccountCreate}\n />\n )}\n </>\n );\n}\n","import { Currency } from '@/components/localization';\nimport { Alert } from '@mui/material';\nimport { usePaymentTotal, usePayInvoicesState } from '../store';\nimport { useTexts } from './useTexts';\n\nexport function PaymentConfirmationAlert() {\n const { paymentMethod } = usePayInvoicesState();\n const { confirmationAlert: texts } = useTexts();\n const total = usePaymentTotal();\n\n return (\n <Alert severity=\"info\">\n {texts.youAreUsing} "{paymentMethod?.friendly}" {texts.toMakeA} <Currency value={total} />{' '}\n {texts.payment}\n </Alert>\n );\n}\n","import { chargePaymentAccount } from '@/api/payments';\nimport { useAccountId, getUser } from '@/atoms/session';\nimport { getAccount } from '@/atoms/session/store';\nimport { useFetchAccountSummary } from '@/common/hooks/query/useFetchAccountSummary';\nimport { useFetchOpenInvoices } from '@/common/hooks/query/useFetchOpenInvoices';\nimport { useFetchUnappliedStartingBalance } from '@/common/hooks/query/useFetchUnappliedStartingBalance';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { InvoicePayment } from '@/common/types/payments';\nimport { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { useToast } from '@/utils/useToast';\nimport { Alert, Link, Stack, Typography } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport { useMutation } from 'react-query';\nimport { ServerError } from '@/utils/ServerError';\nimport { useNavigate } from 'react-router';\nimport { AccountHistoryState } from 'src/sections/AccountHistory/AccountHistory';\nimport { queryClient } from '../../../services/queryClient';\nimport {\n InvoiceWizardStep,\n resetPayInvoicesState,\n setPaymentMethod,\n setWizardStep,\n usePaymentTotal,\n usePayInvoicesState,\n} from '../store';\nimport { AddNewCreditCard } from './AddNewCreditCard';\nimport { PaymentConfirmationAlert } from './PaymentConfirmationAlert';\nimport { PaymentMethodSelect } from './PaymentMethodSelect';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport const Drawer = (props: Props) => {\n const { onClose, open } = props;\n const accountId = useAccountId();\n const account = getAccount();\n const navigate = useNavigate();\n const texts = useTexts();\n const toast = useToast();\n const user = getUser();\n\n const creditCardEnabled = useFeatureEnabled('enableCreditCardPayment');\n\n const {\n invoicePagination: { page, take },\n paymentMethod,\n invoicesSelected,\n startingBalancePayment,\n wizardStep,\n } = usePayInvoicesState();\n\n const { refetch: refetchAccountSummary } = useFetchAccountSummary(accountId || '');\n const { refetch: refetchOpenInvoices } = useFetchOpenInvoices(accountId || '', page, take);\n const { refetch: refetchUnappliedStartingBalance } = useFetchUnappliedStartingBalance(accountId || '');\n\n const paymentTotal = usePaymentTotal();\n\n const mutation = useMutation(chargePaymentAccount, {\n onError: (error: ServerError) => {\n toast.error(error.errorCode == 400 ? texts.chargePaymentMethod.badRequest : texts.chargePaymentMethod.failed);\n },\n onSuccess: async result => {\n if (!result.failureReason) {\n toast.success(texts.chargePaymentMethod.success);\n resetPayInvoicesState();\n queryClient.invalidateQueries([\n 'account-summary',\n 'open-invoices',\n 'unapplied-starting-balance',\n 'accountHistory',\n ]);\n await Promise.all([refetchOpenInvoices(), refetchAccountSummary(), refetchUnappliedStartingBalance()]);\n onClose();\n navigate('/account-history', {\n state: {\n isStale: true,\n } as AccountHistoryState,\n });\n } else {\n toast.error(texts.chargePaymentMethod.failed);\n }\n },\n });\n\n const onSave = useCallback(() => {\n if (\n !account?.accountId ||\n !account?.businessUnitId ||\n !paymentMethod?.paymentAccountId ||\n !user?.identityUserId\n )\n return;\n\n const invoicePayments: InvoicePayment[] = invoicesSelected.map(i => ({\n amount: i.balance,\n invoiceId: i.invoiceId,\n paymentDate: new Date(),\n }));\n\n mutation.mutate({\n accountId: account.accountId,\n amount: paymentTotal,\n businessUnitId: account.businessUnitId,\n employeeId: user.identityUserId,\n invoicePayments: invoicePayments,\n startingBalancePayment: startingBalancePayment || 0,\n paymentAccountId: paymentMethod.paymentAccountId,\n });\n }, [\n account,\n mutation,\n paymentTotal,\n paymentMethod?.paymentAccountId,\n invoicesSelected,\n user,\n startingBalancePayment,\n ]);\n\n const isProcessingPayment = useMemo(() => {\n return mutation.isLoading;\n }, [mutation.isLoading]);\n\n const isSaveDisabled = useMemo(() => {\n return !paymentMethod || (!invoicesSelected.length && !startingBalancePayment) || isProcessingPayment;\n }, [isProcessingPayment, paymentMethod, invoicesSelected, startingBalancePayment]);\n\n const hideSaveBtn = useMemo(() => {\n return wizardStep != InvoiceWizardStep.SelectSavedPaymentMethod;\n }, [wizardStep]);\n\n const goToAddCreditCardStep = useCallback(() => {\n setWizardStep(InvoiceWizardStep.NewCardSave);\n }, []);\n\n const showBackBtn = useMemo(() => {\n return wizardStep != InvoiceWizardStep.SelectSavedPaymentMethod;\n }, [wizardStep]);\n\n const title = useMemo(() => {\n if (wizardStep == InvoiceWizardStep.SelectSavedPaymentMethod) {\n return texts.header.selectPaymentMethod;\n } else {\n return texts.header.addCreditCard;\n }\n }, [texts.header.addCreditCard, texts.header.selectPaymentMethod, wizardStep]);\n\n const onBackBtnClick = useCallback(() => {\n setWizardStep(InvoiceWizardStep.SelectSavedPaymentMethod);\n }, []);\n\n return (\n <SideDrawerForm\n disableSave={isSaveDisabled}\n hidePrimary={hideSaveBtn}\n isOpen={open}\n onBackBtnClick={onBackBtnClick}\n onClose={onClose}\n onSave={onSave}\n primaryBtnLabel={texts.footer.processPayment}\n primaryBtnLoading={isProcessingPayment}\n secondaryBtnDisabled={isProcessingPayment}\n showBackBtn={showBackBtn}\n title={title}\n >\n <Stack direction=\"column\" spacing={1}>\n {wizardStep == InvoiceWizardStep.SelectSavedPaymentMethod && (\n <>\n {!isProcessingPayment && (\n <>\n {creditCardEnabled && (\n <Typography gutterBottom>\n {texts.useSavedPaymentMethod}{' '}\n <Link onClick={goToAddCreditCardStep}>{texts.addNewPaymentMethod}</Link>\n </Typography>\n )}\n <PaymentMethodSelect onSelect={setPaymentMethod} selected={paymentMethod} />\n\n {!!paymentMethod && <PaymentConfirmationAlert />}\n </>\n )}\n\n {isProcessingPayment && <Alert severity=\"warning\">{texts.processingPaymentAlert}</Alert>}\n </>\n )}\n\n {wizardStep != InvoiceWizardStep.SelectSavedPaymentMethod && <AddNewCreditCard onClose={onClose} />}\n </Stack>\n </SideDrawerForm>\n );\n};\n","import { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { Currency } from '@/components/localization';\nimport { Box, Button, Stack, Typography } from '@mui/material';\nimport { makeStyles } from '@mui/styles';\nimport { useCallback, useMemo } from 'react';\nimport { Drawer } from './drawer/Drawer';\nimport { resetInvoicePaymentDetails, usePayInvoicesState } from './store';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n disableSelection: boolean;\n}\n\nconst useStyles = makeStyles({\n root: {\n fontWeight: 500,\n fontSize: '18px',\n },\n});\n\nexport function InvoiceTotal(props: Props) {\n const { disableSelection } = props;\n const classes = useStyles();\n const { invoicesSelected, startingBalancePayment } = usePayInvoicesState();\n const { invoiceTotal: texts } = useTexts();\n\n const total = useMemo(() => {\n return invoicesSelected.reduce((a, b) => a + b.balance || 0, 0) + startingBalancePayment;\n }, [invoicesSelected, startingBalancePayment]);\n\n const selected = useMemo(() => {\n return invoicesSelected.length + (startingBalancePayment > 0 ? 1 : 0);\n }, [invoicesSelected, startingBalancePayment]);\n\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n const onClose = useCallback(() => {\n closeDrawer();\n resetInvoicePaymentDetails();\n }, [closeDrawer]);\n\n return (\n <>\n {selected > 0 && (\n <>\n <Stack spacing={2}>\n <Box display=\"flex\" justifyContent=\"flex-end\">\n <Typography className={classes.root} variant=\"h5\">\n {texts.paymentTotalFor} {selected}{' '}\n {selected == 1 ? texts.invoiceSingular : texts.invoicePlural}:{' '}\n <Currency value={total} />\n </Typography>\n </Box>\n <Box display=\"flex\" justifyContent=\"flex-end\" pb={2}>\n <Button onClick={openDrawer} disabled={disableSelection} variant=\"contained\">\n {texts.selectPaymentMethod}\n </Button>\n </Box>\n </Stack>\n\n <Drawer open={drawerOpen} onClose={onClose} />\n </>\n )}\n </>\n );\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useFetchDefaultBillingLocation } from '@/common/hooks/query/useQueryDefaultBillingLocation';\nimport { PageHeader } from '@/components/PageHeader';\nimport { PageWrapper } from '@/components/PageWrapper';\nimport { Alert, Stack } from '@mui/material';\nimport { useEffect, useMemo } from 'react';\nimport { AccountSummary } from '../AccountOverview/widgets/AccountSummary/AccountSummary';\nimport { InvoiceList } from './InvoiceList';\nimport { InvoiceTotal } from './InvoiceTotal';\nimport { resetPayInvoicesState } from './store';\nimport { useTexts } from './useTexts';\n\nexport function PayInvoicesPage() {\n const texts = useTexts();\n const accountId = useAccountId();\n const { data: billingLocation } = useFetchDefaultBillingLocation(accountId || '');\n\n const hasLocationErrors = useMemo(() => {\n return !!billingLocation?.validationErrors;\n }, [billingLocation?.validationErrors]);\n\n useEffect(() => {\n return () => {\n resetPayInvoicesState();\n };\n }, []);\n\n return (\n <PageWrapper>\n <Stack direction=\"column\" spacing={2}>\n <PageHeader title={texts.pageTitle} description={texts.pageDescription} />\n\n {!!accountId && (\n <>\n <AccountSummary accountId={accountId} hidePrimaryAction />\n <InvoiceList accountId={accountId} disableSelection={hasLocationErrors} />\n <InvoiceTotal disableSelection={hasLocationErrors} />\n {hasLocationErrors && <Alert severity=\"error\">{texts.locationHasErrors}</Alert>}\n </>\n )}\n </Stack>\n </PageWrapper>\n );\n}\n","import { useCallback, useMemo, useState } from 'react';\nimport { PaymentAccountTypes } from '@/common/types/payments';\nimport { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { addAchPaymentAccount } from '@/api/paymentAccounts';\nimport { useToast } from '@/utils/useToast';\nimport { getAccount } from '@/atoms/session/store';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { DrawerContent } from './DrawerContent';\nimport { useIsAchInputValid } from './hooks/useIsAchInputValid';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport interface AchInput {\n accountNumber: string;\n routingNumber: string;\n}\n\nexport function Drawer(props: Props) {\n const account = getAccount();\n const [achInput, setAchInput] = useState<AchInput>({ accountNumber: '', routingNumber: '' });\n const [paymentType, setPaymentType] = useState<PaymentAccountTypes>(PaymentAccountTypes.CREDIT_CARD);\n const { refetch } = useQueryPaymentAccounts(account?.accountId || '');\n\n const { onClose, open } = props;\n const texts = useTexts();\n const toast = useToast();\n\n const closeDrawer = useCallback(() => {\n setAchInput({ accountNumber: '', routingNumber: '' });\n setPaymentType(PaymentAccountTypes.CREDIT_CARD);\n onClose();\n }, [onClose, setAchInput]);\n\n const hideFooter = useMemo(() => {\n return paymentType == PaymentAccountTypes.CREDIT_CARD;\n }, [paymentType]);\n\n const isSaveDisabled = !useIsAchInputValid(achInput);\n\n const onSave = useCallback(async () => {\n if (!account) return;\n\n try {\n await addAchPaymentAccount({\n accountId: account.accountId,\n accountNumber: achInput.accountNumber,\n businessUnitId: account.businessUnitId,\n processorPaymentAccountId: '',\n routingNumber: achInput.routingNumber,\n });\n\n toast.success(texts.successfullyAddedAch);\n refetch();\n closeDrawer();\n } catch {\n toast.error(texts.errorAddingAchAccountNumber);\n }\n }, [account, achInput, closeDrawer, refetch, texts, toast]);\n\n const onAddCreditCardSuccess = useCallback(async () => {\n toast.success(texts.successfullyAddedCreditCard);\n\n try {\n await refetch();\n closeDrawer();\n } catch {\n toast.error(texts.errorAddingCreditCard);\n }\n }, [closeDrawer, refetch, texts, toast]);\n\n return (\n <SideDrawerForm\n isOpen={open}\n onClose={closeDrawer}\n onSave={onSave}\n disableSave={isSaveDisabled}\n hideFooter={hideFooter}\n title={texts.title}\n >\n <DrawerContent\n achInput={achInput}\n onAddCreditCardSuccess={onAddCreditCardSuccess}\n onCancelCreditCardEntry={onClose}\n paymentType={paymentType}\n setAchInput={setAchInput}\n setPaymentType={setPaymentType}\n />\n </SideDrawerForm>\n );\n}\n","import { useContext } from 'react';\nimport { ConfirmationDialogContext, DialogConfig } from '../components/ConfirmationDialog/ConfirmationDialogProvider';\n\nexport function useConfirmationDialog() {\n const { openDialog } = useContext(ConfirmationDialogContext);\n\n const getConfirmation = (options: Pick<DialogConfig, 'title' | 'message' | 'width'>) => {\n return new Promise<boolean>(res => {\n openDialog({ callbackFn: res, ...options });\n });\n };\n return { getConfirmation };\n}\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport { ClickAwayListener, IconButton } from '@mui/material';\nimport { IconButtonProps } from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport { useState } from 'react';\n\nexport interface Props extends IconButtonProps {\n showTooltip?: boolean;\n spanClassName?: string;\n tooltipText?: any;\n}\n\nexport function IconButtonWithTooltip(props: Props) {\n const { tooltipText, showTooltip, spanClassName, ...buttonProps } = props;\n const [open, setOpen] = useState<boolean>(false);\n const layout = useGetUILayout();\n\n const handleTooltipClose = () => {\n setOpen(false);\n };\n\n const handleTooltipOpen = () => {\n setOpen(true);\n };\n\n return (\n <>\n {showTooltip && (\n <>\n {layout == 'desktop' && (\n <>\n <Tooltip enterTouchDelay={0} title={tooltipText}>\n <span className={spanClassName}>\n <IconButton {...buttonProps}>{props.children}</IconButton>\n </span>\n </Tooltip>\n </>\n )}\n\n {layout == 'mobile' && (\n <>\n <ClickAwayListener onClickAway={handleTooltipClose}>\n <div>\n <Tooltip\n disableFocusListener\n disableHoverListener\n disableTouchListener\n onClose={handleTooltipClose}\n open={open}\n PopperProps={{\n disablePortal: true,\n }}\n title={tooltipText}\n >\n <span className={spanClassName} onClick={handleTooltipOpen}>\n <IconButton {...buttonProps}>{props.children}</IconButton>\n </span>\n </Tooltip>\n </div>\n </ClickAwayListener>\n </>\n )}\n </>\n )}\n\n {!showTooltip && <IconButton {...buttonProps}>{props.children}</IconButton>}\n </>\n );\n}\n","import { deletePaymentAccount } from '@/api/paymentAccounts';\nimport { useAccountId } from '@/atoms/session';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { useConfirmationDialog } from '@/common/hooks/useConfirmationDialog';\nimport { PaymentAccount, PaymentAccountTypes } from '@/common/types/payments';\nimport { IconButtonWithTooltip } from '@/components/IconButtonWithTooltip';\nimport { useToast } from '@/utils/useToast';\nimport DeleteIcon from '@mui/icons-material/Delete';\nimport { makeStyles } from '@mui/styles';\nimport { useCallback, useMemo } from 'react';\nimport { useNavigate } from 'react-router';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n isDisabled: boolean;\n paymentAccount: PaymentAccount;\n}\n\nconst useStyles = makeStyles({\n tooltipLink: {\n cursor: 'pointer',\n textDecoration: 'underline',\n },\n});\n\nexport function DeleteButton(props: Props) {\n const accountId = useAccountId();\n const classes = useStyles();\n const navigate = useNavigate();\n const texts = useTexts();\n const toast = useToast();\n\n const { getConfirmation } = useConfirmationDialog();\n const { isDisabled, paymentAccount } = props;\n const { refetch } = useQueryPaymentAccounts(accountId || '');\n\n const isCreditCard = useMemo(() => {\n return paymentAccount.accountType == PaymentAccountTypes.CREDIT_CARD;\n }, [paymentAccount.accountType]);\n\n const handleDelete = useCallback(async () => {\n const confirmed = await getConfirmation({\n title: texts.deleteConfirmation.title,\n message: `${texts.deleteConfirmation.body} ${paymentAccount.friendly}?`,\n });\n\n if (!confirmed) {\n return;\n }\n\n try {\n await deletePaymentAccount(paymentAccount.businessUnitId, paymentAccount.paymentAccountId);\n toast.success(isCreditCard ? texts.card.deleteSuccess : texts.ach.deleteSuccess);\n refetch();\n } catch {\n toast.error(isCreditCard ? texts.card.deleteError : texts.ach.deleteError);\n }\n }, [getConfirmation, isCreditCard, paymentAccount, refetch, toast, texts]);\n\n const redirectToAutoPay = useCallback(() => {\n navigate('/payments/manage-autopay');\n }, [navigate]);\n\n return (\n <IconButtonWithTooltip\n disabled={isDisabled}\n onClick={handleDelete}\n showTooltip={isDisabled}\n tooltipText={\n <>\n {paymentAccount.isAutoPayment && texts.deletePaymentAccountAutoPayTooltip}{' '}\n {paymentAccount.isAutoPayment && (\n <span className={classes.tooltipLink} onClick={redirectToAutoPay}>\n {texts.moreInfo}\n <br />\n </span>\n )}\n {paymentAccount.hasAutoPaymentInstance && texts.deletePaymentAccountAutoPayInstanceTooltip}{' '}\n </>\n }\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButtonWithTooltip>\n );\n}\n","import { PaymentAccount, PaymentAccountTypes } from '@/common/types/payments';\nimport { Box, Stack, Typography } from '@mui/material';\nimport { makeStyles } from '@mui/styles';\nimport { useCallback, useMemo } from 'react';\nimport { CardIcon } from './CardIcon';\nimport { DeleteButton } from './DeleteButton';\nimport { PaymentAccountDetails } from './PaymentAccountDetails';\n\ninterface Props {\n hideActions?: boolean;\n isSelected?: boolean;\n onClick?: () => void;\n paymentAccount: PaymentAccount;\n selectable?: boolean;\n}\n\nconst useStyles = (props: Props) =>\n makeStyles(theme => ({\n root: {\n aspectRatio: '4/2.5',\n backgroundColor: props.isSelected ? theme.palette.primary.main : theme.palette.white,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.spacing(0.5),\n color: props.isSelected ? theme.palette.white : 'inherit',\n cursor: props.selectable ? 'pointer' : 'default',\n },\n cardNumber: {\n fontSize: '24px',\n color: props.isSelected ? theme.palette.white : 'inherit',\n },\n }));\n\nexport function PaymentAccountCard(props: Props) {\n const { hideActions = false, onClick, paymentAccount, selectable, isSelected } = props;\n const classes = useStyles(props)();\n\n const isCreditCard = useMemo(() => {\n return paymentAccount.accountType == PaymentAccountTypes.CREDIT_CARD;\n }, [paymentAccount.accountType]);\n\n const handleClick = useCallback(() => {\n if (selectable && !!onClick) {\n onClick();\n }\n }, [onClick, selectable]);\n\n const accountNumber = useMemo(() => {\n return isCreditCard ? `**** **** **** ${paymentAccount.ending}` : `*****${paymentAccount.ending}`;\n }, [isCreditCard, paymentAccount.ending]);\n\n return (\n <Box display=\"flex\" p={2} className={classes.root} onClick={handleClick}>\n <Stack width=\"100%\">\n <Box display=\"flex\" alignItems=\"center\">\n <Box display=\"flex\" flexGrow={1}>\n <CardIcon accountName={paymentAccount.friendly} />\n </Box>\n {!hideActions && (\n <Box>\n <DeleteButton\n isDisabled={paymentAccount.isAutoPayment || paymentAccount.hasAutoPaymentInstance}\n paymentAccount={paymentAccount}\n />\n </Box>\n )}\n </Box>\n <Box display=\"flex\" flexDirection=\"column\" flexGrow={1} justifyContent=\"center\">\n <Typography className={classes.cardNumber}>{accountNumber}</Typography>\n </Box>\n <PaymentAccountDetails\n isSelected={!!isSelected}\n expMonth={paymentAccount.month}\n expYear={paymentAccount.year}\n friendly={paymentAccount.friendly}\n isCreditCard={isCreditCard}\n isExpired={paymentAccount.isExpired}\n />\n </Stack>\n </Box>\n );\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useQueryPaymentAccounts } from '@/common/hooks/query/useQueryPaymentAccounts';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { Alert, Box, CircularProgress, Grid } from '@mui/material';\nimport { useMemo } from 'react';\nimport { PaymentAccountCard } from './PaymentMethodCard/PaymentAccountCard';\nimport { useTexts } from './useTexts';\n\nexport function PaymentMethodList() {\n const texts = useTexts();\n const accountId = useAccountId();\n\n const { data: paymentMethods, status } = useQueryPaymentAccounts(accountId || '');\n\n const creditCardEnabled = useFeatureEnabled('enableCreditCardPayment');\n const achEnabled = useFeatureEnabled('enableACHPayment');\n\n const paymentAlertText = useMemo(() => {\n if (creditCardEnabled && achEnabled) {\n return texts.noPaymentMethodsAlert;\n } else if (creditCardEnabled && !achEnabled) {\n return texts.noPaymentMethodsAlertCreditCard;\n } else if (!creditCardEnabled && achEnabled) {\n return texts.noPaymentMethodsAlertACH;\n } else {\n return texts.noPaymentMethodsAlert;\n }\n }, [creditCardEnabled, achEnabled, texts]);\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">Failed to load payment methods on file.</Alert>}\n {status == 'success' && (\n <>\n {!paymentMethods && <Alert severity=\"info\">{paymentAlertText}</Alert>}\n\n {!!paymentMethods && (\n <>\n {paymentMethods.length == 0 && <Alert severity=\"info\">{paymentAlertText}</Alert>}\n\n {paymentMethods.length > 0 && (\n <Box sx={{ pb: 2, ml: -2 }}>\n <Grid container spacing={2}>\n {paymentMethods.map((p, i) => (\n <Grid item key={i} xs={12} sm={12} md={6} lg={4}>\n <PaymentAccountCard paymentAccount={p} />\n </Grid>\n ))}\n </Grid>\n </Box>\n )}\n </>\n )}\n </>\n )}\n </>\n );\n}\n","import { PageHeader } from '@/components/PageHeader';\nimport { PageWrapper } from '@/components/PageWrapper';\nimport { Alert, Box, Button, Stack } from '@mui/material';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { useFetchDefaultBillingLocation } from '@/common/hooks/query/useQueryDefaultBillingLocation';\nimport { useAccountId } from '@/atoms/session';\nimport { useMemo } from 'react';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { useTexts } from './useTexts';\nimport { Drawer } from './drawers/AddPaymentMethod/Drawer';\nimport { PaymentMethodList } from './PaymentMethodList';\n\nexport function PaymentMethodsPage() {\n const texts = useTexts();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const accountId = useAccountId();\n const { data: billingLocation } = useFetchDefaultBillingLocation(accountId || '');\n\n const hasLocationErrors = useMemo(() => {\n return !!billingLocation?.validationErrors;\n }, [billingLocation?.validationErrors]);\n\n const creditCardEnabled = useFeatureEnabled('enableCreditCardPayment');\n const achEnabled = useFeatureEnabled('enableACHPayment');\n\n return (\n <PageWrapper>\n <Stack spacing={2}>\n {creditCardEnabled && achEnabled && (\n <PageHeader title={texts.pageTitle} description={texts.pageDescription} />\n )}\n\n {creditCardEnabled && !achEnabled && (\n <PageHeader title={texts.pageTitle} description={texts.creditCardPageDescription} />\n )}\n\n {!creditCardEnabled && achEnabled && (\n <PageHeader title={texts.pageTitle} description={texts.achPageDescription} />\n )}\n <Box>\n <Button variant=\"contained\" onClick={openDrawer} disabled={hasLocationErrors}>\n {texts.addPaymentMethodBtn}\n </Button>\n </Box>\n {hasLocationErrors && <Alert severity=\"error\">{texts.locationHasErrors}</Alert>}\n\n <PaymentMethodList />\n\n <Drawer open={drawerOpen} onClose={closeDrawer} />\n </Stack>\n </PageWrapper>\n );\n}\n","import { useQuery } from 'react-query';\nimport { AgreementsResponse, getAgreements } from '@/api/agreements';\nimport { AgreementStatus } from '@/common/types/agreements';\n\nexport const useQueryActiveAgreements = (accountId: string, page: number, take: number, serviceLocations: string[]) =>\n useQuery<AgreementsResponse, Error>(\n ['activeAgreements', accountId, page, take, serviceLocations, AgreementStatus.ACTIVE],\n () => getAgreements(accountId, page, take, serviceLocations, AgreementStatus.ACTIVE),\n {\n keepPreviousData: true,\n },\n );\n","import Skeleton from '@mui/material/Skeleton';\nimport Grid from '@mui/material/Grid';\n\nexport function LoadingSkeleton() {\n return (\n <Grid container spacing={2} direction=\"column\" item sm={12} lg={8}>\n <Grid item>\n <Skeleton variant=\"text\" />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n </Grid>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n active: translate({ id: 'sections.agreements.status.active' }),\n agreements: translate({ id: 'sections.agreements.agreements' }),\n cancelled: translate({ id: 'sections.agreements.status.cancelled' }),\n completed: translate({ id: 'sections.agreements.status.completed' }),\n drawerTitle: translate({ id: 'sections.agreements.drawer.title' }),\n effectiveDate: translate({ id: 'sections.agreements.effectiveDate' }),\n filtersDrawerTitle: translate({ id: 'sections.agreements.filtersDrawerTitle' }),\n noAgreementsAlert: translate({ id: 'sections.agreements.noAgreementsAlert' }),\n locationHasErrors: translate({ id: 'sections.agreements.locationHasErrors' }),\n notImplementedYet: translate({ id: 'global.notImplementedYet' }),\n pageTitle: translate({ id: 'sections.manageAutopay.pageTitle' }),\n showActiveAgreements: translate({ id: 'sections.agreements.showActiveAgreements' }),\n showAllAgreements: translate({ id: 'sections.agreements.showAllAgreements' }),\n showCancelledAgreements: translate({ id: 'sections.agreements.showCancelledAgreements' }),\n showCompletedAgreements: translate({ id: 'sections.agreements.showCompletedAgreements' }),\n };\n }, [translate]);\n}\n","import { proxy, useSnapshot } from 'valtio';\nimport { useMemo } from 'react';\n\n// Store state\nexport interface ListState {\n page: number;\n take: number;\n selected: string;\n serviceLocations: string[];\n}\n\nexport const initialState: ListState = {\n page: 0,\n take: 10,\n selected: '',\n serviceLocations: [''],\n};\n\n// Valtio store initialization\nexport const state = proxy<ListState>(initialState);\n\n// Setter functions\nexport function setPage(page: number) {\n state.page = page;\n}\n\nexport function setTake(take: number) {\n state.take = take;\n}\n\nexport function setServiceLocations(locations: string[]) {\n state.serviceLocations = locations;\n\n if (!state.serviceLocations.length) {\n state.serviceLocations = initialState.serviceLocations;\n }\n}\n\nexport function clearServiceLocations() {\n state.serviceLocations = initialState.serviceLocations;\n}\n\nexport function setSelectedItem(id: string) {\n state.selected = id;\n}\n\nexport function clearSelectedItem() {\n state.selected = '';\n}\n\nexport function resetFilters() {\n clearServiceLocations();\n}\n\nexport function resetStore() {\n state.page = initialState.page;\n state.selected = initialState.selected;\n state.serviceLocations = initialState.serviceLocations;\n state.take = initialState.take;\n}\n\n//Hooks\nexport function useListState() {\n return useSnapshot(state);\n}\n\nexport function useIsListFiltered() {\n const { serviceLocations } = state;\n\n const isListFiltered = useMemo(() => {\n return !!serviceLocations.length && !!serviceLocations[0];\n }, [serviceLocations]);\n\n return isListFiltered;\n}\n","import { useCallback } from 'react';\nimport { clearServiceLocations, resetFilters, setPage, setServiceLocations, setTake } from '../store';\n\nexport function useListActions() {\n const handleClearServiceLocations = useCallback(() => {\n setPage(0);\n clearServiceLocations();\n }, []);\n\n const handleDeleteServiceLocationFilter = useCallback(\n (id: string, serviceLocations: string[]) => (_e: React.MouseEvent<HTMLElement>) => {\n setPage(0);\n setServiceLocations(serviceLocations.filter(x => x !== id));\n },\n [],\n );\n\n const handleResetFilters = useCallback(() => {\n setPage(0);\n resetFilters();\n }, []);\n\n const handleSetPage = useCallback((_e, page: number) => {\n setPage(page - 1);\n }, []);\n\n const handleSetServiceLocations = useCallback((locations: string[]) => {\n setPage(0);\n setServiceLocations(locations);\n }, []);\n\n const handleSetTake = useCallback((take: number) => {\n setTake(take);\n }, []);\n\n return {\n handleClearServiceLocations,\n handleDeleteServiceLocationFilter,\n handleResetFilters,\n handleSetPage,\n handleSetServiceLocations,\n handleSetTake,\n } as const;\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { ServiceLocationFilterChip } from '@/components/cardList/chips';\nimport { ClearFiltersButton } from '@/components/cardList/filters';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { useListActions } from '../hooks';\nimport { useIsListFiltered, useListState } from '../store';\n\nexport function Chips() {\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations } = useListState();\n const { handleResetFilters, handleDeleteServiceLocationFilter } = useListActions();\n const isListFiltered = useIsListFiltered();\n\n return (\n <>\n {!!locations?.length && (\n <Box display=\"flex\" flexDirection=\"row\" alignItems=\"center\">\n <Box flexGrow={1}>\n <Stack direction=\"row-reverse\" spacing={1} flexWrap=\"wrap\" gap={1}>\n {!!serviceLocations.length &&\n serviceLocations.map(\n x =>\n !!x && (\n <ServiceLocationFilterChip\n key={x}\n id={x}\n onDelete={handleDeleteServiceLocationFilter(x, serviceLocations)}\n serviceLocations={locations}\n />\n ),\n )}\n </Stack>\n </Box>\n\n <Box ml={2} flexGrow={0}>\n {isListFiltered && <ClearFiltersButton onClick={handleResetFilters} />}\n </Box>\n </Box>\n )}\n </>\n );\n}\n","import { ListHeader } from '@/components/cardList';\nimport { useTexts } from '../../useTexts';\nimport { Chips } from './Chips';\n\ninterface Props {\n openDrawer: () => void;\n}\n\nexport function ActiveAgreementsListHeader(props: Props) {\n const { openDrawer } = props;\n const texts = useTexts();\n\n return <ListHeader title={texts.pageTitle} openDrawer={openDrawer} singleLineOnMobile chips={<Chips />} />;\n}\n","import { SideDrawer } from '@/components/SideDrawer';\nimport Stack from '@mui/material/Stack';\nimport { ClearFiltersButton } from '@/components/cardList/filters/ClearFiltersButton';\nimport { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { ServiceLocationFilter } from '@/components/cardList/filters/ServiceLocationFilter';\nimport { useListActions } from '../hooks';\nimport { useListState } from '../store';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function FiltersDrawer(props: Props) {\n const { onClose, open } = props;\n const texts = useTexts();\n const { handleResetFilters, handleSetServiceLocations } = useListActions();\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations } = useListState();\n\n return (\n <SideDrawer isOpen={open} onClose={onClose} title={texts.filtersDrawerTitle}>\n <Stack direction=\"column\" spacing={2}>\n {!!locations && (\n <ServiceLocationFilter\n locations={locations}\n serviceLocations={serviceLocations}\n setServiceLocations={handleSetServiceLocations}\n />\n )}\n <ClearFiltersButton onClick={handleResetFilters} />\n </Stack>\n </SideDrawer>\n );\n}\n","import { AgreementModel } from '@/api/agreements';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { CardList, ListBody, ListFooter } from '@/components/cardList';\nimport { useTexts } from '../useTexts';\nimport { AgreementCard } from '../../Agreements/AgreementsList/cards';\nimport { ActiveAgreementsListHeader } from './header/ActiveAgreementsListHeader';\nimport { useListState } from './store';\nimport { useListActions } from './hooks';\nimport { FiltersDrawer } from './filters/FiltersDrawer';\n\ninterface Props {\n items: AgreementModel[];\n total: number;\n disabled?: boolean;\n}\n\nexport function ActiveAgreementsList(props: Props) {\n const { items, total, disabled } = props;\n const { page, take } = useListState();\n const texts = useTexts();\n const { handleSetPage } = useListActions();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n return (\n <>\n <CardList\n header={<ActiveAgreementsListHeader openDrawer={openDrawer} />}\n body={\n <ListBody\n card={AgreementCard}\n emptyListAlertText={texts.noAgreementsAlert}\n items={items}\n disabled={disabled}\n />\n }\n footer={<ListFooter count={Math.ceil(total / take)} page={page + 1} onChange={handleSetPage} />}\n />\n <FiltersDrawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { useAccountId } from '@/atoms/session';\nimport { PageErrorState } from '@/components/PageErrorState/PageErrorState';\nimport { useEffect, useMemo } from 'react';\nimport { useQueryActiveAgreements } from '@/common/hooks/query/useQueryActiveAgreements';\nimport { Alert, Stack } from '@mui/material';\nimport { LoadingSkeleton } from './LoadingSkeleton';\nimport { ActiveAgreementsList } from './ActiveAgreementsList';\nimport { resetStore, useListState } from './ActiveAgreementsList/store';\nimport { useTexts } from './useTexts';\n\nexport function ManageAutopayPage() {\n const { page, take, serviceLocations } = useListState();\n const accountId = useAccountId();\n const query = useQueryActiveAgreements(accountId || '', page, take, serviceLocations);\n const texts = useTexts();\n\n const hasValidationErrors = useMemo(() => {\n return query.isSuccess && !!query.data.items && query.data.items[0].hasValidationErrors;\n }, [query]);\n\n useEffect(() => {\n resetStore();\n }, [accountId]);\n\n return (\n <PageWrapper disableScroll>\n <Stack direction=\"column\" spacing={2} pb={2}>\n {query.status === 'loading' && <LoadingSkeleton />}\n {query.status === 'success' && (\n <ActiveAgreementsList\n items={query.data.items}\n total={query.data.total}\n disabled={hasValidationErrors}\n />\n )}\n {query.status === 'error' && <PageErrorState />}\n {hasValidationErrors && <Alert severity=\"error\">{texts.locationHasErrors}</Alert>}\n </Stack>\n </PageWrapper>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n changePassword: translate({ id: 'sections.profile.password.changePassword' }),\n emailLabel: translate({ id: `sections.profile.email.label` }),\n header: translate({ id: `sections.profile.header` }),\n passwordLabel: translate({ id: `sections.profile.password.label` }),\n passwordMask: translate({ id: `sections.profile.password.mask` }),\n };\n }, [translate]);\n}\n","import { Box } from '@mui/material';\nimport { getUser } from '@/atoms/session/store';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useTexts } from '../useTexts';\n\nexport function EmailAddress() {\n const user = getUser();\n const texts = useTexts();\n\n return (\n <Box display=\"flex\" width={1}>\n <DefinitionListItem primary={texts.emailLabel} secondary={user?.email} />\n </Box>\n );\n}\n","import type { FormError, FormField } from '@/formState';\n\nconst oldPasswordField: FormField<string> = { value: '', required: true };\nconst passwordField: FormField<string> = { value: '', required: true };\nconst confirmPasswordField: FormField<string> = { value: '', required: true };\n\nexport const formFields = {\n oldPassword: oldPasswordField,\n password: passwordField,\n confirmPassword: confirmPasswordField,\n};\n\nexport type FormFields = typeof formFields;\nexport type FormErrors = FormError<keyof FormFields>;\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n passwordMust: translate({ id: 'sections.passwordRequirements.passwordsMust' }),\n minLength: translate({ id: 'sections.passwordRequirements.minLength' }),\n includeLower: translate({ id: 'sections.passwordRequirements.includeLower' }),\n includeUpper: translate({ id: 'sections.passwordRequirements.includeUpper' }),\n includeNumber: translate({ id: 'sections.passwordRequirements.includeNumber' }),\n includeSpecial: translate({ id: 'sections.passwordRequirements.includeSpecial' }),\n mustMatch: translate({ id: 'sections.passwordRequirements.mustMatch' }),\n };\n }, [translate]);\n}\n","import CloseIcon from '@mui/icons-material/Close';\nimport DoneIcon from '@mui/icons-material/Done';\nimport makeStyles from '@mui/styles/makeStyles';\nimport Typography from '@mui/material/Typography';\nimport { theme } from '@/theme';\nimport { useTexts } from './useTexts';\nimport { PasswordErrors } from './typings';\n\nconst useStyles = makeStyles({\n error: {\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n },\n doneButton: {\n color: theme.palette.success.main,\n marginRight: theme.spacing(1),\n },\n closeButton: {\n color: theme.palette.error.main,\n marginRight: theme.spacing(1),\n },\n});\n\ntype Props<T extends string> = {\n errors: PasswordErrors<T>;\n};\n\nexport const PasswordRequirements = <T extends string>(props: Props<T>) => {\n const { errors } = props;\n const classes = useStyles();\n const texts = useTexts();\n\n return (\n <>\n <Typography>{texts.passwordMust}</Typography>\n <Typography className={classes.error}>\n {!errors.minChar ? (\n <DoneIcon className={classes.doneButton} />\n ) : (\n <CloseIcon className={classes.closeButton} />\n )}\n {texts.minLength}\n </Typography>\n <Typography className={classes.error}>\n {!errors.missingLower ? (\n <DoneIcon className={classes.doneButton} />\n ) : (\n <CloseIcon className={classes.closeButton} />\n )}\n {texts.includeLower}\n </Typography>\n <Typography className={classes.error}>\n {!errors.missingUpper ? (\n <DoneIcon className={classes.doneButton} />\n ) : (\n <CloseIcon className={classes.closeButton} />\n )}\n {texts.includeUpper}\n </Typography>\n <Typography className={classes.error}>\n {!errors.missingNum ? (\n <DoneIcon className={classes.doneButton} />\n ) : (\n <CloseIcon className={classes.closeButton} />\n )}\n {texts.includeNumber}\n </Typography>\n <Typography className={classes.error}>\n {!errors.missingSpecial ? (\n <DoneIcon className={classes.doneButton} />\n ) : (\n <CloseIcon className={classes.closeButton} />\n )}\n {texts.includeSpecial}\n </Typography>\n <Typography className={classes.error}>\n {!errors.missingMatch ? (\n <DoneIcon className={classes.doneButton} />\n ) : (\n <CloseIcon className={classes.closeButton} />\n )}\n {texts.mustMatch}\n </Typography>\n </>\n );\n};\n","import { FormApi, FormError, FormField } from '@/formState';\nimport { useTranslate } from '@/intl';\n\nexport function RequiredFieldValidation<\n FIELDS extends Record<string, FormField>,\n ERROR extends FormError<keyof FIELDS> = FormError<keyof FIELDS>,\n>(fieldName: keyof FIELDS, id: string) {\n const translate = useTranslate();\n\n const validate = (api: Readonly<FormApi<FIELDS, ERROR>>) => {\n const requiredField = api.getField(fieldName);\n const errors = {};\n\n errors[id] = !!requiredField.value\n ? null\n : {\n id: id,\n field: fieldName,\n message: translate({ id: 'global.requiredField' }),\n };\n\n return errors;\n };\n\n return validate;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n heading: translate({ id: `sections.changePassword.heading` }),\n drawerButtonLabel: translate({ id: 'sections.changePassword.drawerButtonLabel' }),\n currentPassword: translate({ id: `sections.changePassword.currentPassword` }),\n passwordFieldLabel: translate({ id: 'sections.register.passwordFieldLabel' }),\n confirmPasswordFieldLabel: translate({ id: 'sections.register.confirmPasswordFieldLabel' }),\n newPassword: translate({ id: `sections.changePassword.newPassword` }),\n success: translate({ id: `sections.changePassword.success` }),\n error: translate({ id: `sections.changePassword.error` }),\n sessionClearWarning: translate({ id: `sections.changePassword.sessionClearWarning` }),\n };\n }, [translate]);\n}\n","import Typography from '@mui/material/Typography';\nimport Box from '@mui/material/Box';\nimport { Grid } from '@mui/material';\nimport { useEffect } from 'react';\nimport { FormError, FormValidator, useForm } from '@/formState';\nimport { TextField } from '@/formUI';\nimport { PasswordRequirements } from '@/components/PasswordRequirements/PasswordRequirements';\nimport { useTexts as useErrorsTexts } from '@/components/PasswordRequirements/useTexts';\nimport { getPasswordErrors } from '@/components/PasswordRequirements/utils';\nimport { RequiredFieldValidation } from '@/utils/requiredValidator';\nimport { FormErrors, FormFields } from './formFields';\nimport { useTexts } from './useTexts';\n\nexport function Form() {\n const texts = useTexts();\n const errorsTexts = useErrorsTexts();\n\n const { api } = useForm<FormFields, FormError<keyof FormFields>>();\n\n const validateForm: FormValidator<FormFields, FormErrors> = formApi => {\n const pwField = formApi.getField('password');\n const confirmPwField = formApi.getField('confirmPassword');\n\n const errors = getPasswordErrors(pwField, confirmPwField, errorsTexts);\n\n return errors;\n };\n\n useEffect(() => {\n if (!api.getValidator('checkPassword')) {\n api.addValidation('checkPassword', validateForm);\n api.addValidation(\n 'oldPassword',\n RequiredFieldValidation<FormFields, FormErrors>('oldPassword', 'oldPasswordRequired'),\n );\n }\n });\n\n return (\n <form onChange={() => api.validate()}>\n <Box width=\"100%\">\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <TextField<'oldPassword', FormFields, FormErrors>\n textField={{\n type: 'password',\n fullWidth: true,\n }}\n validateOn=\"change blur\"\n label={texts.currentPassword}\n name=\"oldPassword\"\n />\n </Grid>\n <Grid item>\n <TextField<'password', FormFields, FormErrors>\n textField={{\n type: 'password',\n fullWidth: true,\n }}\n validateOn=\"change blur\"\n label={texts.newPassword}\n name=\"password\"\n />\n </Grid>\n <Grid item>\n <TextField<'confirmPassword', FormFields, FormErrors>\n textField={{\n type: 'password',\n fullWidth: true,\n }}\n validateOn=\"change blur\"\n label={texts.confirmPasswordFieldLabel}\n name=\"confirmPassword\"\n />\n </Grid>\n <Grid item>\n <PasswordRequirements errors={api.getErrors()} />\n </Grid>\n <Grid item>\n <Typography>{texts.sessionClearWarning}</Typography>\n </Grid>\n </Grid>\n </Box>\n </form>\n );\n}\n","import { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { FormError, useForm } from '@/formState';\nimport { isServerError } from '@/utils/ServerError';\nimport { logout } from '@/atoms/session';\nimport { useCallback } from 'react';\nimport { toast } from 'react-toastify';\nimport { changePassword } from '../../../services/services/userService';\nimport { Form } from './Form';\nimport { FormFields } from './formFields';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function FormWrapper(props: Props) {\n const { onClose, open } = props;\n const texts = useTexts();\n\n const { api, meta } = useForm<FormFields, FormError<keyof FormFields>>();\n\n const onSave = useCallback(async () => {\n if (meta.status == 'valid' && !meta.submitting) {\n const formValues = api.getValues();\n api.setSubmitting(true);\n const response = await changePassword(formValues.oldPassword, formValues.password);\n\n if (!isServerError(response) && response) {\n toast.success(texts.success);\n api.reset('force');\n onClose();\n logout();\n } else {\n toast.error(texts.error);\n }\n api.setSubmitting(false);\n } else {\n api.validate();\n }\n }, [api, meta, texts, onClose]);\n\n return (\n <>\n <SideDrawerForm\n onSave={onSave}\n onClose={onClose}\n isOpen={open}\n title={texts.heading}\n isSubmitting={meta.submitting}\n >\n <Form />\n </SideDrawerForm>\n </>\n );\n}\n","import { FormRoot, useCreateForm } from '@/formState';\nimport { formFields } from './formFields';\nimport { FormWrapper } from './FormWrapper';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function Drawer(props: Props) {\n const { onClose, open } = props;\n const formState = useCreateForm('change-password-form', formFields);\n\n return (\n <FormRoot formState={formState}>\n <FormWrapper onClose={onClose} open={open}></FormWrapper>\n </FormRoot>\n );\n}\n","import { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { Box, Button } from '@mui/material';\nimport { Drawer } from '../drawer';\nimport { useTexts } from '../useTexts';\n\nexport function Password() {\n const [closeDrawer, isOpen, openDrawer] = useDrawerState();\n const texts = useTexts();\n\n return (\n <>\n <Drawer onClose={closeDrawer} open={isOpen} />\n <Box display=\"flex\" flexDirection=\"row\">\n <Box flexGrow={1}>\n <DefinitionListItem primary={texts.passwordLabel} secondary={texts.passwordMask} />\n </Box>\n <Box>\n <Button variant=\"contained\" onClick={openDrawer}>\n {texts.changePassword}\n </Button>\n </Box>\n </Box>\n </>\n );\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { Stack } from '@mui/material';\nimport { EmailAddress } from './sections/EmailAddress';\nimport { Password } from './sections/Password';\nimport { useTexts } from './useTexts';\n\nexport function Profile() {\n const texts = useTexts();\n return (\n <PageWrapper>\n <Section>\n <SectionHeader title={texts.header} />\n <Stack spacing={2}>\n <EmailAddress />\n <Password />\n </Stack>\n </Section>\n </PageWrapper>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n clear: translate({ id: 'sections.questionsAndComments.clear' }),\n description: translate({ id: 'sections.questionsAndComments.description' }),\n error: translate({ id: 'sections.questionsAndComments.error' }),\n header: translate({ id: 'sections.questionsAndComments.header' }),\n questionComment: translate({ id: 'sections.questionsAndComments.questionComment' }),\n send: translate({ id: 'sections.questionsAndComments.send' }),\n serviceLocation: translate({ id: 'sections.questionsAndComments.serviceLocation' }),\n successToast: translate({ id: 'sections.questionsAndComments.successToast' }),\n };\n }, [translate]);\n}\n","import { proxy, useSnapshot } from 'valtio';\n\nexport interface QuestionCommentState {\n comment: string;\n serviceLocationId: string;\n}\n\nexport const initialState: QuestionCommentState = {\n comment: '',\n serviceLocationId: '',\n};\n\n// Valtio store initialization\nexport const state = proxy<QuestionCommentState>(initialState);\n\n// Setter functions\nexport function resetQuestionCommentState() {\n state.comment = '';\n state.serviceLocationId = '';\n}\n\nexport function setComment(comment: string) {\n state.comment = comment;\n}\n\nexport function setLocationId(locationId: string) {\n state.serviceLocationId = locationId;\n}\n\n// Hooks\nexport function useSelectQuestionCommentState() {\n return useSnapshot(state, { sync: true });\n}\n","import { TextField } from '@mui/material';\nimport { useCallback } from 'react';\nimport { useTexts } from '../../useTexts';\nimport { setComment, useSelectQuestionCommentState } from '../../store';\n\nexport function CommentField() {\n const texts = useTexts();\n const { comment } = useSelectQuestionCommentState();\n\n const onChangeComment = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n setComment(event.target.value);\n }, []);\n\n return (\n <TextField\n autoComplete=\"off\"\n data-testid=\"comment\"\n id=\"comment\"\n label={texts.questionComment}\n minRows={5}\n multiline\n onChange={onChangeComment}\n required\n value={comment}\n />\n );\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';\nimport { useCallback, useEffect } from 'react';\nimport { formatAddress } from '@/common/utils/formatAddress';\nimport { setLocationId, useSelectQuestionCommentState } from '../../store';\nimport { useTexts } from '../../useTexts';\n\nexport function ServiceLocationSelect() {\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n\n const texts = useTexts();\n const { serviceLocationId } = useSelectQuestionCommentState();\n\n const onChangeLocation = useCallback((event: SelectChangeEvent<string>) => {\n setLocationId(event.target.value);\n }, []);\n\n useEffect(() => {\n if (!!locations && locations.length == 1) {\n setLocationId(locations[0].serviceLocationId);\n } else {\n setLocationId('');\n }\n }, [locations]);\n\n return (\n <>\n {!!locations && (\n <FormControl fullWidth>\n <InputLabel id=\"service-location-label\">Service Location</InputLabel>\n <Select\n defaultValue=\"\"\n id=\"service-location\"\n label={texts.serviceLocation}\n labelId=\"service-location-label\"\n onChange={onChangeLocation}\n required\n value={serviceLocationId}\n >\n {locations.map((l, i) => (\n <MenuItem key={i} value={l.serviceLocationId}>\n {formatAddress(l)}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n )}\n </>\n );\n}\n","import { post } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/QuestionsAndComments';\n\nexport const createQuestionOrComment = async (serviceLocationId: string, questionOrComment: string) => {\n try {\n const { data, status } = await post<string>(`${baseUrl}`, {\n serviceLocationId: serviceLocationId,\n questionOrComment: questionOrComment,\n });\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to submit question or comment.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { Button, Stack } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport { toast } from 'react-toastify';\nimport { createQuestionOrComment } from '@/api/questionsAndComments';\nimport { useTexts } from '../useTexts';\nimport { resetQuestionCommentState, useSelectQuestionCommentState } from '../store';\n\nexport function FormFooter() {\n const texts = useTexts();\n const { comment, serviceLocationId } = useSelectQuestionCommentState();\n\n const saveDisabled = useMemo(() => {\n return !comment || !serviceLocationId;\n }, [comment, serviceLocationId]);\n\n const onSave = useCallback(async () => {\n try {\n await createQuestionOrComment(serviceLocationId, comment);\n toast.success(texts.successToast);\n resetQuestionCommentState();\n } catch {\n toast.error(texts.error);\n }\n }, [comment, serviceLocationId, texts]);\n\n return (\n <Stack direction=\"row\" spacing={2} justifyContent=\"flex-end\">\n <Button variant=\"outlined\" onClick={resetQuestionCommentState}>\n {texts.clear}\n </Button>\n <Button color=\"primary\" disabled={saveDisabled} onClick={onSave} variant=\"contained\">\n {texts.send}\n </Button>\n </Stack>\n );\n}\n","import { Box, Paper, Stack } from '@mui/material';\nimport { CommentField } from './fields/CommentField';\nimport { ServiceLocationSelect } from './fields/ServiceLocationSelect';\nimport { FormFooter } from './FormFooter';\n\nexport function Form() {\n return (\n <Paper>\n <Box p={2}>\n <Stack direction=\"column\" spacing={2}>\n <ServiceLocationSelect />\n <CommentField />\n <FormFooter />\n </Stack>\n </Box>\n </Paper>\n );\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { Box, Stack, Typography } from '@mui/material';\nimport { Form } from './Form/Form';\nimport { useTexts } from './useTexts';\n\nexport function QuestionsAndCommentsPage() {\n const texts = useTexts();\n\n return (\n <PageWrapper>\n <Stack spacing={2}>\n <Box>\n <Typography variant=\"h2\">{texts.header}</Typography>\n <Typography>{texts.description}</Typography>\n </Box>\n\n <Form />\n </Stack>\n </PageWrapper>\n );\n}\n","import type { FormError, FormField } from '@/formState';\n\nconst passwordField: FormField<string> = { value: '', required: true };\nconst confirmPasswordField: FormField<string> = { value: '', required: true };\n\nexport const formFields = {\n password: passwordField,\n confirmPassword: confirmPasswordField,\n};\n\nexport type FormFields = typeof formFields;\nexport type FormErrors = FormError<keyof FormFields>;\n","import { post } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/customerPortalUsers';\n\nexport const createUser = async (customerPortalUserId: string, password: string) => {\n try {\n const { status } = await post(baseUrl, { customerPortalUserId, password });\n\n if (status === 200) {\n return true;\n }\n\n throw new ServerError('Failed to create user.', status);\n } catch (e) {\n throw e;\n }\n};\n","import { useState, useRef, useEffect, useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { createUser } from '@/api/registration';\nimport { useToast } from '@/utils/useToast';\n\ntype RejectError = {\n message: string;\n type: 'invalid-registration' | 'unknown';\n};\n\nexport function useRegistrationActions() {\n const navigate = useNavigate();\n const toast = useToast();\n\n const unmounted = useRef(false);\n useEffect(() => () => void (unmounted.current = true));\n\n const [submitting, setSubmitting] = useState(false);\n\n const afterRegistrationRedirect = useCallback(() => {\n navigate('/login');\n }, [navigate]);\n\n const register = useCallback(\n async (customerPortalUserId: string, password: string): Promise<true | RejectError> => {\n try {\n setSubmitting(true);\n\n const response = await createUser(customerPortalUserId, password);\n\n if (!unmounted.current) setSubmitting(false);\n\n if (response === true) {\n return true;\n } else {\n return {\n message: 'Error during registration',\n type: 'unknown',\n };\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : 'unknown error';\n\n return {\n message: message || 'Error during registration',\n type: 'invalid-registration',\n };\n } finally {\n setSubmitting(false);\n }\n },\n [],\n );\n\n const notifyError = useCallback((message: string) => toast.error(message), [toast]);\n\n return {\n submitting,\n register,\n afterRegistrationRedirect,\n notifyError,\n } as const;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n title: translate({ id: 'sections.register.title' }),\n createAccount: translate({ id: 'sections.register.createAccount' }),\n registrationFailed: translate({ id: 'sections.register.registrationFailed' }),\n passwordFieldLabel: translate({ id: 'sections.register.passwordFieldLabel' }),\n confirmPasswordFieldLabel: translate({ id: 'sections.register.confirmPasswordFieldLabel' }),\n invalidRegistrationLink: translate({ id: 'sections.register.invalidRegistrationLink' }),\n userAlreadyRegistered: translate({ id: 'sections.register.userAlreadyRegistered' }),\n signIn: translate({ id: 'sections.register.signIn' }),\n };\n }, [translate]);\n}\n","import type { FormFields } from './formFields';\nimport type { FormError } from '@/formState';\nimport Button from '@mui/material/Button';\nimport Box from '@mui/material/Box';\nimport LinearProgress from '@mui/material/LinearProgress';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport { useFormMeta } from '@/formState';\nimport { useCallback, MouseEvent } from 'react';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n handleOnSubmit: () => Promise<void>;\n}\n\nexport function Footer(props: Props) {\n const { handleOnSubmit } = props;\n const { meta } = useFormMeta<FormFields, FormError<keyof FormFields>>();\n const texts = useTexts();\n\n const handleOnClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n handleOnSubmit();\n },\n [handleOnSubmit],\n );\n\n return (\n <Box width=\"100%\">\n {meta.validating && <LinearProgress />}\n\n <Button\n fullWidth\n color=\"primary\"\n variant=\"contained\"\n onClick={handleOnClick}\n disabled={meta.submitting || meta.status !== 'valid'}\n size=\"small\"\n type=\"submit\"\n data-testid=\"btn-register\"\n >\n {meta.submitting && <CircularProgress size={16} />}\n <Box ml={1}>{texts.createAccount}</Box>\n </Button>\n </Box>\n );\n}\n","import Button from '@mui/material/Button';\nimport Box from '@mui/material/Box';\nimport { useCallback } from 'react';\nimport { useNavigate } from 'react-router';\nimport { useTexts } from '../useTexts';\n\nexport function InvalidRegistrationFooter() {\n const texts = useTexts();\n const navigate = useNavigate();\n const handleOnClick = useCallback(() => {\n navigate('/login');\n }, [navigate]);\n\n return (\n <Box width=\"100%\">\n <Button\n fullWidth\n color=\"primary\"\n variant=\"contained\"\n onClick={handleOnClick}\n disabled={false}\n size=\"small\"\n type=\"submit\"\n data-testid=\"btn-signIn\"\n >\n <Box ml={1}>{texts.signIn}</Box>\n </Button>\n </Box>\n );\n}","import { useMemo } from 'react';\n\nexport const useCustomerPortalUserId = () => {\n return useMemo(() => {\n const id = new URL(location.href).searchParams.get('id') ?? '';\n return id;\n }, []);\n};\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface CustomerPortalUserRegistrationViewModel {\n customerPortalUserId: string;\n identityUserId: string | null;\n}\n\nexport const getCustomerPortalUserRegistration = async (customerPortalUserId: string) => {\n try {\n const { status, data } = await get<CustomerPortalUserRegistrationViewModel>(\n `api/customerPortalUsers/${customerPortalUserId}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get customer portal user.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { CustomerPortalUserRegistrationViewModel, getCustomerPortalUserRegistration } from '@/api/customerPortalUserRegistration';\nimport { useQuery } from 'react-query';\n\nexport const useFetchUserRegistration = (customerPortalUserId: string) =>\n useQuery<CustomerPortalUserRegistrationViewModel, Error>('userRegistration', () => getCustomerPortalUserRegistration(customerPortalUserId), {\n staleTime: Infinity\n });","import Box from '@mui/material/Box';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { useFormMeta, FormError, FormValidator } from '@/formState';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport Grid from '@mui/material/Grid';\nimport { TextField } from '@/formUI';\nimport { PasswordRequirements } from '@/components/PasswordRequirements/PasswordRequirements';\nimport { getPasswordErrors } from '@/components/PasswordRequirements/utils';\nimport { useTexts as useErrorsTexts } from '@/components/PasswordRequirements/useTexts';\nimport { toast } from 'react-toastify';\nimport { useRegistrationActions } from '../useRegisterActions';\nimport { useTexts } from '../useTexts';\nimport { Footer } from './Footer';\nimport { InvalidRegistrationFooter } from './InvalidRegistrationFooter';\nimport { FormFields, FormErrors } from './formFields';\nimport { useCustomerPortalUserId } from './hooks/useCustomerPortalUserId';\nimport { useFetchUserRegistration } from './hooks/useFetchUserRegistration';\nimport { Typography } from '@mui/material';\n\nconst useStyles = makeStyles({\n section: {\n width: '350px',\n },\n container: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n },\n});\n\nexport const Form = () => {\n const texts = useTexts();\n const { api } = useFormMeta<FormFields, FormError<keyof FormFields>>();\n const classes = useStyles();\n const customerPortalUserId = useCustomerPortalUserId();\n const userRegistration = useFetchUserRegistration(customerPortalUserId);\n const { register, afterRegistrationRedirect, notifyError } = useRegistrationActions();\n const errorsTexts = useErrorsTexts();\n\n const validateForm: FormValidator<FormFields, FormErrors> = formApi => {\n const pwField = formApi.getField('password');\n const confirmPwField = formApi.getField('confirmPassword');\n\n const errors = getPasswordErrors(pwField, confirmPwField, errorsTexts);\n return errors;\n };\n\n useEffect(() => {\n if (userRegistration.isError)\n {\n api.setDisabled(true);\n toast.error(texts.invalidRegistrationLink);\n }\n }, [userRegistration, customerPortalUserId, api, texts]);\n\n const userRegistrationNotCompletedYet = useMemo(() => userRegistration.status == 'success' && userRegistration.data.identityUserId == null,[userRegistration]);\n const userRegistrationMessage = useMemo(() => {\n let message;\n if (userRegistration.isError)\n message = texts.invalidRegistrationLink;\n if (userRegistration.isSuccess && userRegistration.data.identityUserId != null)\n message = texts.userAlreadyRegistered;\n return message;\n }, [userRegistration, texts]);\n\n useEffect(() => {\n if (!api.getValidator('checkPassword')) {\n api.addValidation('checkPassword', validateForm);\n }\n });\n\n const handleOnSubmit = useCallback(async () => {\n try {\n api.setSubmitting(true);\n\n const valid = await api.validate();\n if (!valid) {\n return;\n }\n\n const values = api.getValues();\n const response = await register(customerPortalUserId, values.password);\n\n if (response == true) {\n afterRegistrationRedirect();\n } else {\n notifyError(response.message || texts.registrationFailed);\n }\n } catch (e) {\n } finally {\n api.setSubmitting(false);\n }\n }, [api, customerPortalUserId, afterRegistrationRedirect, register, notifyError, texts]);\n\n return (\n <Box className={classes.container}>\n <Section className={classes.section}>\n <form onChange={() => api.validate()}>\n <SectionHeader title={texts.title} />\n {userRegistrationNotCompletedYet &&\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <TextField<'password', FormFields, FormErrors>\n name=\"password\"\n label={texts.passwordFieldLabel}\n validateOn=\"change blur\"\n textField={{\n 'type': 'password',\n 'fullWidth': true,\n }}\n UNSTABLE_textField={{ 'autoComplete': 'new-password' }}\n />\n </Grid>\n <Grid item>\n <TextField<'confirmPassword', FormFields, FormErrors>\n name=\"confirmPassword\"\n label={texts.confirmPasswordFieldLabel}\n validateOn=\"change blur\"\n textField={{\n 'type': 'password',\n 'fullWidth': true,\n }}\n UNSTABLE_textField={{ 'autoComplete': 'new-password' }}\n />\n </Grid>\n <Grid item>\n <PasswordRequirements errors={api.getErrors()} />\n </Grid>\n <Grid item>\n <Footer handleOnSubmit={handleOnSubmit} />\n </Grid>\n </Grid>\n }\n {!userRegistrationNotCompletedYet &&\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Typography>\n <i>{userRegistrationMessage}</i>\n </Typography>\n </Grid>\n <Grid item>\n <InvalidRegistrationFooter/>\n </Grid>\n </Grid>\n }\n </form>\n </Section>\n </Box>\n );\n};\n","import { FormRoot, useCreateForm } from '@/formState';\nimport { formFields } from './formFields';\nimport { Form } from './Form';\n\nexport function FormProvider() {\n const formState = useCreateForm('register-form', formFields);\n\n return (\n <FormRoot formState={formState}>\n <Form />\n </FormRoot>\n );\n}\n","import { ContentContainer } from '@/components/ContentContainer';\nimport { ContentPaper } from '@/components/ContentPaper';\nimport { FormProvider } from './form/FormProvider';\n\nexport const Register = () => {\n return (\n <ContentContainer>\n <ContentPaper fullWidth>\n <FormProvider />\n </ContentPaper>\n </ContentContainer>\n );\n};\n\nRegister.displayName = 'Register';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n title: translate({ id: `sections.unknown.title` }),\n message: translate({ id: `sections.unknown.message` }),\n };\n }, [translate]);\n}\n","import Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\n\nimport { ContentContainer } from '@/components/ContentContainer';\nimport { ContentPaper } from '@/components/ContentPaper';\n\nimport { useTexts } from './useTexts';\n\nexport function Unknown() {\n const texts = useTexts();\n\n return (\n <ContentContainer>\n <ContentPaper fullWidth>\n <Box\n width=\"100%\"\n height=\"100%\"\n display=\"flex\"\n flexDirection=\"column\"\n justifyContent=\"center\"\n alignItems=\"center\"\n >\n <Typography variant=\"h1\">{texts.title}</Typography>\n <Typography>{texts.message}</Typography>\n </Box>\n </ContentPaper>\n </ContentContainer>\n );\n}\n","import * as _ from 'lodash';\nimport { PropertyTrait, ServiceLocation } from '@/api/serviceLocations';\nimport { ServiceOffering } from '@/api/services';\nimport { proxy, useSnapshot } from 'valtio';\nimport { ServiceDetails } from './sections/SetServiceDetails/store';\n\n// Store state\nexport interface RequestServiceState {\n note: string;\n serviceDetails: ServiceDetails[];\n serviceLocation: ServiceLocation | null;\n services: ServiceOffering[];\n serviceLocationId: string;\n schedulingPlanId: string;\n}\n\nexport const initialState: RequestServiceState = {\n note: '',\n serviceDetails: [],\n serviceLocation: null,\n services: [],\n serviceLocationId: '',\n schedulingPlanId: '',\n};\n\n// Valtio store initialization\nconst state = proxy<RequestServiceState>(initialState);\n\n// Setter functions\nexport function resetRequestServiceState() {\n state.note = '';\n state.schedulingPlanId = '';\n state.serviceDetails = [];\n state.serviceLocation = null;\n state.serviceLocationId = '';\n state.services = [];\n}\n\nexport function setNote(note: string) {\n state.note = note;\n}\n\nexport function setServices(services: ServiceOffering[]) {\n state.services = services.map(service => {\n const existingService = state.services.find(s => s.serviceId == service.serviceId);\n\n if (existingService) {\n return existingService;\n } else {\n return { propertyTraits: [], ...service };\n }\n });\n\n state.serviceDetails = services.map(service => {\n const existingDetails = state.serviceDetails.find(detail => detail.serviceId == service.serviceId);\n\n if (existingDetails) {\n return existingDetails;\n } else {\n return {\n date: null,\n propertyTraits: [],\n schedulingPlan: null,\n serviceId: service.serviceId,\n timeFrame: null,\n schedulingPlanId: service.schedulingPlanId,\n };\n }\n });\n}\n\nexport function setPropertyTraits(propertyTraits: PropertyTrait[], serviceId: string) {\n const service = state.services.find(s => s.serviceId == serviceId);\n\n if (service) {\n service.servicePropertyTraits = [...propertyTraits];\n }\n}\n\nexport function setServiceDetails(serviceDetails: ServiceDetails[]) {\n state.serviceDetails = serviceDetails;\n}\n\nexport function addServiceOffering(service: ServiceOffering) {\n state.services.push(service);\n}\n\nexport function removeServiceOffering(service: ServiceOffering) {\n state.services = _.cloneDeep(state.services.filter(s => s.serviceId != service.serviceId));\n state.serviceDetails = state.serviceDetails.filter(s => s.serviceId != service.serviceId);\n}\n\nexport function setServiceLocation(serviceLocation: ServiceLocation | null) {\n state.serviceLocation = serviceLocation;\n state.serviceDetails = [];\n state.services = [];\n state.serviceLocationId = serviceLocation?.serviceLocationId || '';\n}\n\n//Hooks\nexport function useRequestServiceState() {\n return useSnapshot(state);\n}\n\nexport function useGetNote() {\n return useSnapshot(state).note;\n}\n\nexport function useGetServices() {\n return useSnapshot(state).services;\n}\n\nexport function useGetServiceDetails() {\n return useSnapshot(state).services;\n}\n\nexport function useGetServiceById(serviceId: string) {\n return useSnapshot(state).services.find(s => s.serviceId == serviceId);\n}\n\nexport function useGetServiceLocation() {\n return useSnapshot(state).serviceLocation;\n}\n\nexport function useLocationRequirementComplete() {\n return useSnapshot(state).serviceLocation != null;\n}\n\nexport function useServiceRequirementComplete() {\n return useSnapshot(state).services.length > 0;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n buttonAdd: translate({ id: 'sections.requestService.addNote.buttonAdd' }),\n buttonEdit: translate({ id: 'sections.requestService.addNote.buttonEdit' }),\n };\n }, [translate]);\n}\n","import { proxy, useSnapshot } from 'valtio';\n\nexport interface AddNoteState {\n note: string;\n}\n\nexport const initialState: AddNoteState = {\n note: '',\n};\n\n// Valtio store initialization\nexport const state = proxy<AddNoteState>(initialState);\n\n// Setter functions\nexport function setNote(note: string) {\n state.note = note;\n}\n\n// Hooks\nexport function useSelectAddNoteState() {\n return useSnapshot(state, { sync: true });\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n header: translate({ id: 'sections.requestService.addNote.drawer.header' }),\n noteFieldLabel: translate({ id: 'sections.requestService.addNote.drawer.noteFieldLabel' }),\n };\n }, [translate]);\n}\n","import { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { useCallback, useEffect } from 'react';\nimport { Grid, TextField } from '@mui/material';\nimport { useRequestServiceState, setNote as setRequestNote } from '../../../store';\nimport { setNote, useSelectAddNoteState } from '../store';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport const Drawer = (props: Props) => {\n const { onClose, open } = props;\n const texts = useTexts();\n const { note: requestNote } = useRequestServiceState();\n const { note } = useSelectAddNoteState();\n\n useEffect(() => {\n if (open) {\n setNote(requestNote);\n }\n }, [requestNote, open]);\n\n const onSave = useCallback(() => {\n setRequestNote(note);\n onClose();\n }, [note, onClose]);\n\n const handleChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n setNote(event.target.value);\n }, []);\n\n return (\n <SideDrawerForm isOpen={open} onClose={onClose} onSave={onSave} title={texts.header}>\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <TextField\n id=\"note\"\n autoComplete=\"off\"\n data-testid=\"note\"\n label={texts.noteFieldLabel}\n multiline\n onChange={handleChange}\n onFocus={e =>\n e.currentTarget.setSelectionRange(\n e.currentTarget.value.length,\n e.currentTarget.value.length,\n )\n }\n minRows={5}\n value={note}\n autoFocus\n />\n </Grid>\n </Grid>\n </SideDrawerForm>\n );\n};\n\nDrawer.displayName = 'Drawer';\n","import { Button } from '@mui/material';\nimport EditIcon from '@mui/icons-material/Edit';\nimport PostAddIcon from '@mui/icons-material/PostAdd';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { useGetNote } from '../../store';\nimport { useTexts } from './useTexts';\nimport { Drawer } from './Drawer/Drawer';\n\nexport const AddNote = () => {\n const note = useGetNote();\n const texts = useTexts();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n return (\n <>\n <Button startIcon={note ? <EditIcon /> : <PostAddIcon />} variant=\"text\" onClick={openDrawer}>\n {note ? texts.buttonEdit : texts.buttonAdd}\n </Button>\n\n <Drawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n};\n\nAddNote.displayName = 'AddNote';\n","import { useGetUILayout } from '@/atoms/UILayout';\nimport { ClickAwayListener } from '@mui/material';\nimport Button, { ButtonProps } from '@mui/material/Button';\nimport Tooltip from '@mui/material/Tooltip';\nimport { useState } from 'react';\n\nexport interface Props extends ButtonProps {\n showTooltip?: boolean;\n spanClassName?: string;\n tooltipText?: any;\n}\n\nexport function ButtonWithTooltip(props: Props) {\n const { tooltipText, showTooltip, spanClassName, ...buttonProps } = props;\n const [open, setOpen] = useState<boolean>(false);\n const layout = useGetUILayout();\n\n const handleTooltipClose = () => {\n setOpen(false);\n };\n\n const handleTooltipOpen = () => {\n setOpen(true);\n };\n\n return (\n <>\n {showTooltip && (\n <>\n {layout == 'desktop' && (\n <Tooltip title={tooltipText}>\n <span className={spanClassName}>\n <Button {...buttonProps}>{props.children}</Button>\n </span>\n </Tooltip>\n )}\n\n {layout == 'mobile' && (\n <>\n <ClickAwayListener onClickAway={handleTooltipClose}>\n <div>\n <Tooltip\n disableFocusListener\n disableHoverListener\n disableTouchListener\n onClose={handleTooltipClose}\n open={open}\n PopperProps={{\n disablePortal: true,\n }}\n title={tooltipText}\n >\n <span className={spanClassName} onClick={handleTooltipOpen}>\n <Button {...buttonProps}>{props.children}</Button>\n </span>\n </Tooltip>\n </div>\n </ClickAwayListener>\n </>\n )}\n </>\n )}\n\n {!showTooltip && <Button {...buttonProps}>{props.children}</Button>}\n </>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n actionBtn: translate({ id: 'sections.requestService.addServices.actionBtn' }),\n actionBtnDisabled: translate({ id: 'sections.requestService.addServices.actionBtnDisabled' }),\n header: translate({ id: 'sections.requestService.addServices.header' }),\n };\n }, [translate]);\n}\n","import * as _ from 'lodash';\nimport { ServiceOffering } from '@/api/services';\nimport { proxy, useSnapshot } from 'valtio';\n\nexport interface AddServicesState {\n all: {\n items: ServiceOffering[];\n page: number;\n take: number;\n totalItems: number;\n };\n selected: ServiceOffering[];\n status: 'error' | 'loading' | 'success';\n}\n\nexport const initialState: AddServicesState = {\n all: {\n items: [],\n page: 0,\n take: 0,\n totalItems: 0,\n },\n selected: [],\n status: 'loading',\n};\n\n// Valtio store initialization\nconst state = proxy<AddServicesState>(initialState);\n\n// Setter functions\nexport function setAllServices(services: ServiceOffering[], page: number, take: number, totalItems: number) {\n state.all.items = services;\n state.all.page = page;\n state.all.take = take;\n state.all.totalItems = totalItems;\n}\n\nexport function clearSelectedServices() {\n state.selected = [];\n}\n\nexport function setSelectedServices(services: ServiceOffering[]) {\n state.selected = [...services];\n}\n\nexport function addService(service: ServiceOffering) {\n state.selected.push(service);\n}\n\nexport function setPage(page: number) {\n state.all.page = page;\n}\n\nexport function setStatus(status: 'error' | 'loading' | 'success') {\n state.status = status;\n}\n\nexport function removeService(service: ServiceOffering) {\n const updatedServices = _.cloneDeep(state.selected.filter(s => s.serviceId != service.serviceId));\n state.selected = updatedServices;\n}\n\n// Hooks\nexport function useAddServicesState() {\n return useSnapshot(state);\n}\n\nexport function useIsServiceSelected(service: ServiceOffering) {\n return useSnapshot(state).selected.filter(s => s.serviceId == service.serviceId).length > 0;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n error: translate({ id: 'sections.requestService.addServices.drawer.error' }),\n noServices: translate({ id: 'sections.requestService.addServices.drawer.noServices' }),\n header: translate({ id: 'sections.requestService.addServices.drawer.header' }),\n save: translate({ id: 'global.save' }),\n search: translate({ id: 'sections.requestService.addServices.drawer.search' }),\n };\n }, [translate]);\n}\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\nimport { PropertyTrait } from './serviceLocations';\n\nexport interface SchedulingPlan {\n schedulingPlanId: string;\n daysOfWeek: string;\n intervalUnit: string;\n interval: string;\n tolerance: string;\n}\n\nexport interface ServiceOffering {\n businessUnitId: string;\n serviceDescription: string;\n serviceId: string;\n serviceName: string;\n servicePropertyTraits: PropertyTrait[];\n serviceSchedulingPlans: SchedulingPlan[];\n schedulingPlanId: string;\n}\n\nexport interface GetServicesResponse {\n items: ServiceOffering[];\n page: number;\n take: number;\n total: number;\n}\n\nconst baseUrl = '/api/BusinessUnits';\n\nexport const getServices = async (businessUnitId: string, page: number, take: number) => {\n try {\n const { data, status } = await get<GetServicesResponse>(\n `${baseUrl}/${businessUnitId}/Services?page=${page}&take=${take}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get services.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { useCallback, useEffect, useState } from 'react';\nimport { isServerError } from '@/utils/ServerError';\nimport { getServices } from '@/api/services';\nimport { setAllServices, setStatus } from './store';\n\nexport const useData = (businessUnitId: string, pageNumber: number) => {\n const [isStale, setIsStale] = useState<boolean>(true);\n\n useEffect(() => {\n let mounted = true;\n\n const getSettings = async (businessUnitId: string) => {\n try {\n setStatus('loading');\n const response = await getServices(businessUnitId, pageNumber, 10);\n const { items, page, take, total } = response;\n\n if (isServerError(response)) {\n setStatus('error');\n }\n\n if (mounted && !!response) {\n setStatus('success');\n setAllServices(items, page, take, total);\n }\n } catch (error) {\n if (mounted) {\n setStatus('error');\n }\n } finally {\n setIsStale(false);\n }\n };\n\n if (isStale && !!businessUnitId) {\n getSettings(businessUnitId);\n }\n\n return () => {\n mounted = false;\n };\n }, [businessUnitId, pageNumber, isStale]);\n\n const refreshData = useCallback(async () => {\n setIsStale(true);\n }, []);\n\n useEffect(() => {\n refreshData();\n }, [businessUnitId, pageNumber, refreshData]);\n\n return [refreshData] as const;\n};\n","import { ServiceOffering } from '@/api/services';\nimport { Box, Checkbox, Typography } from '@mui/material';\nimport { addService, removeService, useIsServiceSelected } from '../store';\ninterface Props {\n service: ServiceOffering;\n}\n\nexport const ServiceCheckbox = (props: Props) => {\n const { service } = props;\n const isSelected = useIsServiceSelected(service);\n\n const handleClick = () => {\n isSelected ? removeService(service) : addService(service);\n };\n\n return (\n <Box display=\"flex\" alignItems=\"center\">\n <Box display=\"flex\" flexGrow={1} flexDirection=\"column\" onClick={handleClick} style={{ cursor: 'pointer' }}>\n <Typography variant=\"h5\">\n <b>{service.serviceName}</b>\n </Typography>\n <Typography>{service.serviceDescription}</Typography>\n </Box>\n <Box>\n <Checkbox checked={isSelected} color=\"primary\" onChange={handleClick} />\n </Box>\n </Box>\n );\n};\n","import { Alert, Stack } from '@mui/material';\nimport { useAddServicesState } from '../store';\nimport { useTexts } from './useTexts';\nimport { ServiceCheckbox } from './ServiceCheckbox';\n\nexport function ServiceList() {\n const texts = useTexts();\n\n const {\n all: { items: services },\n } = useAddServicesState();\n\n return (\n <>\n {services.length == 0 && <Alert severity=\"info\">{texts.noServices}</Alert>}\n\n {services.length > 0 && (\n <Stack direction=\"column\" spacing={2}>\n {services.map((service, i) => (\n <ServiceCheckbox key={i} service={service} />\n ))}\n </Stack>\n )}\n </>\n );\n}\n","import { Alert, Box, CircularProgress } from '@mui/material';\nimport { useAddServicesState } from '../store';\nimport { useRequestServiceState } from '../../../store';\nimport { useData } from '../useData';\nimport { useTexts } from './useTexts';\nimport { ServiceList } from './ServiceList';\n\nexport function DrawerContent() {\n const { serviceLocation } = useRequestServiceState();\n const {\n all: { page },\n status,\n } = useAddServicesState();\n\n const texts = useTexts();\n\n useData(serviceLocation?.businessUnitId || '', page);\n\n return (\n <Box>\n {status == 'loading' && (\n <Box display=\"flex\" p={2} justifyContent=\"center\">\n <CircularProgress />\n </Box>\n )}\n {status == 'success' && <ServiceList />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n </Box>\n );\n}\n","import { Box, Pagination as MuiPagination } from '@mui/material';\nimport { useMemo } from 'react';\nimport { useAddServicesState, setPage } from '../store';\n\nexport const Pagination = () => {\n const {\n all: { page, take, totalItems },\n } = useAddServicesState();\n\n const pageCount = useMemo(() => {\n return Math.ceil(totalItems / take);\n }, [take, totalItems]);\n\n return (\n <>\n {pageCount > 1 && (\n <Box p={1}>\n <MuiPagination\n color=\"primary\"\n count={pageCount}\n page={page + 1}\n onChange={(_e, page) => {\n setPage(page - 1);\n }}\n />\n </Box>\n )}\n </>\n );\n};\n","import { useCallback, useEffect } from 'react';\nimport { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { setServices, useRequestServiceState } from '../../../store';\nimport { setPage, setSelectedServices, useAddServicesState } from '../store';\nimport { useTexts } from './useTexts';\nimport { DrawerContent } from './DrawerContent';\nimport { Pagination } from './Pagination';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function Drawer(props: Props) {\n const { onClose, open } = props;\n const texts = useTexts();\n const { selected: selectedServices } = useAddServicesState();\n const request = useRequestServiceState();\n\n const onSave = useCallback(() => {\n setServices(selectedServices);\n onClose();\n }, [onClose, selectedServices]);\n\n useEffect(() => {\n if (open) {\n setPage(0);\n setSelectedServices(request.services);\n }\n }, [open, request.services]);\n\n return (\n <SideDrawerForm\n disableSave={selectedServices.length == 0}\n footerSecondary={<Pagination />}\n isOpen={open}\n onClose={onClose}\n onSave={onSave}\n title={texts.header}\n >\n <DrawerContent />\n </SideDrawerForm>\n );\n}\n","import { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport AddIcon from '@mui/icons-material/Add';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { ButtonWithTooltip } from '@/components/ButtonWithTooltip';\nimport { useLocationRequirementComplete } from '../../store';\nimport { useTexts } from './useTexts';\nimport { Drawer } from './Drawer/Drawer';\n\nexport const AddServices = () => {\n const texts = useTexts();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n const locationRequirementsComplete = useLocationRequirementComplete();\n\n return (\n <>\n <Section>\n <SectionHeader title={texts.header} />\n <ButtonWithTooltip\n color=\"primary\"\n disabled={!locationRequirementsComplete}\n onClick={openDrawer}\n showTooltip={!locationRequirementsComplete}\n startIcon={<AddIcon />}\n tooltipText={locationRequirementsComplete ? '' : texts.actionBtnDisabled}\n variant=\"contained\"\n >\n {texts.actionBtn}\n </ButtonWithTooltip>\n </Section>\n\n <Drawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n};\n\nAddServices.displayName = 'AddServices';\n","import { ServiceLocation } from '@/api/serviceLocations';\nimport { proxy, useSnapshot } from 'valtio';\n\nexport interface SelectLocationState {\n all: ServiceLocation[];\n searchQuery: string;\n selected: ServiceLocation | null;\n status: 'error' | 'loading' | 'success';\n}\n\nexport const initialState: SelectLocationState = {\n all: [],\n searchQuery: '',\n selected: null,\n status: 'loading',\n};\n\n// Valtio store initialization\nconst state = proxy<SelectLocationState>(initialState);\n\n// Setter functions\nexport function setLocation(location: ServiceLocation | null) {\n if (location?.validationErrors) {\n return;\n }\n state.selected = location ? { ...location } : null;\n}\n\nexport function setLocations(locations: ServiceLocation[]) {\n state.all = [...locations];\n}\n\nexport function setSearchQuery(searchQuery: string) {\n state.searchQuery = searchQuery;\n}\n\nexport function setStatus(status: 'error' | 'loading' | 'success') {\n state.status = status;\n}\n\n// Hooks\nexport function useSelectLocationState() {\n return useSnapshot(state, { sync: true });\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n cancel: translate({ id: 'global.cancel' }),\n error: translate({ id: 'sections.requestService.selectLocation.drawer.error' }),\n header: translate({ id: 'sections.requestService.selectLocation.drawer.header' }),\n locationRequired: translate({ id: 'sections.requestService.selectLocation.drawer.locationRequired' }),\n locationHasErrors: translate({ id: 'sections.requestService.selectLocation.drawer.locationHasErrors' }),\n locations: translate({ id: 'sections.requestService.selectLocation.drawer.locations' }),\n noLocations: translate({ id: 'sections.requestService.selectLocation.drawer.noLocations' }),\n noLocationsMatchQuery: translate({\n id: 'sections.requestService.selectLocation.drawer.noLocationsMatchQuery',\n }),\n save: translate({ id: 'global.save' }),\n };\n }, [translate]);\n}\n","import { useEffect, useState } from 'react';\nimport { isServerError } from '@/utils/ServerError';\nimport { getLocations } from '@/api/serviceLocations';\nimport { getDefaultServiceLocationId } from '@/api/accounts';\nimport { useRequestServiceState } from '../../store';\nimport { setLocation, setLocations, setStatus } from './store';\n\nexport const useData = (accountId: string) => {\n const [isStale, setIsStale] = useState<boolean>(true);\n const request = useRequestServiceState();\n\n useEffect(() => {\n let mounted = true;\n\n const getSettings = async (accountId: string) => {\n try {\n setStatus('loading');\n const response = await getLocations(accountId);\n const defaultLocationId = await getDefaultServiceLocationId(accountId);\n\n if (isServerError(response)) {\n setStatus('error');\n }\n\n if (mounted && !!response) {\n setStatus('success');\n setLocations(response);\n\n if (request.serviceLocation) {\n setLocation(request.serviceLocation);\n } else {\n const matchingLocation = response.find(\n l => l.serviceLocationId == defaultLocationId && !l.validationErrors,\n );\n const firstValidLocation = !matchingLocation ? response.find(l => !l.validationErrors) : null;\n setLocation(matchingLocation || firstValidLocation || null);\n }\n }\n } catch (error) {\n if (mounted) {\n setStatus('error');\n }\n } finally {\n setIsStale(false);\n }\n };\n\n if (isStale && !!accountId) {\n getSettings(accountId);\n }\n\n return () => {\n mounted = false;\n };\n }, [accountId, isStale, request]);\n\n return;\n};\n","import { ServiceLocation } from '@/api/serviceLocations';\nimport { ComponentWithTooltip } from '@/components/ComponentWithTooltip';\nimport { Box, Radio, Typography } from '@mui/material';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { useCallback, useMemo } from 'react';\nimport { setLocation, useSelectLocationState } from '../store';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n location: ServiceLocation;\n}\n\nconst useStyles = makeStyles({\n title: {\n fontSize: '16px',\n fontWeight: 700,\n },\n subTitle: {\n fontSize: '16px',\n fontWeight: 400,\n },\n subSubTitle: {\n fontSize: '14px',\n },\n disabledLabel: {\n opacity: 0.5,\n },\n});\n\nexport const LocationRadioButton = (props: Props) => {\n const { location } = props;\n const { selected } = useSelectLocationState();\n const classes = useStyles();\n const texts = useTexts();\n\n const handleChange = useCallback(\n (_event: React.ChangeEvent<HTMLInputElement>) => {\n setLocation(location);\n },\n [location],\n );\n\n const handleLabelClick = useCallback(\n (_event: React.MouseEvent<HTMLElement>) => {\n setLocation(location);\n },\n [location],\n );\n\n const hasErrors = useMemo(() => {\n return !!location.validationErrors;\n }, [location]);\n\n return (\n <ComponentWithTooltip showTooltip={hasErrors} tooltipText={texts.locationHasErrors}>\n <Box display=\"flex\" alignItems=\"center\" style={{ cursor: 'pointer' }}>\n <Box flexGrow={1} onClick={handleLabelClick} className={hasErrors ? classes.disabledLabel : undefined}>\n <Typography className={classes.subTitle}>{`${location.street1}`}</Typography>\n {location.street2 && <Typography className={classes.subTitle}>{`${location.street2}`}</Typography>}\n <Typography\n className={classes.subSubTitle}\n >{`${location.city}, ${location.stateAbbreviation} ${location.postalCode}`}</Typography>\n </Box>\n <Box>\n <Radio\n checked={location.serviceLocationId == selected?.serviceLocationId}\n color=\"primary\"\n onChange={handleChange}\n value={location}\n disabled={hasErrors}\n />\n </Box>\n </Box>\n </ComponentWithTooltip>\n );\n};\n\nLocationRadioButton.displayName = 'LocationRadioButton';\n","import { Alert, Stack } from '@mui/material';\nimport { useMemo } from 'react';\nimport { useSelectLocationState } from '../store';\nimport { LocationRadioButton } from './LocationRadioButton';\nimport { useTexts } from './useTexts';\n\nexport const LocationList = () => {\n const texts = useTexts();\n const { all: locations, searchQuery } = useSelectLocationState();\n\n const filteredLocations = useMemo(() => {\n return locations.filter(l => {\n const addressString = `${l.name} ${l.street1} ${l.street2} ${l.city} ${l.state} ${l.stateAbbreviation} ${l.country} ${l.countryCode} ${l.postalCode}`;\n return addressString.toLowerCase().includes(searchQuery.toLowerCase());\n });\n }, [locations, searchQuery]);\n\n return (\n <>\n {locations.length == 0 && <Alert severity=\"info\">{texts.noLocations}</Alert>}\n\n {locations.length > 0 && (\n <>\n {filteredLocations.length == 0 && <Alert severity=\"info\">{texts.noLocationsMatchQuery}</Alert>}\n {filteredLocations.length > 0 && (\n <Stack direction=\"column\" spacing={2}>\n {filteredLocations.map((location, i) => (\n <LocationRadioButton key={i} location={location} />\n ))}\n </Stack>\n )}\n </>\n )}\n </>\n );\n};\n","import { Alert, Box, CircularProgress } from '@mui/material';\nimport { useAccountId } from '@/atoms/session';\nimport { useData } from '../useData';\nimport { useSelectLocationState } from '../store';\nimport { LocationList } from './LocationList';\nimport { useTexts } from './useTexts';\n\nexport const DrawerContent = () => {\n const { status } = useSelectLocationState();\n const texts = useTexts();\n const accountId = useAccountId();\n\n useData(accountId || '');\n\n return (\n <Box>\n {status == 'loading' && (\n <Box display=\"flex\" p={2} justifyContent=\"center\">\n <CircularProgress />\n </Box>\n )}\n {status == 'success' && <LocationList />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n </Box>\n );\n};\n\nDrawerContent.displayName = 'DrawerContent';\n","import { SearchBox } from '@/components/SearchBox/SearchBox';\nimport { Box } from '@mui/material';\nimport { useCallback, useEffect } from 'react';\nimport { useRequestServiceState } from '../../../store';\nimport { setLocation, setSearchQuery, useSelectLocationState } from '../store';\n\nexport const LocationSearch = () => {\n const { searchQuery } = useSelectLocationState();\n const request = useRequestServiceState();\n\n useEffect(() => {\n setLocation(request.serviceLocation);\n }, [request.serviceLocation]);\n\n const onChangeSearch = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\n setSearchQuery(event.target.value);\n }, []);\n\n const clearSearch = useCallback(() => {\n setSearchQuery('');\n }, []);\n\n return (\n <Box p={2}>\n <SearchBox onChange={onChangeSearch} onClear={clearSearch} value={searchQuery} />\n </Box>\n );\n};\n","import { useCallback } from 'react';\nimport { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { setServiceLocation } from '../../../store';\nimport { useSelectLocationState } from '../store';\nimport { useTexts } from './useTexts';\nimport { DrawerContent } from './DrawerContent';\nimport { LocationSearch } from './LocationSearch';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport const Drawer = (props: Props) => {\n const { onClose, open } = props;\n const texts = useTexts();\n const { selected } = useSelectLocationState();\n\n const onSave = useCallback(() => {\n setServiceLocation(selected);\n onClose();\n }, [onClose, selected]);\n\n return (\n <SideDrawerForm\n disableSave={!selected}\n headerSecondary={<LocationSearch />}\n isOpen={open}\n onClose={onClose}\n onSave={onSave}\n title={texts.header}\n >\n <DrawerContent />\n </SideDrawerForm>\n );\n};\n\nDrawer.displayName = 'Drawer';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n actionBtn: translate({ id: 'sections.requestService.selectLocation.actionBtn' }),\n header: translate({ id: 'sections.requestService.selectLocation.header' }),\n };\n }, [translate]);\n}\n","import { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { Button } from '@mui/material';\nimport RoomIcon from '@mui/icons-material/Room';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { Drawer } from './Drawer/Drawer';\nimport { useTexts } from './useTexts';\n\nexport const SelectLocation = () => {\n const texts = useTexts();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n return (\n <>\n <Section>\n <SectionHeader title={texts.header} />\n <Button color=\"primary\" startIcon={<RoomIcon />} variant=\"contained\" onClick={openDrawer}>\n {texts.actionBtn}\n </Button>\n </Section>\n\n <Drawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n};\n\nSelectLocation.displayName = 'SelectLocation';\n","import { PropertyTrait } from '@/api/serviceLocations';\nimport { SchedulingPlan } from '@/api/services';\nimport { proxy, snapshot, useSnapshot } from 'valtio';\nimport * as _ from 'lodash';\nimport { TimeFrames } from './Drawer/Form/fields/Timeframe';\n\nexport interface ServiceDetails {\n date: Date | null;\n propertyTraits: PropertyTrait[];\n schedulingPlan: SchedulingPlan | null;\n serviceId: string;\n timeFrame: TimeFrames | null;\n schedulingPlanId: string;\n}\nexport interface SetServiceDetailsState {\n propertyTraits: PropertyTrait[];\n serviceDetails: ServiceDetails[];\n}\n\nexport const initialState: SetServiceDetailsState = {\n propertyTraits: [],\n serviceDetails: [],\n};\n\n// Valtio store initialization\nconst state = proxy<SetServiceDetailsState>(initialState);\n\n// Getter functions\nexport function getServiceDetail() {\n return snapshot(state.serviceDetails);\n}\n\n// Setter functions\nexport function setServiceDate(date: Date | null, serviceId: string) {\n const existingService = state.serviceDetails.find(s => s.serviceId == serviceId);\n\n if (existingService) {\n existingService.date = date;\n existingService.timeFrame = null;\n if (!date) {\n existingService.schedulingPlan = null;\n }\n } else {\n state.serviceDetails.push({\n date,\n propertyTraits: [],\n serviceId,\n schedulingPlan: null,\n timeFrame: null,\n schedulingPlanId: '',\n });\n }\n}\n\nexport function setServiceSchedulingPlan(schedulingPlan: SchedulingPlan, serviceId: string) {\n const existingService = state.serviceDetails.find(s => s.serviceId == serviceId);\n\n if (existingService) {\n existingService.schedulingPlan = schedulingPlan;\n existingService.schedulingPlanId = schedulingPlan.schedulingPlanId;\n }\n}\n\nexport function setServiceTimeFrame(serviceId: string, timeFrame: TimeFrames) {\n const existingService = state.serviceDetails.find(s => s.serviceId == serviceId);\n\n if (existingService) {\n existingService.timeFrame = timeFrame;\n }\n}\n\nexport function addPropertyTrait(serviceId: string, propertyTrait: PropertyTrait) {\n const existingService = state.serviceDetails.find(s => s.serviceId == serviceId);\n\n if (existingService) {\n const existingPropertyTrait = existingService.propertyTraits.find(\n p => p.propertyTraitId == propertyTrait.propertyTraitId,\n );\n\n if (existingPropertyTrait) {\n return;\n } else {\n existingService.propertyTraits.push(propertyTrait);\n }\n }\n}\n\nexport function updatePropertyTrait(serviceId: string, propertyTrait: PropertyTrait) {\n const existingServiceIndex = state.serviceDetails.findIndex(s => s.serviceId == serviceId);\n\n if (existingServiceIndex != -1) {\n const existingPropertyTraitIndex = state.serviceDetails[existingServiceIndex].propertyTraits.findIndex(\n p => p.propertyTraitId == propertyTrait.propertyTraitId,\n );\n\n if (existingPropertyTraitIndex != -1) {\n state.serviceDetails[existingServiceIndex].propertyTraits[existingPropertyTraitIndex].amount =\n propertyTrait.amount;\n } else {\n return;\n }\n }\n}\n\nexport function removeServiceDetailsById(serviceId: string) {\n state.serviceDetails = _.cloneDeep(state.serviceDetails.filter(s => serviceId != s.serviceId));\n}\n\nexport function resetServiceDetails(serviceDetails: ServiceDetails[]) {\n state.serviceDetails = _.cloneDeep(serviceDetails);\n}\n\n// Hooks\nexport function useSelectServiceDetailState() {\n return useSnapshot(state);\n}\n\nexport function useSelectServiceDetail() {\n return useSnapshot(state).serviceDetails;\n}\n\nexport function useSelectServiceDetails(serviceId: string) {\n return useSnapshot(state).serviceDetails.find(s => s.serviceId == serviceId) || null;\n}\n","import { ServiceOffering } from '@/api/services';\nimport { RequestServiceState } from '../../store';\nimport { ServiceDetails } from '../SetServiceDetails/store';\n\nconst arePropertyTraitsSet = (service: ServiceOffering, detail: ServiceDetails) => {\n let isValid = false;\n const propertyTraits = service.servicePropertyTraits || [];\n\n if (propertyTraits.length) {\n isValid = propertyTraits.every(p => {\n const trait = detail.propertyTraits.find(dp => dp.propertyTraitId == p.propertyTraitId);\n return !!trait && !!trait.serviceLocationPropertyTraitId && !!trait.amount;\n });\n } else {\n isValid = true;\n }\n\n return isValid;\n};\n\nconst isSchedulingPlanSet = (service: ServiceOffering, detail: ServiceDetails) => {\n return service.serviceSchedulingPlans?.length > 0 ? !!detail.schedulingPlan?.schedulingPlanId : true;\n};\n\nexport const areServiceDetailsSet = (request: RequestServiceState, details: ServiceDetails[]) => {\n return request.services.every(s => {\n const detail = details.find(d => d.serviceId == s.serviceId);\n\n if (!!detail) {\n const dateIsSet = !!detail.date;\n const dateHasNotPassed =\n !!detail.date && new Date().setHours(0, 0, 0, 0) - detail.date.setHours(0, 0, 0, 0) <= 0;\n const propertyTraitsAreSet = arePropertyTraitsSet(s, detail);\n const schedulingPlanIsSet = isSchedulingPlanSet(s, detail);\n const timeFrameIsSet = !!detail.timeFrame;\n return dateIsSet && dateHasNotPassed && propertyTraitsAreSet && schedulingPlanIsSet && timeFrameIsSet;\n } else {\n return false;\n }\n });\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n cancel: translate({ id: 'global.cancel' }),\n date: translate({ id: 'global.date' }),\n error: translate({ id: 'sections.requestService.setServiceDetails.drawer.error' }),\n errorLoadingPropertyTraits: translate({\n id: 'sections.requestService.setServiceDetails.drawer.errorLoadingPropertyTraits',\n }),\n header: translate({ id: 'sections.requestService.setServiceDetails.drawer.header' }),\n infoBox: translate({ id: 'sections.requestService.setServiceDetails.drawer.infoBox' }),\n noServices: translate({ id: 'sections.requestService.setServiceDetails.drawer.noServices' }),\n save: translate({ id: 'global.save' }),\n };\n }, [translate]);\n}\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nexport interface CompanyHoliday {\n businessUnitId: string;\n date: string;\n generatedFrom: string;\n id: string;\n name: string;\n recurring: boolean;\n}\n\nconst baseUrl = '/api/CompanyHoliday';\n\nexport const getCompanyHolidays = async (businessUnitId: string) => {\n try {\n const { data, status } = await get<CompanyHoliday[]>(`${baseUrl}/${businessUnitId}/CompanyHolidays`);\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get company holidays.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { CompanyHoliday, getCompanyHolidays } from '@/api/companyHolidays';\nimport { useQuery } from 'react-query';\n\nexport const useFetchHolidays = (businessUnitId: string) =>\n useQuery<CompanyHoliday[], Error>('companyHolidays', () => getCompanyHolidays(businessUnitId), {\n staleTime: Infinity,\n });\n","import { useFetchCustomerPortalSettings } from '@/common/hooks/query/useFetchCustomerPortalSettings';\nimport { useCallback } from 'react';\nimport { useFetchHolidays } from '@/common/hooks/query/useFetchHolidays';\nimport { DatePicker } from '@/components/DatePicker';\nimport { useRequestServiceState } from '../../../../../store';\nimport { setServiceDate, useSelectServiceDetails } from '../../../store';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n serviceId: string;\n}\n\nexport const ServiceDatePicker = (props: Props) => {\n const { serviceId } = props;\n const { serviceLocation } = useRequestServiceState();\n const { data: holidays } = useFetchHolidays(serviceLocation?.businessUnitId || '');\n const { data: customerPortalSettings } = useFetchCustomerPortalSettings(serviceLocation?.businessUnitId || '');\n const serviceDetails = useSelectServiceDetails(serviceId);\n const texts = useTexts();\n\n const isClosed = useCallback(\n (date: Date) => {\n const dayOfWeek = date.getDay();\n\n if (dayOfWeek == 0 && customerPortalSettings?.sundayAvailability == 0) {\n return true;\n }\n\n if (dayOfWeek == 1 && customerPortalSettings?.mondayAvailability == 0) {\n return true;\n }\n\n if (dayOfWeek == 2 && customerPortalSettings?.tuesdayAvailability == 0) {\n return true;\n }\n\n if (dayOfWeek == 3 && customerPortalSettings?.wednesdayAvailability == 0) {\n return true;\n }\n\n if (dayOfWeek == 4 && customerPortalSettings?.thursdayAvailability == 0) {\n return true;\n }\n\n if (dayOfWeek == 5 && customerPortalSettings?.fridayAvailability == 0) {\n return true;\n }\n\n if (dayOfWeek == 6 && customerPortalSettings?.saturdayAvailability == 0) {\n return true;\n }\n },\n [customerPortalSettings],\n );\n\n const isHoliday = useCallback(\n (day: Date) => {\n if (!holidays) {\n return false;\n }\n\n return !!holidays.find(h => {\n const holidayDate = new Date(h.date);\n\n if (h.recurring) {\n const isSameMonth = holidayDate.getMonth() === day.getMonth();\n const isSameDay = holidayDate.getDate() === day.getDate();\n return isSameMonth && isSameDay;\n } else {\n return (\n holidayDate.getFullYear() === day.getFullYear() &&\n holidayDate.getMonth() === day.getMonth() &&\n holidayDate.getDate() === day.getDate()\n );\n }\n });\n },\n [holidays],\n );\n\n const shouldDisableDate = useCallback(\n (date: Date | null, _keyboardInputValue?: string | undefined) => {\n if (!date) {\n return false;\n }\n\n return isClosed(date) || isHoliday(date);\n },\n [isClosed, isHoliday],\n );\n\n const handleDateChange = useCallback(\n (date: Date | null, _keyboardInputValue?: string | undefined) => {\n setServiceDate(date, serviceId);\n },\n [serviceId],\n );\n\n return (\n <DatePicker\n disablePast\n label={texts.date}\n onChange={handleDateChange}\n InputProps={{\n required: true,\n }}\n shouldDisableDate={shouldDisableDate}\n value={serviceDetails?.date || null}\n />\n );\n};\n","import { SchedulingPlan } from '@/api/services';\nimport { useHumanizedSchedulingPlan } from '@/common/hooks/schedulingPlan/useHumanizedSchedulingPlan';\n\ninterface Props {\n frequency: SchedulingPlan;\n}\n\nexport function FrequencyMenuItemText(props: Props) {\n const { frequency } = props;\n const humanizedSchedulingPlan = useHumanizedSchedulingPlan(frequency);\n\n return <>{humanizedSchedulingPlan}</>;\n}\n","import { ServiceOffering } from '@/api/services';\nimport { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';\nimport { ReactNode, useCallback, useMemo } from 'react';\nimport { setServiceSchedulingPlan, useSelectServiceDetails } from '../../../store';\nimport { FrequencyMenuItemText } from './FrequencyMenuItemText';\n\ninterface Props {\n service: ServiceOffering;\n}\n\nexport const Frequency = (props: Props) => {\n const { service } = props;\n const serviceDetail = useSelectServiceDetails(service.serviceId);\n\n const frequencies = useMemo(() => {\n return service.serviceSchedulingPlans || [];\n }, [service]);\n\n const handleChange = useCallback(\n (event: SelectChangeEvent<string>, _child: ReactNode) => {\n if (!event.target || !service.serviceId) {\n return;\n }\n\n if (event.target.value == '') {\n return;\n }\n\n const schedulingPlanId = event.target.value as string;\n const selectedPlan = service.serviceSchedulingPlans.find(s => s.schedulingPlanId == schedulingPlanId);\n\n if (!!selectedPlan) {\n setServiceSchedulingPlan(selectedPlan, service.serviceId);\n }\n },\n [service.serviceId, service.serviceSchedulingPlans],\n );\n\n const isDisabled = useMemo(() => {\n return !serviceDetail?.date;\n }, [serviceDetail?.date]);\n\n return (\n <FormControl fullWidth variant=\"outlined\" margin=\"dense\" required>\n <InputLabel id=\"frequency\">Frequency</InputLabel>\n <Select<string>\n defaultValue={''}\n disabled={isDisabled}\n id=\"frequency\"\n label=\"Frequency\"\n labelId=\"frequency\"\n onChange={handleChange}\n required\n value={serviceDetail?.schedulingPlan?.schedulingPlanId || ''}\n >\n {frequencies.map((f, i) => (\n <MenuItem key={i} value={f.schedulingPlanId}>\n <FrequencyMenuItemText frequency={f} />\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n","import { useCallback, useEffect, useState } from 'react';\nimport { getPropertyTraitsByService } from '@/api/serviceLocations';\nimport { isServerError } from '@/utils/ServerError';\nimport { addPropertyTrait } from '../../../store';\n\ntype Status = 'error' | 'loading' | 'success';\n\nexport const useGetPropertyTraitsOnMount = (serviceId: string, serviceLocationId: string) => {\n const [status, setStatus] = useState<Status>('loading');\n const [isStale, setIsStale] = useState<boolean>(true);\n\n useEffect(() => {\n let mounted = true;\n\n const getData = async (serviceId: string, serviceLocationId: string) => {\n try {\n if (mounted) {\n setStatus('loading');\n }\n\n const response = await getPropertyTraitsByService(serviceId, serviceLocationId);\n\n if (isServerError(response)) {\n throw new Error(response.message);\n }\n\n if (mounted && !!response) {\n setStatus('success');\n\n response.forEach(p => {\n addPropertyTrait(serviceId, p);\n });\n }\n } catch (error) {\n if (mounted) {\n setStatus('error');\n }\n } finally {\n if (mounted) {\n setIsStale(false);\n }\n }\n };\n\n if (isStale && !!serviceId && !!serviceLocationId) {\n getData(serviceId, serviceLocationId);\n }\n\n return () => {\n mounted = false;\n };\n }, [isStale, serviceId, serviceLocationId]);\n\n const refreshData = useCallback(async () => {\n setIsStale(true);\n }, []);\n\n useEffect(() => {\n refreshData();\n }, [refreshData, serviceId, serviceLocationId]);\n\n return [status] as const;\n};\n","import { PropertyTrait } from '@/api/serviceLocations';\nimport { ServiceOffering } from '@/api/services';\nimport { Alert, CircularProgress, Grid, InputAdornment, TextField } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport { useRequestServiceState } from '../../../../../store';\nimport { updatePropertyTrait, useSelectServiceDetails } from '../../../store';\nimport { useGetPropertyTraitsOnMount } from '../utils/useGetPropertyTraitsOnMount';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n columnSize: 6 | 12;\n service: ServiceOffering;\n}\n\nexport const PropertyTraits = (props: Props) => {\n const { columnSize, service } = props;\n const serviceDetails = useSelectServiceDetails(service.serviceId);\n const { serviceLocation } = useRequestServiceState();\n const texts = useTexts();\n\n const propertyTraits = useMemo(() => {\n return serviceDetails?.propertyTraits || [];\n }, [serviceDetails]);\n\n const [status] = useGetPropertyTraitsOnMount(service.serviceId, serviceLocation?.serviceLocationId || '');\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<{ value: unknown }>, propertyTrait: PropertyTrait) => {\n if (!event.target) {\n return;\n }\n const amount = event.target.value as number;\n updatePropertyTrait(service.serviceId, { ...propertyTrait, amount: Number(amount) });\n },\n [service.serviceId],\n );\n\n return (\n <>\n {status == 'loading' && (\n <Grid item xs={columnSize}>\n <CircularProgress size={14} />\n </Grid>\n )}\n {status == 'success' && (\n <>\n {propertyTraits.map((p, i) => (\n <Grid item key={i} xs={columnSize}>\n <TextField\n fullWidth\n InputProps={{\n inputProps: {\n min: 0,\n },\n endAdornment: <InputAdornment position=\"end\">{p.unitOfMeasure}</InputAdornment>,\n }}\n label={p.name}\n margin=\"dense\"\n name={p.name}\n onChange={e => handleChange(e, p)}\n required\n type=\"number\"\n value={\n serviceDetails?.propertyTraits.find(pt => pt.propertyTraitId == p.propertyTraitId)\n ?.amount ?? 0\n }\n />\n </Grid>\n ))}\n </>\n )}\n {status == 'error' && (\n <Grid item xs={columnSize}>\n <Alert severity=\"error\">{texts.errorLoadingPropertyTraits}</Alert>\n </Grid>\n )}\n </>\n );\n};\n","import { getAccount } from '@/atoms/session/store';\nimport { useFetchCustomerPortalSettings } from '@/common/hooks/query/useFetchCustomerPortalSettings';\nimport { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material';\nimport { useCallback, useMemo } from 'react';\nimport { setServiceTimeFrame, useSelectServiceDetails } from '../../../store';\n\nexport enum TimeFrames {\n Morning = 'morning',\n Afternoon = 'afternoon',\n Evening = 'evening',\n}\n\nconst humanizedTimeFrames = {\n [TimeFrames.Morning]: 'Morning',\n [TimeFrames.Afternoon]: 'Afternoon',\n [TimeFrames.Evening]: 'Evening',\n};\n\ninterface Props {\n serviceId: string;\n}\n\nexport const TimeFrame = (props: Props) => {\n const { serviceId } = props;\n const serviceDetails = useSelectServiceDetails(serviceId);\n const account = getAccount();\n const { data: settings } = useFetchCustomerPortalSettings(account?.businessUnitId || '');\n\n const handleChange = useCallback(\n (event: SelectChangeEvent<TimeFrames | ''>) => {\n if (!event.target) {\n return;\n }\n\n if (event.target.value == '') {\n return;\n }\n\n setServiceTimeFrame(serviceId, event.target.value as TimeFrames);\n },\n [serviceId],\n );\n\n const getAvailability = useCallback(\n (date: Date) => {\n const day = date.getDay();\n\n switch (day) {\n case 0:\n return settings?.sundayAvailability || 0;\n case 1:\n return settings?.mondayAvailability || 0;\n case 2:\n return settings?.tuesdayAvailability || 0;\n case 3:\n return settings?.wednesdayAvailability || 0;\n case 4:\n return settings?.thursdayAvailability || 0;\n case 5:\n return settings?.fridayAvailability || 0;\n case 6:\n return settings?.saturdayAvailability || 0;\n default:\n return 0;\n }\n },\n [settings],\n );\n\n const timeFrames = useMemo(() => {\n const availableTimeFrames: TimeFrames[] = [];\n if (serviceDetails?.date) {\n const availability = getAvailability(serviceDetails.date);\n\n if (availability & 1) {\n availableTimeFrames.push(TimeFrames.Morning);\n }\n\n if (availability & 2) {\n availableTimeFrames.push(TimeFrames.Afternoon);\n }\n\n if (availability & 4) {\n availableTimeFrames.push(TimeFrames.Evening);\n }\n }\n\n return availableTimeFrames;\n }, [getAvailability, serviceDetails]);\n\n const isDisabled = useMemo(() => {\n return !serviceDetails?.date;\n }, [serviceDetails?.date]);\n\n return (\n <FormControl fullWidth variant=\"outlined\" margin=\"dense\" required>\n <InputLabel id=\"timeframe\">Timeframe</InputLabel>\n <Select<TimeFrames | ''>\n defaultValue={''}\n disabled={isDisabled}\n id=\"timeframe\"\n label=\"Timeframe\"\n labelId=\"timeframe\"\n onChange={handleChange}\n required\n value={serviceDetails?.timeFrame || ''}\n >\n {timeFrames.map((t, i) => (\n <MenuItem key={i} value={t}>\n {humanizedTimeFrames[t]}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n","import { ServiceOffering } from '@/api/services';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { Box, Grid, Typography } from '@mui/material';\nimport { useMemo } from 'react';\nimport { ServiceDatePicker } from './fields/ServiceDatePicker';\nimport { Frequency } from './fields/Frequency';\nimport { PropertyTraits } from './fields/PropertyTraits';\nimport { TimeFrame } from './fields/Timeframe';\n\ninterface Props {\n service: ServiceOffering;\n}\n\nexport const ServiceDetailForm = (props: Props) => {\n const { service } = props;\n\n const layout = useGetUILayout();\n const columnSize = useMemo(() => {\n return layout == 'desktop' ? 6 : 12;\n }, [layout]);\n\n return (\n <Box>\n <Typography gutterBottom>\n <b>{service.serviceName}</b>\n </Typography>\n <Grid container spacing={1} alignItems=\"center\">\n <Grid item xs={columnSize}>\n <ServiceDatePicker serviceId={service.serviceId} />\n </Grid>\n\n <Grid item xs={columnSize}>\n <TimeFrame serviceId={service.serviceId} />\n </Grid>\n\n {service.serviceSchedulingPlans && service.serviceSchedulingPlans.length > 0 && (\n <Grid item xs={columnSize}>\n <Frequency service={service} />\n </Grid>\n )}\n\n <PropertyTraits columnSize={columnSize} service={service} />\n </Grid>\n </Box>\n );\n};\n","import { Alert, Stack } from '@mui/material';\nimport { useEffect } from 'react';\n\nimport { useRequestServiceState } from '../../../store';\nimport { resetServiceDetails } from '../store';\nimport { ServiceDetailForm } from './Form/ServiceDetailForm';\nimport { useTexts } from './useTexts';\n\nexport const ServiceDetailList = () => {\n const texts = useTexts();\n const { services, serviceDetails } = useRequestServiceState();\n\n useEffect(() => {\n resetServiceDetails(serviceDetails);\n }, [serviceDetails]);\n\n return (\n <>\n {services.length == 0 && <Alert severity=\"info\">{texts.noServices}</Alert>}\n\n {services.length > 0 && (\n <Stack direction=\"column\" spacing={2}>\n {services.map((s, i) => (\n <ServiceDetailForm key={i} service={s} />\n ))}\n </Stack>\n )}\n </>\n );\n};\n","import { useCallback, useMemo } from 'react';\nimport { SideDrawerForm } from '@/components/form/SideDrawerForm';\nimport { Alert, Box } from '@mui/material';\nimport { setServiceDetails, useRequestServiceState } from '../../../store';\nimport { getServiceDetail, useSelectServiceDetail } from '../store';\nimport { areServiceDetailsSet } from '../../YourRequest/validation';\nimport { useTexts } from './useTexts';\nimport { ServiceDetailList } from './ServiceDetailList';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport const Drawer = (props: Props) => {\n const { onClose, open } = props;\n const texts = useTexts();\n const request = useRequestServiceState();\n const serviceDetails = useSelectServiceDetail();\n\n const onSave = useCallback(() => {\n const detail = getServiceDetail();\n setServiceDetails(detail);\n onClose();\n }, [onClose]);\n\n const isSaveDisabled = useMemo(() => {\n if (serviceDetails.length == 0) {\n return true;\n }\n\n const isValid = areServiceDetailsSet(request, serviceDetails);\n\n return !isValid;\n }, [request, serviceDetails]);\n\n return (\n <SideDrawerForm\n disableSave={isSaveDisabled}\n isOpen={open}\n headerSecondary={\n <Box p={2}>\n <Alert severity=\"info\">{texts.infoBox}</Alert>\n </Box>\n }\n onClose={onClose}\n onSave={onSave}\n title={texts.header}\n >\n <ServiceDetailList />\n </SideDrawerForm>\n );\n};\n\nDrawer.displayName = 'Drawer';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n actionBtn: translate({ id: 'sections.requestService.setServiceDetails.actionBtn' }),\n actionBtnDisabled: translate({ id: 'sections.requestService.setServiceDetails.actionBtnDisabled' }),\n header: translate({ id: 'sections.requestService.setServiceDetails.header' }),\n };\n }, [translate]);\n}\n","import { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport SettingsIcon from '@mui/icons-material/Settings';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { ButtonWithTooltip } from '@/components/ButtonWithTooltip';\nimport { useServiceRequirementComplete } from '../../store';\nimport { Drawer } from './Drawer/Drawer';\nimport { useTexts } from './useTexts';\n\nexport const SetServiceDetails = () => {\n const texts = useTexts();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const serviceRequirementsComplete = useServiceRequirementComplete();\n\n return (\n <>\n <Section>\n <SectionHeader title={texts.header} />\n <ButtonWithTooltip\n color=\"primary\"\n disabled={!serviceRequirementsComplete}\n onClick={openDrawer}\n showTooltip={!serviceRequirementsComplete}\n startIcon={<SettingsIcon />}\n tooltipText={serviceRequirementsComplete ? '' : texts.actionBtnDisabled}\n variant=\"contained\"\n >\n {texts.actionBtn}\n </ButtonWithTooltip>\n </Section>\n\n <Drawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n};\n\nSetServiceDetails.displayName = 'SetServiceDetails';\n","import { Box, Divider } from '@mui/material';\n\nexport const PaddedDivider = () => {\n return (\n <Box my={2}>\n <Divider />\n </Box>\n );\n};\n\nPaddedDivider.displayName = 'PaddedDivider';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n header: translate({ id: 'sections.requestService.yourRequest.header' }),\n noServicesSelected: translate({ id: 'sections.requestService.yourRequest.noServicesSelected' }),\n removeService: translate({ id: 'sections.requestService.yourRequest.removeService' }),\n setServiceDetails: translate({ id: 'sections.requestService.yourRequest.setServiceDetails' }),\n submitButton: translate({ id: 'sections.requestService.yourRequest.submitButton' }),\n submitButtonDisabledTooltip: translate({\n id: 'sections.requestService.yourRequest.submitButtonDisabledTooltip',\n }),\n submitError: translate({ id: 'sections.requestService.yourRequest.submitServiceRequestError' }),\n submitSuccess: translate({ id: 'sections.requestService.yourRequest.submitServiceRequestSuccess' }),\n };\n }, [translate]);\n}\n","import { useHumanizedSchedulingPlan } from '@/common/hooks/schedulingPlan/useHumanizedSchedulingPlan';\nimport { LongDate } from '@/components/localization';\nimport Typography from '@mui/material/Typography';\nimport * as _ from 'lodash';\nimport { ServiceDetails as ServiceDetailsModel } from '../SetServiceDetails/store';\n\ninterface Props {\n details: ServiceDetailsModel;\n}\n\nexport function ServiceDetails(props: Props) {\n const { details } = props;\n const humanizedSchedulingPlan = useHumanizedSchedulingPlan(details.schedulingPlan);\n\n return (\n <>\n {details.date && (\n <Typography>\n <LongDate value={details.date} />\n {details.timeFrame && <span> • {_.startCase(_.camelCase(details.timeFrame))}</span>}\n </Typography>\n )}\n {details.schedulingPlan && <Typography>{humanizedSchedulingPlan}</Typography>}\n {details.propertyTraits && (\n <>\n {details.propertyTraits.map((p, i) => (\n <Typography key={i} display=\"inline\">{`${p.amount} ${p.unitOfMeasure}${\n i == details.propertyTraits.length - 1 ? '' : ', '\n }`}</Typography>\n ))}\n </>\n )}\n </>\n );\n}\n","import { ServiceOffering } from '@/api/services';\nimport { Box, Grid, Typography } from '@mui/material';\nimport CloseIcon from '@mui/icons-material/Close';\nimport SettingsIcon from '@mui/icons-material/Settings';\nimport { useCallback, useMemo } from 'react';\nimport { IconButtonWithTooltip } from '@/components/IconButtonWithTooltip';\nimport { removeServiceOffering, useRequestServiceState } from '../../store';\nimport { useTexts } from './useTexts';\nimport { ServiceDetails } from './ServiceDetails';\n\ninterface Props {\n onEditDetails: () => void;\n service: ServiceOffering;\n}\n\nexport const Service = (props: Props) => {\n const { onEditDetails, service } = props;\n const texts = useTexts();\n\n const { serviceDetails } = useRequestServiceState();\n\n const details = useMemo(() => {\n return serviceDetails.find(d => d.serviceId == service.serviceId);\n }, [service.serviceId, serviceDetails]);\n\n const removeService = useCallback(() => {\n removeServiceOffering(service);\n }, [service]);\n\n return (\n <Box>\n <Grid container direction=\"column\">\n <Grid item>\n <Box display=\"flex\" alignItems=\"center\">\n <Box display=\"flex\" flexGrow={1}>\n <Typography>\n <b>{service.serviceName}</b>\n </Typography>\n </Box>\n <Box>\n <IconButtonWithTooltip\n edge=\"end\"\n onClick={onEditDetails}\n showTooltip={true}\n size=\"small\"\n tooltipText={texts.setServiceDetails}\n >\n <SettingsIcon fontSize=\"small\" />\n </IconButtonWithTooltip>\n\n <IconButtonWithTooltip\n edge=\"end\"\n onClick={removeService}\n showTooltip={true}\n size=\"small\"\n tooltipText={texts.removeService}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButtonWithTooltip>\n </Box>\n </Box>\n\n <Typography>{service.serviceDescription}</Typography>\n\n {details && <ServiceDetails details={details} />}\n </Grid>\n </Grid>\n </Box>\n );\n};\n\nService.displayName = 'Service';\n","import { post } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\n\nconst baseUrl = '/api/opportunities';\n\nexport const createOpportunity = async (object: any) => {\n try {\n const { data, status } = await post<any>(`${baseUrl}`, object);\n\n if (status === 200) {\n return data;\n }\n\n throw new ServerError(`Failed to request a service.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { ButtonWithTooltip } from '@/components/ButtonWithTooltip';\nimport { createOpportunity } from '@/api/opportunities';\nimport { useCallback, useMemo } from 'react';\nimport { toast } from 'react-toastify';\nimport { useNavigate } from 'react-router';\nimport { Box, CircularProgress } from '@mui/material';\nimport { useMutation } from 'react-query';\nimport { resetRequestServiceState, useRequestServiceState } from '../../store';\nimport { queryClient } from '../../../../services/queryClient';\nimport { useTexts } from './useTexts';\nimport { areServiceDetailsSet } from './validation';\n\nexport const SubmitRequestButton = () => {\n const request = useRequestServiceState();\n const texts = useTexts();\n const navigate = useNavigate();\n\n const mutation = useMutation(createOpportunity, {\n onError: () => {\n toast.error(texts.submitError);\n },\n onSuccess: async () => {\n toast.success(texts.submitSuccess);\n resetRequestServiceState();\n navigate('/your-services/your-requests');\n return queryClient.invalidateQueries('your-requests');\n },\n });\n\n const isValidRequest = useMemo(() => {\n const isLocationSelected = !!request.serviceLocation?.serviceLocationId;\n const areServicesSelected = request.services?.length > 0;\n const isDetailSet = areServiceDetailsSet(request, request.serviceDetails);\n\n return isLocationSelected && areServicesSelected && isDetailSet;\n }, [request]);\n\n const handleClick = useCallback(async () => {\n mutation.mutate(request);\n }, [mutation, request]);\n\n return (\n <ButtonWithTooltip\n color=\"primary\"\n disabled={!isValidRequest || mutation.isLoading}\n onClick={handleClick}\n showTooltip={!isValidRequest}\n tooltipText={!isValidRequest ? texts.submitButtonDisabledTooltip : ''}\n variant=\"contained\"\n >\n {mutation.isLoading && (\n <Box mr={1} display=\"flex\">\n <CircularProgress size={16} />\n </Box>\n )}\n {texts.submitButton}\n </ButtonWithTooltip>\n );\n};\n\nSubmitRequestButton.displayName = 'SubmitRequestButton';\n","import { useServiceLocationAddress } from '@/common/hooks/useAddress';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { PaddedDivider } from '@/components/PaddedDivider';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { Grid, Typography } from '@mui/material';\nimport { useRequestServiceState } from '../../store';\nimport { Drawer } from '../SetServiceDetails/Drawer/Drawer';\nimport { Service } from './Service';\nimport { SubmitRequestButton } from './SubmitRequestButton';\nimport { useTexts } from './useTexts';\n\nexport const YourRequest = () => {\n const texts = useTexts();\n const { note, serviceLocation, services } = useRequestServiceState();\n const address = useServiceLocationAddress(serviceLocation);\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n\n return (\n <>\n <Section>\n <SectionHeader title={texts.header} primaryAction={<SubmitRequestButton />} />\n {!!serviceLocation && (\n <>\n {serviceLocation.name && (\n <Typography>\n <b>{serviceLocation.name}</b>\n </Typography>\n )}\n <Typography>{address}</Typography>\n <PaddedDivider />\n </>\n )}\n\n {services.length > 0 ? (\n <Grid container direction=\"column\" spacing={2}>\n {services.map((service, i) => (\n <Grid item key={i}>\n <Service service={service} onEditDetails={openDrawer} />\n </Grid>\n ))}\n </Grid>\n ) : (\n <Typography>\n <i>{texts.noServicesSelected}</i>\n </Typography>\n )}\n {!!note && (\n <>\n <PaddedDivider />\n <Typography gutterBottom>\n <b>Note:</b>\n </Typography>\n <Typography style={{ whiteSpace: 'pre-line' }}>{note}</Typography>\n </>\n )}\n </Section>\n\n <Drawer open={drawerOpen} onClose={closeDrawer} />\n </>\n );\n};\n\nYourRequest.displayName = 'YourRequest';\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n pageHeader: translate({ id: 'sections.requestService.pageHeader' }),\n pageDescription: translate({ id: 'sections.requestService.pageDescription' }),\n };\n }, [translate]);\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { Box, Grid, Typography } from '@mui/material';\nimport { useAccountId } from '@/atoms/session';\nimport { useEffect } from 'react';\nimport { Unknown } from '../../sections/Unknown/Unknown';\nimport { AddNote } from './sections/AddNote/AddNote';\nimport { AddServices } from './sections/AddServices/AddServices';\nimport { SelectLocation } from './sections/SelectLocation/SelectLocation';\nimport { SetServiceDetails } from './sections/SetServiceDetails/SetServiceDetails';\nimport { YourRequest } from './sections/YourRequest/YourRequest';\nimport { useTexts } from './useTexts';\nimport { resetRequestServiceState } from './store';\n\nexport const RequestService = () => {\n const texts = useTexts();\n const featureEnabled = useFeatureEnabled('enableRequestNewService');\n const accountId = useAccountId();\n\n useEffect(() => {\n resetRequestServiceState();\n }, [accountId]);\n\n return (\n <PageWrapper fullWidth>\n {featureEnabled && (\n <>\n <Box mb={2}>\n <Typography variant=\"h2\" gutterBottom>\n {texts.pageHeader}\n </Typography>\n <Typography>{texts.pageDescription}</Typography>\n </Box>\n <Grid container direction=\"row\" spacing={2}>\n <Grid item container direction=\"column\" spacing={2} xs={12} md={8}>\n <Grid item>\n <SelectLocation />\n </Grid>\n <Grid item>\n <AddServices />\n </Grid>\n <Grid item>\n <SetServiceDetails />\n </Grid>\n <Grid item>\n <AddNote />\n </Grid>\n </Grid>\n <Grid item xs={12} md={4}>\n <YourRequest />\n </Grid>\n </Grid>\n </>\n )}\n {!featureEnabled && <Unknown />}\n </PageWrapper>\n );\n};\n\nRequestService.displayName = 'RequestService';\n","import type { FormError, FormField } from '@/formState';\n\nconst passwordField: FormField<string> = { value: '', required: true };\nconst reEnterPasswordField: FormField<string> = { value: '', required: true };\n\nexport const formFields = {\n password: passwordField,\n reEnterPassword: reEnterPasswordField,\n};\n\nexport type FormFields = typeof formFields;\nexport type FormErrors = FormError<keyof FormFields>;\n","import { useState, useRef, useEffect, useCallback } from 'react';\n\nimport { resetPassword as resetPasswordAction, validateLinkHash as validateLinkHashAction } from '@/services';\nimport { useToast } from '@/utils/useToast';\n\nexport function useResetPasswordActions() {\n const toast = useToast();\n\n // --------------------------------------\n // Mounted state ref for async callbacks\n\n const unmounted = useRef(false);\n useEffect(() => () => void (unmounted.current = true));\n\n // --------------------------------------\n // local state to track state of the login request\n\n const [submitting, setSubmitting] = useState(false);\n\n // --------------------------------------\n // callbacks\n const resetPassword = useCallback(async (linkHash: string, newPassword: string): Promise<boolean> => {\n try {\n setSubmitting(true);\n\n await resetPasswordAction(linkHash, newPassword);\n\n if (!unmounted.current) setSubmitting(false);\n\n return true;\n } catch (e) {\n // TODO: navigate 404 page\n return false;\n } finally {\n setSubmitting(false);\n }\n }, []);\n\n const validateLinkHash = useCallback(async (linkHash: string): Promise<boolean> => {\n return await validateLinkHashAction(linkHash);\n }, []);\n\n const notifyError = useCallback((message: string) => toast.error(message), [toast]);\n\n const notifySuccess = useCallback((message: string) => toast.success(message), [toast]);\n\n // --------------------------------------\n // --------------------------------------\n return {\n submitting,\n\n resetPassword,\n validateLinkHash,\n notifyError,\n notifySuccess,\n } as const;\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n passwordLabel: translate({ id: `sections.resetPassword.passwordLabel` }),\n reEnterPasswordLabel: translate({ id: `sections.resetPassword.reEnterPasswordLabel` }),\n passwordReset: translate({ id: `sections.resetPassword.passwordReset` }),\n enterNew: translate({ id: `sections.resetPassword.enterNew` }),\n changePassword: translate({ id: `sections.resetPassword.changePassword` }),\n success: translate({ id: `sections.resetPassword.success` }),\n succesfullyReset: translate({ id: `sections.resetPassword.succesfullyReset` }),\n invalid: translate({ id: `sections.resetPassword.invalid` }),\n error: translate({ id: `sections.resetPassword.error` }),\n signIn: translate({ id: `sections.login.login` }),\n invalidLink: translate({ id: `sections.resetPassword.invalidLink` }),\n serverError: translate({ id: `sections.resetPassword.serverError` }),\n };\n }, [translate]);\n}\n","import type { FormFields } from './formFields';\nimport type { FormError } from '@/formState';\nimport Button from '@mui/material/Button';\nimport Box from '@mui/material/Box';\nimport LinearProgress from '@mui/material/LinearProgress';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Typography from '@mui/material/Typography';\nimport { useFormMeta } from '@/formState';\nimport { useCallback, MouseEvent } from 'react';\n\ninterface Props {\n handleOnSubmit: () => Promise<void>;\n buttonText: string;\n failedText?: string;\n disabled?: boolean;\n}\n\nexport function Footer(props: Props) {\n const { handleOnSubmit, buttonText, failedText, disabled = false } = props;\n const { meta, api } = useFormMeta<FormFields, FormError<keyof FormFields>>();\n\n const formInvalid = meta.status === 'invalid';\n const formIndeterminate = meta.status === 'indeterminate';\n const formHasError = formInvalid || (formIndeterminate && Object.keys(api.getErrors()).length > 0);\n\n const handleOnClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n handleOnSubmit();\n },\n [handleOnSubmit],\n );\n\n return (\n <Box width=\"100%\">\n {meta.validating && <LinearProgress />}\n\n <Button\n fullWidth\n color=\"primary\"\n variant=\"contained\"\n onClick={handleOnClick}\n disabled={meta.submitting || disabled}\n type=\"submit\"\n size=\"small\"\n data-testid=\"btn-resetPassword\"\n >\n {meta.submitting && <CircularProgress size={16} />}\n <Box ml={1}>{buttonText}</Box>\n </Button>\n\n {formHasError && !!failedText ? <Typography color=\"error\">{failedText}</Typography> : null}\n </Box>\n );\n}\n","import Typography from '@mui/material/Typography';\nimport Box from '@mui/material/Box';\nimport { useCallback, useEffect, useState } from 'react';\nimport { FormError, FormValidator, useForm } from '@/formState';\nimport makeStyles from '@mui/styles/makeStyles';\nimport { Section } from '@/components/Section';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport Grid from '@mui/material/Grid';\nimport { useNavigate } from 'react-router';\nimport { TextField } from '@/formUI';\nimport { getPasswordErrors } from '@/components/PasswordRequirements/utils';\nimport { PasswordRequirements } from '@/components/PasswordRequirements/PasswordRequirements';\nimport { useTexts as useErrorsTexts } from '@/components/PasswordRequirements/useTexts';\nimport { useResetPasswordActions } from '../useResetPasswordActions';\nimport { useTexts } from '../useTexts';\nimport { Footer } from './Footer';\nimport { FormErrors, FormFields } from './formFields';\n\nconst useStyles = makeStyles({\n section: {\n width: '350px',\n },\n container: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n },\n});\n\nenum formStates {\n EnterPassword,\n ResetSuccesful,\n}\n\nexport const Form = () => {\n const texts = useTexts();\n const [formState, setFormState] = useState<formStates>(formStates.EnterPassword);\n const [validLink, setValidLink] = useState<boolean>(false);\n const { api, meta } = useForm<FormFields, FormError<keyof FormFields>>();\n const { resetPassword, validateLinkHash, notifyError } = useResetPasswordActions();\n const classes = useStyles();\n const navigate = useNavigate();\n const errorsTexts = useErrorsTexts();\n const linkHash = new URL(location.href).searchParams.get('hash') ?? '';\n\n const validateForm: FormValidator<FormFields, FormErrors> = formApi => {\n const pwField = formApi.getField('password');\n const reEnterPwField = formApi.getField('reEnterPassword');\n\n const errors = getPasswordErrors(pwField, reEnterPwField, errorsTexts);\n return errors;\n };\n\n useEffect(() => {\n if (!api.getValidator('checkPassword')) {\n api.addValidation('checkPassword', validateForm);\n }\n });\n\n const validateLink = useCallback(async () => {\n try {\n const linkIsValid = await validateLinkHash(linkHash);\n if (linkIsValid) {\n setValidLink(true);\n } else {\n notifyError(texts.invalidLink);\n }\n } catch (e) {\n notifyError(texts.serverError);\n }\n }, [linkHash, validateLinkHash, setValidLink, notifyError, texts]);\n\n useEffect(() => {\n validateLink();\n }, [validateLink]);\n\n const handleOnUpdate = useCallback(async () => {\n let passwordUpdated = false;\n try {\n api.setSubmitting(true);\n const values = api.getValues();\n passwordUpdated = await resetPassword(linkHash, values.password);\n } catch (e) {\n notifyError(texts.error);\n } finally {\n api.setSubmitting(false);\n if (passwordUpdated) {\n setFormState(formStates.ResetSuccesful);\n } else {\n notifyError(texts.error);\n }\n }\n }, [api, notifyError, resetPassword, linkHash, texts.error]);\n\n return (\n <Box className={classes.container}>\n <Section className={classes.section}>\n {formState === formStates.EnterPassword && (\n <form onChange={() => api.validate()}>\n <SectionHeader title={texts.passwordReset} />\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Typography>{texts.enterNew}</Typography>\n </Grid>\n <Grid item>\n <TextField<'password', FormFields, FormErrors>\n name=\"password\"\n textField={{\n type: 'password',\n }}\n UNSTABLE_textField={{ 'autoComplete': 'new-password' }}\n validateOn=\"change\"\n label={texts.passwordLabel}\n />\n </Grid>\n <Grid item>\n <TextField<'reEnterPassword', FormFields, FormErrors>\n name=\"reEnterPassword\"\n textField={{\n type: 'password',\n }}\n UNSTABLE_textField={{ 'autoComplete': 'new-password' }}\n validateOn=\"change blur\"\n label={texts.reEnterPasswordLabel}\n />\n </Grid>\n <Grid item>\n <Footer\n handleOnSubmit={handleOnUpdate}\n buttonText={texts.changePassword}\n disabled={meta.status !== 'valid' || !validLink}\n />\n </Grid>\n <Grid item>\n <PasswordRequirements errors={api.getErrors()} />\n </Grid>\n </Grid>\n </form>\n )}\n\n {formState == formStates.ResetSuccesful && (\n <>\n <SectionHeader title={texts.success} />\n <Grid container direction=\"column\" spacing={2}>\n <Grid item>\n <Typography>{texts.succesfullyReset}</Typography>\n </Grid>\n <Grid item>\n <Footer\n handleOnSubmit={async () => {\n navigate('/login');\n }}\n buttonText={texts.signIn}\n />\n </Grid>\n </Grid>\n </>\n )}\n </Section>\n </Box>\n );\n};\n","import { FormRoot, useCreateForm } from '@/formState';\nimport { formFields } from './formFields';\nimport { Form } from './Form';\n\nexport function FormProvider() {\n const formState = useCreateForm('update-password-form', formFields);\n\n return (\n <FormRoot formState={formState}>\n <Form />\n </FormRoot>\n );\n}\n","import { ContentContainer } from '@/components/ContentContainer';\nimport { ContentPaper } from '@/components/ContentPaper';\nimport { FormProvider } from './form/FormProvider';\n\nexport const ResetPassword = () => {\n return (\n <ContentContainer>\n <ContentPaper fullWidth>\n <FormProvider />\n </ContentPaper>\n </ContentContainer>\n );\n};\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\nimport { CommitmentWindowCustomerResponse } from './workOrderDetails';\n\nexport interface UpcomingServicesResponse {\n total: number;\n page: number;\n take: number;\n items: UpcomingServicesModel[];\n}\n\nexport interface UpcomingServicesModel {\n commitmentWindowConfirmationRequested: boolean;\n commitmentWindowCustomerResponse: CommitmentWindowCustomerResponse;\n endingEligibleDate: Date | null;\n estimatedTimeOfArrival: Date | null;\n number: number | null;\n projectSequence: number | null;\n startingEligibleDate: Date | null;\n subNumber: number | null;\n workOrderId: string;\n workOrderServices: string[];\n}\n\nconst baseUrl = 'api/Accounts';\n\nfunction getQueryString(page: number, take: number, search: string, serviceLocations: string[]) {\n const params = new URLSearchParams({\n page: page.toString(),\n take: take.toString(),\n });\n\n if (!!search) {\n params.append('searchTerm', search);\n }\n if (!!serviceLocations.length) {\n serviceLocations.map(x => !!x && params.append('serviceLocation', x));\n }\n\n return params;\n}\n\nexport const getUpcomingServices = async (\n accountId: string,\n page: number,\n take: number,\n search: string,\n serviceLocations: string[],\n) => {\n try {\n const queryString = getQueryString(page, take, search, serviceLocations);\n const { status, data } = await get<UpcomingServicesResponse>(\n `${baseUrl}/${accountId}/upcomingServices?${queryString}`,\n );\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError(`Failed to get upcoming services.`, status);\n } catch (e) {\n throw e;\n }\n};\n","import { useQuery } from 'react-query';\nimport { getUpcomingServices, UpcomingServicesResponse } from '@/api/upcomingServices';\n\nexport const useQueryUpcomingServices = (\n accountId: string,\n page: number,\n take: number,\n search: string,\n serviceLocations: string[],\n) =>\n useQuery<UpcomingServicesResponse, Error>(\n ['upcomingServices', accountId, page, take, search, serviceLocations],\n () => getUpcomingServices(accountId, page, take, search, serviceLocations),\n {\n keepPreviousData: true,\n },\n );\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n clearAll: translate({ id: 'sections.accountHistory.filters.clearAll' }),\n emptyState_getStarted: translate({ id: 'sections.upcomingServices.emptyState.getStarted' }),\n emptyState_newRequestsText: translate({ id: 'sections.upcomingServices.emptyState.newRequestsText' }),\n emptyState_noUpcomingServicesText: translate({\n id: 'sections.upcomingServices.emptyState.noUpcomingServicesText',\n }),\n emptyState_pleaseContact: translate({ id: 'sections.upcomingServices.emptyState.pleaseContact' }),\n emptyState_requestService: translate({ id: 'sections.upcomingServices.emptyState.requestService' }),\n emptyState_toSchedule: translate({ id: 'sections.upcomingServices.emptyState.toSchedule' }),\n filters: translate({ id: 'sections.upcomingServices.filters' }),\n noHistoryAlert: translate({ id: 'sections.upcomingServices.noHistoryAlert' }),\n searchPlaceholder: translate({ id: 'global.search' }),\n serviceEligible: translate({ id: 'sections.upcomingServices.serviceEligible' }),\n title: translate({ id: 'sections.upcomingServices.title' }),\n unscheduled: translate({ id: 'sections.upcomingServices.unscheduled' }),\n workOrder: translate({ id: 'global.workOrder' }),\n };\n }, [translate]);\n}\n","import Button from '@mui/material/Button';\nimport { useCallback } from 'react';\nimport { Section } from '@/components/Section';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AddIcon from '@mui/icons-material/Add';\nimport { useNavigate } from 'react-router';\nimport Box from '@mui/material/Box';\nimport { SectionHeader } from '@/components/SectionHeader';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { useBusinessUnitDetails } from '@/common/hooks/useBusinessUnitDetails';\nimport { PhoneNumber } from '@/components/localization/PhoneNumber';\nimport { useTexts } from './useTexts';\n\nexport function NoUpcomingServicesSection() {\n const texts = useTexts();\n const navigate = useNavigate();\n const requestServiceEnabled = useFeatureEnabled('enableRequestNewService');\n const details = useBusinessUnitDetails();\n\n const goToRequestServicePage = useCallback(\n (_event: React.MouseEvent<HTMLButtonElement>) => {\n navigate('/your-services/request-service');\n },\n [navigate],\n );\n\n return (\n <Stack spacing={2} direction=\"column\">\n <Typography variant=\"h2\">{texts.title}</Typography>\n <Section>\n <SectionHeader title={texts.emptyState_getStarted} />\n <Stack direction=\"column\" spacing={2}>\n {requestServiceEnabled && (\n <>\n <Typography>\n {texts.emptyState_noUpcomingServicesText} {texts.emptyState_newRequestsText}\n </Typography>\n <Box>\n <Button variant=\"contained\" onClick={goToRequestServicePage} startIcon={<AddIcon />}>\n {texts.emptyState_requestService}\n </Button>\n </Box>\n </>\n )}\n {!requestServiceEnabled && !!details && (\n <Typography>\n {`${texts.emptyState_noUpcomingServicesText} ${texts.emptyState_pleaseContact} ${\n !!details && details.name\n } ${texts.emptyState_toSchedule} `}\n <PhoneNumber phone={details.phone} phoneExt={details.phoneExt} />\n </Typography>\n )}\n </Stack>\n </Section>\n </Stack>\n );\n}\n","import { proxy, useSnapshot } from 'valtio';\nimport { useMemo } from 'react';\n\n// Store state\nexport interface ListState {\n page: number;\n take: number;\n search: string;\n selected: string;\n serviceLocations: string[];\n}\n\nexport const initialState: ListState = {\n page: 0,\n take: 10,\n selected: '',\n search: '',\n serviceLocations: [''],\n};\n\n// Valtio store initialization\nexport const state = proxy<ListState>(initialState);\n\n// Setter functions\nexport function setPage(page: number) {\n state.page = page;\n}\n\nexport function setTake(take: number) {\n state.take = take;\n}\n\nexport function setSearch(search: string) {\n state.search = search;\n}\n\nexport function setServiceLocations(locations: string[]) {\n state.serviceLocations = locations;\n\n if (!state.serviceLocations.length) {\n state.serviceLocations = initialState.serviceLocations;\n }\n}\n\nexport function clearServiceLocations() {\n state.serviceLocations = initialState.serviceLocations;\n}\n\nexport function setSelectedItem(id: string) {\n state.selected = id;\n}\n\nexport function clearSelectedItem() {\n state.selected = '';\n}\n\nexport function resetFilters() {\n clearServiceLocations();\n}\n\nexport function resetStore() {\n state.page = initialState.page;\n state.take = initialState.take;\n state.selected = initialState.selected;\n state.search = initialState.search;\n state.serviceLocations = initialState.serviceLocations;\n}\n\n//Hooks\nexport function useListState() {\n return useSnapshot(state);\n}\n\nexport function useIsListFiltered() {\n const { serviceLocations } = state;\n\n const isListFiltered = useMemo(() => {\n return !!serviceLocations.length && !!serviceLocations[0];\n }, [serviceLocations]);\n\n return isListFiltered;\n}\n","import { useCallback } from 'react';\nimport { clearServiceLocations, resetFilters, setPage, setSearch, setServiceLocations, setTake } from '../store';\n\nexport function useListActions() {\n const handleClearServiceLocations = useCallback(() => {\n setPage(0);\n clearServiceLocations();\n }, []);\n\n const handleDeleteServiceLocationFilter = useCallback(\n (id: string, serviceLocations: string[]) => (_e: React.MouseEvent<HTMLElement>) => {\n setPage(0);\n setServiceLocations(serviceLocations.filter(x => x !== id));\n },\n [],\n );\n\n const handleResetFilters = useCallback(() => {\n setPage(0);\n resetFilters();\n }, []);\n\n const handleSetPage = useCallback((_e, page: number) => {\n setPage(page - 1);\n }, []);\n\n const handleSetSearch = useCallback((search: string) => {\n setPage(0);\n setSearch(search);\n }, []);\n\n const handleSetServiceLocations = useCallback((locations: string[]) => {\n setPage(0);\n setServiceLocations(locations);\n }, []);\n\n const handleSetTake = useCallback((take: number) => {\n setTake(take);\n }, []);\n\n return {\n handleClearServiceLocations,\n handleDeleteServiceLocationFilter,\n handleResetFilters,\n handleSetPage,\n handleSetSearch,\n handleSetServiceLocations,\n handleSetTake,\n } as const;\n}\n","import { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { ServiceLocationFilterChip } from '@/components/cardList/chips';\nimport { ClearFiltersButton } from '@/components/cardList/filters';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { useListActions } from '../hooks';\nimport { useIsListFiltered, useListState } from '../store';\n\nexport function Chips() {\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations } = useListState();\n const { handleResetFilters, handleDeleteServiceLocationFilter } = useListActions();\n const isListFiltered = useIsListFiltered();\n\n return (\n <>\n {!!locations?.length && (\n <Box display=\"flex\" flexDirection=\"row\" alignItems=\"center\">\n <Box flexGrow={1}>\n <Stack direction=\"row-reverse\" spacing={1} flexWrap=\"wrap\" gap={1}>\n {!!serviceLocations.length &&\n serviceLocations.map(\n x =>\n !!x && (\n <ServiceLocationFilterChip\n key={x}\n id={x}\n onDelete={handleDeleteServiceLocationFilter(x, serviceLocations)}\n serviceLocations={locations}\n />\n ),\n )}\n </Stack>\n </Box>\n\n <Box ml={2} flexGrow={0}>\n {isListFiltered && <ClearFiltersButton onClick={handleResetFilters} />}\n </Box>\n </Box>\n )}\n </>\n );\n}\n","import { DebouncedSearchBox } from '@/components/cardList/DebouncedSearchBox';\nimport { ListHeader } from '@/components/cardList';\nimport { useTexts } from '../../useTexts';\nimport { useListActions } from '../hooks';\nimport { useListState } from '../store';\nimport { Chips } from './Chips';\n\ninterface Props {\n openDrawer: () => void;\n}\n\nexport function UpcomingServicesListHeader(props: Props) {\n const { openDrawer } = props;\n const texts = useTexts();\n const { search } = useListState();\n const { handleSetSearch } = useListActions();\n\n return (\n <ListHeader\n title={texts.title}\n openDrawer={openDrawer}\n searchBox={\n <DebouncedSearchBox placeholder={texts.searchPlaceholder} value={search} setValue={handleSetSearch} />\n }\n chips={<Chips />}\n />\n );\n}\n","import { FormattedDate } from 'react-intl';\n\ninterface Props {\n value: string | number | Date | undefined;\n}\n\nexport function ShortTime(props: Props) {\n const { value } = props;\n return <FormattedDate value={value} hour=\"numeric\" minute=\"2-digit\" dayPeriod=\"short\" />;\n}\n","import { CommitmentWindowCustomerResponse } from '@/api/workOrderDetails';\nimport { Box, Button, Stack } from '@mui/material';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n commitmentWindowCustomerResponse: CommitmentWindowCustomerResponse;\n onConfirm: () => void;\n onDecline: () => void;\n}\n\nexport function ConfirmationActions(props: Props) {\n const { commitmentWindowCustomerResponse, onConfirm, onDecline } = props;\n const texts = useTexts();\n\n return (\n <Stack spacing={1}>\n {commitmentWindowCustomerResponse !== CommitmentWindowCustomerResponse.DECLINED && (\n <Box>\n <Button color=\"error\" onClick={onDecline} variant=\"outlined\">\n {texts.declineVisit}\n </Button>\n </Box>\n )}\n {commitmentWindowCustomerResponse !== CommitmentWindowCustomerResponse.CONFIRMED && (\n <Box>\n <Button onClick={onConfirm} variant=\"contained\">\n {texts.confirmVisit}\n </Button>\n </Box>\n )}\n </Stack>\n );\n}\n","import { CommitmentWindowCustomerResponse, WorkOrderDetails, WorkOrderStatus } from '@/api/workOrderDetails';\nimport ListItemText from '@mui/material/ListItemText';\nimport { useFormattedWorkOrderNumber } from '@/common/hooks/useFormattedWorkOrderNumber';\nimport { Alert, Box, Stack, Typography } from '@mui/material';\nimport { ResourceDisplay } from '@/common/components/ResourceDisplay';\nimport { Currency, ShortDate, LongDateTime } from '@/components/localization';\nimport { useFormattedAddress } from '@/common/hooks/useAddress';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useCallback, useMemo } from 'react';\nimport { ShortTime } from '@/components/localization/Times';\nimport { setCommitmentWindowCustomerResponse } from '@/api/workOrders';\nimport { useAccountId } from '@/atoms/session';\nimport { useQueryUpcomingServices } from '@/common/hooks/query/useQueryUpcomingServices';\nimport { useQueryWorkOrderDetails } from '@/common/hooks/query/useQueryWorkOrderDetails';\nimport { useQueryYourNextService } from '@/common/hooks/query/useQueryYourNextService';\nimport { useToast } from '@/utils/useToast';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { DateOnly, Time } from '@/components/localization/Dates';\nimport { useListState } from '../UpcomingServicesList/store';\nimport { ConfirmationBadge } from '../components/ConfirmationBadge';\nimport { ServicesPerformedSecondary } from '../../AccountHistory/AccountHistoryList/cards/services/drawer/DetailListItems';\nimport { ConfirmationActions } from './ConfirmationActions';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n details: WorkOrderDetails;\n workOrderId: string;\n}\n\nexport function DetailListItems(props: Props) {\n const {\n details,\n details: { resource },\n workOrderId,\n } = props;\n const texts = useTexts();\n const isScheduled = useMemo(() => !!details.estimatedStartTime, [details]);\n const { page, take, search, serviceLocations } = useListState();\n const accountId = useAccountId();\n const { refetch: refetchCards } = useQueryUpcomingServices(accountId || '', page, take, search, serviceLocations);\n const { refetch: refetchDetails } = useQueryWorkOrderDetails(workOrderId);\n const { refetch: refetchYourNextService } = useQueryYourNextService(accountId || '');\n const toast = useToast();\n\n const enableWorkOrderNumber = useFeatureEnabled('enableWorkOrderNumber');\n const enableScheduledDate = useFeatureEnabled('enableScheduledDate');\n const enableScheduledTime = useFeatureEnabled('enableScheduledTime');\n const enableServiceLocation = useFeatureEnabled('enableServiceLocation');\n const enableIncludedServices = useFeatureEnabled('enableIncludedServices');\n const enableTeamTechnicianInfo = useFeatureEnabled('enableTeamTechnicianInfo');\n const enablePriceOfServiceVisit = useFeatureEnabled('enablePriceOfServiceVisit');\n\n const formattedWorkOrderNumber = useFormattedWorkOrderNumber(\n details.number,\n details.projectSequence,\n details.subNumber,\n );\n\n const serviceLocationAddress = useFormattedAddress(\n details.serviceLocation.street1,\n details.serviceLocation.street2,\n details.serviceLocation.city,\n details.serviceLocation.stateAbbreviation,\n details.serviceLocation.postalCode,\n details.serviceLocation.countryCode,\n );\n\n const refetchData = useCallback(() => {\n refetchDetails();\n refetchCards();\n refetchYourNextService();\n }, [refetchCards, refetchDetails, refetchYourNextService]);\n\n const confirmVisit = useCallback(async () => {\n try {\n await setCommitmentWindowCustomerResponse(workOrderId, CommitmentWindowCustomerResponse.CONFIRMED);\n toast.success(texts.successfullyConfirmed);\n refetchData();\n } catch (e) {\n toast.error(texts.failedToConfirm);\n }\n }, [refetchData, texts.failedToConfirm, texts.successfullyConfirmed, toast, workOrderId]);\n\n const declineVisit = useCallback(async () => {\n try {\n await setCommitmentWindowCustomerResponse(workOrderId, CommitmentWindowCustomerResponse.DECLINED);\n toast.success(texts.successfullyDeclined);\n refetchData();\n } catch (e) {\n toast.error(texts.failedToDecline);\n }\n }, [refetchData, texts.failedToDecline, texts.successfullyDeclined, toast, workOrderId]);\n\n return (\n <Stack direction=\"column\" spacing={2}>\n <Box display=\"flex\" alignItems=\"center\">\n {enableWorkOrderNumber && (\n <>\n <Box flexGrow={1}>\n <ListItemText\n primary={formattedWorkOrderNumber}\n primaryTypographyProps={{ fontWeight: 'bold' }}\n />\n </Box>\n </>\n )}\n {isScheduled && (\n <Box>\n <ConfirmationBadge\n confirmationRequested={details.commitmentWindowConfirmationRequested}\n status={details.commitmentWindowCustomerResponse}\n />\n </Box>\n )}\n </Box>\n {isScheduled && enableScheduledDate && enableScheduledTime && (\n <DefinitionListItem\n primary={texts.scheduledDateAndTime}\n secondary={<LongDateTime value={details.estimatedStartTime as Date} />}\n />\n )}\n\n {isScheduled && !enableScheduledDate && enableScheduledTime && (\n <DefinitionListItem\n primary={texts.scheduledTime}\n secondary={<Time value={details.estimatedStartTime as Date} />}\n />\n )}\n\n {isScheduled && enableScheduledDate && !enableScheduledTime && (\n <DefinitionListItem\n primary={texts.scheduledDate}\n secondary={<DateOnly value={details.estimatedStartTime as Date} />}\n />\n )}\n\n {isScheduled && (\n <DefinitionListItem\n primary={texts.eligibilityDate}\n secondary={\n <>\n <ShortDate value={details.startingEligibleDate as Date} />\n {` - `}\n <ShortDate value={details.endingEligibleDate as Date} />\n </>\n }\n />\n )}\n {details.commitmentWindowConfirmationRequested &&\n isScheduled &&\n details.startOfCommitmentWindow &&\n details.endOfCommitmentWindow && (\n <DefinitionListItem\n primary={texts.commitmentWindow}\n secondary={\n <span>\n <ShortTime value={details.startOfCommitmentWindow} />\n {' - '}\n <ShortTime value={details.endOfCommitmentWindow} />\n </span>\n }\n />\n )}\n {!isScheduled && enableServiceLocation && <Alert severity=\"info\">{texts.notYetScheduled}</Alert>}\n\n {enableServiceLocation && (\n <DefinitionListItem primary={texts.serviceLocation} secondary={serviceLocationAddress} />\n )}\n\n {enableIncludedServices && (\n <DefinitionListItem\n primary={texts.includedServices}\n secondary={<ServicesPerformedSecondary services={details.services} />}\n />\n )}\n {isScheduled && !!resource && enableTeamTechnicianInfo && (\n <ResourceDisplay imageId={resource.imageId} isCustom={resource.isCustomImage} name={resource.name} />\n )}\n {enablePriceOfServiceVisit && (\n <DefinitionListItem\n primary={texts.price}\n secondary={\n <Box>\n <Box>\n <Currency value={details.totals.subTotal} />\n </Box>\n <Box sx={{ fontStyle: 'italic' }}>\n <Typography variant=\"caption\">{texts.doesNotIncludeTax}</Typography>\n </Box>\n </Box>\n }\n />\n )}\n {details.commitmentWindowConfirmationRequested &&\n isScheduled &&\n details.status !== WorkOrderStatus.IN_PROGRESS && (\n <ConfirmationActions\n commitmentWindowCustomerResponse={details.commitmentWindowCustomerResponse}\n onConfirm={confirmVisit}\n onDecline={declineVisit}\n />\n )}\n </Stack>\n );\n}\n","import { useQueryWorkOrderDetails } from '@/common/hooks/query/useQueryWorkOrderDetails';\nimport { Alert, CircularProgress } from '@mui/material';\nimport { DetailListItems } from './DetailListItems';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n workOrderId: string;\n}\n\nexport function DrawerContent(props: Props) {\n const { workOrderId } = props;\n const texts = useTexts();\n const { data: details, status } = useQueryWorkOrderDetails(workOrderId);\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n {status == 'success' && (\n <>\n {!details && <Alert severity=\"error\">{texts.error}</Alert>}\n {details && <DetailListItems details={details} workOrderId={workOrderId} />}\n </>\n )}\n </>\n );\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faTools } from '@fortawesome/pro-regular-svg-icons';\nimport { FormattedDate } from 'react-intl';\nimport Box from '@mui/material/Box';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { useFormattedWorkOrderNumber } from '@/common/hooks/useFormattedWorkOrderNumber';\nimport { SideDrawer } from '@/components/SideDrawer';\nimport { theme } from '@/theme';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport Typography from '@mui/material/Typography';\nimport { useCallback } from 'react';\nimport { useFeatureEnabled } from '@/common/hooks/useFeatureEnabled';\nimport { useTexts } from '../../useTexts';\nimport { DrawerContent } from '../../drawer/DrawerContent';\nimport { ConfirmationBadge } from '../../components/ConfirmationBadge';\nimport { setSelectedItem, useListState } from '../store';\nimport { CardProps } from './typings';\n\nconst Title = (props: { date: Date | null | undefined; services: string[] }) => {\n const { date, services } = props;\n const texts = useTexts();\n\n return (\n <Box display=\"flex\" flexDirection=\"row\">\n <Typography noWrap>\n {!!date && date != undefined && (\n <FormattedDate value={date} day=\"2-digit\" month=\"2-digit\" year=\"2-digit\" />\n )}{' '}\n {!date && date != undefined && `${texts.unscheduled} | `}\n {services.join(', ')}\n </Typography>\n </Box>\n );\n};\n\nexport const ServiceCard = (props: CardProps) => {\n const { item } = props;\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const texts = useTexts();\n const layout = useGetUILayout();\n const enableWorkOrderNumber = useFeatureEnabled('enableWorkOrderNumber');\n const enableIncludedServices = useFeatureEnabled('enableIncludedServices');\n const enableScheduledDate = useFeatureEnabled('enableScheduledDate');\n\n const workOrderNumber = useFormattedWorkOrderNumber(\n item.number?.toString() || '',\n item.projectSequence,\n item.subNumber,\n );\n const formattedWorkOrderNumber = enableWorkOrderNumber ? workOrderNumber : '';\n const { selected } = useListState();\n\n const handleOpen = useCallback(() => {\n setSelectedItem(item.workOrderId!);\n openDrawer();\n }, [openDrawer, item.workOrderId]);\n\n const handleClose = useCallback(() => {\n setSelectedItem('');\n closeDrawer();\n }, [closeDrawer]);\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n badge={\n !!item.estimatedTimeOfArrival ? (\n <ConfirmationBadge\n confirmationRequested={item.commitmentWindowConfirmationRequested}\n status={item.commitmentWindowCustomerResponse}\n />\n ) : undefined\n }\n icon={<FontAwesomeIcon icon={faTools} />}\n onClick={handleOpen}\n selected={item.workOrderId === selected}\n styleOverrides={{\n container: {\n backgroundColor: !item.estimatedTimeOfArrival\n ? theme.palette.custom.lightGrey\n : theme.palette.white,\n },\n }}\n subTitle={formattedWorkOrderNumber}\n title={\n <Title\n date={enableScheduledDate ? item.estimatedTimeOfArrival : undefined}\n services={enableIncludedServices ? item.workOrderServices : []}\n />\n }\n />\n ) : (\n <MobileListCard\n badge={\n !!item.estimatedTimeOfArrival ? (\n <ConfirmationBadge\n confirmationRequested={item.commitmentWindowConfirmationRequested}\n status={item.commitmentWindowCustomerResponse}\n />\n ) : undefined\n }\n icon={<FontAwesomeIcon icon={faTools} />}\n onClick={handleOpen}\n selected={item.workOrderId === selected}\n styleOverrides={{\n container: {\n backgroundColor: !item.estimatedTimeOfArrival\n ? theme.palette.custom.lightGrey\n : theme.palette.white,\n },\n }}\n subTitle={formattedWorkOrderNumber}\n title={<Title date={item.estimatedTimeOfArrival} services={item.workOrderServices} />}\n />\n )}\n\n <SideDrawer isOpen={drawerOpen} onClose={handleClose} title={texts.title}>\n <DrawerContent workOrderId={item.workOrderId} />\n </SideDrawer>\n </>\n );\n};\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n clearAll: translate({ id: 'sections.accountHistory.filters.clearAll' }),\n title: translate({ id: 'sections.upcomingServices.drawer.title' }),\n };\n }, [translate]);\n}\n","import { SideDrawer } from '@/components/SideDrawer';\nimport Stack from '@mui/material/Stack';\nimport { ClearFiltersButton } from '@/components/cardList/filters/ClearFiltersButton';\nimport { useAccountId } from '@/atoms/session';\nimport { useFetchServiceLocations } from '@/common/hooks/query/useQueryServiceLocations';\nimport { ServiceLocationFilter } from '@/components/cardList/filters/ServiceLocationFilter';\nimport { useListActions } from '../hooks';\nimport { useListState } from '../store';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n onClose: () => void;\n open: boolean;\n}\n\nexport function FiltersDrawer(props: Props) {\n const { onClose, open } = props;\n const texts = useTexts();\n const { handleResetFilters, handleSetServiceLocations } = useListActions();\n const accountId = useAccountId();\n const { data: locations } = useFetchServiceLocations(accountId || '');\n const { serviceLocations } = useListState();\n\n return (\n <SideDrawer isOpen={open} onClose={onClose} title={texts.title}>\n <Stack direction=\"column\" spacing={2}>\n {!!locations && (\n <ServiceLocationFilter\n locations={locations}\n serviceLocations={serviceLocations}\n setServiceLocations={handleSetServiceLocations}\n />\n )}\n <ClearFiltersButton onClick={handleResetFilters} />\n </Stack>\n </SideDrawer>\n );\n}\n","import { UpcomingServicesModel } from '@/api/upcomingServices';\nimport { useMemo } from 'react';\n\nexport function useAccountHasNoUpcomingServices(\n serviceLocations: string[],\n search: string,\n items: UpcomingServicesModel[],\n) {\n return useMemo(\n () => !!serviceLocations.length && !serviceLocations[0] && !search && !items.length,\n [items, search, serviceLocations],\n );\n}\n","import { UpcomingServicesModel } from '@/api/upcomingServices';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { CardList, ListBody, ListFooter } from '@/components/cardList';\nimport { useTexts } from '../useTexts';\nimport { NoUpcomingServicesSection } from '../NoUpcomingServicesSection';\nimport { UpcomingServicesListHeader } from './header/UpcomingServicesListHeader';\nimport { ServiceCard } from './cards';\nimport { useListState } from './store';\nimport { useListActions } from './hooks';\nimport { FiltersDrawer } from './filters/FiltersDrawer';\nimport { useAccountHasNoUpcomingServices } from './hooks/useAccountHasNoUpcomingServices';\n\ninterface Props {\n items: UpcomingServicesModel[];\n total: number;\n}\n\nexport function UpcomingServicesList(props: Props) {\n const { items, total } = props;\n const { page, take, search, serviceLocations } = useListState();\n const texts = useTexts();\n const { handleSetPage } = useListActions();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const noUpcomingServices = useAccountHasNoUpcomingServices(serviceLocations, search, items);\n\n return (\n <>\n {!noUpcomingServices && (\n <>\n <CardList\n header={<UpcomingServicesListHeader openDrawer={openDrawer} />}\n body={<ListBody card={ServiceCard} emptyListAlertText={texts.noHistoryAlert} items={items} />}\n footer={<ListFooter count={Math.ceil(total / take)} page={page + 1} onChange={handleSetPage} />}\n />\n <FiltersDrawer open={drawerOpen} onClose={closeDrawer} />\n </>\n )}\n {noUpcomingServices && <NoUpcomingServicesSection />}\n </>\n );\n}\n","import Skeleton from '@mui/material/Skeleton';\nimport Grid from '@mui/material/Grid';\n\nexport function LoadingSkeleton() {\n return (\n <Grid container spacing={2} direction=\"column\" item sm={12} lg={8}>\n <Grid item>\n <Skeleton variant=\"text\" />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n </Grid>\n );\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { useAccountId } from '@/atoms/session';\nimport { PageErrorState } from '@/components/PageErrorState/PageErrorState';\nimport { useQueryUpcomingServices } from '@/common/hooks/query/useQueryUpcomingServices';\nimport { useEffect } from 'react';\nimport { UpcomingServicesList } from './UpcomingServicesList';\nimport { resetStore, useListState } from './UpcomingServicesList/store';\nimport { LoadingSkeleton } from './LoadingSkeleton';\n\nexport function UpcomingServicesPage() {\n const { page, take, search, serviceLocations } = useListState();\n const accountId = useAccountId();\n const query = useQueryUpcomingServices(accountId || '', page, take, search, serviceLocations);\n\n useEffect(() => {\n resetStore();\n }, [accountId]);\n\n return (\n <PageWrapper disableScroll>\n {query.status === 'loading' && <LoadingSkeleton />}\n {query.status === 'success' && <UpcomingServicesList items={query.data.items} total={query.data.total} />}\n {query.status === 'error' && <PageErrorState />}\n </PageWrapper>\n );\n}\n","import { get } from '@/utils/http';\nimport { ServerError } from '@/utils/ServerError';\nimport { SchedulingPlan } from './services';\n\nconst baseUrl = '/api/opportunities';\n\nexport interface ServiceRequestsListReponse {\n total: number;\n page: number;\n take: number;\n items: ServiceRequestListItemModel[];\n}\nexport enum ServiceRequestStatus {\n Declined = 'Declined',\n Pending = 'Pending',\n Processed = 'Processed',\n}\n\nexport interface ServiceRequestListItemModel {\n protoServiceAgreementId: string;\n status: ServiceRequestStatus;\n servicesRequested: string[];\n dateTimeCreated: Date;\n}\n\nexport interface PropertyTraitWithAmountModel {\n name: string;\n amount: number;\n unitOfMeasure: string;\n}\n\nexport enum ReservationTimeFrame {\n Afternoon = 'afternoon',\n Evening = 'evening',\n Morning = 'morning',\n}\n\nexport interface ReservationModel {\n workOrderId: string;\n serviceName: string;\n timeFrame: ReservationTimeFrame;\n schedulingPlan: SchedulingPlan;\n startingEligibleDate: Date | null;\n propertyTraits: PropertyTraitWithAmountModel[];\n}\n\nexport interface ServiceRequestDetails {\n reservations: ReservationModel[];\n serviceLocationContactName: string;\n serviceLocationContactEmail: string;\n serviceLocationContactPhone: string;\n serviceLocationAddress: string;\n serviceLocationCity: string;\n serviceLocationState: string;\n serviceLocationStateAbbreviation: string;\n serviceLocationPostalCode: string;\n serviceLocationCountry: string;\n status: ServiceRequestStatus;\n issue: string;\n}\n\nexport const getServiceRequests = async (accountId: string, page: number, take: number) => {\n try {\n const queryString = new URLSearchParams({\n page: page.toString(),\n take: take.toString(),\n });\n\n const { data, status } = await get<ServiceRequestsListReponse>(`${baseUrl}?${queryString}`, {\n params: { accountId },\n });\n\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError('Failed to get your service requests.', status);\n } catch (e) {\n throw e;\n }\n};\n\nexport const getServiceRequestDetails = async (protoServiceAgreementId: string) => {\n try {\n const { data, status } = await get<ServiceRequestDetails>(`${baseUrl}/${protoServiceAgreementId}`);\n if (status === 200 || status == 204) {\n return data;\n }\n\n throw new ServerError('Failed to get your service request details.', status);\n } catch (e) {\n throw e;\n }\n};\n","import { useQuery } from 'react-query';\nimport { getServiceRequests, ServiceRequestsListReponse } from '@/api/serviceRequests';\n\nexport const useQueryServiceRequests = (accountId: string, page: number, take: number) =>\n useQuery<ServiceRequestsListReponse, Error>(\n ['your-requests', accountId, page, take],\n () => getServiceRequests(accountId, page, take),\n {\n keepPreviousData: true,\n },\n );\n","import Skeleton from '@mui/material/Skeleton';\nimport Grid from '@mui/material/Grid';\n\nexport function LoadingSkeleton() {\n return (\n <Grid container spacing={2} direction=\"column\" item sm={12} lg={8}>\n <Grid item>\n <Skeleton variant=\"text\" />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n <Grid item>\n <Skeleton variant=\"rectangular\" height={65} />\n </Grid>\n </Grid>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n dateAndTimeRequested: translate({ id: 'sections.yourRequests.dateAndTimeRequested' }),\n declined: translate({ id: 'sections.yourRequests.declined' }),\n drawerTitle: translate({ id: 'sections.yourRequests.drawer.title' }),\n noServiceRequestsAlert: translate({ id: 'sections.yourRequests.noServiceRequestsAlert' }),\n pageTitle: translate({ id: 'sections.yourRequests.pageTitle' }),\n pending: translate({ id: 'sections.yourRequests.pending' }),\n processed: translate({ id: 'sections.yourRequests.processed' }),\n };\n }, [translate]);\n}\n","import { ListHeader } from '@/components/cardList';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n openDrawer?: () => void;\n}\n\nexport function YourRequestsListHeader(props: Props) {\n const { openDrawer } = props;\n const texts = useTexts();\n\n return <ListHeader title={texts.pageTitle} openDrawer={openDrawer} hideFilters singleLineOnMobile />;\n}\n","import { ServiceRequestStatus } from '@/api/serviceRequests';\nimport { CardBadge } from '@/components/cardList/CardBadge';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n status: string;\n}\n\nexport function StatusBadge(props: Props) {\n const { status } = props;\n const texts = useTexts();\n\n switch (status) {\n case ServiceRequestStatus.Pending:\n return <CardBadge severity=\"warning\" text={texts.pending} />;\n case ServiceRequestStatus.Processed:\n return <CardBadge severity=\"success\" text={texts.processed} />;\n case ServiceRequestStatus.Declined:\n return <CardBadge severity=\"error\" text={texts.declined} />;\n default:\n return null;\n }\n}\n","import { useQuery } from 'react-query';\nimport { getServiceRequestDetails, ServiceRequestDetails } from '@/api/serviceRequests';\n\nexport const useQueryServiceRequestDetails = (protoServiceAgreementId: string) =>\n useQuery<ServiceRequestDetails, Error>(['your-request-details', protoServiceAgreementId], () =>\n getServiceRequestDetails(protoServiceAgreementId),\n );\n","import Stack from '@mui/material/Stack';\nimport PostAddIcon from '@mui/icons-material/PostAdd';\nimport Typography from '@mui/material/Typography';\n\ninterface Props {\n issue: string;\n}\n\nexport function Issue(props: Props) {\n const { issue } = props;\n\n return (\n <Stack direction=\"row\" spacing={1}>\n <PostAddIcon />\n <Typography>{issue}</Typography>\n </Stack>\n );\n}\n","import { useMemo } from 'react';\nimport { useTranslate } from '@/intl';\n\nexport function useTexts() {\n const translate = useTranslate();\n\n return useMemo(() => {\n return {\n afternoon: translate({ id: 'sections.yourRequests.timeFrame.afternoon' }),\n error: translate({ id: 'sections.yourRequests.drawer.error' }),\n evening: translate({ id: 'sections.yourRequests.timeFrame.evening' }),\n morning: translate({ id: 'sections.yourRequests.timeFrame.morning' }),\n serviceAddress: translate({ id: 'sections.yourRequests.serviceAddress' }),\n serviceContact: translate({ id: 'sections.yourRequests.serviceContact' }),\n };\n }, [translate]);\n}\n","import { ReservationModel, ReservationTimeFrame } from '@/api/serviceRequests';\nimport { DefinitionListItem } from '@/components/DefinitionListItem';\nimport Stack from '@mui/material/Stack';\nimport Box from '@mui/material/Box';\nimport { LongDate } from '@/components/localization';\nimport { useHumanizedSchedulingPlan } from '@/common/hooks/schedulingPlan/useHumanizedSchedulingPlan';\nimport { useMemo } from 'react';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n reservation: ReservationModel;\n}\n\nexport function Reservation(props: Props) {\n const { reservation } = props;\n const { propertyTraits, schedulingPlan, serviceName, startingEligibleDate, timeFrame } = reservation;\n const texts = useTexts();\n const humanizedSchedulingPlan = useHumanizedSchedulingPlan(schedulingPlan);\n\n const humanizedPropertyTraits = useMemo(() => {\n return propertyTraits.map(x => `${x.amount} ${x.unitOfMeasure}`).join(', ');\n }, [propertyTraits]);\n\n const translatedTimeFrame = useMemo(() => {\n switch (timeFrame) {\n case ReservationTimeFrame.Afternoon:\n return texts.afternoon;\n case ReservationTimeFrame.Evening:\n return texts.evening;\n case ReservationTimeFrame.Morning:\n return texts.morning;\n }\n }, [timeFrame, texts.afternoon, texts.evening, texts.morning]);\n\n return (\n <DefinitionListItem\n primary={serviceName}\n secondary={\n <Stack>\n <Box>\n {!!startingEligibleDate && (\n <span>\n <LongDate value={startingEligibleDate} /> •{' '}\n </span>\n )}\n {translatedTimeFrame}\n </Box>\n <Box>{humanizedSchedulingPlan}</Box>\n <Box>{humanizedPropertyTraits}</Box>\n </Stack>\n }\n />\n );\n}\n","import { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useFormattedAddress } from '@/common/hooks/useAddress';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n street: string;\n city: string;\n country: string;\n postalCode: string;\n state: string;\n}\n\nexport function ServiceAddress(props: Props) {\n const { city, country, postalCode, state, street } = props;\n const texts = useTexts();\n const formattedAddress = useFormattedAddress(street, '', city, state, postalCode, country);\n\n return <DefinitionListItem primary={texts.serviceAddress} secondary={formattedAddress} />;\n}\n","import { DefinitionListItem } from '@/components/DefinitionListItem';\nimport { useTexts } from '../useTexts';\n\ninterface Props {\n contactName: string;\n}\n\nexport function ServiceContact(props: Props) {\n const { contactName } = props;\n const texts = useTexts();\n\n return <DefinitionListItem primary={texts.serviceContact} secondary={contactName} />;\n}\n","import { ServiceRequestDetails } from '@/api/serviceRequests';\nimport Box from '@mui/material/Box';\nimport Stack from '@mui/material/Stack';\nimport { Fragment } from 'react';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { Issue } from './listItems/Issue';\nimport { Reservation } from './listItems/Reservation';\nimport { ServiceAddress } from './listItems/ServiceAddress';\nimport { ServiceContact } from './listItems/ServiceContact';\n\ninterface Props {\n details: ServiceRequestDetails;\n}\n\nexport function DetailListItems(props: Props) {\n const { details } = props;\n const {\n issue,\n status,\n reservations,\n serviceLocationContactName,\n serviceLocationAddress,\n serviceLocationCity,\n serviceLocationCountry,\n serviceLocationPostalCode,\n serviceLocationStateAbbreviation,\n } = details;\n\n return (\n <Stack direction=\"column\" spacing={2}>\n <Box display=\"flex\" alignItems=\"flex-start\">\n <Box flexGrow={1}>\n <Reservation reservation={reservations[0]} />\n </Box>\n <StatusBadge status={status} />\n </Box>\n\n {reservations?.map((r, i) => (\n <Fragment key={i}>{!!i && <Reservation reservation={r} />}</Fragment>\n ))}\n\n <ServiceContact contactName={serviceLocationContactName} />\n\n <ServiceAddress\n city={serviceLocationCity}\n country={serviceLocationCountry}\n postalCode={serviceLocationPostalCode}\n state={serviceLocationStateAbbreviation}\n street={serviceLocationAddress}\n />\n\n {issue && <Issue issue={issue} />}\n </Stack>\n );\n}\n","import { useQueryServiceRequestDetails } from '@/common/hooks/query/useQueryServiceRequestDetails';\nimport { Alert, CircularProgress } from '@mui/material';\nimport { DetailListItems } from './DetailListItems';\nimport { useTexts } from './useTexts';\n\ninterface Props {\n protoServiceAgreementId: string;\n}\n\nexport function DrawerContent(props: Props) {\n const { protoServiceAgreementId } = props;\n const texts = useTexts();\n const { data: details, status } = useQueryServiceRequestDetails(protoServiceAgreementId);\n\n return (\n <>\n {status == 'loading' && <CircularProgress />}\n {status == 'error' && <Alert severity=\"error\">{texts.error}</Alert>}\n {status == 'success' && (\n <>\n {!details && <Alert severity=\"error\">{texts.error}</Alert>}\n {details && <DetailListItems details={details} />}\n </>\n )}\n </>\n );\n}\n","import { proxy, useSnapshot } from 'valtio';\n\n// Store state\nexport interface ListState {\n page: number;\n take: number;\n selected: string;\n}\n\nexport const initialState: ListState = {\n page: 0,\n take: 10,\n selected: '',\n};\n\n// Valtio store initialization\nexport const state = proxy<ListState>(initialState);\n\n// Setter functions\nexport function setPage(page: number) {\n state.page = page;\n}\n\nexport function setTake(take: number) {\n state.take = take;\n}\n\nexport function setSelectedItem(id: string) {\n state.selected = id;\n}\n\nexport function clearSelectedItem() {\n state.selected = '';\n}\n\nexport function resetStore() {\n state.page = initialState.page;\n state.selected = initialState.selected;\n state.take = initialState.take;\n}\n\n//Hooks\nexport function useListState() {\n return useSnapshot(state);\n}\n","import { ServiceRequestListItemModel } from '@/api/serviceRequests';\nimport { FormattedDate, FormattedTime } from 'react-intl';\nimport { useTexts } from '../../useTexts';\n\ninterface Props {\n item: ServiceRequestListItemModel;\n}\n\nexport function SubTitle(props: Props) {\n const { item } = props;\n const { dateTimeCreated } = item;\n const texts = useTexts();\n\n return (\n <span>\n <>\n {`${texts.dateAndTimeRequested} `}\n <FormattedDate value={dateTimeCreated} day=\"2-digit\" month=\"2-digit\" year=\"2-digit\" />{' '}\n <FormattedTime value={dateTimeCreated} />\n </>\n </span>\n );\n}\n","import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faAward } from '@fortawesome/pro-regular-svg-icons';\nimport { DesktopListCard } from '@/components/cardList/DesktopListCard';\nimport { useGetUILayout } from '@/atoms/UILayout';\nimport { MobileListCard } from '@/components/cardList/MobileListCard';\nimport { SideDrawer } from '@/components/SideDrawer';\nimport { useDrawerState } from '@/common/hooks/useDrawerState';\nimport { useCallback, useMemo } from 'react';\nimport { ServiceRequestListItemModel } from '@/api/serviceRequests';\nimport { useTexts } from '../../useTexts';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DrawerContent } from '../../drawer/DrawerContent';\nimport { setSelectedItem, useListState } from '../store';\nimport { SubTitle } from './SubTitle';\n\nexport interface CardProps {\n item: ServiceRequestListItemModel;\n}\n\nexport const RequestCard = (props: CardProps) => {\n const { item } = props;\n const texts = useTexts();\n const layout = useGetUILayout();\n const [closeDrawer, drawerOpen, openDrawer] = useDrawerState();\n const { selected } = useListState();\n\n const handleOpen = useCallback(() => {\n setSelectedItem(item.protoServiceAgreementId!);\n openDrawer();\n }, [openDrawer, item.protoServiceAgreementId]);\n\n const handleClose = useCallback(() => {\n setSelectedItem('');\n closeDrawer();\n }, [closeDrawer]);\n\n const title = useMemo(() => {\n return item.servicesRequested.join(', ');\n }, [item.servicesRequested]);\n\n return (\n <>\n {layout == 'desktop' ? (\n <DesktopListCard\n badge={<StatusBadge status={item.status} />}\n icon={<FontAwesomeIcon icon={faAward} />}\n onClick={handleOpen}\n selected={item.protoServiceAgreementId === selected}\n subTitle={<SubTitle item={item} />}\n title={title}\n />\n ) : (\n <MobileListCard\n badge={<StatusBadge status={item.status} />}\n icon={<FontAwesomeIcon icon={faAward} />}\n onClick={handleOpen}\n selected={item.protoServiceAgreementId === selected}\n subTitle={<SubTitle item={item} />}\n title={title}\n />\n )}\n\n <SideDrawer isOpen={drawerOpen} onClose={handleClose} title={texts.drawerTitle}>\n <DrawerContent protoServiceAgreementId={item.protoServiceAgreementId} />\n </SideDrawer>\n </>\n );\n};\n","import { useCallback } from 'react';\nimport { setPage, setTake } from '../store';\n\nexport function useListActions() {\n const handleSetPage = useCallback((_e, page: number) => {\n setPage(page - 1);\n }, []);\n\n const handleSetTake = useCallback((take: number) => {\n setTake(take);\n }, []);\n\n return {\n handleSetPage,\n handleSetTake,\n } as const;\n}\n","import { ServiceRequestListItemModel } from '@/api/serviceRequests';\nimport { CardList, ListBody, ListFooter } from '@/components/cardList';\nimport { useTexts } from '../useTexts';\nimport { YourRequestsListHeader } from './header/YourRequestsListHeader';\nimport { RequestCard } from './cards';\nimport { useListState } from './store';\nimport { useListActions } from './hooks';\n\ninterface Props {\n items: ServiceRequestListItemModel[];\n total: number;\n}\n\nexport function YourRequestsList(props: Props) {\n const { items, total } = props;\n const { page, take } = useListState();\n const texts = useTexts();\n const { handleSetPage } = useListActions();\n\n return (\n <CardList\n header={<YourRequestsListHeader />}\n body={<ListBody card={RequestCard} emptyListAlertText={texts.noServiceRequestsAlert} items={items} />}\n footer={<ListFooter count={Math.ceil(total / take)} page={page + 1} onChange={handleSetPage} />}\n />\n );\n}\n","import { PageWrapper } from '@/components/PageWrapper';\nimport { useAccountId } from '@/atoms/session';\nimport { PageErrorState } from '@/components/PageErrorState/PageErrorState';\nimport { useQueryServiceRequests } from '@/common/hooks/query/useQueryServiceRequests';\nimport { useEffect } from 'react';\nimport { LoadingSkeleton } from './LoadingSkeleton';\nimport { YourRequestsList } from './YourRequestsList';\nimport { resetStore, useListState } from './YourRequestsList/store';\n\nexport function YourRequestsPage() {\n const { page, take } = useListState();\n const accountId = useAccountId();\n const query = useQueryServiceRequests(accountId || '', page, take);\n\n useEffect(() => {\n resetStore();\n }, [accountId]);\n\n return (\n <PageWrapper disableScroll>\n {query.status === 'loading' && <LoadingSkeleton />}\n {query.status === 'success' && <YourRequestsList items={query.data.items} total={query.data.total} />}\n {query.status === 'error' && <PageErrorState />}\n </PageWrapper>\n );\n}\n","import type { ReactElement } from 'react';\nimport { useLocation, Navigate } from 'react-router-dom';\nimport { useIsUserAuthorized } from '@/atoms/session';\n\ninterface Props {\n element: ReactElement;\n}\n\nexport function PrivateRoute(props: Props): ReactElement<Props> {\n const { element } = props;\n\n const location = useLocation();\n const authorized = useIsUserAuthorized();\n\n if (!authorized) {\n return <Navigate to=\"/login\" replace state={{ from: location }} />;\n }\n\n return element;\n}\n","import * as sections from '@/sections';\nimport { Route, Routes } from 'react-router-dom';\nimport { PrivateRoute } from '@/router';\n\nexport function Sections() {\n return (\n // All URL driven sections must be nested under `RouterSections`\n <Routes>\n {/* Login screens */}\n <Route path=\"login\" element={<sections.Login />} />\n <Route path=\"register\" element={<sections.Register />} />\n <Route path=\"forgot-password\" element={<sections.ForgotPassword />} />\n <Route path=\"reset-password\" element={<sections.ResetPassword />} />\n\n <Route path=\"/\" element={<PrivateRoute element={<sections.App />} />}>\n <Route path=\"/\" element={<PrivateRoute element={<sections.AccountOverview />} />} />\n <Route path=\"account-history\" element={<PrivateRoute element={<sections.AccountHistory />} />} />\n <Route path=\"account-overview\" element={<PrivateRoute element={<sections.AccountOverview />} />} />\n <Route path=\"payments/pay-invoices\" element={<PrivateRoute element={<sections.PayInvoicesPage />} />} />\n <Route\n path=\"payments/payment-methods\"\n element={<PrivateRoute element={<sections.PaymentMethodsPage />} />}\n />\n <Route\n path=\"payments/manage-autopay\"\n element={<PrivateRoute element={<sections.ManageAutopayPage />} />}\n />\n <Route path=\"profile\" element={<PrivateRoute element={<sections.Profile />} />} />\n <Route\n path=\"questions-and-comments\"\n element={<PrivateRoute element={<sections.QuestionsAndCommentsPage />} />}\n />\n <Route\n path=\"your-services/agreements\"\n element={<PrivateRoute element={<sections.AgreementsPage />} />}\n />\n <Route\n path=\"your-services/request-service\"\n element={<PrivateRoute element={<sections.RequestService />} />}\n />\n <Route\n path=\"your-services/upcoming-services\"\n element={<PrivateRoute element={<sections.UpcomingServicesPage />} />}\n />\n <Route\n path=\"your-services/your-requests\"\n element={<PrivateRoute element={<sections.YourRequestsPage />} />}\n />\n\n <Route path=\"*\" element={<PrivateRoute element={<sections.Unknown />} />} />\n </Route>\n\n <Route path=\"forbidden\" element={<sections.Forbidden />} />\n <Route path=\"unknown\" element={<sections.Unknown />} />\n <Route path=\"*\" element={<sections.Unknown />} />\n </Routes>\n );\n}\n","import { setState } from '@/atoms/session/store';\nimport { useFetchTenantId } from '@/common/hooks/query/useQueryLoadTenant';\n\nexport const usePreload = () => {\n const storedStateString = localStorage.getItem('state');\n const initialState = storedStateString ? JSON.parse(storedStateString) : { authorized: false };\n setState(initialState);\n\n return useFetchTenantId();\n};\n","import { IntlLoadingScreen } from '@/intl';\nimport { Provider } from './Provider';\nimport { Layout } from './Layout';\nimport { Sections } from './Sections';\nimport { usePreload } from './usePreload';\n\n/**\n * Application's root component.\n * This component is the static root of the application.\n * It will never unmount and is responsible for rendering providers, layouts, and the main UI\n */\nexport function Root() {\n const appReady = usePreload();\n\n return (\n <>\n {appReady.isFetched && (\n <Provider>\n {/* main layout component. It wraps all rendered UIs */}\n <Layout>\n {/* Component used to show a loading screen during a change of language */}\n <IntlLoadingScreen>\n {/* URL navigation root and main entry point of the real UI */}\n <Sections />\n </IntlLoadingScreen>\n </Layout>\n </Provider>\n )}\n </>\n );\n}\n","import { ReportHandler } from 'web-vitals';\n\nexport function reportWebVitals(onPerfEntry?: ReportHandler): void {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n}\n","import 'react-toastify/dist/ReactToastify.css';\nimport './main.css';\n\nimport { StrictMode } from 'react';\nimport * as ReactDOM from 'react-dom';\n\nimport { Root } from './Root';\nimport { reportWebVitals } from './reportWebVitals';\nimport { printHostEnvironmentInfo } from './utils/hostEnvironmentInfo';\nimport { ReactQueryProvider } from './services';\n\nasync function main() {\n if (import.meta.env.DEV && import.meta.env.VITE_ENABLE_MOCK_SERVER == 'true') {\n // ------------------------------\n // conditional import executed only in DEV mode\n // the production build will not bundle or execute the mock server\n\n const { makeServer } = await import('./server');\n makeServer({ environment: 'development' });\n }\n\n // ------------------------------\n // mount the React Root component\n\n ReactDOM.render(\n <StrictMode>\n <ReactQueryProvider>\n <Root />\n </ReactQueryProvider>\n </StrictMode>,\n document.getElementById('root'),\n );\n\n // ------------------------------\n // If you want to start measuring performance in your app, pass a function\n // to log results (for example: reportWebVitals(console.log))\n // or send to an analytics endpoint.\n reportWebVitals();\n}\n\nmain();\n\nif (import.meta.env.DEV) {\n // print useful information on the host environment\n printHostEnvironmentInfo();\n}\n"],"names":["intlAPI","getIntlAPI","Error","IntlManagerComp","memo","props","intl","children","prevProps","nextProps","prevIntl","displayName","IntlManager","injectIntl","translate","options","formatMessage","values","useStyles","makeStyles","theme","contentContainer","display","width","height","flex","paddingTop","spacing","paddingBottom","paddingLeft","paddingRight","className","other","classes","toggleCss","position","contentPaper","padding","overflow","flexDirection","fullWidth","fullHeight","getInitialState","storage.getValue","state","initialState","baseUrl","useMemo","messages","useActiveLanguage","culture","useLocalizationSettings","language","selectLanguage","Content","texts","useTexts","useLanguageLoading","loading","error","actions","open","title","message","onConfirm","onDismiss","Button","no","yes","ConfirmationDialogContext","createContext","dialogOpen","setDialogOpen","useState","dialogConfig","setDialogConfig","openDialog","config","resetDialog","callbackFn","defaultTitle","confirmationWarning","localeMap","CultureCode","en_AU","enAULocale","en_CA","enCALocale","en_GB","enGBLocale","en_IE","en_NZ","enNZLocale","en_US","enUSLocale","customTheme","useCustomTheme","AdapterDateFns","Router","root","backgroundColor","palette","background","default","getQueryString","desktop","appbarHeight","overflowY","disableScroll","desktopContainer","marginLeft","marginRight","mobile","layout","useGetUILayout","errorMessage","useCallback","body","footer","header","chips","hideFilters","openDrawer","searchBox","singleLineOnMobile","FilterListIcon","filter","undefined","card","Card","emptyListAlertText","items","disabled","length","map","x","i","count","page","onChange","siblingCount","handlePageChange","event","Pagination","debounce","SearchBox","onClear","placeholder","value","TextField","startAdornment","SearchIcon","endAdornment","CloseIcon","search","setValue","internalValue","setInternalValue","debouncedValue","useDebounce","handleSearchChanged","e","target","handleSearchCleared","CommonSearchBox","DefaultCurrencyCode","callingCode","phone","phoneExt","formattedPhoneNumber","usePhoneNumber","telLink","usePhoneNumberTelLink","onDelete","startDate","endDate","label","onOrBefore","onOrAfter","type","HistoryItemType","INVOICE","invoices","WORK_ORDER","serviceVisits","PAYMENT","payments","id","serviceLocations","location","find","serviceLocationId","street1","street2","button","whiteSpace","minWidth","onClick","clearAll","useListState","isListFiltered","useIsListFiltered","accountId","useAccountId","data","locations","useFetchServiceLocations","handleClearDates","handleClearType","handleResetFilters","handleDeleteServiceLocationFilter","useListActions","handleSetSearch","searchPlaceholder","Chips","SideDrawer","useFormStyles","container","drawer","flexShrink","maxWidth","footerSecondary","headerSecondary","isOpen","onClose","Drawer","paper","setServiceLocations","handleAllClicked","dataset","handleOptionClicked","val","showAllServiceLocations","formatAddress","renderInput","params","handleSetStartDate","startDateLabel","handleSetEndDate","shouldDisableDate","date","_keyboardInputValue","endDateLabel","handleSetType","serviceHistoryEnabled","useFeatureEnabled","paymentHistoryEnabled","invoiceHistoryEnabled","formatMenuItemText","shouldDisableOption","showCompleteAccountHistory","Object","key","handleSetServiceLocations","tooltipText","showTooltip","spanClassName","setOpen","handleTooltipClose","handleTooltipOpen","disablePortal","marginBottom","border","selected","primary","main","subTitle","color","text","secondary","contentWrapper","alignItems","content","flexGrow","badgeContainer","DesktopListCard","actionBtnText","badge","icon","secondaryIcon","styleOverrides","toolTipText","view","borderRadius","fontSize","fontWeight","black","badges","info","success","warning","severity","right","lineHeight","maxHeight","textOverflow","MobileListCard","DefinitionListItem","useTheme","toast","useToast","errorText","mutation","useMutation","onError","onSuccess","handleClick","mutate","isLoading","invoiceDetails","workOrders","associatedWorkOrders","formattedNumbers","workOrder","number","join","none","billingCity","billingCountryCode","billingPostalCode","billingStateAbbreviation","billingStreet","billingStreet2","billingAddress","useFormattedAddress","billingLocation","p","amount","paymentMadeOn","paymentDate","refunds","r","index","refundTime","balance","total","paidStatusBadge","paid","partiallyPaid","unpaid","paymentStatus","serviceLocationCity","serviceLocationCountryCode","serviceLocationPostalCode","serviceLocationStateAbbreviation","serviceLocationStreet","serviceLocationStreet2","serviceAddress","serviceLocation","servicesPerformed","w","services","s","j","serviceName","navigate","useNavigate","paymentsEnabled","usePaymentsEnabled","details","invoiceDate","invoiceNum","showMakePaymentButton","redirectToMakePayment","onInvoiceReportClick","getInvoiceReport","invoiceId","invoice","PaymentStatus","makePayment","invoiceReportFailed","pdf","status","useQueryInvoiceDetail","DetailListItems","Title","invoiceNumber","Badge","InvoiceStatus","OPEN","PAID","InvoiceCard","item","closeDrawer","drawerOpen","useDrawerState","handleOpen","handleClose","invoiceStatus","faFileInvoiceDollar","invoiceTotal","DrawerContent","downloadLink","justifyContent","accountType","associatedInvoiceNumbers","paymentId","reference","associatedInvoiceTitle","associatedInvoiceNumber","associatedInvoiceSubTitle","onPaymentReceiptReportClick","getPaymentReceipt","onRefundReceiptReportClick","getRefundReceipt","isRefund","PARTIALLY_REFUNDED","REFUNDED","showReceipt","SUCCEEDED","paymentType","checkNumber","refundDetailsTitle","refundDate","refundAmount","refundPaymentType","refundMethod","paymentReceiptReportFailed","viewReceipt","refundReceiptReportFailed","viewRefundReceipt","useQueryPaymentDetail","PaymentSubtitle","identifier","invoiceNums","invoiceNumsStr","nums","split","trim","payment","forInvoice","PENDING","pending","succeeded","refunded","partiallyRefunded","CANCELLED","cancelled","FAILED","failed","Icon","PaymentMethod","CASH","faSackDollar","CREDIT_CARD","faCreditCard","CHECK","faMoneyCheck","ACH","faUniversity","faDollarSign","PaymentCard","useDrawerTexts","formattedAccountType","useFormattedAccountNumber","paymentAccountType","paymentMethod","itemPaymentStatus","isPartiallyRefunded","paymentAmount","paymentInvoiceNums","AccountCircle","avatarSize","img","imageId","isCustom","name","useFetchAvatarUrl","Avatar","team","technician","city","countryCode","postalCode","stateAbbreviation","resource","formattedWorkOrderNumber","useFormattedWorkOrderNumber","projectSequence","subNumber","onServiceReportClick","getServiceReport","workOrderId","enableLastServiceWorkOrderNumber","CustomerPortalLastServiceFields","EnableLastServiceWorkOrderNumber","enableLastServiceScheduledDate","EnableLastServiceScheduledDate","enableLastServiceScheduledTime","EnableLastServiceScheduledTime","enableLastServiceServiceLocation","EnableLastServiceServiceLocation","enableLastServiceIncludedServices","EnableLastServiceIncludedServices","enableLastServiceTeamTechnicianInfo","EnableLastServiceTeamTechnicianInfo","enableLastServicePriceOfServiceVisit","EnableLastServicePriceOfServiceVisit","enableLastServiceServiceReport","EnableLastServiceServiceReport","completedDateAndTimeOutput","correctedCompletedDateTime","actualCompletedTime","estimatedCompletedTime","completedDateAndTimeOutputText","dateCompleted","timeCompleted","dateAndTimeCompleted","isCustomImage","subTotal","failedToDownloadPDF","service","useQueryWorkOrderDetails","serviceVisit","ServiceCard","workOrderNumber","toString","workOrderProjectSequence","workOrderSubNumber","faTools","itemType","AccountHistoryList","take","handleSetPage","AccountHistoryCard","noHistoryAlert","Math","ceil","FiltersDrawer","AccountHistory","query","useQueryAccountHistory","useLocation","isStale","refetch","LoadingSkeleton","Section","typography","h3","primaryAction","secondaryAction","SectionHeader","SummaryValue","columnContainer","minInlineSize","accountBalance","openInvoices","openBalance","credits","prepayments","prePayments","hidePrimaryAction","useFetchAccountSummary","navigateToPayInvoices","confirmationRequested","CommitmentWindowCustomerResponse","CONFIRMED","confirmed","DECLINED","declined","UNKNOWN","needsConfirmation","textAlign","breakpoints","down","marginTop","servicesHiddenStyles","ServiceAmount","defaultClass","servicesHiddenClass","ServicesList","ServiceLocationDetail","serviceLocationName","zipCode","enableScheduledDate","enableScheduledTime","enableServiceLocation","enableIncludedServices","enableTeamTechnicianInfo","enablePriceOfServiceVisit","scheduledDateText","time","dateAndTime","estimatedTimeOfArrival","eta","notSet","eligibilityDate","startingEligibleDate","endingEligibleDate","notScheduled","servicesToBePerformed","noResults","useQueryYourNextService","setLoading","confirmVisit","setCommitmentWindowCustomerResponse","invalidateQueries","successfullyConfirmed","failedToConfirm","showBadge","commitmentWindowCustomerResponse","showButton","commitmentWindowConfirmationRequested","WorkOrderStatus","IN_PROGRESS","faClock","pl","confirmBtn","useData","setData","setIsStale","mounted","response","getLastServicePerformedWidget","isServerError","payload","refreshData","datePerformed","YourLastService","faHistory","upcomingServicesEnabled","requestServiceEnabled","goToRequestService","requestServices","AgreementStatus","ACTIVE","active","agreements","COMPLETED","completed","handleDeleteStatus","pageTitle","save","close","disableSave","hideFooter","hidePrimary","isSubmitting","onBackBtnClick","onSave","onSecondaryAction","primaryBtnLabel","primaryBtnLoading","secondaryBtnDisabled","secondaryBtnLabel","cancel","showBackBtn","ArrowBackIcon","achInput","accountNumber","routingNumber","setAchInput","isAccountNumberInvalid","isNaN","Number","isRoutingNumberInvalid","invalidAccountNumber","maxLength","invalidRoutingNumber","onCancel","transactionSetupMethod","url","account","getAccount","isListening","setIsListening","useRef","current","hostedPaymentsCallback","JSON","parse","isCancelledCreditCardCallback","isSuccessfulCreditCardCallback","businessUnitId","TransactionSetupMethod","PaymentAccountCreate","addCreditCardPaymentAccount","cardType","cardLogo","lastFour","month","expirationMonth","processorPaymentAccountId","paymentAccountId","year","expirationYear","hostedPaymentStatus","formatCreditCardFriendly","lastFourDigits","transactionId","approvalNumber","partnerRefId","errorAddingCreditCard","CreditCardSale","processorTransactionLogId","errorMakingPayment","addEventListener","removeEventListener","getPaymentTransactionsIframeUrl","log","errorLoadingIframe","onAddCreditCardSuccess","onCancelCreditCardEntry","setPaymentType","humanizedPaymentAccountTypes","useHumanizedPaymentAccountTypes","handleChange","creditCardEnabled","achEnabled","PaymentAccountTypes","selectPaymentType","inputCreditCard","inputACH","useAgreementDrawerState","useQueryPaymentAccounts","newPaymentMethod","WizardStep","ManageAutopay","AddPaymentMethodDrawerContent","setPaymentAccountType","email","contact","firstName","lastName","preferredMethodOfContact","MethodOfContact","Email","Phone","extension","Other","contactValue","address","subtitle","isSelected","white","styles","isExpired","textTransform","expMonth","expYear","friendly","isCreditCard","friendlyName","cardName","achName","expired","expires","padStart","agreementId","autoPaymentAccounts","hasValidationErrors","handleRemoveAutopay","useRemoveAutoPayActions","handleManageClick","AutoPaymentAccountType","autopayIsEnabled","autopayIsDisabled","locationHasErrors","AutorenewIcon","manageAutopay","disableAutopay","interval","intervalUnit","schedulingPlanDaysOfWeek","tolerance","schedulingPlan","useHumanizedSchedulingPlan","daysOfWeek","schedulingPlanId","Service","agreementServices","billingContact","invoiceMode","serviceContact","onAgreementReportClick","getAgreementReport","agreementName","StatusBadge","invoicingType","humanizedInvoiceModes","agreement","accountName","size","startsWith","CreditCardIcon","onSelect","select","paymentMethods","selectPaymentMethod","selectedPaymentMethod","noSavedPaymentMethodsText","noSavedPaymentMethods","noSavedPaymentMethodsCreditCard","noSavedPaymentMethodsACH","failedToLoadPaymentMethods","isCardExpired","paymentAccount","paymentAccounts","selectedPaymentAccount","handleOnSelect","goToAddPaymentMethodStep","AddPaymentMethod","hasAutoPaymentInstance","hasAutoPayInstance","useSavedPaymentMethod","addNewPaymentMethod","useQueryAgreementDetails","wizardStep","Detail","hasAutoPayment","hasExpiredPaymentMethod","autopayMethodIsExpired","WarningAmberRoundedIcon","agreementDate","effectiveDate","AgreementCard","handleOnSave","useAgreementCardActions","handleBackBtnClick","useDisableSave","faAward","SubTitle","drawerTitle","setStatus","statusProp","showAllAgreements","showActiveAgreements","showCancelledAgreements","showCompletedAgreements","handleSetStatus","filtersDrawerTitle","noAgreementsAlert","useQueryAgreements","greetingText","useDesktopGreeting","greeting","tagLine","popover","anchorEl","setAnchorEl","logout","useLogoutActions","getDisplayName","handleMenu","currentTarget","goToProfileSettings","_event","Boolean","AccountCircleIcon","vertical","horizontal","viewProfileSettings","drawerWidth","cursor","Header","handleContentClick","toggleSidebar","MenuIcon","iconContainer","ListItemWithChildren","hidden","path","setSubList","subList","_e","pathname","ArrowRightIcon","viewAgreementsEnabled","MuiList","payInvoices","requestService","yourRequests","upcomingServices","questionsAndCommentsEnabled","viewBillingHistoryEnabled","viewPaymentHistoryEnabled","DashboardIcon","accountOverview","yourServices","SubLists.YourServicesSubList","accountHistory","makePayments","SubLists.PaymentsSubList","faCommentAltSmile","questionsAndComments","ListItem","useTranslate","viewPaymentHistory","wrappingContainer","list","accountsList","onAccountSelected","List","AccountSwitchList","clearSubList","useFetchCustomerPortalSettings","heading","AccountSwitchAction","accountSwitch","switchLink","SwitchAccountView","contactId","getUser","accountFetchResults","useFetchAccountByContactId","isSuccess","Sidebar","footerContent","headerContent","selectedSubList","setSelectedSubList","Fragment","phoneNumber","useBusinessUnitDetails","companyName","useSplitAddress","logoImg","businessUnitDetails","companyLogoExists","useCompanyLogoExists","logoUrl","useFetchLogoUrl","drawerPaper","SidebarDrawer","useIsOpen","closeSidebar","mobileAppbarHeight","menuButton","useMobileGreeting","appBar","toolbar","mixins","overflowX","unauthorized","produce","castDraft","formContext","createEmptyFormState","formState","useContext","useReducer","emailField","formFields","CoreSmoothScrollbar","defaultScrollbarPosition","gap","SmoothScrollbar","forwardRef","forwardedRef","testId","scrollbarPosition","qa","onScroll","scrollTo","scrollIntoView","onChangeScrollbarVisibility","onChangeOutOfViewportHeight","rContainer","rScrollbar","useClasses","top","left","FitBox","ref","helperText","fieldsContainer","validateOn","autoFocus","textField","UNSTABLE_textField","field","errors","fieldApi","change","apiChange","validate","formApi","useFormField","required","visible","validateOnBlur","validateOnChange","validateOnFocus","useValidateOn","changeAndValidate","useDebounceText","onBlur","onFocus","fieldHasError","fieldInvalid","fieldIndeterminate","fieldDisabled","getMeta","submitting","MuiTextField","queryClient","handleOnSubmit","buttonText","failedText","meta","api","useFormMeta","formInvalid","formIndeterminate","formHasError","keys","getErrors","preventDefault","validating","section","Form","setFormState","formStates","resetPassword","useForgotPasswordActions","handleOnResetPassword","setSubmitting","getValues","validateForm","getField","getEmailErrors","mustBeValidEmail","getValidator","addValidation","enterEmail","emailLabel","Footer","sendEmail","emailHasBeenSent","resetRequested","useCreateForm","ForgotPassword","FormProvider","passwordField","login","loginAction","handleOnClick","loginFailed","MuiProps","MuiButton","ForgotPasswordButton","forgotPassword","accountSelect","useLoginState","handleOnAccountSelect","handleOnForgotPasswordClick","useLoginActions","welcome","passwordLabel","selectAnAccount","Login","useCheckSubdomain","description","_.cloneDeep","disableSelection","useIsInvoiceSelected","removeInvoice","addInvoice","deselect","unappliedStartingBalance","startingBalancePayment","usePayInvoicesState","unSelectUnappliedStartingBalance","selectUnappliedStartingBalance","invoicePagination","useFetchUnappliedStartingBalance","hasStartingBalance","useFetchOpenInvoices","mb","noInvoicesToDisplay","user","selection","setSelection","usePaymentTotal","addCard","invoicesSelected","refetchOpenInvoices","refetchAccountSummary","refetchUnappliedStartingBalance","handleSelection","handleCancel","InvoiceWizardStep","SelectSavedPaymentMethod","onOneTimePaymentSuccess","_paymentAccountId","friendlyValue","transactionReferenceNumber","processPayment","employeeId","identityUserId","invoicePayments","Date","PaymentMethodMapping","paymentSource","PaymentSource","PORTAL","HostedPaymentStatus","SUCCESS","processorTransactionId","paymentFailed","paymentSuccessful","Promise","all","onSaveCreditCardSuccess","prompt","yesOption","noOption","infoBox","infoBoxPayment","confirmationAlert","youAreUsing","toMakeA","paymentTotal","chargePaymentAccount","errorCode","chargePaymentMethod","badRequest","result","failureReason","isProcessingPayment","isSaveDisabled","hideSaveBtn","goToAddCreditCardStep","NewCardSave","addCreditCard","setPaymentMethod","processingPaymentAlert","reduce","a","b","paymentTotalFor","invoiceSingular","invoicePlural","useFetchDefaultBillingLocation","hasLocationErrors","validationErrors","pageDescription","useIsAchInputValid","addAchPaymentAccount","successfullyAddedAch","errorAddingAchAccountNumber","successfullyAddedCreditCard","buttonProps","tooltipLink","textDecoration","getConfirmation","useConfirmationDialog","isDisabled","handleDelete","deleteConfirmation","deletePaymentAccount","deleteSuccess","ach","deleteError","redirectToAutoPay","isAutoPayment","deletePaymentAccountAutoPayTooltip","moreInfo","deletePaymentAccountAutoPayInstanceTooltip","DeleteIcon","aspectRatio","divider","selectable","cardNumber","hideActions","ending","paymentAlertText","noPaymentMethodsAlert","noPaymentMethodsAlertCreditCard","noPaymentMethodsAlertACH","pb","ml","creditCardPageDescription","achPageDescription","addPaymentMethodBtn","useQueryActiveAgreements","oldPasswordField","confirmPasswordField","oldPassword","password","confirmPassword","doneButton","closeButton","PasswordRequirements","passwordMust","minChar","DoneIcon","minLength","missingLower","includeLower","missingUpper","includeUpper","missingNum","includeNumber","missingSpecial","includeSpecial","missingMatch","mustMatch","errorsTexts","useErrorsTexts","useForm","pwField","confirmPwField","getPasswordErrors","RequiredFieldValidation","currentPassword","newPassword","confirmPasswordFieldLabel","sessionClearWarning","formValues","changePassword","reset","passwordMask","comment","useSelectQuestionCommentState","onChangeComment","questionComment","onChangeLocation","l","saveDisabled","createQuestionOrComment","successToast","resetQuestionCommentState","clear","send","createAccount","signIn","customerPortalUserId","useCustomerPortalUserId","userRegistration","useFetchUserRegistration","register","afterRegistrationRedirect","notifyError","useRegistrationActions","isError","setDisabled","invalidRegistrationLink","userRegistrationNotCompletedYet","userRegistrationMessage","userAlreadyRegistered","registrationFailed","passwordFieldLabel","Register","note","requestNote","useRequestServiceState","useSelectAddNoteState","noteFieldLabel","setSelectionRange","AddNote","useGetNote","EditIcon","PostAddIcon","buttonEdit","buttonAdd","pageNumber","getServices","ServiceCheckbox","useIsServiceSelected","removeService","addService","serviceDescription","useAddServicesState","noServices","totalItems","pageCount","selectedServices","request","AddServices","locationRequirementsComplete","useLocationRequirementComplete","AddIcon","actionBtnDisabled","actionBtn","getLocations","defaultLocationId","getDefaultServiceLocationId","matchingLocation","firstValidLocation","subSubTitle","disabledLabel","opacity","LocationRadioButton","useSelectLocationState","handleLabelClick","hasErrors","LocationList","searchQuery","filteredLocations","addressString","country","toLowerCase","includes","noLocations","noLocationsMatchQuery","LocationSearch","onChangeSearch","clearSearch","SelectLocation","RoomIcon","arePropertyTraitsSet","detail","isValid","propertyTraits","servicePropertyTraits","every","trait","dp","propertyTraitId","serviceLocationPropertyTraitId","isSchedulingPlanSet","serviceSchedulingPlans","areServiceDetailsSet","d","serviceId","dateIsSet","dateHasNotPassed","setHours","propertyTraitsAreSet","schedulingPlanIsSet","timeFrameIsSet","timeFrame","ServiceDatePicker","holidays","useFetchHolidays","customerPortalSettings","serviceDetails","useSelectServiceDetails","isClosed","dayOfWeek","getDay","sundayAvailability","mondayAvailability","tuesdayAvailability","wednesdayAvailability","thursdayAvailability","fridayAvailability","saturdayAvailability","isHoliday","day","h","holidayDate","recurring","isSameMonth","getMonth","isSameDay","getDate","getFullYear","handleDateChange","frequency","humanizedSchedulingPlan","Frequency","serviceDetail","frequencies","_child","selectedPlan","f","useGetPropertyTraitsOnMount","getPropertyTraitsByService","forEach","PropertyTraits","columnSize","propertyTrait","inputProps","min","unitOfMeasure","pt","errorLoadingPropertyTraits","humanizedTimeFrames","TimeFrames","TimeFrame","settings","getAvailability","timeFrames","availableTimeFrames","availability","push","t","ServiceDetailForm","ServiceDetailList","useSelectServiceDetail","getServiceDetail","SetServiceDetails","serviceRequirementsComplete","useServiceRequirementComplete","SettingsIcon","PaddedDivider","_","onEditDetails","setServiceDetails","SubmitRequestButton","createOpportunity","submitError","submitSuccess","isValidRequest","isLocationSelected","areServicesSelected","isDetailSet","submitButtonDisabledTooltip","submitButton","YourRequest","useServiceLocationAddress","noServicesSelected","RequestService","featureEnabled","pageHeader","resetPasswordAction","validateLinkHash","validateLinkHashAction","validLink","setValidLink","useResetPasswordActions","linkHash","URL","href","searchParams","get","reEnterPwField","validateLink","invalidLink","serverError","handleOnUpdate","passwordUpdated","passwordReset","enterNew","reEnterPasswordLabel","succesfullyReset","ResetPassword","goToRequestServicePage","emptyState_getStarted","emptyState_noUpcomingServicesText","emptyState_newRequestsText","emptyState_requestService","emptyState_pleaseContact","emptyState_toSchedule","onDecline","declineVisit","isScheduled","estimatedStartTime","refetchCards","useQueryUpcomingServices","refetchDetails","refetchYourNextService","enableWorkOrderNumber","serviceLocationAddress","refetchData","successfullyDeclined","failedToDecline","scheduledDateAndTime","scheduledTime","scheduledDate","startOfCommitmentWindow","endOfCommitmentWindow","commitmentWindow","notYetScheduled","includedServices","price","totals","fontStyle","doesNotIncludeTax","unscheduled","custom","lightGrey","workOrderServices","noUpcomingServices","useAccountHasNoUpcomingServices","ServiceRequestStatus","Pending","Processed","processed","Declined","issue","reservation","humanizedPropertyTraits","translatedTimeFrame","ReservationTimeFrame","Afternoon","afternoon","Evening","evening","Morning","morning","street","formattedAddress","contactName","reservations","serviceLocationContactName","serviceLocationCountry","protoServiceAgreementId","useQueryServiceRequestDetails","dateTimeCreated","dateAndTimeRequested","RequestCard","servicesRequested","noServiceRequestsAlert","useQueryServiceRequests","element","useIsUserAuthorized","from","sections.Login","sections.Register","sections.ForgotPassword","sections.ResetPassword","sections.App","sections.AccountOverview","sections.AccountHistory","sections.PayInvoicesPage","sections.PaymentMethodsPage","sections.ManageAutopayPage","sections.Profile","sections.QuestionsAndCommentsPage","sections.AgreementsPage","sections.RequestService","sections.UpcomingServicesPage","sections.YourRequestsPage","sections.Unknown","sections.Forbidden","usePreload","storedStateString","localStorage","getItem","authorized","useFetchTenantId","appReady","isFetched","StrictMode","document","getElementById"],"mappings":"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"}